diff --git a/.mailmap b/.mailmap index 1dab0a156489..967f88210b12 100644 --- a/.mailmap +++ b/.mailmap @@ -160,6 +160,7 @@ Valdis Kletnieks Viresh Kumar Viresh Kumar Viresh Kumar +Vlad Dogaru Vladimir Davydov Vladimir Davydov Takashi YOSHII diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 5c70ce9c1954..1416c6a0d2cd 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -38,6 +38,7 @@ dallas,ds4510 CPU Supervisor with Nonvolatile Memory and Programmable I/O dallas,ds75 Digital Thermometer and Thermostat dlg,da9053 DA9053: flexible system level PMIC with multicore support dlg,da9063 DA9063: system PMIC for quad-core application processors +domintech,dmard09 DMARD09: 3-axis Accelerometer epson,rx8010 I2C-BUS INTERFACE REAL TIME CLOCK MODULE epson,rx8025 High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE @@ -56,6 +57,7 @@ maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface mc,rv3029c2 Real Time Clock Module with I2C-Bus +mcube,mc3230 mCube 3-axis 8-bit digital accelerometer microchip,mcp4531-502 Microchip 7-bit Single I2C Digital Potentiometer (5k) microchip,mcp4531-103 Microchip 7-bit Single I2C Digital Potentiometer (10k) microchip,mcp4531-503 Microchip 7-bit Single I2C Digital Potentiometer (50k) diff --git a/Documentation/devicetree/bindings/iio/accel/dmard06.txt b/Documentation/devicetree/bindings/iio/accel/dmard06.txt new file mode 100644 index 000000000000..ce105a12c645 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/dmard06.txt @@ -0,0 +1,19 @@ +Device tree bindings for Domintech DMARD05, DMARD06, DMARD07 accelerometers + +Required properties: + - compatible : Should be "domintech,dmard05" + or "domintech,dmard06" + or "domintech,dmard07" + - reg : I2C address of the chip. Should be 0x1c + +Example: + &i2c1 { + /* ... */ + + accelerometer@1c { + compatible = "domintech,dmard06"; + reg = <0x1c>; + }; + + /* ... */ + }; diff --git a/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt b/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt new file mode 100644 index 000000000000..b25bf3a77e0f --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt @@ -0,0 +1,22 @@ +Kionix KXSD9 Accelerometer device tree bindings + +Required properties: + - compatible: should be set to "kionix,kxsd9" + - reg: i2c slave address + +Optional properties: + - vdd-supply: The input supply for VDD + - iovdd-supply: The input supply for IOVDD + - interrupts: The movement detection interrupt + - mount-matrix: See mount-matrix.txt + +Example: + +kxsd9@18 { + compatible = "kionix,kxsd9"; + reg = <0x18>; + interrupt-parent = <&foo>; + interrupts = <57 IRQ_TYPE_EDGE_FALLING>; + iovdd-supply = <&bar>; + vdd-supply = <&baz>; +}; diff --git a/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt b/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt new file mode 100644 index 000000000000..68c45cbbe3d9 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt @@ -0,0 +1,29 @@ +* Mediatek AUXADC - Analog to Digital Converter on Mediatek mobile soc (mt65xx/mt81xx/mt27xx) +=============== + +The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found +in some Mediatek SoCs which among other things measures the temperatures +in the SoC. It can be used directly with register accesses, but it is also +used by thermal controller which reads the temperatures from the AUXADC +directly via its own bus interface. See +Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +for the Thermal Controller which holds a phandle to the AUXADC. + +Required properties: + - compatible: Should be one of: + - "mediatek,mt2701-auxadc": For MT2701 family of SoCs + - "mediatek,mt8173-auxadc": For MT8173 family of SoCs + - reg: Address range of the AUXADC unit. + - clocks: Should contain a clock specifier for each entry in clock-names + - clock-names: Should contain "main". + - #io-channel-cells: Should be 1, see ../iio-bindings.txt + +Example: + +auxadc: adc@11001000 { + compatible = "mediatek,mt2701-auxadc"; + reg = <0 0x11001000 0 0x1000>; + clocks = <&pericfg CLK_PERI_AUXADC>; + clock-names = "main"; + #io-channel-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt new file mode 100644 index 000000000000..049a1d36f013 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt @@ -0,0 +1,37 @@ +* Texas Instruments' ADC12130/ADC12132/ADC12138 + +Required properties: + - compatible: Should be one of + * "ti,adc12130" + * "ti,adc12132" + * "ti,adc12138" + - reg: SPI chip select number for the device + - interrupts: Should contain interrupt for EOC (end of conversion) + - clocks: phandle to conversion clock input + - spi-max-frequency: Definision as per + Documentation/devicetree/bindings/spi/spi-bus.txt + - vref-p-supply: The regulator supply for positive analog voltage reference + +Optional properties: + - vref-n-supply: The regulator supply for negative analog voltage reference + (Note that this must not go below GND or exceed vref-p) + If not specified, this is assumed to be analog ground. + - ti,acquisition-time: The number of conversion clock periods for the S/H's + acquisition time. Should be one of 6, 10, 18, 34. If not specified, + default value of 10 is used. + For high source impedances, this value can be increased to 18 or 34. + For less ADC accuracy and/or slower CCLK frequencies this value may be + decreased to 6. See section 6.0 INPUT SOURCE RESISTANCE in the + datasheet for details. + +Example: +adc@0 { + compatible = "ti,adc12138"; + reg = <0>; + interrupts = <28 IRQ_TYPE_EDGE_RISING>; + interrupt-parent = <&gpio1>; + clocks = <&cclk>; + vref-p-supply = <&ldo4_reg>; + spi-max-frequency = <5000000>; + ti,acquisition-time = <6>; +}; diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt new file mode 100644 index 000000000000..9ed2315781e4 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt @@ -0,0 +1,16 @@ +* Texas Instruments ADC141S626 and ADC161S626 chips + +Required properties: + - compatible: Should be "ti,adc141s626" or "ti,adc161s626" + - reg: spi chip select number for the device + +Recommended properties: + - spi-max-frequency: Definition as per + Documentation/devicetree/bindings/spi/spi-bus.txt + +Example: +adc@0 { + compatible = "ti,adc161s626"; + reg = <0>; + spi-max-frequency = <4300000>; +}; diff --git a/Documentation/devicetree/bindings/iio/chemical/atlas,orp-sm.txt b/Documentation/devicetree/bindings/iio/chemical/atlas,orp-sm.txt new file mode 100644 index 000000000000..5d8b687d5edc --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/atlas,orp-sm.txt @@ -0,0 +1,22 @@ +* Atlas Scientific ORP-SM OEM sensor + +https://www.atlas-scientific.com/_files/_datasheets/_oem/ORP_oem_datasheet.pdf + +Required properties: + + - compatible: must be "atlas,orp-sm" + - reg: the I2C address of the sensor + - interrupt-parent: should be the phandle for the interrupt controller + - interrupts: the sole interrupt generated by the device + + Refer to interrupt-controller/interrupts.txt for generic interrupt client + node bindings. + +Example: + +atlas@66 { + compatible = "atlas,orp-sm"; + reg = <0x66>; + interrupt-parent = <&gpio1>; + interrupts = <16 2>; +}; diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt new file mode 100644 index 000000000000..77d5aba1bd8c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt @@ -0,0 +1,29 @@ +* Asahi Kasei AK8974 magnetometer sensor + +Required properties: + +- compatible : should be "asahi-kasei,ak8974" +- reg : the I2C address of the magnetometer + +Optional properties: + +- avdd-supply: regulator supply for the analog voltage + (see regulator/regulator.txt) +- dvdd-supply: regulator supply for the digital voltage + (see regulator/regulator.txt) +- interrupts: data ready (DRDY) and interrupt (INT1) lines + from the chip, the DRDY interrupt must be placed first. + The interrupts can be triggered on rising or falling + edges alike. +- mount-matrix: an optional 3x3 mounting rotation matrix + +Example: + +ak8974@0f { + compatible = "asahi-kasei,ak8974"; + reg = <0x0f>; + avdd-supply = <&foo_reg>; + dvdd-supply = <&bar_reg>; + interrupts = <0 IRQ_TYPE_EDGE_RISING>, + <1 IRQ_TYPE_EDGE_RISING>; +}; diff --git a/Documentation/devicetree/bindings/iio/pressure/zpa2326.txt b/Documentation/devicetree/bindings/iio/pressure/zpa2326.txt new file mode 100644 index 000000000000..fb85de676e03 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/pressure/zpa2326.txt @@ -0,0 +1,31 @@ +Murata ZPA2326 pressure sensor + +Pressure sensor from Murata with SPI and I2C bus interfaces. + +Required properties: +- compatible: "murata,zpa2326" +- reg: the I2C address or SPI chip select the device will respond to + +Recommended properties for SPI bus usage: +- spi-max-frequency: maximum SPI bus frequency as documented in + Documentation/devicetree/bindings/spi/spi-bus.txt + +Optional properties: +- vref-supply: an optional regulator that needs to be on to provide VREF + power to the sensor +- vdd-supply: an optional regulator that needs to be on to provide VDD + power to the sensor +- interrupt-parent: phandle to the parent interrupt controller as documented in + Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +- interrupts: interrupt mapping for IRQ as documented in + Documentation/devicetree/bindings/interrupt-controller/interrupts.txt + +Example: + +zpa2326@5c { + compatible = "murata,zpa2326"; + reg = <0x5c>; + interrupt-parent = <&gpio>; + interrupts = <12>; + vdd-supply = <&ldo_1v8_gnss>; +}; diff --git a/Documentation/devicetree/bindings/iio/proximity/sx9500.txt b/Documentation/devicetree/bindings/iio/proximity/sx9500.txt new file mode 100644 index 000000000000..b301dd2b35da --- /dev/null +++ b/Documentation/devicetree/bindings/iio/proximity/sx9500.txt @@ -0,0 +1,24 @@ +Semtech's SX9500 capacitive proximity button device driver + +Required properties: + - compatible: must be "semtech,sx9500" + - reg: i2c address where to find the device + - interrupt-parent : should be the phandle for the interrupt controller + - interrupts : the sole interrupt generated by the device + + Refer to interrupt-controller/interrupts.txt for generic + interrupt client node bindings. + +Optional properties: + - reset-gpios: Reference to the GPIO connected to the device's active + low reset pin. + +Example: + +sx9500@28 { + compatible = "semtech,sx9500"; + reg = <0x28>; + interrupt-parent = <&gpio2>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; +}; diff --git a/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt b/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt new file mode 100644 index 000000000000..28bc5c4d965b --- /dev/null +++ b/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt @@ -0,0 +1,21 @@ +Maxim thermocouple support + +* https://datasheets.maximintegrated.com/en/ds/MAX6675.pdf +* https://datasheets.maximintegrated.com/en/ds/MAX31855.pdf + +Required properties: + + - compatible: must be "maxim,max31855" or "maxim,max6675" + - reg: SPI chip select number for the device + - spi-max-frequency: must be 4300000 + - spi-cpha: must be defined for max6675 to enable SPI mode 1 + + Refer to spi/spi-bus.txt for generic SPI slave bindings. + +Example: + + max31855@0 { + compatible = "maxim,max31855"; + reg = <0>; + spi-max-frequency = <4300000>; + }; diff --git a/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt b/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt deleted file mode 100644 index bdb782918a72..000000000000 --- a/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt +++ /dev/null @@ -1,21 +0,0 @@ -MediaTek AUXADC -=============== - -The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found -in some Mediatek SoCs which among other things measures the temperatures -in the SoC. It can be used directly with register accesses, but it is also -used by thermal controller which reads the temperatures from the AUXADC -directly via its own bus interface. See -Documentation/devicetree/bindings/thermal/mediatek-thermal.txt -for the Thermal Controller which holds a phandle to the AUXADC. - -Required properties: -- compatible: Must be "mediatek,mt8173-auxadc" -- reg: Address range of the AUXADC unit - -Example: - -auxadc: auxadc@11001000 { - compatible = "mediatek,mt8173-auxadc"; - reg = <0 0x11001000 0 0x1000>; -}; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 851e2caf9ae0..77e985f21707 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -76,6 +76,7 @@ digilent Diglent, Inc. dlg Dialog Semiconductor dlink D-Link Corporation dmo Data Modul AG +domintech Domintech Co., Ltd. dptechnics DPTechnics dragino Dragino Technology Co., Limited ea Embedded Artists AB diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index b0d775d28e97..75bc5b8add2f 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -266,8 +266,12 @@ IIO devm_iio_device_unregister() devm_iio_kfifo_allocate() devm_iio_kfifo_free() + devm_iio_triggered_buffer_setup() + devm_iio_triggered_buffer_cleanup() devm_iio_trigger_alloc() devm_iio_trigger_free() + devm_iio_trigger_register() + devm_iio_trigger_unregister() devm_iio_channel_get() devm_iio_channel_release() devm_iio_channel_get_all() diff --git a/MAINTAINERS b/MAINTAINERS index 4f4d56123099..841ffa3833ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -819,11 +819,11 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: sound/aoa/ -APEX EMBEDDED SYSTEMS STX104 DAC DRIVER +APEX EMBEDDED SYSTEMS STX104 IIO DRIVER M: William Breathitt Gray L: linux-iio@vger.kernel.org S: Maintained -F: drivers/iio/dac/stx104.c +F: drivers/iio/adc/stx104.c APM DRIVER M: Jiri Kosina @@ -1993,6 +1993,13 @@ S: Maintained F: drivers/media/i2c/as3645a.c F: include/media/i2c/as3645a.h +ASAHI KASEI AK8974 DRIVER +M: Linus Walleij +L: linux-iio@vger.kernel.org +W: http://www.akm.com/ +S: Supported +F: drivers/iio/magnetometer/ak8974.c + ASC7621 HARDWARE MONITOR DRIVER M: George Joseph L: linux-hwmon@vger.kernel.org @@ -5318,6 +5325,77 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/aeroflex/ +GREYBUS SUBSYSTEM +M: Johan Hovold +M: Alex Elder +M: Greg Kroah-Hartman +S: Maintained +F: drivers/staging/greybus/ + +GREYBUS AUDIO PROTOCOLS DRIVERS +M: Vaibhav Agarwal +M: Mark Greer +S: Maintained +F: drivers/staging/greybus/audio_apbridgea.c +F: drivers/staging/greybus/audio_apbridgea.h +F: drivers/staging/greybus/audio_codec.c +F: drivers/staging/greybus/audio_codec.h +F: drivers/staging/greybus/audio_gb.c +F: drivers/staging/greybus/audio_manager.c +F: drivers/staging/greybus/audio_manager.h +F: drivers/staging/greybus/audio_manager_module.c +F: drivers/staging/greybus/audio_manager_private.h +F: drivers/staging/greybus/audio_manager_sysfs.c +F: drivers/staging/greybus/audio_module.c +F: drivers/staging/greybus/audio_topology.c + +GREYBUS PROTOCOLS DRIVERS +M: Rui Miguel Silva +S: Maintained +F: drivers/staging/greybus/sdio.c +F: drivers/staging/greybus/light.c +F: drivers/staging/greybus/gpio.c +F: drivers/staging/greybus/power_supply.c +F: drivers/staging/greybus/spi.c +F: drivers/staging/greybus/spilib.c + +GREYBUS PROTOCOLS DRIVERS +M: Bryan O'Donoghue +S: Maintained +F: drivers/staging/greybus/loopback.c +F: drivers/staging/greybus/timesync.c +F: drivers/staging/greybus/timesync_platform.c + +GREYBUS PROTOCOLS DRIVERS +M: Viresh Kumar +S: Maintained +F: drivers/staging/greybus/authentication.c +F: drivers/staging/greybus/bootrom.c +F: drivers/staging/greybus/firmware.h +F: drivers/staging/greybus/fw-core.c +F: drivers/staging/greybus/fw-download.c +F: drivers/staging/greybus/fw-managament.c +F: drivers/staging/greybus/greybus_authentication.h +F: drivers/staging/greybus/greybus_firmware.h +F: drivers/staging/greybus/hid.c +F: drivers/staging/greybus/i2c.c +F: drivers/staging/greybus/spi.c +F: drivers/staging/greybus/spilib.c +F: drivers/staging/greybus/spilib.h + +GREYBUS PROTOCOLS DRIVERS +M: David Lin +S: Maintained +F: drivers/staging/greybus/uart.c +F: drivers/staging/greybus/log.c + +GREYBUS PLATFORM DRIVERS +M: Vaibhav Hiremath +S: Maintained +F: drivers/staging/greybus/arche-platform.c +F: drivers/staging/greybus/arche-apb-ctrl.c +F: drivers/staging/greybus/arche_platform.h + GSPCA FINEPIX SUBDRIVER M: Frank Zago L: linux-media@vger.kernel.org @@ -7548,6 +7626,12 @@ L: linux-iio@vger.kernel.org S: Maintained F: drivers/iio/potentiometer/mcp4531.c +MEASUREMENT COMPUTING CIO-DAC IIO DRIVER +M: William Breathitt Gray +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/iio/dac/cio-dac.c + MEDIA DRIVERS FOR RENESAS - FCP M: Laurent Pinchart L: linux-media@vger.kernel.org @@ -11263,6 +11347,7 @@ F: drivers/staging/media/lirc/ STAGING - LUSTRE PARALLEL FILESYSTEM M: Oleg Drokin M: Andreas Dilger +M: James Simmons L: lustre-devel@lists.lustre.org (moderated for non-subscribers) W: http://wiki.lustre.org/ S: Maintained @@ -11289,13 +11374,6 @@ M: Florian Schilhabel . S: Odd Fixes F: drivers/staging/rtl8712/ -STAGING - REALTEK RTL8723U WIRELESS DRIVER -M: Larry Finger -M: Jes Sorensen -L: linux-wireless@vger.kernel.org -S: Maintained -F: drivers/staging/rtl8723au/ - STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER M: Sudip Mukherjee M: Teddy Wang diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 16288e777ec3..562af94bec35 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -59,7 +59,6 @@ static struct dentry *binder_debugfs_dir_entry_proc; static struct binder_node *binder_context_mgr_node; static kuid_t binder_context_mgr_uid = INVALID_UID; static int binder_last_id; -static struct workqueue_struct *binder_deferred_workqueue; #define BINDER_DEBUG_ENTRY(name) \ static int binder_##name##_open(struct inode *inode, struct file *file) \ @@ -3227,7 +3226,7 @@ binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer) if (hlist_unhashed(&proc->deferred_work_node)) { hlist_add_head(&proc->deferred_work_node, &binder_deferred_list); - queue_work(binder_deferred_workqueue, &binder_deferred_work); + schedule_work(&binder_deferred_work); } mutex_unlock(&binder_deferred_lock); } @@ -3679,10 +3678,6 @@ static int __init binder_init(void) { int ret; - binder_deferred_workqueue = create_singlethread_workqueue("binder"); - if (!binder_deferred_workqueue) - return -ENOMEM; - binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); if (binder_debugfs_dir_entry_root) binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig index 25bcfa0b474f..2585821b24ab 100644 --- a/drivers/dma-buf/Kconfig +++ b/drivers/dma-buf/Kconfig @@ -17,4 +17,17 @@ config SYNC_FILE Files fds, to the DRM driver for example. More details at Documentation/sync_file.txt. +config SW_SYNC + bool "Sync File Validation Framework" + default n + depends on SYNC_FILE + depends on DEBUG_FS + ---help--- + A sync object driver that uses a 32bit counter to coordinate + synchronization. Useful when there is no hardware primitive backing + the synchronization. + + WARNING: improper use of this can result in deadlocking kernel + drivers from userspace. Intended for test and debug only. + endmenu diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile index f353db213a81..210a10bfad2b 100644 --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1,2 +1,3 @@ obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o obj-$(CONFIG_SYNC_FILE) += sync_file.o +obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o diff --git a/drivers/staging/android/sw_sync.c b/drivers/dma-buf/sw_sync.c similarity index 87% rename from drivers/staging/android/sw_sync.c rename to drivers/dma-buf/sw_sync.c index 115c9174705f..62e8e6dc7953 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -1,5 +1,5 @@ /* - * drivers/dma-buf/sw_sync.c + * Sync File validation framework * * Copyright (C) 2012 Google, Inc. * @@ -23,8 +23,38 @@ #include "sync_debug.h" #define CREATE_TRACE_POINTS -#include "trace/sync.h" +#include "sync_trace.h" +/* + * SW SYNC validation framework + * + * A sync object driver that uses a 32bit counter to coordinate + * synchronization. Useful when there is no hardware primitive backing + * the synchronization. + * + * To start the framework just open: + * + * /sync/sw_sync + * + * That will create a sync timeline, all fences created under this timeline + * file descriptor will belong to the this timeline. + * + * The 'sw_sync' file can be opened many times as to create different + * timelines. + * + * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct + * sw_sync_ioctl_create_fence as parameter. + * + * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used + * with the increment as u32. This will update the last signaled value + * from the timeline and signal any fence that has a seqno smaller or equal + * to it. + * + * struct sw_sync_ioctl_create_fence + * @value: the seqno to initialise the fence with + * @name: the name of the new sync point + * @fence: return the fd of the new sync_file with the created fence + */ struct sw_sync_create_fence_data { __u32 value; char name[32]; @@ -35,6 +65,7 @@ struct sw_sync_create_fence_data { #define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ struct sw_sync_create_fence_data) + #define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) static const struct fence_ops timeline_fence_ops; @@ -176,7 +207,7 @@ static void timeline_fence_release(struct fence *fence) spin_lock_irqsave(fence->lock, flags); list_del(&pt->child_list); - if (WARN_ON_ONCE(!list_empty(&pt->active_list))) + if (!list_empty(&pt->active_list)) list_del(&pt->active_list); spin_unlock_irqrestore(fence->lock, flags); diff --git a/drivers/staging/android/sync_debug.c b/drivers/dma-buf/sync_debug.c similarity index 99% rename from drivers/staging/android/sync_debug.c rename to drivers/dma-buf/sync_debug.c index 4c5a85595a85..fab95204cf74 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/dma-buf/sync_debug.c @@ -1,5 +1,5 @@ /* - * drivers/base/sync.c + * Sync File validation framework and debug information * * Copyright (C) 2012 Google, Inc. * diff --git a/drivers/staging/android/sync_debug.h b/drivers/dma-buf/sync_debug.h similarity index 97% rename from drivers/staging/android/sync_debug.h rename to drivers/dma-buf/sync_debug.h index fab66396d421..d269aa6783aa 100644 --- a/drivers/staging/android/sync_debug.h +++ b/drivers/dma-buf/sync_debug.h @@ -1,5 +1,5 @@ /* - * include/linux/sync.h + * Sync File validation framework and debug infomation * * Copyright (C) 2012 Google, Inc. * diff --git a/drivers/staging/android/trace/sync.h b/drivers/dma-buf/sync_trace.h similarity index 84% rename from drivers/staging/android/trace/sync.h rename to drivers/dma-buf/sync_trace.h index 6b5ce9640ddd..d13d59ff1b85 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/dma-buf/sync_trace.h @@ -1,11 +1,11 @@ #undef TRACE_SYSTEM -#define TRACE_INCLUDE_PATH ../../drivers/staging/android/trace -#define TRACE_SYSTEM sync +#define TRACE_INCLUDE_PATH ../../drivers/dma-buf +#define TRACE_SYSTEM sync_trace #if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_SYNC_H -#include "../sync_debug.h" +#include "sync_debug.h" #include TRACE_EVENT(sync_timeline, diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 78f148ea9d9f..2b791fe1e2bc 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -52,6 +52,27 @@ config BMC150_ACCEL_SPI tristate select REGMAP_SPI +config DMARD06 + tristate "Domintech DMARD06 Digital Accelerometer Driver" + depends on OF || COMPILE_TEST + depends on I2C + help + Say yes here to build support for the Domintech low-g tri-axial + digital accelerometers: DMARD05, DMARD06, DMARD07. + + To compile this driver as a module, choose M here: the + module will be called dmard06. + +config DMARD09 + tristate "Domintech DMARD09 3-axis Accelerometer Driver" + depends on I2C + help + Say yes here to get support for the Domintech DMARD09 3-axis + accelerometer. + + Choosing M will build the driver as a module. If so, the module + will be called dmard09. + config HID_SENSOR_ACCEL_3D depends on HID_SENSOR_HUB select IIO_BUFFER @@ -98,14 +119,35 @@ config IIO_ST_ACCEL_SPI_3AXIS config KXSD9 tristate "Kionix KXSD9 Accelerometer Driver" - depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for the Kionix KXSD9 accelerometer. - Currently this only supports the device via an SPI interface. + It can be accessed using an (optional) SPI or I2C interface. To compile this driver as a module, choose M here: the module will be called kxsd9. +config KXSD9_SPI + tristate "Kionix KXSD9 SPI transport" + depends on KXSD9 + depends on SPI + default KXSD9 + select REGMAP_SPI + help + Say yes here to enable the Kionix KXSD9 accelerometer + SPI transport channel. + +config KXSD9_I2C + tristate "Kionix KXSD9 I2C transport" + depends on KXSD9 + depends on I2C + default KXSD9 + select REGMAP_I2C + help + Say yes here to enable the Kionix KXSD9 accelerometer + I2C transport channel. + config KXCJK1013 tristate "Kionix 3-Axis Accelerometer Driver" depends on I2C @@ -119,6 +161,16 @@ config KXCJK1013 To compile this driver as a module, choose M here: the module will be called kxcjk-1013. +config MC3230 + tristate "mCube MC3230 Digital Accelerometer Driver" + depends on I2C + help + Say yes here to build support for the mCube MC3230 low-g tri-axial + digital accelerometer. + + To compile this driver as a module, choose M here: the + module will be called mc3230. + config MMA7455 tristate select IIO_BUFFER diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 6cedbecca2ee..f5d3ddee619e 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -8,9 +8,14 @@ obj-$(CONFIG_BMA220) += bma220_spi.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o +obj-$(CONFIG_DMARD06) += dmard06.o +obj-$(CONFIG_DMARD09) += dmard09.o obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o +obj-$(CONFIG_KXSD9_SPI) += kxsd9-spi.o +obj-$(CONFIG_KXSD9_I2C) += kxsd9-i2c.o +obj-$(CONFIG_MC3230) += mc3230.o obj-$(CONFIG_MMA7455) += mma7455_core.o obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index e3f88ba5faf3..0890934ef66f 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -469,13 +469,14 @@ static int bma180_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + mutex_lock(&data->mutex); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&data->mutex); - return -EBUSY; - } ret = bma180_get_data_reg(data, chan->scan_index); mutex_unlock(&data->mutex); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; *val = sign_extend32(ret >> chan->scan_type.shift, diff --git a/drivers/iio/accel/dmard06.c b/drivers/iio/accel/dmard06.c new file mode 100644 index 000000000000..656ca8e1927f --- /dev/null +++ b/drivers/iio/accel/dmard06.c @@ -0,0 +1,241 @@ +/* + * IIO driver for Domintech DMARD06 accelerometer + * + * Copyright (C) 2016 Aleksei Mamlin + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include + +#define DMARD06_DRV_NAME "dmard06" + +/* Device data registers */ +#define DMARD06_CHIP_ID_REG 0x0f +#define DMARD06_TOUT_REG 0x40 +#define DMARD06_XOUT_REG 0x41 +#define DMARD06_YOUT_REG 0x42 +#define DMARD06_ZOUT_REG 0x43 +#define DMARD06_CTRL1_REG 0x44 + +/* Device ID value */ +#define DMARD05_CHIP_ID 0x05 +#define DMARD06_CHIP_ID 0x06 +#define DMARD07_CHIP_ID 0x07 + +/* Device values */ +#define DMARD05_AXIS_SCALE_VAL 15625 +#define DMARD06_AXIS_SCALE_VAL 31250 +#define DMARD06_TEMP_CENTER_VAL 25 +#define DMARD06_SIGN_BIT 7 + +/* Device power modes */ +#define DMARD06_MODE_NORMAL 0x27 +#define DMARD06_MODE_POWERDOWN 0x00 + +/* Device channels */ +#define DMARD06_ACCEL_CHANNEL(_axis, _reg) { \ + .type = IIO_ACCEL, \ + .address = _reg, \ + .channel2 = IIO_MOD_##_axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .modified = 1, \ +} + +#define DMARD06_TEMP_CHANNEL(_reg) { \ + .type = IIO_TEMP, \ + .address = _reg, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ +} + +struct dmard06_data { + struct i2c_client *client; + u8 chip_id; +}; + +static const struct iio_chan_spec dmard06_channels[] = { + DMARD06_ACCEL_CHANNEL(X, DMARD06_XOUT_REG), + DMARD06_ACCEL_CHANNEL(Y, DMARD06_YOUT_REG), + DMARD06_ACCEL_CHANNEL(Z, DMARD06_ZOUT_REG), + DMARD06_TEMP_CHANNEL(DMARD06_TOUT_REG), +}; + +static int dmard06_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct dmard06_data *dmard06 = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = i2c_smbus_read_byte_data(dmard06->client, + chan->address); + if (ret < 0) { + dev_err(&dmard06->client->dev, + "Error reading data: %d\n", ret); + return ret; + } + + *val = sign_extend32(ret, DMARD06_SIGN_BIT); + + if (dmard06->chip_id == DMARD06_CHIP_ID) + *val = *val >> 1; + + switch (chan->type) { + case IIO_ACCEL: + return IIO_VAL_INT; + case IIO_TEMP: + if (dmard06->chip_id != DMARD06_CHIP_ID) + *val = *val / 2; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + *val = DMARD06_TEMP_CENTER_VAL; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + *val = 0; + if (dmard06->chip_id == DMARD06_CHIP_ID) + *val2 = DMARD06_AXIS_SCALE_VAL; + else + *val2 = DMARD05_AXIS_SCALE_VAL; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const struct iio_info dmard06_info = { + .driver_module = THIS_MODULE, + .read_raw = dmard06_read_raw, +}; + +static int dmard06_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct dmard06_data *dmard06; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "I2C check functionality failed\n"); + return -ENXIO; + } + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*dmard06)); + if (!indio_dev) { + dev_err(&client->dev, "Failed to allocate iio device\n"); + return -ENOMEM; + } + + dmard06 = iio_priv(indio_dev); + dmard06->client = client; + + ret = i2c_smbus_read_byte_data(dmard06->client, DMARD06_CHIP_ID_REG); + if (ret < 0) { + dev_err(&client->dev, "Error reading chip id: %d\n", ret); + return ret; + } + + if (ret != DMARD05_CHIP_ID && ret != DMARD06_CHIP_ID && + ret != DMARD07_CHIP_ID) { + dev_err(&client->dev, "Invalid chip id: %02d\n", ret); + return -ENODEV; + } + + dmard06->chip_id = ret; + + i2c_set_clientdata(client, indio_dev); + indio_dev->dev.parent = &client->dev; + indio_dev->name = DMARD06_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = dmard06_channels; + indio_dev->num_channels = ARRAY_SIZE(dmard06_channels); + indio_dev->info = &dmard06_info; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +#ifdef CONFIG_PM_SLEEP +static int dmard06_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct dmard06_data *dmard06 = iio_priv(indio_dev); + int ret; + + ret = i2c_smbus_write_byte_data(dmard06->client, DMARD06_CTRL1_REG, + DMARD06_MODE_POWERDOWN); + if (ret < 0) + return ret; + + return 0; +} + +static int dmard06_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct dmard06_data *dmard06 = iio_priv(indio_dev); + int ret; + + ret = i2c_smbus_write_byte_data(dmard06->client, DMARD06_CTRL1_REG, + DMARD06_MODE_NORMAL); + if (ret < 0) + return ret; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(dmard06_pm_ops, dmard06_suspend, dmard06_resume); +#define DMARD06_PM_OPS (&dmard06_pm_ops) +#else +#define DMARD06_PM_OPS NULL +#endif + +static const struct i2c_device_id dmard06_id[] = { + { "dmard05", 0 }, + { "dmard06", 0 }, + { "dmard07", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, dmard06_id); + +static const struct of_device_id dmard06_of_match[] = { + { .compatible = "domintech,dmard05" }, + { .compatible = "domintech,dmard06" }, + { .compatible = "domintech,dmard07" }, + { } +}; +MODULE_DEVICE_TABLE(of, dmard06_of_match); + +static struct i2c_driver dmard06_driver = { + .probe = dmard06_probe, + .id_table = dmard06_id, + .driver = { + .name = DMARD06_DRV_NAME, + .of_match_table = of_match_ptr(dmard06_of_match), + .pm = DMARD06_PM_OPS, + }, +}; +module_i2c_driver(dmard06_driver); + +MODULE_AUTHOR("Aleksei Mamlin "); +MODULE_DESCRIPTION("Domintech DMARD06 accelerometer driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/dmard09.c b/drivers/iio/accel/dmard09.c new file mode 100644 index 000000000000..d3a28f96565c --- /dev/null +++ b/drivers/iio/accel/dmard09.c @@ -0,0 +1,157 @@ +/* + * IIO driver for the 3-axis accelerometer Domintech DMARD09. + * + * Copyright (c) 2016, Jelle van der Waa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include + +#define DMARD09_DRV_NAME "dmard09" + +#define DMARD09_REG_CHIPID 0x18 +#define DMARD09_REG_STAT 0x0A +#define DMARD09_REG_X 0x0C +#define DMARD09_REG_Y 0x0E +#define DMARD09_REG_Z 0x10 +#define DMARD09_CHIPID 0x95 + +#define DMARD09_BUF_LEN 8 +#define DMARD09_AXIS_X 0 +#define DMARD09_AXIS_Y 1 +#define DMARD09_AXIS_Z 2 +#define DMARD09_AXIS_X_OFFSET ((DMARD09_AXIS_X + 1) * 2) +#define DMARD09_AXIS_Y_OFFSET ((DMARD09_AXIS_Y + 1 )* 2) +#define DMARD09_AXIS_Z_OFFSET ((DMARD09_AXIS_Z + 1) * 2) + +struct dmard09_data { + struct i2c_client *client; +}; + +#define DMARD09_CHANNEL(_axis, offset) { \ + .type = IIO_ACCEL, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .modified = 1, \ + .address = offset, \ + .channel2 = IIO_MOD_##_axis, \ +} + +static const struct iio_chan_spec dmard09_channels[] = { + DMARD09_CHANNEL(X, DMARD09_AXIS_X_OFFSET), + DMARD09_CHANNEL(Y, DMARD09_AXIS_Y_OFFSET), + DMARD09_CHANNEL(Z, DMARD09_AXIS_Z_OFFSET), +}; + +static int dmard09_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct dmard09_data *data = iio_priv(indio_dev); + u8 buf[DMARD09_BUF_LEN]; + int ret; + s16 accel; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + /* + * Read from the DMAR09_REG_STAT register, since the chip + * caches reads from the individual X, Y, Z registers. + */ + ret = i2c_smbus_read_i2c_block_data(data->client, + DMARD09_REG_STAT, + DMARD09_BUF_LEN, buf); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg %d\n", + DMARD09_REG_STAT); + return ret; + } + + accel = get_unaligned_le16(&buf[chan->address]); + + /* Remove lower 3 bits and sign extend */ + accel <<= 4; + accel >>= 7; + + *val = accel; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_info dmard09_info = { + .driver_module = THIS_MODULE, + .read_raw = dmard09_read_raw, +}; + +static int dmard09_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct dmard09_data *data; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) { + dev_err(&client->dev, "iio allocation failed\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + data->client = client; + + ret = i2c_smbus_read_byte_data(data->client, DMARD09_REG_CHIPID); + if (ret < 0) { + dev_err(&client->dev, "Error reading chip id %d\n", ret); + return ret; + } + + if (ret != DMARD09_CHIPID) { + dev_err(&client->dev, "Invalid chip id %d\n", ret); + return -ENODEV; + } + + i2c_set_clientdata(client, indio_dev); + indio_dev->dev.parent = &client->dev; + indio_dev->name = DMARD09_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = dmard09_channels; + indio_dev->num_channels = ARRAY_SIZE(dmard09_channels); + indio_dev->info = &dmard09_info; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id dmard09_id[] = { + { "dmard09", 0}, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, dmard09_id); + +static struct i2c_driver dmard09_driver = { + .driver = { + .name = DMARD09_DRV_NAME + }, + .probe = dmard09_probe, + .id_table = dmard09_id, +}; + +module_i2c_driver(dmard09_driver); + +MODULE_AUTHOR("Jelle van der Waa "); +MODULE_DESCRIPTION("DMARD09 3-axis accelerometer driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 765a72362dc6..3f968c46e667 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1392,6 +1392,7 @@ static const struct acpi_device_id kx_acpi_match[] = { {"KXCJ1013", KXCJK1013}, {"KXCJ1008", KXCJ91008}, {"KXCJ9000", KXCJ91008}, + {"KIOX000A", KXCJ91008}, {"KXTJ1009", KXTJ21009}, {"SMO8500", KXCJ91008}, { }, diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c new file mode 100644 index 000000000000..95e20855d2ef --- /dev/null +++ b/drivers/iio/accel/kxsd9-i2c.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "kxsd9.h" + +static int kxsd9_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x0e, + }; + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(i2c, &config); + if (IS_ERR(regmap)) { + dev_err(&i2c->dev, "Failed to register i2c regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return kxsd9_common_probe(&i2c->dev, + regmap, + i2c->name); +} + +static int kxsd9_i2c_remove(struct i2c_client *client) +{ + return kxsd9_common_remove(&client->dev); +} + +#ifdef CONFIG_OF +static const struct of_device_id kxsd9_of_match[] = { + { .compatible = "kionix,kxsd9", }, + { }, +}; +MODULE_DEVICE_TABLE(of, kxsd9_of_match); +#else +#define kxsd9_of_match NULL +#endif + +static const struct i2c_device_id kxsd9_i2c_id[] = { + {"kxsd9", 0}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, kxsd9_i2c_id); + +static struct i2c_driver kxsd9_i2c_driver = { + .driver = { + .name = "kxsd9", + .of_match_table = of_match_ptr(kxsd9_of_match), + .pm = &kxsd9_dev_pm_ops, + }, + .probe = kxsd9_i2c_probe, + .remove = kxsd9_i2c_remove, + .id_table = kxsd9_i2c_id, +}; +module_i2c_driver(kxsd9_i2c_driver); diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c new file mode 100644 index 000000000000..b7d0078fd00e --- /dev/null +++ b/drivers/iio/accel/kxsd9-spi.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include + +#include "kxsd9.h" + +static int kxsd9_spi_probe(struct spi_device *spi) +{ + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x0e, + }; + struct regmap *regmap; + + spi->mode = SPI_MODE_0; + regmap = devm_regmap_init_spi(spi, &config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n", + __func__, PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return kxsd9_common_probe(&spi->dev, + regmap, + spi_get_device_id(spi)->name); +} + +static int kxsd9_spi_remove(struct spi_device *spi) +{ + return kxsd9_common_remove(&spi->dev); +} + +static const struct spi_device_id kxsd9_spi_id[] = { + {"kxsd9", 0}, + { }, +}; +MODULE_DEVICE_TABLE(spi, kxsd9_spi_id); + +static struct spi_driver kxsd9_spi_driver = { + .driver = { + .name = "kxsd9", + .pm = &kxsd9_dev_pm_ops, + }, + .probe = kxsd9_spi_probe, + .remove = kxsd9_spi_remove, + .id_table = kxsd9_spi_id, +}; +module_spi_driver(kxsd9_spi_driver); + +MODULE_AUTHOR("Jonathan Cameron "); +MODULE_DESCRIPTION("Kionix KXSD9 SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 9d72d4bcf5e9..9af60ac70738 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -12,19 +12,25 @@ * I have a suitable wire made up. * * TODO: Support the motion detector - * Uses register address incrementing so could have a - * heavily optimized ring buffer access function. */ #include #include -#include #include #include #include - +#include +#include +#include +#include +#include #include #include +#include +#include +#include + +#include "kxsd9.h" #define KXSD9_REG_X 0x00 #define KXSD9_REG_Y 0x02 @@ -33,28 +39,45 @@ #define KXSD9_REG_RESET 0x0a #define KXSD9_REG_CTRL_C 0x0c -#define KXSD9_FS_MASK 0x03 +#define KXSD9_CTRL_C_FS_MASK 0x03 +#define KXSD9_CTRL_C_FS_8G 0x00 +#define KXSD9_CTRL_C_FS_6G 0x01 +#define KXSD9_CTRL_C_FS_4G 0x02 +#define KXSD9_CTRL_C_FS_2G 0x03 +#define KXSD9_CTRL_C_MOT_LAT BIT(3) +#define KXSD9_CTRL_C_MOT_LEV BIT(4) +#define KXSD9_CTRL_C_LP_MASK 0xe0 +#define KXSD9_CTRL_C_LP_NONE 0x00 +#define KXSD9_CTRL_C_LP_2000HZC BIT(5) +#define KXSD9_CTRL_C_LP_2000HZB BIT(6) +#define KXSD9_CTRL_C_LP_2000HZA (BIT(5)|BIT(6)) +#define KXSD9_CTRL_C_LP_1000HZ BIT(7) +#define KXSD9_CTRL_C_LP_500HZ (BIT(7)|BIT(5)) +#define KXSD9_CTRL_C_LP_100HZ (BIT(7)|BIT(6)) +#define KXSD9_CTRL_C_LP_50HZ (BIT(7)|BIT(6)|BIT(5)) #define KXSD9_REG_CTRL_B 0x0d + +#define KXSD9_CTRL_B_CLK_HLD BIT(7) +#define KXSD9_CTRL_B_ENABLE BIT(6) +#define KXSD9_CTRL_B_ST BIT(5) /* Self-test */ + #define KXSD9_REG_CTRL_A 0x0e -#define KXSD9_READ(a) (0x80 | (a)) -#define KXSD9_WRITE(a) (a) - -#define KXSD9_STATE_RX_SIZE 2 -#define KXSD9_STATE_TX_SIZE 2 /** * struct kxsd9_state - device related storage - * @buf_lock: protect the rx and tx buffers. - * @us: spi device - * @rx: single rx buffer storage - * @tx: single tx buffer storage - **/ + * @dev: pointer to the parent device + * @map: regmap to the device + * @orientation: mounting matrix, flipped axis etc + * @regs: regulators for this device, VDD and IOVDD + * @scale: the current scaling setting + */ struct kxsd9_state { - struct mutex buf_lock; - struct spi_device *us; - u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned; - u8 tx[KXSD9_STATE_TX_SIZE]; + struct device *dev; + struct regmap *map; + struct iio_mount_matrix orientation; + struct regulator_bulk_data regs[2]; + u8 scale; }; #define KXSD9_SCALE_2G "0.011978" @@ -65,6 +88,14 @@ struct kxsd9_state { /* reverse order */ static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 }; +#define KXSD9_ZERO_G_OFFSET -2048 + +/* + * Regulator names + */ +static const char kxsd9_reg_vdd[] = "vdd"; +static const char kxsd9_reg_iovdd[] = "iovdd"; + static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) { int ret, i; @@ -79,42 +110,17 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) if (!foundit) return -EINVAL; - mutex_lock(&st->buf_lock); - ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); + ret = regmap_update_bits(st->map, + KXSD9_REG_CTRL_C, + KXSD9_CTRL_C_FS_MASK, + i); if (ret < 0) goto error_ret; - st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C); - st->tx[1] = (ret & ~KXSD9_FS_MASK) | i; - ret = spi_write(st->us, st->tx, 2); + /* Cached scale when the sensor is powered down */ + st->scale = i; + error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int kxsd9_read(struct iio_dev *indio_dev, u8 address) -{ - int ret; - struct kxsd9_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .bits_per_word = 8, - .len = 1, - .delay_usecs = 200, - .tx_buf = st->tx, - }, { - .bits_per_word = 8, - .len = 2, - .rx_buf = st->rx, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = KXSD9_READ(address); - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (!ret) - ret = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); - mutex_unlock(&st->buf_lock); return ret; } @@ -136,6 +142,9 @@ static int kxsd9_write_raw(struct iio_dev *indio_dev, long mask) { int ret = -EINVAL; + struct kxsd9_state *st = iio_priv(indio_dev); + + pm_runtime_get_sync(st->dev); if (mask == IIO_CHAN_INFO_SCALE) { /* Check no integer component */ @@ -144,6 +153,9 @@ static int kxsd9_write_raw(struct iio_dev *indio_dev, ret = kxsd9_write_scale(indio_dev, val2); } + pm_runtime_mark_last_busy(st->dev); + pm_runtime_put_autosuspend(st->dev); + return ret; } @@ -153,46 +165,154 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, { int ret = -EINVAL; struct kxsd9_state *st = iio_priv(indio_dev); + unsigned int regval; + __be16 raw_val; + u16 nval; + + pm_runtime_get_sync(st->dev); switch (mask) { case IIO_CHAN_INFO_RAW: - ret = kxsd9_read(indio_dev, chan->address); - if (ret < 0) + ret = regmap_bulk_read(st->map, chan->address, &raw_val, + sizeof(raw_val)); + if (ret) goto error_ret; - *val = ret; + nval = be16_to_cpu(raw_val); + /* Only 12 bits are valid */ + nval >>= 4; + *val = nval; + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_OFFSET: + /* This has a bias of -2048 */ + *val = KXSD9_ZERO_G_OFFSET; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); + ret = regmap_read(st->map, + KXSD9_REG_CTRL_C, + ®val); if (ret < 0) goto error_ret; *val = 0; - *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; + *val2 = kxsd9_micro_scales[regval & KXSD9_CTRL_C_FS_MASK]; ret = IIO_VAL_INT_PLUS_MICRO; break; } error_ret: + pm_runtime_mark_last_busy(st->dev); + pm_runtime_put_autosuspend(st->dev); + return ret; }; -#define KXSD9_ACCEL_CHAN(axis) \ + +static irqreturn_t kxsd9_trigger_handler(int irq, void *p) +{ + const struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct kxsd9_state *st = iio_priv(indio_dev); + int ret; + /* 4 * 16bit values AND timestamp */ + __be16 hw_values[8]; + + ret = regmap_bulk_read(st->map, + KXSD9_REG_X, + &hw_values, + 8); + if (ret) { + dev_err(st->dev, + "error reading data\n"); + return ret; + } + + iio_push_to_buffers_with_timestamp(indio_dev, + hw_values, + iio_get_time_ns(indio_dev)); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int kxsd9_buffer_preenable(struct iio_dev *indio_dev) +{ + struct kxsd9_state *st = iio_priv(indio_dev); + + pm_runtime_get_sync(st->dev); + + return 0; +} + +static int kxsd9_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct kxsd9_state *st = iio_priv(indio_dev); + + pm_runtime_mark_last_busy(st->dev); + pm_runtime_put_autosuspend(st->dev); + + return 0; +} + +static const struct iio_buffer_setup_ops kxsd9_buffer_setup_ops = { + .preenable = kxsd9_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = kxsd9_buffer_postdisable, +}; + +static const struct iio_mount_matrix * +kxsd9_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct kxsd9_state *st = iio_priv(indio_dev); + + return &st->orientation; +} + +static const struct iio_chan_spec_ext_info kxsd9_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, kxsd9_get_mount_matrix), + { }, +}; + +#define KXSD9_ACCEL_CHAN(axis, index) \ { \ .type = IIO_ACCEL, \ .modified = 1, \ .channel2 = IIO_MOD_##axis, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .ext_info = kxsd9_ext_info, \ .address = KXSD9_REG_##axis, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_BE, \ + }, \ } static const struct iio_chan_spec kxsd9_channels[] = { - KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z), + KXSD9_ACCEL_CHAN(X, 0), + KXSD9_ACCEL_CHAN(Y, 1), + KXSD9_ACCEL_CHAN(Z, 2), { .type = IIO_VOLTAGE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .indexed = 1, .address = KXSD9_REG_AUX, - } + .scan_index = 3, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16, + .shift = 4, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(4), }; static const struct attribute_group kxsd9_attribute_group = { @@ -203,17 +323,69 @@ static int kxsd9_power_up(struct kxsd9_state *st) { int ret; - st->tx[0] = 0x0d; - st->tx[1] = 0x40; - ret = spi_write(st->us, st->tx, 2); + /* Enable the regulators */ + ret = regulator_bulk_enable(ARRAY_SIZE(st->regs), st->regs); + if (ret) { + dev_err(st->dev, "Cannot enable regulators\n"); + return ret; + } + + /* Power up */ + ret = regmap_write(st->map, + KXSD9_REG_CTRL_B, + KXSD9_CTRL_B_ENABLE); if (ret) return ret; - st->tx[0] = 0x0c; - st->tx[1] = 0x9b; - return spi_write(st->us, st->tx, 2); + /* + * Set 1000Hz LPF, 2g fullscale, motion wakeup threshold 1g, + * latched wakeup + */ + ret = regmap_write(st->map, + KXSD9_REG_CTRL_C, + KXSD9_CTRL_C_LP_1000HZ | + KXSD9_CTRL_C_MOT_LEV | + KXSD9_CTRL_C_MOT_LAT | + st->scale); + if (ret) + return ret; + + /* + * Power-up time depends on the LPF setting, but typ 15.9 ms, let's + * set 20 ms to allow for some slack. + */ + msleep(20); + + return 0; }; +static int kxsd9_power_down(struct kxsd9_state *st) +{ + int ret; + + /* + * Set into low power mode - since there may be more users of the + * regulators this is the first step of the power saving: it will + * make sure we conserve power even if there are others users on the + * regulators. + */ + ret = regmap_update_bits(st->map, + KXSD9_REG_CTRL_B, + KXSD9_CTRL_B_ENABLE, + 0); + if (ret) + return ret; + + /* Disable the regulators */ + ret = regulator_bulk_disable(ARRAY_SIZE(st->regs), st->regs); + if (ret) { + dev_err(st->dev, "Cannot disable regulators\n"); + return ret; + } + + return 0; +} + static const struct iio_info kxsd9_info = { .read_raw = &kxsd9_read_raw, .write_raw = &kxsd9_write_raw, @@ -221,57 +393,136 @@ static const struct iio_info kxsd9_info = { .driver_module = THIS_MODULE, }; -static int kxsd9_probe(struct spi_device *spi) +/* Four channels apart from timestamp, scan mask = 0x0f */ +static const unsigned long kxsd9_scan_masks[] = { 0xf, 0 }; + +int kxsd9_common_probe(struct device *dev, + struct regmap *map, + const char *name) { struct iio_dev *indio_dev; struct kxsd9_state *st; + int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); + st->dev = dev; + st->map = map; - st->us = spi; - mutex_init(&st->buf_lock); indio_dev->channels = kxsd9_channels; indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; + indio_dev->name = name; + indio_dev->dev.parent = dev; indio_dev->info = &kxsd9_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->available_scan_masks = kxsd9_scan_masks; + + /* Read the mounting matrix, if present */ + ret = of_iio_read_mount_matrix(dev, + "mount-matrix", + &st->orientation); + if (ret) + return ret; + + /* Fetch and turn on regulators */ + st->regs[0].supply = kxsd9_reg_vdd; + st->regs[1].supply = kxsd9_reg_iovdd; + ret = devm_regulator_bulk_get(dev, + ARRAY_SIZE(st->regs), + st->regs); + if (ret) { + dev_err(dev, "Cannot get regulators\n"); + return ret; + } + /* Default scaling */ + st->scale = KXSD9_CTRL_C_FS_2G; - spi->mode = SPI_MODE_0; - spi_setup(spi); kxsd9_power_up(st); - return iio_device_register(indio_dev); -} + ret = iio_triggered_buffer_setup(indio_dev, + iio_pollfunc_store_time, + kxsd9_trigger_handler, + &kxsd9_buffer_setup_ops); + if (ret) { + dev_err(dev, "triggered buffer setup failed\n"); + goto err_power_down; + } -static int kxsd9_remove(struct spi_device *spi) + ret = iio_device_register(indio_dev); + if (ret) + goto err_cleanup_buffer; + + dev_set_drvdata(dev, indio_dev); + + /* Enable runtime PM */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + /* + * Set autosuspend to two orders of magnitude larger than the + * start-up time. 20ms start-up time means 2000ms autosuspend, + * i.e. 2 seconds. + */ + pm_runtime_set_autosuspend_delay(dev, 2000); + pm_runtime_use_autosuspend(dev); + pm_runtime_put(dev); + + return 0; + +err_cleanup_buffer: + iio_triggered_buffer_cleanup(indio_dev); +err_power_down: + kxsd9_power_down(st); + + return ret; +} +EXPORT_SYMBOL(kxsd9_common_probe); + +int kxsd9_common_remove(struct device *dev) { - iio_device_unregister(spi_get_drvdata(spi)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct kxsd9_state *st = iio_priv(indio_dev); + + iio_triggered_buffer_cleanup(indio_dev); + iio_device_unregister(indio_dev); + pm_runtime_get_sync(dev); + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + kxsd9_power_down(st); return 0; } +EXPORT_SYMBOL(kxsd9_common_remove); -static const struct spi_device_id kxsd9_id[] = { - {"kxsd9", 0}, - { }, -}; -MODULE_DEVICE_TABLE(spi, kxsd9_id); +#ifdef CONFIG_PM +static int kxsd9_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct kxsd9_state *st = iio_priv(indio_dev); -static struct spi_driver kxsd9_driver = { - .driver = { - .name = "kxsd9", - }, - .probe = kxsd9_probe, - .remove = kxsd9_remove, - .id_table = kxsd9_id, + return kxsd9_power_down(st); +} + +static int kxsd9_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct kxsd9_state *st = iio_priv(indio_dev); + + return kxsd9_power_up(st); +} +#endif /* CONFIG_PM */ + +const struct dev_pm_ops kxsd9_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(kxsd9_runtime_suspend, + kxsd9_runtime_resume, NULL) }; -module_spi_driver(kxsd9_driver); +EXPORT_SYMBOL(kxsd9_dev_pm_ops); MODULE_AUTHOR("Jonathan Cameron "); -MODULE_DESCRIPTION("Kionix KXSD9 SPI driver"); +MODULE_DESCRIPTION("Kionix KXSD9 driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/kxsd9.h b/drivers/iio/accel/kxsd9.h new file mode 100644 index 000000000000..7e8a28168310 --- /dev/null +++ b/drivers/iio/accel/kxsd9.h @@ -0,0 +1,12 @@ +#include +#include + +#define KXSD9_STATE_RX_SIZE 2 +#define KXSD9_STATE_TX_SIZE 2 + +int kxsd9_common_probe(struct device *dev, + struct regmap *map, + const char *name); +int kxsd9_common_remove(struct device *dev); + +extern const struct dev_pm_ops kxsd9_dev_pm_ops; diff --git a/drivers/iio/accel/mc3230.c b/drivers/iio/accel/mc3230.c new file mode 100644 index 000000000000..4ea2ff623a6d --- /dev/null +++ b/drivers/iio/accel/mc3230.c @@ -0,0 +1,211 @@ +/** + * mCube MC3230 3-Axis Accelerometer + * + * Copyright (c) 2016 Hans de Goede + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * IIO driver for mCube MC3230; 7-bit I2C address: 0x4c. + */ + +#include +#include +#include +#include + +#define MC3230_REG_XOUT 0x00 +#define MC3230_REG_YOUT 0x01 +#define MC3230_REG_ZOUT 0x02 + +#define MC3230_REG_MODE 0x07 +#define MC3230_MODE_OPCON_MASK 0x03 +#define MC3230_MODE_OPCON_WAKE 0x01 +#define MC3230_MODE_OPCON_STANDBY 0x03 + +#define MC3230_REG_CHIP_ID 0x18 +#define MC3230_CHIP_ID 0x01 + +#define MC3230_REG_PRODUCT_CODE 0x3b +#define MC3230_PRODUCT_CODE 0x19 + +/* + * The accelerometer has one measurement range: + * + * -1.5g - +1.5g (8-bit, signed) + * + * scale = (1.5 + 1.5) * 9.81 / (2^8 - 1) = 0.115411765 + */ + +static const int mc3230_nscale = 115411765; + +#define MC3230_CHANNEL(reg, axis) { \ + .type = IIO_ACCEL, \ + .address = reg, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec mc3230_channels[] = { + MC3230_CHANNEL(MC3230_REG_XOUT, X), + MC3230_CHANNEL(MC3230_REG_YOUT, Y), + MC3230_CHANNEL(MC3230_REG_ZOUT, Z), +}; + +struct mc3230_data { + struct i2c_client *client; +}; + +static int mc3230_set_opcon(struct mc3230_data *data, int opcon) +{ + int ret; + struct i2c_client *client = data->client; + + ret = i2c_smbus_read_byte_data(client, MC3230_REG_MODE); + if (ret < 0) { + dev_err(&client->dev, "failed to read mode reg: %d\n", ret); + return ret; + } + + ret &= ~MC3230_MODE_OPCON_MASK; + ret |= opcon; + + ret = i2c_smbus_write_byte_data(client, MC3230_REG_MODE, ret); + if (ret < 0) { + dev_err(&client->dev, "failed to write mode reg: %d\n", ret); + return ret; + } + + return 0; +} + +static int mc3230_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mc3230_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = i2c_smbus_read_byte_data(data->client, chan->address); + if (ret < 0) + return ret; + *val = sign_extend32(ret, 7); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = mc3230_nscale; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static const struct iio_info mc3230_info = { + .driver_module = THIS_MODULE, + .read_raw = mc3230_read_raw, +}; + +static int mc3230_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct mc3230_data *data; + + /* First check chip-id and product-id */ + ret = i2c_smbus_read_byte_data(client, MC3230_REG_CHIP_ID); + if (ret != MC3230_CHIP_ID) + return (ret < 0) ? ret : -ENODEV; + + ret = i2c_smbus_read_byte_data(client, MC3230_REG_PRODUCT_CODE); + if (ret != MC3230_PRODUCT_CODE) + return (ret < 0) ? ret : -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) { + dev_err(&client->dev, "iio allocation failed!\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &mc3230_info; + indio_dev->name = "mc3230"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = mc3230_channels; + indio_dev->num_channels = ARRAY_SIZE(mc3230_channels); + + ret = mc3230_set_opcon(data, MC3230_MODE_OPCON_WAKE); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "device_register failed\n"); + mc3230_set_opcon(data, MC3230_MODE_OPCON_STANDBY); + } + + return ret; +} + +static int mc3230_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + + return mc3230_set_opcon(iio_priv(indio_dev), MC3230_MODE_OPCON_STANDBY); +} + +#ifdef CONFIG_PM_SLEEP +static int mc3230_suspend(struct device *dev) +{ + struct mc3230_data *data; + + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return mc3230_set_opcon(data, MC3230_MODE_OPCON_STANDBY); +} + +static int mc3230_resume(struct device *dev) +{ + struct mc3230_data *data; + + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return mc3230_set_opcon(data, MC3230_MODE_OPCON_WAKE); +} +#endif + +static SIMPLE_DEV_PM_OPS(mc3230_pm_ops, mc3230_suspend, mc3230_resume); + +static const struct i2c_device_id mc3230_i2c_id[] = { + {"mc3230", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, mc3230_i2c_id); + +static struct i2c_driver mc3230_driver = { + .driver = { + .name = "mc3230", + .pm = &mc3230_pm_ops, + }, + .probe = mc3230_probe, + .remove = mc3230_remove, + .id_table = mc3230_i2c_id, +}; + +module_i2c_driver(mc3230_driver); + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("mCube MC3230 3-Axis Accelerometer driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index 0acdee516973..03beadf14ad3 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -251,6 +251,7 @@ static const struct i2c_device_id mma7660_i2c_id[] = { {"mma7660", 0}, {} }; +MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id); static const struct acpi_device_id mma7660_acpi_id[] = { {"MMA7660", 0}, diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c index 97ccde722e7b..0abad6948201 100644 --- a/drivers/iio/accel/mxc6255.c +++ b/drivers/iio/accel/mxc6255.c @@ -154,7 +154,7 @@ static int mxc6255_probe(struct i2c_client *client, return ret; } - if (chip_id != MXC6255_CHIP_ID) { + if ((chip_id & 0x1f) != MXC6255_CHIP_ID) { dev_err(&client->dev, "Invalid chip id %x\n", chip_id); return -ENODEV; } @@ -171,12 +171,14 @@ static int mxc6255_probe(struct i2c_client *client, } static const struct acpi_device_id mxc6255_acpi_match[] = { + {"MXC6225", 0}, {"MXC6255", 0}, { } }; MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match); static const struct i2c_device_id mxc6255_id[] = { + {"mxc6225", 0}, {"mxc6255", 0}, { } }; diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c index 4ae05fce9f24..31db00970fa0 100644 --- a/drivers/iio/accel/ssp_accel_sensor.c +++ b/drivers/iio/accel/ssp_accel_sensor.c @@ -74,7 +74,7 @@ static int ssp_accel_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static struct iio_info ssp_accel_iio_info = { +static const struct iio_info ssp_accel_iio_info = { .read_raw = &ssp_accel_read_raw, .write_raw = &ssp_accel_write_raw, }; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 767577298ee3..7edcf3238620 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -264,6 +264,15 @@ config LPC18XX_ADC To compile this driver as a module, choose M here: the module will be called lpc18xx_adc. +config LTC2485 + tristate "Linear Technology LTC2485 ADC driver" + depends on I2C + help + Say yes here to build support for Linear Technology LTC2485 ADC. + + To compile this driver as a module, choose M here: the module will be + called ltc2485. + config MAX1027 tristate "Maxim max1027 ADC driver" depends on SPI @@ -317,6 +326,19 @@ config MCP3422 This driver can also be built as a module. If so, the module will be called mcp3422. +config MEDIATEK_MT6577_AUXADC + tristate "MediaTek AUXADC driver" + depends on ARCH_MEDIATEK || COMPILE_TEST + depends on HAS_IOMEM + help + Say yes here to enable support for MediaTek mt65xx AUXADC. + + The driver supports immediate mode operation to read from one of sixteen + channels (external or internal). + + This driver can also be built as a module. If so, the module will be + called mt6577_auxadc. + config MEN_Z188_ADC tristate "MEN 16z188 ADC IP Core support" depends on MCB @@ -397,6 +419,21 @@ config ROCKCHIP_SARADC To compile this driver as a module, choose M here: the module will be called rockchip_saradc. +config STX104 + tristate "Apex Embedded Systems STX104 driver" + depends on X86 && ISA_BUS_API + select GPIOLIB + help + Say yes here to build support for the Apex Embedded Systems STX104 + integrated analog PC/104 card. + + This driver supports the 16 channels of single-ended (8 channels of + differential) analog inputs, 2 channels of analog output, 4 digital + inputs, and 4 digital outputs provided by the STX104. + + The base port addresses for the devices may be configured via the base + array module parameter. + config TI_ADC081C tristate "Texas Instruments ADC081C/ADC101C/ADC121C family" depends on I2C @@ -417,6 +454,18 @@ config TI_ADC0832 This driver can also be built as a module. If so, the module will be called ti-adc0832. +config TI_ADC12138 + tristate "Texas Instruments ADC12130/ADC12132/ADC12138" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADC12130, + ADC12132 and ADC12138 chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc12138. + config TI_ADC128S052 tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" depends on SPI @@ -427,6 +476,18 @@ config TI_ADC128S052 This driver can also be built as a module. If so, the module will be called ti-adc128s052. +config TI_ADC161S626 + tristate "Texas Instruments ADC161S626 1-channel differential ADC" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADC141S626, + and ADC161S626 chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc161s626. + config TI_ADS1015 tristate "Texas Instruments ADS1015 ADC" depends on I2C && !SENSORS_ADS1015 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 0ba0d500eedb..7a40c04c311f 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -27,10 +27,12 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o +obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o +obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o obj-$(CONFIG_NAU7802) += nau7802.o @@ -38,9 +40,12 @@ obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o +obj-$(CONFIG_STX104) += stx104.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o +obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o +obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index c0f6a98fd9bd..b8d5cfd57ec4 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -481,7 +481,7 @@ error_free_gpios: if (!st->fixed_addr) gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); error_disable_reg: - if (!IS_ERR_OR_NULL(st->reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); return ret; @@ -496,7 +496,7 @@ static int ad7266_remove(struct spi_device *spi) iio_triggered_buffer_cleanup(indio_dev); if (!st->fixed_addr) gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); - if (!IS_ERR_OR_NULL(st->reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); return 0; diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c index 10ec8fce395f..e399bf04c73a 100644 --- a/drivers/iio/adc/ad7298.c +++ b/drivers/iio/adc/ad7298.c @@ -239,16 +239,16 @@ static int ad7298_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { - ret = -EBUSY; - } else { - if (chan->address == AD7298_CH_TEMP) - ret = ad7298_scan_temp(st, val); - else - ret = ad7298_scan_direct(st, chan->address); - } - mutex_unlock(&indio_dev->mlock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + if (chan->address == AD7298_CH_TEMP) + ret = ad7298_scan_temp(st, val); + else + ret = ad7298_scan_direct(st, chan->address); + + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 847789bae821..e6706a09e100 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -519,11 +519,9 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, int ret, i; unsigned int tmp; - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -548,7 +546,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, ret = -EINVAL; } - mutex_unlock(&indio_dev->mlock); + iio_device_release_direct_mode(indio_dev); return ret; } diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 0438c68015e8..bbdac07f4aaa 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -113,6 +113,7 @@ #define AT91_ADC_TSMR_TSAV (3 << 4) /* Averages samples */ #define AT91_ADC_TSMR_TSAV_(x) ((x) << 4) #define AT91_ADC_TSMR_SCTIM (0x0f << 16) /* Switch closure time */ +#define AT91_ADC_TSMR_SCTIM_(x) ((x) << 16) #define AT91_ADC_TSMR_PENDBC (0x0f << 28) /* Pen Debounce time */ #define AT91_ADC_TSMR_PENDBC_(x) ((x) << 28) #define AT91_ADC_TSMR_NOTSDMA (1 << 22) /* No Touchscreen DMA */ @@ -150,6 +151,7 @@ #define MAX_RLPOS_BITS 10 #define TOUCH_SAMPLE_PERIOD_US_RL 10000 /* 10ms, the SoC can't keep up with 2ms */ #define TOUCH_SHTIM 0xa +#define TOUCH_SCTIM_US 10 /* 10us for the Touchscreen Switches Closure Time */ /** * struct at91_adc_reg_desc - Various informations relative to registers @@ -1001,7 +1003,9 @@ static void atmel_ts_close(struct input_dev *dev) static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) { + struct iio_dev *idev = iio_priv_to_dev(st); u32 reg = 0; + u32 tssctim = 0; int i = 0; /* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid @@ -1034,11 +1038,20 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) return 0; } + /* Touchscreen Switches Closure time needed for allowing the value to + * stabilize. + * Switch Closure Time = (TSSCTIM * 4) ADCClock periods + */ + tssctim = DIV_ROUND_UP(TOUCH_SCTIM_US * adc_clk_khz / 1000, 4); + dev_dbg(&idev->dev, "adc_clk at: %d KHz, tssctim at: %d\n", + adc_clk_khz, tssctim); + if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE) reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS; else reg = AT91_ADC_TSMR_TSMODE_5WIRE; + reg |= AT91_ADC_TSMR_SCTIM_(tssctim) & AT91_ADC_TSMR_SCTIM; reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average) & AT91_ADC_TSMR_TSAV; reg |= AT91_ADC_TSMR_PENDBC_(st->ts_pendbc) & AT91_ADC_TSMR_PENDBC; diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 955f3fdaf519..59b7d76e1ad2 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -114,7 +114,6 @@ struct ina2xx_chip_info { struct mutex state_lock; unsigned int shunt_resistor; int avg; - s64 prev_ns; /* track buffer capture time, check for underruns */ int int_time_vbus; /* Bus voltage integration time uS */ int int_time_vshunt; /* Shunt voltage integration time uS */ bool allow_async_readout; @@ -509,8 +508,6 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) iio_push_to_buffers_with_timestamp(indio_dev, (unsigned int *)data, time_a); - chip->prev_ns = time_a; - return (unsigned long)(time_b - time_a) / 1000; }; @@ -554,8 +551,6 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev) dev_dbg(&indio_dev->dev, "Async readout mode: %d\n", chip->allow_async_readout); - chip->prev_ns = iio_get_time_ns(indio_dev); - chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev, "%s:%d-%uus", indio_dev->name, indio_dev->id, sampling_us); diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c new file mode 100644 index 000000000000..eab91f12454a --- /dev/null +++ b/drivers/iio/adc/ltc2485.c @@ -0,0 +1,148 @@ +/* + * ltc2485.c - Driver for Linear Technology LTC2485 ADC + * + * Copyright (C) 2016 Alison Schofield + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Datasheet: http://cds.linear.com/docs/en/datasheet/2485fd.pdf + */ + +#include +#include +#include + +#include +#include + +/* Power-on configuration: rejects both 50/60Hz, operates at 1x speed */ +#define LTC2485_CONFIG_DEFAULT 0 + +struct ltc2485_data { + struct i2c_client *client; + ktime_t time_prev; /* last conversion */ +}; + +static void ltc2485_wait_conv(struct ltc2485_data *data) +{ + const unsigned int conv_time = 147; /* conversion time ms */ + unsigned int time_elapsed; + + /* delay if conversion time not passed since last read or write */ + time_elapsed = ktime_ms_delta(ktime_get(), data->time_prev); + + if (time_elapsed < conv_time) + msleep(conv_time - time_elapsed); +} + +static int ltc2485_read(struct ltc2485_data *data, int *val) +{ + struct i2c_client *client = data->client; + __be32 buf = 0; + int ret; + + ltc2485_wait_conv(data); + + ret = i2c_master_recv(client, (char *)&buf, 4); + if (ret < 0) { + dev_err(&client->dev, "i2c_master_recv failed\n"); + return ret; + } + data->time_prev = ktime_get(); + *val = sign_extend32(be32_to_cpu(buf) >> 6, 24); + + return ret; +} + +static int ltc2485_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ltc2485_data *data = iio_priv(indio_dev); + int ret; + + if (mask == IIO_CHAN_INFO_RAW) { + ret = ltc2485_read(data, val); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + + } else if (mask == IIO_CHAN_INFO_SCALE) { + *val = 5000; /* on board vref millivolts */ + *val2 = 25; /* 25 (24 + sign) data bits */ + return IIO_VAL_FRACTIONAL_LOG2; + + } else { + return -EINVAL; + } +} + +static const struct iio_chan_spec ltc2485_channel[] = { + { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) + }, +}; + +static const struct iio_info ltc2485_info = { + .read_raw = ltc2485_read_raw, + .driver_module = THIS_MODULE, +}; + +static int ltc2485_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ltc2485_data *data; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | + I2C_FUNC_SMBUS_WRITE_BYTE)) + return -EOPNOTSUPP; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; + indio_dev->info = <c2485_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ltc2485_channel; + indio_dev->num_channels = ARRAY_SIZE(ltc2485_channel); + + ret = i2c_smbus_write_byte(data->client, LTC2485_CONFIG_DEFAULT); + if (ret < 0) + return ret; + + data->time_prev = ktime_get(); + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id ltc2485_id[] = { + { "ltc2485", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ltc2485_id); + +static struct i2c_driver ltc2485_driver = { + .driver = { + .name = "ltc2485", + }, + .probe = ltc2485_probe, + .id_table = ltc2485_id, +}; +module_i2c_driver(ltc2485_driver); + +MODULE_AUTHOR("Alison Schofield "); +MODULE_DESCRIPTION("Linear Technology LTC2485 ADC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c index d095efe1ba14..8f3606de4eaf 100644 --- a/drivers/iio/adc/men_z188_adc.c +++ b/drivers/iio/adc/men_z188_adc.c @@ -78,7 +78,7 @@ static int z188_iio_read_raw(struct iio_dev *iio_dev, return ret; } -static struct iio_info z188_adc_info = { +static const struct iio_info z188_adc_info = { .read_raw = &z188_iio_read_raw, .driver_module = THIS_MODULE, }; diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c new file mode 100644 index 000000000000..2d104c828041 --- /dev/null +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * Author: Zhiyong Tao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register definitions */ +#define MT6577_AUXADC_CON0 0x00 +#define MT6577_AUXADC_CON1 0x04 +#define MT6577_AUXADC_CON2 0x10 +#define MT6577_AUXADC_STA BIT(0) + +#define MT6577_AUXADC_DAT0 0x14 +#define MT6577_AUXADC_RDY0 BIT(12) + +#define MT6577_AUXADC_MISC 0x94 +#define MT6577_AUXADC_PDN_EN BIT(14) + +#define MT6577_AUXADC_DAT_MASK 0xfff +#define MT6577_AUXADC_SLEEP_US 1000 +#define MT6577_AUXADC_TIMEOUT_US 10000 +#define MT6577_AUXADC_POWER_READY_MS 1 +#define MT6577_AUXADC_SAMPLE_READY_US 25 + +struct mt6577_auxadc_device { + void __iomem *reg_base; + struct clk *adc_clk; + struct mutex lock; +}; + +#define MT6577_AUXADC_CHANNEL(idx) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (idx), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ +} + +static const struct iio_chan_spec mt6577_auxadc_iio_channels[] = { + MT6577_AUXADC_CHANNEL(0), + MT6577_AUXADC_CHANNEL(1), + MT6577_AUXADC_CHANNEL(2), + MT6577_AUXADC_CHANNEL(3), + MT6577_AUXADC_CHANNEL(4), + MT6577_AUXADC_CHANNEL(5), + MT6577_AUXADC_CHANNEL(6), + MT6577_AUXADC_CHANNEL(7), + MT6577_AUXADC_CHANNEL(8), + MT6577_AUXADC_CHANNEL(9), + MT6577_AUXADC_CHANNEL(10), + MT6577_AUXADC_CHANNEL(11), + MT6577_AUXADC_CHANNEL(12), + MT6577_AUXADC_CHANNEL(13), + MT6577_AUXADC_CHANNEL(14), + MT6577_AUXADC_CHANNEL(15), +}; + +static inline void mt6577_auxadc_mod_reg(void __iomem *reg, + u32 or_mask, u32 and_mask) +{ + u32 val; + + val = readl(reg); + val |= or_mask; + val &= ~and_mask; + writel(val, reg); +} + +static int mt6577_auxadc_read(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + u32 val; + void __iomem *reg_channel; + int ret; + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + + reg_channel = adc_dev->reg_base + MT6577_AUXADC_DAT0 + + chan->channel * 0x04; + + mutex_lock(&adc_dev->lock); + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_CON1, + 0, 1 << chan->channel); + + /* read channel and make sure old ready bit == 0 */ + ret = readl_poll_timeout(reg_channel, val, + ((val & MT6577_AUXADC_RDY0) == 0), + MT6577_AUXADC_SLEEP_US, + MT6577_AUXADC_TIMEOUT_US); + if (ret < 0) { + dev_err(indio_dev->dev.parent, + "wait for channel[%d] ready bit clear time out\n", + chan->channel); + goto err_timeout; + } + + /* set bit to trigger sample */ + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_CON1, + 1 << chan->channel, 0); + + /* we must delay here for hardware sample channel data */ + udelay(MT6577_AUXADC_SAMPLE_READY_US); + + /* check MTK_AUXADC_CON2 if auxadc is idle */ + ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2, val, + ((val & MT6577_AUXADC_STA) == 0), + MT6577_AUXADC_SLEEP_US, + MT6577_AUXADC_TIMEOUT_US); + if (ret < 0) { + dev_err(indio_dev->dev.parent, + "wait for auxadc idle time out\n"); + goto err_timeout; + } + + /* read channel and make sure ready bit == 1 */ + ret = readl_poll_timeout(reg_channel, val, + ((val & MT6577_AUXADC_RDY0) != 0), + MT6577_AUXADC_SLEEP_US, + MT6577_AUXADC_TIMEOUT_US); + if (ret < 0) { + dev_err(indio_dev->dev.parent, + "wait for channel[%d] data ready time out\n", + chan->channel); + goto err_timeout; + } + + /* read data */ + val = readl(reg_channel) & MT6577_AUXADC_DAT_MASK; + + mutex_unlock(&adc_dev->lock); + + return val; + +err_timeout: + + mutex_unlock(&adc_dev->lock); + + return -ETIMEDOUT; +} + +static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long info) +{ + switch (info) { + case IIO_CHAN_INFO_PROCESSED: + *val = mt6577_auxadc_read(indio_dev, chan); + if (*val < 0) { + dev_err(indio_dev->dev.parent, + "failed to sample data on channel[%d]\n", + chan->channel); + return *val; + } + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static const struct iio_info mt6577_auxadc_info = { + .driver_module = THIS_MODULE, + .read_raw = &mt6577_auxadc_read_raw, +}; + +static int mt6577_auxadc_probe(struct platform_device *pdev) +{ + struct mt6577_auxadc_device *adc_dev; + unsigned long adc_clk_rate; + struct resource *res; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev)); + if (!indio_dev) + return -ENOMEM; + + adc_dev = iio_priv(indio_dev); + indio_dev->dev.parent = &pdev->dev; + indio_dev->name = dev_name(&pdev->dev); + indio_dev->info = &mt6577_auxadc_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = mt6577_auxadc_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(adc_dev->reg_base)) { + dev_err(&pdev->dev, "failed to get auxadc base address\n"); + return PTR_ERR(adc_dev->reg_base); + } + + adc_dev->adc_clk = devm_clk_get(&pdev->dev, "main"); + if (IS_ERR(adc_dev->adc_clk)) { + dev_err(&pdev->dev, "failed to get auxadc clock\n"); + return PTR_ERR(adc_dev->adc_clk); + } + + ret = clk_prepare_enable(adc_dev->adc_clk); + if (ret) { + dev_err(&pdev->dev, "failed to enable auxadc clock\n"); + return ret; + } + + adc_clk_rate = clk_get_rate(adc_dev->adc_clk); + if (!adc_clk_rate) { + ret = -EINVAL; + dev_err(&pdev->dev, "null clock rate\n"); + goto err_disable_clk; + } + + mutex_init(&adc_dev->lock); + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + MT6577_AUXADC_PDN_EN, 0); + mdelay(MT6577_AUXADC_POWER_READY_MS); + + platform_set_drvdata(pdev, indio_dev); + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register iio device\n"); + goto err_power_off; + } + + return 0; + +err_power_off: + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + 0, MT6577_AUXADC_PDN_EN); +err_disable_clk: + clk_disable_unprepare(adc_dev->adc_clk); + return ret; +} + +static int mt6577_auxadc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + 0, MT6577_AUXADC_PDN_EN); + + clk_disable_unprepare(adc_dev->adc_clk); + + return 0; +} + +static const struct of_device_id mt6577_auxadc_of_match[] = { + { .compatible = "mediatek,mt2701-auxadc", }, + { .compatible = "mediatek,mt8173-auxadc", }, + { } +}; +MODULE_DEVICE_TABLE(of, mt6577_auxadc_of_match); + +static struct platform_driver mt6577_auxadc_driver = { + .driver = { + .name = "mt6577-auxadc", + .of_match_table = mt6577_auxadc_of_match, + }, + .probe = mt6577_auxadc_probe, + .remove = mt6577_auxadc_remove, +}; +module_platform_driver(mt6577_auxadc_driver); + +MODULE_AUTHOR("Zhiyong Tao "); +MODULE_DESCRIPTION("MTK AUXADC Device Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index db9b829ccf0d..08f446695f97 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -197,7 +197,7 @@ static irqreturn_t nau7802_eoc_trigger(int irq, void *private) if (st->conversion_count < NAU7802_MIN_CONVERSIONS) st->conversion_count++; if (st->conversion_count >= NAU7802_MIN_CONVERSIONS) - complete_all(&st->value_ok); + complete(&st->value_ok); return IRQ_HANDLED; } diff --git a/drivers/iio/dac/stx104.c b/drivers/iio/adc/stx104.c similarity index 62% rename from drivers/iio/dac/stx104.c rename to drivers/iio/adc/stx104.c index bebbd00304ce..7e3645749eaf 100644 --- a/drivers/iio/dac/stx104.c +++ b/drivers/iio/adc/stx104.c @@ -1,5 +1,5 @@ /* - * DAC driver for the Apex Embedded Systems STX104 + * IIO driver for the Apex Embedded Systems STX104 * Copyright (C) 2016 William Breathitt Gray * * This program is free software; you can redistribute it and/or modify @@ -20,19 +20,30 @@ #include #include #include +#include #include #include #include -#define STX104_NUM_CHAN 2 - -#define STX104_CHAN(chan) { \ +#define STX104_OUT_CHAN(chan) { \ .type = IIO_VOLTAGE, \ .channel = chan, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .indexed = 1, \ .output = 1 \ } +#define STX104_IN_CHAN(chan, diff) { \ + .type = IIO_VOLTAGE, \ + .channel = chan, \ + .channel2 = chan, \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \ + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .indexed = 1, \ + .differential = diff \ +} + +#define STX104_NUM_OUT_CHAN 2 #define STX104_EXTENT 16 @@ -47,8 +58,8 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); * @base: base port address of the IIO device */ struct stx104_iio { - unsigned chan_out_states[STX104_NUM_CHAN]; - unsigned base; + unsigned int chan_out_states[STX104_NUM_OUT_CHAN]; + unsigned int base; }; /** @@ -79,28 +90,95 @@ static int stx104_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct stx104_iio *const priv = iio_priv(indio_dev); + unsigned int adc_config; + int adbu; + int gain; - if (mask != IIO_CHAN_INFO_RAW) - return -EINVAL; + switch (mask) { + case IIO_CHAN_INFO_HARDWAREGAIN: + /* get gain configuration */ + adc_config = inb(priv->base + 11); + gain = adc_config & 0x3; - *val = priv->chan_out_states[chan->channel]; + *val = 1 << gain; + return IIO_VAL_INT; + case IIO_CHAN_INFO_RAW: + if (chan->output) { + *val = priv->chan_out_states[chan->channel]; + return IIO_VAL_INT; + } - return IIO_VAL_INT; + /* select ADC channel */ + outb(chan->channel | (chan->channel << 4), priv->base + 2); + + /* trigger ADC sample capture and wait for completion */ + outb(0, priv->base); + while (inb(priv->base + 8) & BIT(7)); + + *val = inw(priv->base); + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + /* get ADC bipolar/unipolar configuration */ + adc_config = inb(priv->base + 11); + adbu = !(adc_config & BIT(2)); + + *val = -32768 * adbu; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* get ADC bipolar/unipolar and gain configuration */ + adc_config = inb(priv->base + 11); + adbu = !(adc_config & BIT(2)); + gain = adc_config & 0x3; + + *val = 5; + *val2 = 15 - adbu + gain; + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; } static int stx104_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct stx104_iio *const priv = iio_priv(indio_dev); - const unsigned chan_addr_offset = 2 * chan->channel; - if (mask != IIO_CHAN_INFO_RAW) + switch (mask) { + case IIO_CHAN_INFO_HARDWAREGAIN: + /* Only four gain states (x1, x2, x4, x8) */ + switch (val) { + case 1: + outb(0, priv->base + 11); + break; + case 2: + outb(1, priv->base + 11); + break; + case 4: + outb(2, priv->base + 11); + break; + case 8: + outb(3, priv->base + 11); + break; + default: + return -EINVAL; + } + + return 0; + case IIO_CHAN_INFO_RAW: + if (chan->output) { + /* DAC can only accept up to a 16-bit value */ + if ((unsigned int)val > 65535) + return -EINVAL; + + priv->chan_out_states[chan->channel] = val; + outw(val, priv->base + 4 + 2 * chan->channel); + + return 0; + } return -EINVAL; + } - priv->chan_out_states[chan->channel] = val; - outw(val, priv->base + 4 + chan_addr_offset); - - return 0; + return -EINVAL; } static const struct iio_info stx104_info = { @@ -109,9 +187,22 @@ static const struct iio_info stx104_info = { .write_raw = stx104_write_raw }; -static const struct iio_chan_spec stx104_channels[STX104_NUM_CHAN] = { - STX104_CHAN(0), - STX104_CHAN(1) +/* single-ended input channels configuration */ +static const struct iio_chan_spec stx104_channels_sing[] = { + STX104_OUT_CHAN(0), STX104_OUT_CHAN(1), + STX104_IN_CHAN(0, 0), STX104_IN_CHAN(1, 0), STX104_IN_CHAN(2, 0), + STX104_IN_CHAN(3, 0), STX104_IN_CHAN(4, 0), STX104_IN_CHAN(5, 0), + STX104_IN_CHAN(6, 0), STX104_IN_CHAN(7, 0), STX104_IN_CHAN(8, 0), + STX104_IN_CHAN(9, 0), STX104_IN_CHAN(10, 0), STX104_IN_CHAN(11, 0), + STX104_IN_CHAN(12, 0), STX104_IN_CHAN(13, 0), STX104_IN_CHAN(14, 0), + STX104_IN_CHAN(15, 0) +}; +/* differential input channels configuration */ +static const struct iio_chan_spec stx104_channels_diff[] = { + STX104_OUT_CHAN(0), STX104_OUT_CHAN(1), + STX104_IN_CHAN(0, 1), STX104_IN_CHAN(1, 1), STX104_IN_CHAN(2, 1), + STX104_IN_CHAN(3, 1), STX104_IN_CHAN(4, 1), STX104_IN_CHAN(5, 1), + STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1) }; static int stx104_gpio_get_direction(struct gpio_chip *chip, @@ -204,13 +295,27 @@ static int stx104_probe(struct device *dev, unsigned int id) indio_dev->info = &stx104_info; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = stx104_channels; - indio_dev->num_channels = STX104_NUM_CHAN; + + /* determine if differential inputs */ + if (inb(base[id] + 8) & BIT(5)) { + indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff); + indio_dev->channels = stx104_channels_diff; + } else { + indio_dev->num_channels = ARRAY_SIZE(stx104_channels_sing); + indio_dev->channels = stx104_channels_sing; + } + indio_dev->name = dev_name(dev); priv = iio_priv(indio_dev); priv->base = base[id]; + /* configure device for software trigger operation */ + outb(0, base[id] + 9); + + /* initialize gain setting to x1 */ + outb(0, base[id] + 11); + /* initialize DAC output to 0V */ outw(0, base[id] + 4); outw(0, base[id] + 6); @@ -271,5 +376,5 @@ static struct isa_driver stx104_driver = { module_isa_driver(stx104_driver, num_stx104); MODULE_AUTHOR("William Breathitt Gray "); -MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver"); +MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c new file mode 100644 index 000000000000..072f03bfe6a0 --- /dev/null +++ b/drivers/iio/adc/ti-adc12138.c @@ -0,0 +1,552 @@ +/* + * ADC12130/ADC12132/ADC12138 12-bit plus sign ADC driver + * + * Copyright (c) 2016 Akinobu Mita + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * Datasheet: http://www.ti.com/lit/ds/symlink/adc12138.pdf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADC12138_MODE_AUTO_CAL 0x08 +#define ADC12138_MODE_READ_STATUS 0x0c +#define ADC12138_MODE_ACQUISITION_TIME_6 0x0e +#define ADC12138_MODE_ACQUISITION_TIME_10 0x4e +#define ADC12138_MODE_ACQUISITION_TIME_18 0x8e +#define ADC12138_MODE_ACQUISITION_TIME_34 0xce + +#define ADC12138_STATUS_CAL BIT(6) + +enum { + adc12130, + adc12132, + adc12138, +}; + +struct adc12138 { + struct spi_device *spi; + unsigned int id; + /* conversion clock */ + struct clk *cclk; + /* positive analog voltage reference */ + struct regulator *vref_p; + /* negative analog voltage reference */ + struct regulator *vref_n; + struct mutex lock; + struct completion complete; + /* The number of cclk periods for the S/H's acquisition time */ + unsigned int acquisition_time; + + u8 tx_buf[2] ____cacheline_aligned; + u8 rx_buf[2]; +}; + +#define ADC12138_VOLTAGE_CHANNEL(chan) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_OFFSET), \ + .scan_index = chan, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 13, \ + .storagebits = 16, \ + .shift = 3, \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADC12138_VOLTAGE_CHANNEL_DIFF(chan1, chan2, si) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (chan1), \ + .channel2 = (chan2), \ + .differential = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_OFFSET), \ + .scan_index = si, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 13, \ + .storagebits = 16, \ + .shift = 3, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec adc12132_channels[] = { + ADC12138_VOLTAGE_CHANNEL(0), + ADC12138_VOLTAGE_CHANNEL(1), + ADC12138_VOLTAGE_CHANNEL_DIFF(0, 1, 2), + ADC12138_VOLTAGE_CHANNEL_DIFF(1, 0, 3), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static const struct iio_chan_spec adc12138_channels[] = { + ADC12138_VOLTAGE_CHANNEL(0), + ADC12138_VOLTAGE_CHANNEL(1), + ADC12138_VOLTAGE_CHANNEL(2), + ADC12138_VOLTAGE_CHANNEL(3), + ADC12138_VOLTAGE_CHANNEL(4), + ADC12138_VOLTAGE_CHANNEL(5), + ADC12138_VOLTAGE_CHANNEL(6), + ADC12138_VOLTAGE_CHANNEL(7), + ADC12138_VOLTAGE_CHANNEL_DIFF(0, 1, 8), + ADC12138_VOLTAGE_CHANNEL_DIFF(1, 0, 9), + ADC12138_VOLTAGE_CHANNEL_DIFF(2, 3, 10), + ADC12138_VOLTAGE_CHANNEL_DIFF(3, 2, 11), + ADC12138_VOLTAGE_CHANNEL_DIFF(4, 5, 12), + ADC12138_VOLTAGE_CHANNEL_DIFF(5, 4, 13), + ADC12138_VOLTAGE_CHANNEL_DIFF(6, 7, 14), + ADC12138_VOLTAGE_CHANNEL_DIFF(7, 6, 15), + IIO_CHAN_SOFT_TIMESTAMP(16), +}; + +static int adc12138_mode_programming(struct adc12138 *adc, u8 mode, + void *rx_buf, int len) +{ + struct spi_transfer xfer = { + .tx_buf = adc->tx_buf, + .rx_buf = adc->rx_buf, + .len = len, + }; + int ret; + + /* Skip unused bits for ADC12130 and ADC12132 */ + if (adc->id != adc12138) + mode = (mode & 0xc0) | ((mode & 0x0f) << 2); + + adc->tx_buf[0] = mode; + + ret = spi_sync_transfer(adc->spi, &xfer, 1); + if (ret) + return ret; + + memcpy(rx_buf, adc->rx_buf, len); + + return 0; +} + +static int adc12138_read_status(struct adc12138 *adc) +{ + u8 rx_buf[2]; + int ret; + + ret = adc12138_mode_programming(adc, ADC12138_MODE_READ_STATUS, + rx_buf, 2); + if (ret) + return ret; + + return (rx_buf[0] << 1) | (rx_buf[1] >> 7); +} + +static int __adc12138_start_conv(struct adc12138 *adc, + struct iio_chan_spec const *channel, + void *data, int len) + +{ + const u8 ch_to_mux[] = { 0, 4, 1, 5, 2, 6, 3, 7 }; + u8 mode = (ch_to_mux[channel->channel] << 4) | + (channel->differential ? 0 : 0x80); + + return adc12138_mode_programming(adc, mode, data, len); +} + +static int adc12138_start_conv(struct adc12138 *adc, + struct iio_chan_spec const *channel) +{ + u8 trash; + + return __adc12138_start_conv(adc, channel, &trash, 1); +} + +static int adc12138_start_and_read_conv(struct adc12138 *adc, + struct iio_chan_spec const *channel, + __be16 *data) +{ + return __adc12138_start_conv(adc, channel, data, 2); +} + +static int adc12138_read_conv_data(struct adc12138 *adc, __be16 *value) +{ + /* Issue a read status instruction and read previous conversion data */ + return adc12138_mode_programming(adc, ADC12138_MODE_READ_STATUS, + value, sizeof(*value)); +} + +static int adc12138_wait_eoc(struct adc12138 *adc, unsigned long timeout) +{ + if (!wait_for_completion_timeout(&adc->complete, timeout)) + return -ETIMEDOUT; + + return 0; +} + +static int adc12138_adc_conversion(struct adc12138 *adc, + struct iio_chan_spec const *channel, + __be16 *value) +{ + int ret; + + reinit_completion(&adc->complete); + + ret = adc12138_start_conv(adc, channel); + if (ret) + return ret; + + ret = adc12138_wait_eoc(adc, msecs_to_jiffies(100)); + if (ret) + return ret; + + return adc12138_read_conv_data(adc, value); +} + +static int adc12138_read_raw(struct iio_dev *iio, + struct iio_chan_spec const *channel, int *value, + int *shift, long mask) +{ + struct adc12138 *adc = iio_priv(iio); + int ret; + __be16 data; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&adc->lock); + ret = adc12138_adc_conversion(adc, channel, &data); + mutex_unlock(&adc->lock); + if (ret) + return ret; + + *value = sign_extend32(be16_to_cpu(data) >> 3, 12); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + ret = regulator_get_voltage(adc->vref_p); + if (ret < 0) + return ret; + *value = ret; + + if (!IS_ERR(adc->vref_n)) { + ret = regulator_get_voltage(adc->vref_n); + if (ret < 0) + return ret; + *value -= ret; + } + + /* convert regulator output voltage to mV */ + *value /= 1000; + *shift = channel->scan_type.realbits - 1; + + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + if (!IS_ERR(adc->vref_n)) { + *value = regulator_get_voltage(adc->vref_n); + if (*value < 0) + return *value; + } else { + *value = 0; + } + + /* convert regulator output voltage to mV */ + *value /= 1000; + + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const struct iio_info adc12138_info = { + .read_raw = adc12138_read_raw, + .driver_module = THIS_MODULE, +}; + +static int adc12138_init(struct adc12138 *adc) +{ + int ret; + int status; + u8 mode; + u8 trash; + + reinit_completion(&adc->complete); + + ret = adc12138_mode_programming(adc, ADC12138_MODE_AUTO_CAL, &trash, 1); + if (ret) + return ret; + + /* data output at this time has no significance */ + status = adc12138_read_status(adc); + if (status < 0) + return status; + + adc12138_wait_eoc(adc, msecs_to_jiffies(100)); + + status = adc12138_read_status(adc); + if (status & ADC12138_STATUS_CAL) { + dev_warn(&adc->spi->dev, + "Auto Cal sequence is still in progress: %#x\n", + status); + return -EIO; + } + + switch (adc->acquisition_time) { + case 6: + mode = ADC12138_MODE_ACQUISITION_TIME_6; + break; + case 10: + mode = ADC12138_MODE_ACQUISITION_TIME_10; + break; + case 18: + mode = ADC12138_MODE_ACQUISITION_TIME_18; + break; + case 34: + mode = ADC12138_MODE_ACQUISITION_TIME_34; + break; + default: + return -EINVAL; + } + + return adc12138_mode_programming(adc, mode, &trash, 1); +} + +static irqreturn_t adc12138_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc12138 *adc = iio_priv(indio_dev); + __be16 data[20] = { }; /* 16x 2 bytes ADC data + 8 bytes timestamp */ + __be16 trash; + int ret; + int scan_index; + int i = 0; + + mutex_lock(&adc->lock); + + for_each_set_bit(scan_index, indio_dev->active_scan_mask, + indio_dev->masklength) { + const struct iio_chan_spec *scan_chan = + &indio_dev->channels[scan_index]; + + reinit_completion(&adc->complete); + + ret = adc12138_start_and_read_conv(adc, scan_chan, + i ? &data[i - 1] : &trash); + if (ret) { + dev_warn(&adc->spi->dev, + "failed to start conversion\n"); + goto out; + } + + ret = adc12138_wait_eoc(adc, msecs_to_jiffies(100)); + if (ret) { + dev_warn(&adc->spi->dev, "wait eoc timeout\n"); + goto out; + } + + i++; + } + + if (i) { + ret = adc12138_read_conv_data(adc, &data[i - 1]); + if (ret) { + dev_warn(&adc->spi->dev, + "failed to get conversion data\n"); + goto out; + } + } + + iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_get_time_ns(indio_dev)); +out: + mutex_unlock(&adc->lock); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static irqreturn_t adc12138_eoc_handler(int irq, void *p) +{ + struct iio_dev *indio_dev = p; + struct adc12138 *adc = iio_priv(indio_dev); + + complete(&adc->complete); + + return IRQ_HANDLED; +} + +static int adc12138_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct adc12138 *adc; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); + if (!indio_dev) + return -ENOMEM; + + adc = iio_priv(indio_dev); + adc->spi = spi; + adc->id = spi_get_device_id(spi)->driver_data; + mutex_init(&adc->lock); + init_completion(&adc->complete); + + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &adc12138_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + switch (adc->id) { + case adc12130: + case adc12132: + indio_dev->channels = adc12132_channels; + indio_dev->num_channels = ARRAY_SIZE(adc12132_channels); + break; + case adc12138: + indio_dev->channels = adc12138_channels; + indio_dev->num_channels = ARRAY_SIZE(adc12138_channels); + break; + default: + return -EINVAL; + } + + ret = of_property_read_u32(spi->dev.of_node, "ti,acquisition-time", + &adc->acquisition_time); + if (ret) + adc->acquisition_time = 10; + + adc->cclk = devm_clk_get(&spi->dev, NULL); + if (IS_ERR(adc->cclk)) + return PTR_ERR(adc->cclk); + + adc->vref_p = devm_regulator_get(&spi->dev, "vref-p"); + if (IS_ERR(adc->vref_p)) + return PTR_ERR(adc->vref_p); + + adc->vref_n = devm_regulator_get_optional(&spi->dev, "vref-n"); + if (IS_ERR(adc->vref_n)) { + /* + * Assume vref_n is 0V if an optional regulator is not + * specified, otherwise return the error code. + */ + ret = PTR_ERR(adc->vref_n); + if (ret != -ENODEV) + return ret; + } + + ret = devm_request_irq(&spi->dev, spi->irq, adc12138_eoc_handler, + IRQF_TRIGGER_RISING, indio_dev->name, indio_dev); + if (ret) + return ret; + + ret = clk_prepare_enable(adc->cclk); + if (ret) + return ret; + + ret = regulator_enable(adc->vref_p); + if (ret) + goto err_clk_disable; + + if (!IS_ERR(adc->vref_n)) { + ret = regulator_enable(adc->vref_n); + if (ret) + goto err_vref_p_disable; + } + + ret = adc12138_init(adc); + if (ret) + goto err_vref_n_disable; + + spi_set_drvdata(spi, indio_dev); + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + adc12138_trigger_handler, NULL); + if (ret) + goto err_vref_n_disable; + + ret = iio_device_register(indio_dev); + if (ret) + goto err_buffer_cleanup; + + return 0; +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +err_vref_n_disable: + if (!IS_ERR(adc->vref_n)) + regulator_disable(adc->vref_n); +err_vref_p_disable: + regulator_disable(adc->vref_p); +err_clk_disable: + clk_disable_unprepare(adc->cclk); + + return ret; +} + +static int adc12138_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adc12138 *adc = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + if (!IS_ERR(adc->vref_n)) + regulator_disable(adc->vref_n); + regulator_disable(adc->vref_p); + clk_disable_unprepare(adc->cclk); + + return 0; +} + +#ifdef CONFIG_OF + +static const struct of_device_id adc12138_dt_ids[] = { + { .compatible = "ti,adc12130", }, + { .compatible = "ti,adc12132", }, + { .compatible = "ti,adc12138", }, + {} +}; +MODULE_DEVICE_TABLE(of, adc12138_dt_ids); + +#endif + +static const struct spi_device_id adc12138_id[] = { + { "adc12130", adc12130 }, + { "adc12132", adc12132 }, + { "adc12138", adc12138 }, + {} +}; +MODULE_DEVICE_TABLE(spi, adc12138_id); + +static struct spi_driver adc12138_driver = { + .driver = { + .name = "adc12138", + .of_match_table = of_match_ptr(adc12138_dt_ids), + }, + .probe = adc12138_probe, + .remove = adc12138_remove, + .id_table = adc12138_id, +}; +module_spi_driver(adc12138_driver); + +MODULE_AUTHOR("Akinobu Mita "); +MODULE_DESCRIPTION("ADC12130/ADC12132/ADC12138 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c new file mode 100644 index 000000000000..f94b69f9c288 --- /dev/null +++ b/drivers/iio/adc/ti-adc161s626.c @@ -0,0 +1,248 @@ +/* + * ti-adc161s626.c - Texas Instruments ADC161S626 1-channel differential ADC + * + * ADC Devices Supported: + * adc141s626 - 14-bit ADC + * adc161s626 - 16-bit ADC + * + * Copyright (C) 2016 Matt Ranostay + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TI_ADC_DRV_NAME "ti-adc161s626" + +enum { + TI_ADC141S626, + TI_ADC161S626, +}; + +static const struct iio_chan_spec ti_adc141s626_channels[] = { + { + .type = IIO_VOLTAGE, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 14, + .storagebits = 16, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static const struct iio_chan_spec ti_adc161s626_channels[] = { + { + .type = IIO_VOLTAGE, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +struct ti_adc_data { + struct iio_dev *indio_dev; + struct spi_device *spi; + u8 read_size; + u8 shift; + + u8 buffer[16] ____cacheline_aligned; +}; + +static int ti_adc_read_measurement(struct ti_adc_data *data, + struct iio_chan_spec const *chan, int *val) +{ + int ret; + + switch (data->read_size) { + case 2: { + __be16 buf; + + ret = spi_read(data->spi, (void *) &buf, 2); + if (ret) + return ret; + + *val = be16_to_cpu(buf); + break; + } + case 3: { + __be32 buf; + + ret = spi_read(data->spi, (void *) &buf, 3); + if (ret) + return ret; + + *val = be32_to_cpu(buf) >> 8; + break; + } + default: + return -EINVAL; + } + + *val = sign_extend32(*val >> data->shift, chan->scan_type.realbits - 1); + + return 0; +} + +static irqreturn_t ti_adc_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct ti_adc_data *data = iio_priv(indio_dev); + int ret; + + ret = ti_adc_read_measurement(data, &indio_dev->channels[0], + (int *) &data->buffer); + if (!ret) + iio_push_to_buffers_with_timestamp(indio_dev, + data->buffer, + iio_get_time_ns(indio_dev)); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int ti_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ti_adc_data *data = iio_priv(indio_dev); + int ret; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = ti_adc_read_measurement(data, chan, val); + iio_device_release_direct_mode(indio_dev); + + if (!ret) + return IIO_VAL_INT; + + return 0; +} + +static const struct iio_info ti_adc_info = { + .driver_module = THIS_MODULE, + .read_raw = ti_adc_read_raw, +}; + +static int ti_adc_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ti_adc_data *data; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &ti_adc_info; + indio_dev->dev.parent = &spi->dev; + indio_dev->dev.of_node = spi->dev.of_node; + indio_dev->name = TI_ADC_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + spi_set_drvdata(spi, indio_dev); + + data = iio_priv(indio_dev); + data->spi = spi; + + switch (spi_get_device_id(spi)->driver_data) { + case TI_ADC141S626: + indio_dev->channels = ti_adc141s626_channels; + indio_dev->num_channels = ARRAY_SIZE(ti_adc141s626_channels); + data->shift = 0; + data->read_size = 2; + break; + case TI_ADC161S626: + indio_dev->channels = ti_adc161s626_channels; + indio_dev->num_channels = ARRAY_SIZE(ti_adc161s626_channels); + data->shift = 6; + data->read_size = 3; + break; + } + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + ti_adc_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 ti_adc_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; +} + +static const struct of_device_id ti_adc_dt_ids[] = { + { .compatible = "ti,adc141s626", }, + { .compatible = "ti,adc161s626", }, + {} +}; +MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); + +static const struct spi_device_id ti_adc_id[] = { + {"adc141s626", TI_ADC141S626}, + {"adc161s626", TI_ADC161S626}, + {}, +}; +MODULE_DEVICE_TABLE(spi, ti_adc_id); + +static struct spi_driver ti_adc_driver = { + .driver = { + .name = TI_ADC_DRV_NAME, + .of_match_table = of_match_ptr(ti_adc_dt_ids), + }, + .probe = ti_adc_probe, + .remove = ti_adc_remove, + .id_table = ti_adc_id, +}; +module_spi_driver(ti_adc_driver); + +MODULE_AUTHOR("Matt Ranostay "); +MODULE_DESCRIPTION("Texas Instruments ADC1x1S 1-channel differential ADC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 066abaf80201..cde6f130a99a 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -522,6 +522,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) if (pga > 6) { dev_err(&client->dev, "invalid gain on %s\n", node->full_name); + of_node_put(node); return -EINVAL; } } @@ -532,6 +533,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) dev_err(&client->dev, "invalid data_rate on %s\n", node->full_name); + of_node_put(node); return -EINVAL; } } diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index c400439900af..4a163496d9e4 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -438,7 +438,7 @@ static int ads8688_probe(struct spi_device *spi) return 0; error_out: - if (!IS_ERR_OR_NULL(st->reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); return ret; @@ -451,7 +451,7 @@ static int ads8688_remove(struct spi_device *spi) iio_device_unregister(indio_dev); - if (!IS_ERR_OR_NULL(st->reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); return 0; diff --git a/drivers/iio/buffer/industrialio-buffer-cb.c b/drivers/iio/buffer/industrialio-buffer-cb.c index 323079c3ccce..b8f550e47d3d 100644 --- a/drivers/iio/buffer/industrialio-buffer-cb.c +++ b/drivers/iio/buffer/industrialio-buffer-cb.c @@ -18,6 +18,7 @@ struct iio_cb_buffer { int (*cb)(const void *data, void *private); void *private; struct iio_channel *channels; + struct iio_dev *indio_dev; }; static struct iio_cb_buffer *buffer_to_cb_buffer(struct iio_buffer *buffer) @@ -52,7 +53,6 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, { int ret; struct iio_cb_buffer *cb_buff; - struct iio_dev *indio_dev; struct iio_channel *chan; cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL); @@ -72,17 +72,17 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, goto error_free_cb_buff; } - indio_dev = cb_buff->channels[0].indio_dev; + cb_buff->indio_dev = cb_buff->channels[0].indio_dev; cb_buff->buffer.scan_mask - = kcalloc(BITS_TO_LONGS(indio_dev->masklength), sizeof(long), - GFP_KERNEL); + = kcalloc(BITS_TO_LONGS(cb_buff->indio_dev->masklength), + sizeof(long), GFP_KERNEL); if (cb_buff->buffer.scan_mask == NULL) { ret = -ENOMEM; goto error_release_channels; } chan = &cb_buff->channels[0]; while (chan->indio_dev) { - if (chan->indio_dev != indio_dev) { + if (chan->indio_dev != cb_buff->indio_dev) { ret = -EINVAL; goto error_free_scan_mask; } @@ -105,17 +105,14 @@ EXPORT_SYMBOL_GPL(iio_channel_get_all_cb); int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff) { - return iio_update_buffers(cb_buff->channels[0].indio_dev, - &cb_buff->buffer, + return iio_update_buffers(cb_buff->indio_dev, &cb_buff->buffer, NULL); } EXPORT_SYMBOL_GPL(iio_channel_start_all_cb); void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff) { - iio_update_buffers(cb_buff->channels[0].indio_dev, - NULL, - &cb_buff->buffer); + iio_update_buffers(cb_buff->indio_dev, NULL, &cb_buff->buffer); } EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb); @@ -133,6 +130,13 @@ struct iio_channel } EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels); +struct iio_dev +*iio_channel_cb_get_iio_dev(const struct iio_cb_buffer *cb_buffer) +{ + return cb_buffer->indio_dev; +} +EXPORT_SYMBOL_GPL(iio_channel_cb_get_iio_dev); + MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Industrial I/O callback buffer"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c index 4b2858ba1fd6..d3db1fce54d2 100644 --- a/drivers/iio/buffer/industrialio-triggered-buffer.c +++ b/drivers/iio/buffer/industrialio-triggered-buffer.c @@ -98,6 +98,48 @@ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) } EXPORT_SYMBOL(iio_triggered_buffer_cleanup); +static void devm_iio_triggered_buffer_clean(struct device *dev, void *res) +{ + iio_triggered_buffer_cleanup(*(struct iio_dev **)res); +} + +int devm_iio_triggered_buffer_setup(struct device *dev, + struct iio_dev *indio_dev, + irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + const struct iio_buffer_setup_ops *ops) +{ + struct iio_dev **ptr; + int ret; + + ptr = devres_alloc(devm_iio_triggered_buffer_clean, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + *ptr = indio_dev; + + ret = iio_triggered_buffer_setup(indio_dev, h, thread, ops); + if (!ret) + devres_add(dev, ptr); + else + devres_free(ptr); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup); + +void devm_iio_triggered_buffer_cleanup(struct device *dev, + struct iio_dev *indio_dev) +{ + int rc; + + rc = devres_release(dev, devm_iio_triggered_buffer_clean, + devm_iio_device_match, indio_dev); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_cleanup); + MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 4bcc025e8c8a..cea7f9857a1f 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -16,6 +16,7 @@ config ATLAS_PH_SENSOR Atlas Scientific OEM SM sensors: * pH SM sensor * EC SM sensor + * ORP SM sensor To compile this driver as module, choose M here: the module will be called atlas-ph-sensor. diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c index 407f141a1eee..bd321b305a0a 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-ph-sensor.c @@ -66,12 +66,17 @@ #define ATLAS_REG_TDS_DATA 0x1c #define ATLAS_REG_PSS_DATA 0x20 +#define ATLAS_REG_ORP_CALIB_STATUS 0x0d +#define ATLAS_REG_ORP_DATA 0x0e + #define ATLAS_PH_INT_TIME_IN_US 450000 #define ATLAS_EC_INT_TIME_IN_US 650000 +#define ATLAS_ORP_INT_TIME_IN_US 450000 enum { ATLAS_PH_SM, ATLAS_EC_SM, + ATLAS_ORP_SM, }; struct atlas_data { @@ -84,26 +89,10 @@ struct atlas_data { __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ }; -static const struct regmap_range atlas_volatile_ranges[] = { - regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL), - regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4), - regmap_reg_range(ATLAS_REG_EC_DATA, ATLAS_REG_PSS_DATA + 4), -}; - -static const struct regmap_access_table atlas_volatile_table = { - .yes_ranges = atlas_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(atlas_volatile_ranges), -}; - static const struct regmap_config atlas_regmap_config = { .name = ATLAS_REGMAP_NAME, - .reg_bits = 8, .val_bits = 8, - - .volatile_table = &atlas_volatile_table, - .max_register = ATLAS_REG_PSS_DATA + 4, - .cache_type = REGCACHE_RBTREE, }; static const struct iio_chan_spec atlas_ph_channels[] = { @@ -175,6 +164,23 @@ static const struct iio_chan_spec atlas_ec_channels[] = { }, }; +static const struct iio_chan_spec atlas_orp_channels[] = { + { + .type = IIO_VOLTAGE, + .address = ATLAS_REG_ORP_DATA, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + static int atlas_check_ph_calibration(struct atlas_data *data) { struct device *dev = &data->client->dev; @@ -240,6 +246,22 @@ static int atlas_check_ec_calibration(struct atlas_data *data) return 0; } +static int atlas_check_orp_calibration(struct atlas_data *data) +{ + struct device *dev = &data->client->dev; + int ret; + unsigned int val; + + ret = regmap_read(data->regmap, ATLAS_REG_ORP_CALIB_STATUS, &val); + if (ret) + return ret; + + if (!val) + dev_warn(dev, "device has not been calibrated\n"); + + return 0; +}; + struct atlas_device { const struct iio_chan_spec *channels; int num_channels; @@ -264,7 +286,13 @@ static struct atlas_device atlas_devices[] = { .calibration = &atlas_check_ec_calibration, .delay = ATLAS_EC_INT_TIME_IN_US, }, - + [ATLAS_ORP_SM] = { + .channels = atlas_orp_channels, + .num_channels = 2, + .data_reg = ATLAS_REG_ORP_DATA, + .calibration = &atlas_check_orp_calibration, + .delay = ATLAS_ORP_INT_TIME_IN_US, + }, }; static int atlas_set_powermode(struct atlas_data *data, int on) @@ -402,15 +430,14 @@ static int atlas_read_raw(struct iio_dev *indio_dev, case IIO_PH: case IIO_CONCENTRATION: case IIO_ELECTRICALCONDUCTIVITY: - mutex_lock(&indio_dev->mlock); + case IIO_VOLTAGE: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = atlas_read_measurement(data, - chan->address, ®); + ret = atlas_read_measurement(data, chan->address, ®); - mutex_unlock(&indio_dev->mlock); + iio_device_release_direct_mode(indio_dev); break; default: ret = -EINVAL; @@ -440,6 +467,10 @@ static int atlas_read_raw(struct iio_dev *indio_dev, *val = 0; /* 0.000000001 */ *val2 = 1000; return IIO_VAL_INT_PLUS_NANO; + case IIO_VOLTAGE: + *val = 1; /* 0.1 */ + *val2 = 10; + break; default: return -EINVAL; } @@ -475,6 +506,7 @@ static const struct iio_info atlas_info = { static const struct i2c_device_id atlas_id[] = { { "atlas-ph-sm", ATLAS_PH_SM}, { "atlas-ec-sm", ATLAS_EC_SM}, + { "atlas-orp-sm", ATLAS_ORP_SM}, {} }; MODULE_DEVICE_TABLE(i2c, atlas_id); @@ -482,6 +514,7 @@ MODULE_DEVICE_TABLE(i2c, atlas_id); static const struct of_device_id atlas_dt_ids[] = { { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, }, { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, }, + { .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, }, { } }; MODULE_DEVICE_TABLE(of, atlas_dt_ids); diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index 652649da500f..8e0e4415c161 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -19,25 +19,55 @@ #include #include #include +#include +#include #include #include #define VZ89X_REG_MEASUREMENT 0x09 -#define VZ89X_REG_MEASUREMENT_SIZE 6 +#define VZ89X_REG_MEASUREMENT_RD_SIZE 6 +#define VZ89X_REG_MEASUREMENT_WR_SIZE 3 #define VZ89X_VOC_CO2_IDX 0 #define VZ89X_VOC_SHORT_IDX 1 #define VZ89X_VOC_TVOC_IDX 2 #define VZ89X_VOC_RESISTANCE_IDX 3 +#define VZ89TE_REG_MEASUREMENT 0x0c +#define VZ89TE_REG_MEASUREMENT_RD_SIZE 7 +#define VZ89TE_REG_MEASUREMENT_WR_SIZE 6 + +#define VZ89TE_VOC_TVOC_IDX 0 +#define VZ89TE_VOC_CO2_IDX 1 +#define VZ89TE_VOC_RESISTANCE_IDX 2 + +enum { + VZ89X, + VZ89TE, +}; + +struct vz89x_chip_data; + struct vz89x_data { struct i2c_client *client; + const struct vz89x_chip_data *chip; struct mutex lock; int (*xfer)(struct vz89x_data *data, u8 cmd); + bool is_valid; unsigned long last_update; - u8 buffer[VZ89X_REG_MEASUREMENT_SIZE]; + u8 buffer[VZ89TE_REG_MEASUREMENT_RD_SIZE]; +}; + +struct vz89x_chip_data { + bool (*valid)(struct vz89x_data *data); + const struct iio_chan_spec *channels; + u8 num_channels; + + u8 cmd; + u8 read_size; + u8 write_size; }; static const struct iio_chan_spec vz89x_channels[] = { @@ -70,6 +100,40 @@ static const struct iio_chan_spec vz89x_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .address = VZ89X_VOC_RESISTANCE_IDX, + .scan_index = -1, + .scan_type = { + .endianness = IIO_LE, + }, + }, +}; + +static const struct iio_chan_spec vz89te_channels[] = { + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_VOC, + .modified = 1, + .info_mask_separate = + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW), + .address = VZ89TE_VOC_TVOC_IDX, + }, + + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_CO2, + .modified = 1, + .info_mask_separate = + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW), + .address = VZ89TE_VOC_CO2_IDX, + }, + { + .type = IIO_RESISTANCE, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .address = VZ89TE_VOC_RESISTANCE_IDX, + .scan_index = -1, + .scan_type = { + .endianness = IIO_BE, + }, }, }; @@ -93,29 +157,45 @@ static const struct attribute_group vz89x_attrs_group = { * always zero, and by also confirming the VOC_short isn't zero. */ -static int vz89x_measurement_is_valid(struct vz89x_data *data) +static bool vz89x_measurement_is_valid(struct vz89x_data *data) { if (data->buffer[VZ89X_VOC_SHORT_IDX] == 0) - return 1; + return true; - return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0); + return !!(data->buffer[data->chip->read_size - 1] > 0); +} + +/* VZ89TE device has a modified CRC-8 two complement check */ +static bool vz89te_measurement_is_valid(struct vz89x_data *data) +{ + u8 crc = 0; + int i, sum = 0; + + for (i = 0; i < (data->chip->read_size - 1); i++) { + sum = crc + data->buffer[i]; + crc = sum; + crc += sum / 256; + } + + return !((0xff - crc) == data->buffer[data->chip->read_size - 1]); } static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd) { + const struct vz89x_chip_data *chip = data->chip; struct i2c_client *client = data->client; struct i2c_msg msg[2]; int ret; - u8 buf[3] = { cmd, 0, 0}; + u8 buf[6] = { cmd, 0, 0, 0, 0, 0xf3 }; msg[0].addr = client->addr; msg[0].flags = client->flags; - msg[0].len = 3; + msg[0].len = chip->write_size; msg[0].buf = (char *) &buf; msg[1].addr = client->addr; msg[1].flags = client->flags | I2C_M_RD; - msg[1].len = VZ89X_REG_MEASUREMENT_SIZE; + msg[1].len = chip->read_size; msg[1].buf = (char *) &data->buffer; ret = i2c_transfer(client->adapter, msg, 2); @@ -133,7 +213,7 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd) if (ret < 0) return ret; - for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) { + for (i = 0; i < data->chip->read_size; i++) { ret = i2c_smbus_read_byte(client); if (ret < 0) return ret; @@ -145,30 +225,47 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd) static int vz89x_get_measurement(struct vz89x_data *data) { + const struct vz89x_chip_data *chip = data->chip; int ret; /* sensor can only be polled once a second max per datasheet */ if (!time_after(jiffies, data->last_update + HZ)) - return 0; + return data->is_valid ? 0 : -EAGAIN; - ret = data->xfer(data, VZ89X_REG_MEASUREMENT); + data->is_valid = false; + data->last_update = jiffies; + + ret = data->xfer(data, chip->cmd); if (ret < 0) return ret; - ret = vz89x_measurement_is_valid(data); + ret = chip->valid(data); if (ret) return -EAGAIN; - data->last_update = jiffies; + data->is_valid = true; return 0; } -static int vz89x_get_resistance_reading(struct vz89x_data *data) +static int vz89x_get_resistance_reading(struct vz89x_data *data, + struct iio_chan_spec const *chan, + int *val) { - u8 *buf = &data->buffer[VZ89X_VOC_RESISTANCE_IDX]; + u8 *tmp = (u8 *) &data->buffer[chan->address]; - return buf[0] | (buf[1] << 8); + switch (chan->scan_type.endianness) { + case IIO_LE: + *val = le32_to_cpup((__le32 *) tmp) & GENMASK(23, 0); + break; + case IIO_BE: + *val = be32_to_cpup((__be32 *) tmp) >> 8; + break; + default: + return -EINVAL; + } + + return 0; } static int vz89x_read_raw(struct iio_dev *indio_dev, @@ -187,15 +284,15 @@ static int vz89x_read_raw(struct iio_dev *indio_dev, if (ret) return ret; - switch (chan->address) { - case VZ89X_VOC_CO2_IDX: - case VZ89X_VOC_SHORT_IDX: - case VZ89X_VOC_TVOC_IDX: + switch (chan->type) { + case IIO_CONCENTRATION: *val = data->buffer[chan->address]; return IIO_VAL_INT; - case VZ89X_VOC_RESISTANCE_IDX: - *val = vz89x_get_resistance_reading(data); - return IIO_VAL_INT; + case IIO_RESISTANCE: + ret = vz89x_get_resistance_reading(data, chan, val); + if (!ret) + return IIO_VAL_INT; + break; default: return -EINVAL; } @@ -210,12 +307,12 @@ static int vz89x_read_raw(struct iio_dev *indio_dev, } break; case IIO_CHAN_INFO_OFFSET: - switch (chan->address) { - case VZ89X_VOC_CO2_IDX: + switch (chan->channel2) { + case IIO_MOD_CO2: *val = 44; *val2 = 250000; return IIO_VAL_INT_PLUS_MICRO; - case VZ89X_VOC_TVOC_IDX: + case IIO_MOD_VOC: *val = -13; return IIO_VAL_INT; default: @@ -232,11 +329,43 @@ static const struct iio_info vz89x_info = { .driver_module = THIS_MODULE, }; +static const struct vz89x_chip_data vz89x_chips[] = { + { + .valid = vz89x_measurement_is_valid, + + .cmd = VZ89X_REG_MEASUREMENT, + .read_size = VZ89X_REG_MEASUREMENT_RD_SIZE, + .write_size = VZ89X_REG_MEASUREMENT_WR_SIZE, + + .channels = vz89x_channels, + .num_channels = ARRAY_SIZE(vz89x_channels), + }, + { + .valid = vz89te_measurement_is_valid, + + .cmd = VZ89TE_REG_MEASUREMENT, + .read_size = VZ89TE_REG_MEASUREMENT_RD_SIZE, + .write_size = VZ89TE_REG_MEASUREMENT_WR_SIZE, + + .channels = vz89te_channels, + .num_channels = ARRAY_SIZE(vz89te_channels), + }, +}; + +static const struct of_device_id vz89x_dt_ids[] = { + { .compatible = "sgx,vz89x", .data = (void *) VZ89X }, + { .compatible = "sgx,vz89te", .data = (void *) VZ89TE }, + { } +}; +MODULE_DEVICE_TABLE(of, vz89x_dt_ids); + static int vz89x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct iio_dev *indio_dev; struct vz89x_data *data; + const struct of_device_id *of_id; + int chip_id; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -251,8 +380,15 @@ static int vz89x_probe(struct i2c_client *client, else return -EOPNOTSUPP; + of_id = of_match_device(vz89x_dt_ids, &client->dev); + if (!of_id) + chip_id = id->driver_data; + else + chip_id = (unsigned long)of_id->data; + i2c_set_clientdata(client, indio_dev); data->client = client; + data->chip = &vz89x_chips[chip_id]; data->last_update = jiffies - HZ; mutex_init(&data->lock); @@ -261,24 +397,19 @@ static int vz89x_probe(struct i2c_client *client, indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = vz89x_channels; - indio_dev->num_channels = ARRAY_SIZE(vz89x_channels); + indio_dev->channels = data->chip->channels; + indio_dev->num_channels = data->chip->num_channels; return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id vz89x_id[] = { - { "vz89x", 0 }, + { "vz89x", VZ89X }, + { "vz89te", VZ89TE }, { } }; MODULE_DEVICE_TABLE(i2c, vz89x_id); -static const struct of_device_id vz89x_dt_ids[] = { - { .compatible = "sgx,vz89x" }, - { } -}; -MODULE_DEVICE_TABLE(of, vz89x_dt_ids); - static struct i2c_driver vz89x_driver = { .driver = { .name = "vz89x", diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 5b41f9d0d4f3..a3cce3a38300 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -122,6 +122,14 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) #endif } +static void hid_sensor_set_power_work(struct work_struct *work) +{ + struct hid_sensor_common *attrb = container_of(work, + struct hid_sensor_common, + work); + _hid_sensor_power_state(attrb, true); +} + static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { @@ -130,6 +138,7 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) { + cancel_work_sync(&attrb->work); iio_trigger_unregister(attrb->trigger); iio_trigger_free(attrb->trigger); } @@ -170,6 +179,9 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, goto error_unreg_trigger; iio_device_set_drvdata(indio_dev, attrb); + + INIT_WORK(&attrb->work, hid_sensor_set_power_work); + pm_suspend_ignore_children(&attrb->pdev->dev, true); pm_runtime_enable(&attrb->pdev->dev); /* Default to 3 seconds, but can be changed from sysfs */ @@ -187,8 +199,7 @@ error_ret: } EXPORT_SYMBOL(hid_sensor_setup_trigger); -#ifdef CONFIG_PM -static int hid_sensor_suspend(struct device *dev) +static int __maybe_unused hid_sensor_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = platform_get_drvdata(pdev); @@ -197,21 +208,27 @@ static int hid_sensor_suspend(struct device *dev) return _hid_sensor_power_state(attrb, false); } -static int hid_sensor_resume(struct device *dev) +static int __maybe_unused hid_sensor_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); - - return _hid_sensor_power_state(attrb, true); + schedule_work(&attrb->work); + return 0; } -#endif +static int __maybe_unused hid_sensor_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + return _hid_sensor_power_state(attrb, true); +} const struct dev_pm_ops hid_sensor_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(hid_sensor_suspend, hid_sensor_resume) SET_RUNTIME_PM_OPS(hid_sensor_suspend, - hid_sensor_resume, NULL) + hid_sensor_runtime_resume, NULL) }; EXPORT_SYMBOL(hid_sensor_pm_ops); diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index d06e728cea37..fe7775bb3740 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -63,7 +63,7 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p) * the hardware trigger) and the hw_timestamp may get updated. * By storing it in a local variable first, we are safe. */ - if (sdata->hw_irq_trigger) + if (iio_trigger_using_own(indio_dev)) timestamp = sdata->hw_timestamp; else timestamp = iio_get_time_ns(indio_dev); diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 2d5282e05482..285a64a589d7 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -234,39 +234,35 @@ int st_sensors_power_enable(struct iio_dev *indio_dev) int err; /* Regulators not mandatory, but if requested we should enable them. */ - pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd"); - if (!IS_ERR(pdata->vdd)) { - err = regulator_enable(pdata->vdd); - if (err != 0) { - dev_warn(&indio_dev->dev, - "Failed to enable specified Vdd supply\n"); - return err; - } - } else { - err = PTR_ERR(pdata->vdd); - if (err != -ENODEV) - return err; + pdata->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd"); + if (IS_ERR(pdata->vdd)) { + dev_err(&indio_dev->dev, "unable to get Vdd supply\n"); + return PTR_ERR(pdata->vdd); + } + err = regulator_enable(pdata->vdd); + if (err != 0) { + dev_warn(&indio_dev->dev, + "Failed to enable specified Vdd supply\n"); + return err; } - pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio"); - if (!IS_ERR(pdata->vdd_io)) { - err = regulator_enable(pdata->vdd_io); - if (err != 0) { - dev_warn(&indio_dev->dev, - "Failed to enable specified Vdd_IO supply\n"); - goto st_sensors_disable_vdd; - } - } else { + pdata->vdd_io = devm_regulator_get(indio_dev->dev.parent, "vddio"); + if (IS_ERR(pdata->vdd_io)) { + dev_err(&indio_dev->dev, "unable to get Vdd_IO supply\n"); err = PTR_ERR(pdata->vdd_io); - if (err != -ENODEV) - goto st_sensors_disable_vdd; + goto st_sensors_disable_vdd; + } + err = regulator_enable(pdata->vdd_io); + if (err != 0) { + dev_warn(&indio_dev->dev, + "Failed to enable specified Vdd_IO supply\n"); + goto st_sensors_disable_vdd; } return 0; st_sensors_disable_vdd: - if (!IS_ERR_OR_NULL(pdata->vdd)) - regulator_disable(pdata->vdd); + regulator_disable(pdata->vdd); return err; } EXPORT_SYMBOL(st_sensors_power_enable); @@ -275,11 +271,8 @@ void st_sensors_power_disable(struct iio_dev *indio_dev) { struct st_sensor_data *pdata = iio_priv(indio_dev); - if (!IS_ERR_OR_NULL(pdata->vdd)) - regulator_disable(pdata->vdd); - - if (!IS_ERR_OR_NULL(pdata->vdd_io)) - regulator_disable(pdata->vdd_io); + regulator_disable(pdata->vdd); + regulator_disable(pdata->vdd_io); } EXPORT_SYMBOL(st_sensors_power_disable); diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index e66f12ee8a55..fa73e6795359 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -66,7 +66,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, * @irq: irq number * @p: private handler data */ -irqreturn_t st_sensors_irq_handler(int irq, void *p) +static irqreturn_t st_sensors_irq_handler(int irq, void *p) { struct iio_trigger *trig = p; struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); @@ -82,7 +82,7 @@ irqreturn_t st_sensors_irq_handler(int irq, void *p) * @irq: irq number * @p: private handler data */ -irqreturn_t st_sensors_irq_thread(int irq, void *p) +static irqreturn_t st_sensors_irq_thread(int irq, void *p) { struct iio_trigger *trig = p; struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index ca814479fadf..120b24478469 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -181,6 +181,25 @@ config AD7303 To compile this driver as module choose M here: the module will be called ad7303. +config CIO_DAC + tristate "Measurement Computing CIO-DAC IIO driver" + depends on X86 && ISA_BUS_API + help + Say yes here to build support for the Measurement Computing CIO-DAC + analog output device family (CIO-DAC16, CIO-DAC08, PC104-DAC06). The + base port addresses for the devices may be configured via the base + array module parameter. + +config AD8801 + tristate "Analog Devices AD8801/AD8803 DAC driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD8801, AD8803 Digital to + Analog Converters (DAC). + + To compile this driver as a module choose M here: the module will be called + ad8801. + config LPC18XX_DAC tristate "NXP LPC18xx DAC driver" depends on ARCH_LPC18XX || COMPILE_TEST @@ -245,16 +264,6 @@ config MCP4922 To compile this driver as a module, choose M here: the module will be called mcp4922. -config STX104 - tristate "Apex Embedded Systems STX104 DAC driver" - depends on X86 && ISA_BUS_API - select GPIOLIB - help - Say yes here to build support for the 2-channel DAC and GPIO on the - Apex Embedded Systems STX104 integrated analog PC/104 card. The base - port addresses for the devices may be configured via the base array - module parameter. - config VF610_DAC tristate "Vybrid vf610 DAC driver" depends on OF diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 8b78d5ca9b11..27642bbf75f2 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -20,11 +20,12 @@ obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD7303) += ad7303.o +obj-$(CONFIG_AD8801) += ad8801.o +obj-$(CONFIG_CIO_DAC) += cio-dac.o obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o obj-$(CONFIG_M62332) += m62332.o obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MAX5821) += max5821.o obj-$(CONFIG_MCP4725) += mcp4725.o obj-$(CONFIG_MCP4922) += mcp4922.o -obj-$(CONFIG_STX104) += stx104.o obj-$(CONFIG_VF610_DAC) += vf610_dac.o diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 0fde593ec0d9..5f7968232564 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -655,7 +655,7 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev) devnr = 0; for_each_child_of_node(np, pp) { - if (devnr > AD5755_NUM_CHANNELS) { + if (devnr >= AD5755_NUM_CHANNELS) { dev_err(dev, "There is to many channels defined in DT\n"); goto error_out; diff --git a/drivers/iio/dac/ad8801.c b/drivers/iio/dac/ad8801.c new file mode 100644 index 000000000000..f06faa1aec09 --- /dev/null +++ b/drivers/iio/dac/ad8801.c @@ -0,0 +1,239 @@ +/* + * IIO DAC driver for Analog Devices AD8801 DAC + * + * Copyright (C) 2016 Gwenhael Goavec-Merou + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include +#include +#include +#include +#include + +#define AD8801_CFG_ADDR_OFFSET 8 + +enum ad8801_device_ids { + ID_AD8801, + ID_AD8803, +}; + +struct ad8801_state { + struct spi_device *spi; + unsigned char dac_cache[8]; /* Value write on each channel */ + unsigned int vrefh_mv; + unsigned int vrefl_mv; + struct regulator *vrefh_reg; + struct regulator *vrefl_reg; + + __be16 data ____cacheline_aligned; +}; + +static int ad8801_spi_write(struct ad8801_state *state, + u8 channel, unsigned char value) +{ + state->data = cpu_to_be16((channel << AD8801_CFG_ADDR_OFFSET) | value); + return spi_write(state->spi, &state->data, sizeof(state->data)); +} + +static int ad8801_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct ad8801_state *state = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val >= 256 || val < 0) + return -EINVAL; + + ret = ad8801_spi_write(state, chan->channel, val); + if (ret == 0) + state->dac_cache[chan->channel] = val; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int ad8801_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long info) +{ + struct ad8801_state *state = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + *val = state->dac_cache[chan->channel]; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = state->vrefh_mv - state->vrefl_mv; + *val2 = 8; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + *val = state->vrefl_mv; + return IIO_VAL_INT; + default: + return -EINVAL; + } + + return -EINVAL; +} + +static const struct iio_info ad8801_info = { + .read_raw = ad8801_read_raw, + .write_raw = ad8801_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD8801_CHANNEL(chan) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ +} + +static const struct iio_chan_spec ad8801_channels[] = { + AD8801_CHANNEL(0), + AD8801_CHANNEL(1), + AD8801_CHANNEL(2), + AD8801_CHANNEL(3), + AD8801_CHANNEL(4), + AD8801_CHANNEL(5), + AD8801_CHANNEL(6), + AD8801_CHANNEL(7), +}; + +static int ad8801_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ad8801_state *state; + const struct spi_device_id *id; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state)); + if (indio_dev == NULL) + return -ENOMEM; + + state = iio_priv(indio_dev); + state->spi = spi; + id = spi_get_device_id(spi); + + state->vrefh_reg = devm_regulator_get(&spi->dev, "vrefh"); + if (IS_ERR(state->vrefh_reg)) { + dev_err(&spi->dev, "Vrefh regulator not specified\n"); + return PTR_ERR(state->vrefh_reg); + } + + ret = regulator_enable(state->vrefh_reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable vrefh regulator: %d\n", + ret); + return ret; + } + + ret = regulator_get_voltage(state->vrefh_reg); + if (ret < 0) { + dev_err(&spi->dev, "Failed to read vrefh regulator: %d\n", + ret); + goto error_disable_vrefh_reg; + } + state->vrefh_mv = ret / 1000; + + if (id->driver_data == ID_AD8803) { + state->vrefl_reg = devm_regulator_get(&spi->dev, "vrefl"); + if (IS_ERR(state->vrefl_reg)) { + dev_err(&spi->dev, "Vrefl regulator not specified\n"); + ret = PTR_ERR(state->vrefl_reg); + goto error_disable_vrefh_reg; + } + + ret = regulator_enable(state->vrefl_reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable vrefl regulator: %d\n", + ret); + goto error_disable_vrefh_reg; + } + + ret = regulator_get_voltage(state->vrefl_reg); + if (ret < 0) { + dev_err(&spi->dev, "Failed to read vrefl regulator: %d\n", + ret); + goto error_disable_vrefl_reg; + } + state->vrefl_mv = ret / 1000; + } else { + state->vrefl_mv = 0; + state->vrefl_reg = NULL; + } + + spi_set_drvdata(spi, indio_dev); + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &ad8801_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad8801_channels; + indio_dev->num_channels = ARRAY_SIZE(ad8801_channels); + indio_dev->name = id->name; + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register iio device: %d\n", + ret); + goto error_disable_vrefl_reg; + } + + return 0; + +error_disable_vrefl_reg: + if (state->vrefl_reg) + regulator_disable(state->vrefl_reg); +error_disable_vrefh_reg: + regulator_disable(state->vrefh_reg); + return ret; +} + +static int ad8801_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad8801_state *state = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + if (state->vrefl_reg) + regulator_disable(state->vrefl_reg); + regulator_disable(state->vrefh_reg); + + return 0; +} + +static const struct spi_device_id ad8801_ids[] = { + {"ad8801", ID_AD8801}, + {"ad8803", ID_AD8803}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad8801_ids); + +static struct spi_driver ad8801_driver = { + .driver = { + .name = "ad8801", + }, + .probe = ad8801_probe, + .remove = ad8801_remove, + .id_table = ad8801_ids, +}; +module_spi_driver(ad8801_driver); + +MODULE_AUTHOR("Gwenhael Goavec-Merou "); +MODULE_DESCRIPTION("Analog Devices AD8801/AD8803 DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/cio-dac.c b/drivers/iio/dac/cio-dac.c new file mode 100644 index 000000000000..5a743e2a779d --- /dev/null +++ b/drivers/iio/dac/cio-dac.c @@ -0,0 +1,144 @@ +/* + * IIO driver for the Measurement Computing CIO-DAC + * Copyright (C) 2016 William Breathitt Gray + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * This driver supports the following Measurement Computing devices: CIO-DAC16, + * CIO-DAC06, and PC104-DAC06. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CIO_DAC_NUM_CHAN 16 + +#define CIO_DAC_CHAN(chan) { \ + .type = IIO_VOLTAGE, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .indexed = 1, \ + .output = 1 \ +} + +#define CIO_DAC_EXTENT 32 + +static unsigned int base[max_num_isa_dev(CIO_DAC_EXTENT)]; +static unsigned int num_cio_dac; +module_param_array(base, uint, &num_cio_dac, 0); +MODULE_PARM_DESC(base, "Measurement Computing CIO-DAC base addresses"); + +/** + * struct cio_dac_iio - IIO device private data structure + * @chan_out_states: channels' output states + * @base: base port address of the IIO device + */ +struct cio_dac_iio { + int chan_out_states[CIO_DAC_NUM_CHAN]; + unsigned int base; +}; + +static int cio_dac_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long mask) +{ + struct cio_dac_iio *const priv = iio_priv(indio_dev); + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + *val = priv->chan_out_states[chan->channel]; + + return IIO_VAL_INT; +} + +static int cio_dac_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct cio_dac_iio *const priv = iio_priv(indio_dev); + const unsigned int chan_addr_offset = 2 * chan->channel; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + /* DAC can only accept up to a 16-bit value */ + if ((unsigned int)val > 65535) + return -EINVAL; + + priv->chan_out_states[chan->channel] = val; + outw(val, priv->base + chan_addr_offset); + + return 0; +} + +static const struct iio_info cio_dac_info = { + .driver_module = THIS_MODULE, + .read_raw = cio_dac_read_raw, + .write_raw = cio_dac_write_raw +}; + +static const struct iio_chan_spec cio_dac_channels[CIO_DAC_NUM_CHAN] = { + CIO_DAC_CHAN(0), CIO_DAC_CHAN(1), CIO_DAC_CHAN(2), CIO_DAC_CHAN(3), + CIO_DAC_CHAN(4), CIO_DAC_CHAN(5), CIO_DAC_CHAN(6), CIO_DAC_CHAN(7), + CIO_DAC_CHAN(8), CIO_DAC_CHAN(9), CIO_DAC_CHAN(10), CIO_DAC_CHAN(11), + CIO_DAC_CHAN(12), CIO_DAC_CHAN(13), CIO_DAC_CHAN(14), CIO_DAC_CHAN(15) +}; + +static int cio_dac_probe(struct device *dev, unsigned int id) +{ + struct iio_dev *indio_dev; + struct cio_dac_iio *priv; + unsigned int i; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + if (!devm_request_region(dev, base[id], CIO_DAC_EXTENT, + dev_name(dev))) { + dev_err(dev, "Unable to request port addresses (0x%X-0x%X)\n", + base[id], base[id] + CIO_DAC_EXTENT); + return -EBUSY; + } + + indio_dev->info = &cio_dac_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = cio_dac_channels; + indio_dev->num_channels = CIO_DAC_NUM_CHAN; + indio_dev->name = dev_name(dev); + + priv = iio_priv(indio_dev); + priv->base = base[id]; + + /* initialize DAC outputs to 0V */ + for (i = 0; i < 32; i += 2) + outw(0, base[id] + i); + + return devm_iio_device_register(dev, indio_dev); +} + +static struct isa_driver cio_dac_driver = { + .probe = cio_dac_probe, + .driver = { + .name = "cio-dac" + } +}; + +module_isa_driver(cio_dac_driver, num_cio_dac); + +MODULE_AUTHOR("William Breathitt Gray "); +MODULE_DESCRIPTION("Measurement Computing CIO-DAC IIO driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c index 0a8afdd21728..1f25f406c545 100644 --- a/drivers/iio/gyro/ssp_gyro_sensor.c +++ b/drivers/iio/gyro/ssp_gyro_sensor.c @@ -74,7 +74,7 @@ static int ssp_gyro_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static struct iio_info ssp_gyro_iio_info = { +static const struct iio_info ssp_gyro_iio_info = { .read_raw = &ssp_gyro_read_raw, .write_raw = &ssp_gyro_write_raw, }; diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index d04124345992..b17e2e2bd4f5 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -28,11 +28,11 @@ config HDC100X tristate "TI HDC100x relative humidity and temperature sensor" depends on I2C help - Say yes here to build support for the TI HDC100x series of - relative humidity and temperature sensors. + Say yes here to build support for the Texas Instruments + HDC1000 and HDC1008 relative humidity and temperature sensors. - To compile this driver as a module, choose M here: the module - will be called hdc100x. + To compile this driver as a module, choose M here: the module + will be called hdc100x. config HTU21 tristate "Measurement Specialties HTU21 humidity & temperature sensor" diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index d2b889918c3e..fc340ed3dca1 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1308,7 +1308,7 @@ static void devm_iio_device_release(struct device *dev, void *res) iio_device_free(*(struct iio_dev **)res); } -static int devm_iio_device_match(struct device *dev, void *res, void *data) +int devm_iio_device_match(struct device *dev, void *res, void *data) { struct iio_dev **r = res; if (!r || !*r) { @@ -1317,6 +1317,7 @@ static int devm_iio_device_match(struct device *dev, void *res, void *data) } return *r == data; } +EXPORT_SYMBOL_GPL(devm_iio_device_match); /** * devm_iio_device_alloc - Resource-managed iio_device_alloc() diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 0ebfc923a997..90fac8ec63c9 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -57,6 +57,11 @@ bool iio_event_enabled(const struct iio_event_interface *ev_int) * * Note: The caller must make sure that this function is not running * concurrently for the same indio_dev more than once. + * + * This function may be safely used as soon as a valid reference to iio_dev has + * been obtained via iio_device_alloc(), but any events that are submitted + * before iio_device_register() has successfully completed will be silently + * discarded. **/ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) { @@ -64,6 +69,9 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) struct iio_event_data ev; int copied; + if (!ev_int) + return 0; + /* Does anyone care? */ if (iio_event_enabled(ev_int)) { diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 7ad82fdd3e5b..e1e104845e38 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -119,6 +119,22 @@ void iio_trigger_unregister(struct iio_trigger *trig_info) } EXPORT_SYMBOL(iio_trigger_unregister); +int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig) +{ + if (!indio_dev || !trig) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + WARN_ON(indio_dev->trig_readonly); + + indio_dev->trig = iio_trigger_get(trig); + indio_dev->trig_readonly = true; + mutex_unlock(&indio_dev->mlock); + + return 0; +} +EXPORT_SYMBOL(iio_trigger_set_immutable); + /* Search for trigger by name, assuming iio_trigger_list_lock held */ static struct iio_trigger *__iio_trigger_find_by_name(const char *name) { @@ -255,6 +271,14 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, goto out_free_irq; } + /* + * Check if we just registered to our own trigger: we determine that + * this is the case if the IIO device and the trigger device share the + * same parent device. + */ + if (pf->indio_dev->dev.parent == trig->dev.parent) + trig->attached_own_device = true; + return ret; out_free_irq: @@ -279,6 +303,8 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig, if (ret) return ret; } + if (pf->indio_dev->dev.parent == trig->dev.parent) + trig->attached_own_device = false; iio_trigger_put_irq(trig, pf->irq); free_irq(pf->irq, pf); module_put(pf->indio_dev->info->driver_module); @@ -384,6 +410,10 @@ static ssize_t iio_trigger_write_current(struct device *dev, mutex_unlock(&indio_dev->mlock); return -EBUSY; } + if (indio_dev->trig_readonly) { + mutex_unlock(&indio_dev->mlock); + return -EPERM; + } mutex_unlock(&indio_dev->mlock); trig = iio_trigger_find_by_name(buf, len); @@ -622,6 +652,71 @@ void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig) } EXPORT_SYMBOL_GPL(devm_iio_trigger_free); +static void devm_iio_trigger_unreg(struct device *dev, void *res) +{ + iio_trigger_unregister(*(struct iio_trigger **)res); +} + +/** + * devm_iio_trigger_register - Resource-managed iio_trigger_register() + * @dev: device this trigger was allocated for + * @trig_info: trigger to register + * + * Managed iio_trigger_register(). The IIO trigger registered with this + * function is automatically unregistered on driver detach. This function + * calls iio_trigger_register() internally. Refer to that function for more + * information. + * + * If an iio_trigger registered with this function needs to be unregistered + * separately, devm_iio_trigger_unregister() must be used. + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int devm_iio_trigger_register(struct device *dev, struct iio_trigger *trig_info) +{ + struct iio_trigger **ptr; + int ret; + + ptr = devres_alloc(devm_iio_trigger_unreg, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + *ptr = trig_info; + ret = iio_trigger_register(trig_info); + if (!ret) + devres_add(dev, ptr); + else + devres_free(ptr); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_iio_trigger_register); + +/** + * devm_iio_trigger_unregister - Resource-managed iio_trigger_unregister() + * @dev: device this iio_trigger belongs to + * @trig_info: the trigger associated with the device + * + * Unregister trigger registered with devm_iio_trigger_register(). + */ +void devm_iio_trigger_unregister(struct device *dev, + struct iio_trigger *trig_info) +{ + int rc; + + rc = devres_release(dev, devm_iio_trigger_unreg, devm_iio_trigger_match, + trig_info); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister); + +bool iio_trigger_using_own(struct iio_dev *indio_dev) +{ + return indio_dev->trig->attached_own_device; +} +EXPORT_SYMBOL(iio_trigger_using_own); + void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { indio_dev->groups[indio_dev->groupcounter++] = diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 3574945183fe..ba2e64d7ee58 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -267,6 +267,19 @@ config PA12203001 This driver can also be built as a module. If so, the module will be called pa12203001. +config SI1145 + tristate "SI1132 and SI1141/2/3/5/6/7 combined ALS, UV index and proximity sensor" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here if you want to build a driver for the Silicon Labs SI1132 or + SI1141/2/3/5/6/7 combined ambient light, UV index and proximity sensor + chips. + + To compile this driver as a module, choose M here: the module will be + called si1145. + config STK3310 tristate "STK3310 ALS and proximity sensor" depends on I2C @@ -334,11 +347,11 @@ config US5182D will be called us5182d. config VCNL4000 - tristate "VCNL4000 combined ALS and proximity sensor" + tristate "VCNL4000/4010/4020 combined ALS and proximity sensor" depends on I2C help - Say Y here if you want to build a driver for the Vishay VCNL4000 - combined ambient light and proximity sensor. + Say Y here if you want to build a driver for the Vishay VCNL4000, + VCNL4010, VCNL4020 combined ambient light and proximity sensor. To compile this driver as a module, choose M here: the module will be called vcnl4000. diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 6f2a3c62de27..c5768df87a17 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_OPT3001) += opt3001.o obj-$(CONFIG_PA12203001) += pa12203001.o obj-$(CONFIG_RPR0521) += rpr0521.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o +obj-$(CONFIG_SI1145) += si1145.o obj-$(CONFIG_STK3310) += stk3310.o obj-$(CONFIG_TCS3414) += tcs3414.o obj-$(CONFIG_TCS3472) += tcs3472.o diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c new file mode 100644 index 000000000000..096034c126a4 --- /dev/null +++ b/drivers/iio/light/si1145.c @@ -0,0 +1,1404 @@ +/* + * si1145.c - Support for Silabs SI1132 and SI1141/2/3/5/6/7 combined ambient + * light, UV index and proximity sensors + * + * Copyright 2014-16 Peter Meerwald-Stadler + * Copyright 2016 Crestez Dan Leonard + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * SI1132 (7-bit I2C slave address 0x60) + * SI1141/2/3 (7-bit I2C slave address 0x5a) + * SI1145/6/6 (7-bit I2C slave address 0x60) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define SI1145_REG_PART_ID 0x00 +#define SI1145_REG_REV_ID 0x01 +#define SI1145_REG_SEQ_ID 0x02 +#define SI1145_REG_INT_CFG 0x03 +#define SI1145_REG_IRQ_ENABLE 0x04 +#define SI1145_REG_IRQ_MODE 0x05 +#define SI1145_REG_HW_KEY 0x07 +#define SI1145_REG_MEAS_RATE 0x08 +#define SI1145_REG_PS_LED21 0x0f +#define SI1145_REG_PS_LED3 0x10 +#define SI1145_REG_UCOEF1 0x13 +#define SI1145_REG_UCOEF2 0x14 +#define SI1145_REG_UCOEF3 0x15 +#define SI1145_REG_UCOEF4 0x16 +#define SI1145_REG_PARAM_WR 0x17 +#define SI1145_REG_COMMAND 0x18 +#define SI1145_REG_RESPONSE 0x20 +#define SI1145_REG_IRQ_STATUS 0x21 +#define SI1145_REG_ALSVIS_DATA 0x22 +#define SI1145_REG_ALSIR_DATA 0x24 +#define SI1145_REG_PS1_DATA 0x26 +#define SI1145_REG_PS2_DATA 0x28 +#define SI1145_REG_PS3_DATA 0x2a +#define SI1145_REG_AUX_DATA 0x2c +#define SI1145_REG_PARAM_RD 0x2e +#define SI1145_REG_CHIP_STAT 0x30 + +#define SI1145_UCOEF1_DEFAULT 0x7b +#define SI1145_UCOEF2_DEFAULT 0x6b +#define SI1145_UCOEF3_DEFAULT 0x01 +#define SI1145_UCOEF4_DEFAULT 0x00 + +/* Helper to figure out PS_LED register / shift per channel */ +#define SI1145_PS_LED_REG(ch) \ + (((ch) == 2) ? SI1145_REG_PS_LED3 : SI1145_REG_PS_LED21) +#define SI1145_PS_LED_SHIFT(ch) \ + (((ch) == 1) ? 4 : 0) + +/* Parameter offsets */ +#define SI1145_PARAM_CHLIST 0x01 +#define SI1145_PARAM_PSLED12_SELECT 0x02 +#define SI1145_PARAM_PSLED3_SELECT 0x03 +#define SI1145_PARAM_PS_ENCODING 0x05 +#define SI1145_PARAM_ALS_ENCODING 0x06 +#define SI1145_PARAM_PS1_ADC_MUX 0x07 +#define SI1145_PARAM_PS2_ADC_MUX 0x08 +#define SI1145_PARAM_PS3_ADC_MUX 0x09 +#define SI1145_PARAM_PS_ADC_COUNTER 0x0a +#define SI1145_PARAM_PS_ADC_GAIN 0x0b +#define SI1145_PARAM_PS_ADC_MISC 0x0c +#define SI1145_PARAM_ALS_ADC_MUX 0x0d +#define SI1145_PARAM_ALSIR_ADC_MUX 0x0e +#define SI1145_PARAM_AUX_ADC_MUX 0x0f +#define SI1145_PARAM_ALSVIS_ADC_COUNTER 0x10 +#define SI1145_PARAM_ALSVIS_ADC_GAIN 0x11 +#define SI1145_PARAM_ALSVIS_ADC_MISC 0x12 +#define SI1145_PARAM_LED_RECOVERY 0x1c +#define SI1145_PARAM_ALSIR_ADC_COUNTER 0x1d +#define SI1145_PARAM_ALSIR_ADC_GAIN 0x1e +#define SI1145_PARAM_ALSIR_ADC_MISC 0x1f +#define SI1145_PARAM_ADC_OFFSET 0x1a + +/* Channel enable masks for CHLIST parameter */ +#define SI1145_CHLIST_EN_PS1 BIT(0) +#define SI1145_CHLIST_EN_PS2 BIT(1) +#define SI1145_CHLIST_EN_PS3 BIT(2) +#define SI1145_CHLIST_EN_ALSVIS BIT(4) +#define SI1145_CHLIST_EN_ALSIR BIT(5) +#define SI1145_CHLIST_EN_AUX BIT(6) +#define SI1145_CHLIST_EN_UV BIT(7) + +/* Proximity measurement mode for ADC_MISC parameter */ +#define SI1145_PS_ADC_MODE_NORMAL BIT(2) +/* Signal range mask for ADC_MISC parameter */ +#define SI1145_ADC_MISC_RANGE BIT(5) + +/* Commands for REG_COMMAND */ +#define SI1145_CMD_NOP 0x00 +#define SI1145_CMD_RESET 0x01 +#define SI1145_CMD_PS_FORCE 0x05 +#define SI1145_CMD_ALS_FORCE 0x06 +#define SI1145_CMD_PSALS_FORCE 0x07 +#define SI1145_CMD_PS_PAUSE 0x09 +#define SI1145_CMD_ALS_PAUSE 0x0a +#define SI1145_CMD_PSALS_PAUSE 0x0b +#define SI1145_CMD_PS_AUTO 0x0d +#define SI1145_CMD_ALS_AUTO 0x0e +#define SI1145_CMD_PSALS_AUTO 0x0f +#define SI1145_CMD_PARAM_QUERY 0x80 +#define SI1145_CMD_PARAM_SET 0xa0 + +#define SI1145_RSP_INVALID_SETTING 0x80 +#define SI1145_RSP_COUNTER_MASK 0x0F + +/* Minimum sleep after each command to ensure it's received */ +#define SI1145_COMMAND_MINSLEEP_MS 5 +/* Return -ETIMEDOUT after this long */ +#define SI1145_COMMAND_TIMEOUT_MS 25 + +/* Interrupt configuration masks for INT_CFG register */ +#define SI1145_INT_CFG_OE BIT(0) /* enable interrupt */ +#define SI1145_INT_CFG_MODE BIT(1) /* auto reset interrupt pin */ + +/* Interrupt enable masks for IRQ_ENABLE register */ +#define SI1145_MASK_ALL_IE (BIT(4) | BIT(3) | BIT(2) | BIT(0)) + +#define SI1145_MUX_TEMP 0x65 +#define SI1145_MUX_VDD 0x75 + +/* Proximity LED current; see Table 2 in datasheet */ +#define SI1145_LED_CURRENT_45mA 0x04 + +enum { + SI1132, + SI1141, + SI1142, + SI1143, + SI1145, + SI1146, + SI1147, +}; + +struct si1145_part_info { + u8 part; + const struct iio_info *iio_info; + const struct iio_chan_spec *channels; + unsigned int num_channels; + unsigned int num_leds; + bool uncompressed_meas_rate; +}; + +/** + * struct si1145_data - si1145 chip state data + * @client: I2C client + * @lock: mutex to protect shared state. + * @cmdlock: Low-level mutex to protect command execution only + * @rsp_seq: Next expected response number or -1 if counter reset required + * @scan_mask: Saved scan mask to avoid duplicate set_chlist + * @autonomous: If automatic measurements are active (for buffer support) + * @part_info: Part information + * @trig: Pointer to iio trigger + * @meas_rate: Value of MEAS_RATE register. Only set in HW in auto mode + */ +struct si1145_data { + struct i2c_client *client; + struct mutex lock; + struct mutex cmdlock; + int rsp_seq; + const struct si1145_part_info *part_info; + unsigned long scan_mask; + bool autonomous; + struct iio_trigger *trig; + int meas_rate; +}; + +/** + * __si1145_command_reset() - Send CMD_NOP and wait for response 0 + * + * Does not modify data->rsp_seq + * + * Return: 0 on success and -errno on error. + */ +static int __si1145_command_reset(struct si1145_data *data) +{ + struct device *dev = &data->client->dev; + unsigned long stop_jiffies; + int ret; + + ret = i2c_smbus_write_byte_data(data->client, SI1145_REG_COMMAND, + SI1145_CMD_NOP); + if (ret < 0) + return ret; + msleep(SI1145_COMMAND_MINSLEEP_MS); + + stop_jiffies = jiffies + SI1145_COMMAND_TIMEOUT_MS * HZ / 1000; + while (true) { + ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_RESPONSE); + if (ret <= 0) + return ret; + if (time_after(jiffies, stop_jiffies)) { + dev_warn(dev, "timeout on reset\n"); + return -ETIMEDOUT; + } + msleep(SI1145_COMMAND_MINSLEEP_MS); + continue; + } +} + +/** + * si1145_command() - Execute a command and poll the response register + * + * All conversion overflows are reported as -EOVERFLOW + * INVALID_SETTING is reported as -EINVAL + * Timeouts are reported as -ETIMEDOUT + * + * Return: 0 on success or -errno on failure + */ +static int si1145_command(struct si1145_data *data, u8 cmd) +{ + struct device *dev = &data->client->dev; + unsigned long stop_jiffies; + int ret; + + mutex_lock(&data->cmdlock); + + if (data->rsp_seq < 0) { + ret = __si1145_command_reset(data); + if (ret < 0) { + dev_err(dev, "failed to reset command counter, ret=%d\n", + ret); + goto out; + } + data->rsp_seq = 0; + } + + ret = i2c_smbus_write_byte_data(data->client, SI1145_REG_COMMAND, cmd); + if (ret) { + dev_warn(dev, "failed to write command, ret=%d\n", ret); + goto out; + } + /* Sleep a little to ensure the command is received */ + msleep(SI1145_COMMAND_MINSLEEP_MS); + + stop_jiffies = jiffies + SI1145_COMMAND_TIMEOUT_MS * HZ / 1000; + while (true) { + ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_RESPONSE); + if (ret < 0) { + dev_warn(dev, "failed to read response, ret=%d\n", ret); + break; + } + + if ((ret & ~SI1145_RSP_COUNTER_MASK) == 0) { + if (ret == data->rsp_seq) { + if (time_after(jiffies, stop_jiffies)) { + dev_warn(dev, "timeout on command %#02hhx\n", + cmd); + ret = -ETIMEDOUT; + break; + } + msleep(SI1145_COMMAND_MINSLEEP_MS); + continue; + } + if (ret == ((data->rsp_seq + 1) & + SI1145_RSP_COUNTER_MASK)) { + data->rsp_seq = ret; + ret = 0; + break; + } + dev_warn(dev, "unexpected response counter %d instead of %d\n", + ret, (data->rsp_seq + 1) & + SI1145_RSP_COUNTER_MASK); + ret = -EIO; + } else { + if (ret == SI1145_RSP_INVALID_SETTING) { + dev_warn(dev, "INVALID_SETTING error on command %#02hhx\n", + cmd); + ret = -EINVAL; + } else { + /* All overflows are treated identically */ + dev_dbg(dev, "overflow, ret=%d, cmd=%#02hhx\n", + ret, cmd); + ret = -EOVERFLOW; + } + } + + /* Force a counter reset next time */ + data->rsp_seq = -1; + break; + } + +out: + mutex_unlock(&data->cmdlock); + + return ret; +} + +static int si1145_param_update(struct si1145_data *data, u8 op, u8 param, + u8 value) +{ + int ret; + + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_PARAM_WR, value); + if (ret < 0) + return ret; + + return si1145_command(data, op | (param & 0x1F)); +} + +static int si1145_param_set(struct si1145_data *data, u8 param, u8 value) +{ + return si1145_param_update(data, SI1145_CMD_PARAM_SET, param, value); +} + +/* Set param. Returns negative errno or current value */ +static int si1145_param_query(struct si1145_data *data, u8 param) +{ + int ret; + + ret = si1145_command(data, SI1145_CMD_PARAM_QUERY | (param & 0x1F)); + if (ret < 0) + return ret; + + return i2c_smbus_read_byte_data(data->client, SI1145_REG_PARAM_RD); +} + +/* Expand 8 bit compressed value to 16 bit, see Silabs AN498 */ +static u16 si1145_uncompress(u8 x) +{ + u16 result = 0; + u8 exponent = 0; + + if (x < 8) + return 0; + + exponent = (x & 0xf0) >> 4; + result = 0x10 | (x & 0x0f); + + if (exponent >= 4) + return result << (exponent - 4); + return result >> (4 - exponent); +} + +/* Compress 16 bit value to 8 bit, see Silabs AN498 */ +static u8 si1145_compress(u16 x) +{ + u32 exponent = 0; + u32 significand = 0; + u32 tmp = x; + + if (x == 0x0000) + return 0x00; + if (x == 0x0001) + return 0x08; + + while (1) { + tmp >>= 1; + exponent += 1; + if (tmp == 1) + break; + } + + if (exponent < 5) { + significand = x << (4 - exponent); + return (exponent << 4) | (significand & 0xF); + } + + significand = x >> (exponent - 5); + if (significand & 1) { + significand += 2; + if (significand & 0x0040) { + exponent += 1; + significand >>= 1; + } + } + + return (exponent << 4) | ((significand >> 1) & 0xF); +} + +/* Write meas_rate in hardware */ +static int si1145_set_meas_rate(struct si1145_data *data, int interval) +{ + if (data->part_info->uncompressed_meas_rate) + return i2c_smbus_write_word_data(data->client, + SI1145_REG_MEAS_RATE, interval); + else + return i2c_smbus_write_byte_data(data->client, + SI1145_REG_MEAS_RATE, interval); +} + +static int si1145_read_samp_freq(struct si1145_data *data, int *val, int *val2) +{ + *val = 32000; + if (data->part_info->uncompressed_meas_rate) + *val2 = data->meas_rate; + else + *val2 = si1145_uncompress(data->meas_rate); + return IIO_VAL_FRACTIONAL; +} + +/* Set the samp freq in driver private data */ +static int si1145_store_samp_freq(struct si1145_data *data, int val) +{ + int ret = 0; + int meas_rate; + + if (val <= 0 || val > 32000) + return -ERANGE; + meas_rate = 32000 / val; + + mutex_lock(&data->lock); + if (data->autonomous) { + ret = si1145_set_meas_rate(data, meas_rate); + if (ret) + goto out; + } + if (data->part_info->uncompressed_meas_rate) + data->meas_rate = meas_rate; + else + data->meas_rate = si1145_compress(meas_rate); + +out: + mutex_unlock(&data->lock); + + return ret; +} + +static irqreturn_t si1145_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct si1145_data *data = iio_priv(indio_dev); + /* + * Maximum buffer size: + * 6*2 bytes channels data + 4 bytes alignment + + * 8 bytes timestamp + */ + u8 buffer[24]; + int i, j = 0; + int ret; + u8 irq_status = 0; + + if (!data->autonomous) { + ret = si1145_command(data, SI1145_CMD_PSALS_FORCE); + if (ret < 0 && ret != -EOVERFLOW) + goto done; + } else { + irq_status = ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_IRQ_STATUS); + if (ret < 0) + goto done; + if (!(irq_status & SI1145_MASK_ALL_IE)) + goto done; + } + + for_each_set_bit(i, indio_dev->active_scan_mask, + indio_dev->masklength) { + int run = 1; + + while (i + run < indio_dev->masklength) { + if (!test_bit(i + run, indio_dev->active_scan_mask)) + break; + if (indio_dev->channels[i + run].address != + indio_dev->channels[i].address + 2 * run) + break; + run++; + } + + ret = i2c_smbus_read_i2c_block_data_or_emulated( + data->client, indio_dev->channels[i].address, + sizeof(u16) * run, &buffer[j]); + if (ret < 0) + goto done; + j += run * sizeof(u16); + i += run - 1; + } + + if (data->autonomous) { + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_IRQ_STATUS, + irq_status & SI1145_MASK_ALL_IE); + if (ret < 0) + goto done; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + iio_get_time_ns(indio_dev)); + +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int si1145_set_chlist(struct iio_dev *indio_dev, unsigned long scan_mask) +{ + struct si1145_data *data = iio_priv(indio_dev); + u8 reg = 0, mux; + int ret; + int i; + + /* channel list already set, no need to reprogram */ + if (data->scan_mask == scan_mask) + return 0; + + for_each_set_bit(i, &scan_mask, indio_dev->masklength) { + switch (indio_dev->channels[i].address) { + case SI1145_REG_ALSVIS_DATA: + reg |= SI1145_CHLIST_EN_ALSVIS; + break; + case SI1145_REG_ALSIR_DATA: + reg |= SI1145_CHLIST_EN_ALSIR; + break; + case SI1145_REG_PS1_DATA: + reg |= SI1145_CHLIST_EN_PS1; + break; + case SI1145_REG_PS2_DATA: + reg |= SI1145_CHLIST_EN_PS2; + break; + case SI1145_REG_PS3_DATA: + reg |= SI1145_CHLIST_EN_PS3; + break; + case SI1145_REG_AUX_DATA: + switch (indio_dev->channels[i].type) { + case IIO_UVINDEX: + reg |= SI1145_CHLIST_EN_UV; + break; + default: + reg |= SI1145_CHLIST_EN_AUX; + if (indio_dev->channels[i].type == IIO_TEMP) + mux = SI1145_MUX_TEMP; + else + mux = SI1145_MUX_VDD; + ret = si1145_param_set(data, + SI1145_PARAM_AUX_ADC_MUX, mux); + if (ret < 0) + return ret; + + break; + } + } + } + + data->scan_mask = scan_mask; + ret = si1145_param_set(data, SI1145_PARAM_CHLIST, reg); + + return ret < 0 ? ret : 0; +} + +static int si1145_measure(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct si1145_data *data = iio_priv(indio_dev); + u8 cmd; + int ret; + + ret = si1145_set_chlist(indio_dev, BIT(chan->scan_index)); + if (ret < 0) + return ret; + + cmd = (chan->type == IIO_PROXIMITY) ? SI1145_CMD_PS_FORCE : + SI1145_CMD_ALS_FORCE; + ret = si1145_command(data, cmd); + if (ret < 0 && ret != -EOVERFLOW) + return ret; + + return i2c_smbus_read_word_data(data->client, chan->address); +} + +/* + * Conversion between iio scale and ADC_GAIN values + * These could be further adjusted but proximity/intensity are dimensionless + */ +static const int si1145_proximity_scale_available[] = { + 128, 64, 32, 16, 8, 4}; +static const int si1145_intensity_scale_available[] = { + 128, 64, 32, 16, 8, 4, 2, 1}; +static IIO_CONST_ATTR(in_proximity_scale_available, + "128 64 32 16 8 4"); +static IIO_CONST_ATTR(in_intensity_scale_available, + "128 64 32 16 8 4 2 1"); +static IIO_CONST_ATTR(in_intensity_ir_scale_available, + "128 64 32 16 8 4 2 1"); + +static int si1145_scale_from_adcgain(int regval) +{ + return 128 >> regval; +} + +static int si1145_proximity_adcgain_from_scale(int val, int val2) +{ + val = find_closest_descending(val, si1145_proximity_scale_available, + ARRAY_SIZE(si1145_proximity_scale_available)); + if (val < 0 || val > 5 || val2 != 0) + return -EINVAL; + + return val; +} + +static int si1145_intensity_adcgain_from_scale(int val, int val2) +{ + val = find_closest_descending(val, si1145_intensity_scale_available, + ARRAY_SIZE(si1145_intensity_scale_available)); + if (val < 0 || val > 7 || val2 != 0) + return -EINVAL; + + return val; +} + +static int si1145_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct si1145_data *data = iio_priv(indio_dev); + int ret; + u8 reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_INTENSITY: + case IIO_PROXIMITY: + case IIO_VOLTAGE: + case IIO_TEMP: + case IIO_UVINDEX: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = si1145_measure(indio_dev, chan); + iio_device_release_direct_mode(indio_dev); + + if (ret < 0) + return ret; + + *val = ret; + + return IIO_VAL_INT; + case IIO_CURRENT: + ret = i2c_smbus_read_byte_data(data->client, + SI1145_PS_LED_REG(chan->channel)); + if (ret < 0) + return ret; + + *val = (ret >> SI1145_PS_LED_SHIFT(chan->channel)) + & 0x0f; + + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_PROXIMITY: + reg = SI1145_PARAM_PS_ADC_GAIN; + break; + case IIO_INTENSITY: + if (chan->channel2 == IIO_MOD_LIGHT_IR) + reg = SI1145_PARAM_ALSIR_ADC_GAIN; + else + reg = SI1145_PARAM_ALSVIS_ADC_GAIN; + break; + case IIO_TEMP: + *val = 28; + *val2 = 571429; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_UVINDEX: + *val = 0; + *val2 = 10000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + + ret = si1145_param_query(data, reg); + if (ret < 0) + return ret; + + *val = si1145_scale_from_adcgain(ret & 0x07); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + /* + * -ADC offset - ADC counts @ 25°C - + * 35 * ADC counts / °C + */ + *val = -256 - 11136 + 25 * 35; + return IIO_VAL_INT; + default: + /* + * All ADC measurements have are by default offset + * by -256 + * See AN498 5.6.3 + */ + ret = si1145_param_query(data, SI1145_PARAM_ADC_OFFSET); + if (ret < 0) + return ret; + *val = -si1145_uncompress(ret); + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_SAMP_FREQ: + return si1145_read_samp_freq(data, val, val2); + default: + return -EINVAL; + } +} + +static int si1145_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct si1145_data *data = iio_priv(indio_dev); + u8 reg1, reg2, shift; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_PROXIMITY: + val = si1145_proximity_adcgain_from_scale(val, val2); + if (val < 0) + return val; + reg1 = SI1145_PARAM_PS_ADC_GAIN; + reg2 = SI1145_PARAM_PS_ADC_COUNTER; + break; + case IIO_INTENSITY: + val = si1145_intensity_adcgain_from_scale(val, val2); + if (val < 0) + return val; + if (chan->channel2 == IIO_MOD_LIGHT_IR) { + reg1 = SI1145_PARAM_ALSIR_ADC_GAIN; + reg2 = SI1145_PARAM_ALSIR_ADC_COUNTER; + } else { + reg1 = SI1145_PARAM_ALSVIS_ADC_GAIN; + reg2 = SI1145_PARAM_ALSVIS_ADC_COUNTER; + } + break; + default: + return -EINVAL; + } + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = si1145_param_set(data, reg1, val); + if (ret < 0) { + iio_device_release_direct_mode(indio_dev); + return ret; + } + /* Set recovery period to one's complement of gain */ + ret = si1145_param_set(data, reg2, (~val & 0x07) << 4); + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_RAW: + if (chan->type != IIO_CURRENT) + return -EINVAL; + + if (val < 0 || val > 15 || val2 != 0) + return -EINVAL; + + reg1 = SI1145_PS_LED_REG(chan->channel); + shift = SI1145_PS_LED_SHIFT(chan->channel); + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, reg1); + if (ret < 0) { + iio_device_release_direct_mode(indio_dev); + return ret; + } + ret = i2c_smbus_write_byte_data(data->client, reg1, + (ret & ~(0x0f << shift)) | + ((val & 0x0f) << shift)); + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return si1145_store_samp_freq(data, val); + default: + return -EINVAL; + } +} + +#define SI1145_ST { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ +} + +#define SI1145_INTENSITY_CHANNEL(_si) { \ + .type = IIO_INTENSITY, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_ALSVIS_DATA, \ +} + +#define SI1145_INTENSITY_IR_CHANNEL(_si) { \ + .type = IIO_INTENSITY, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .modified = 1, \ + .channel2 = IIO_MOD_LIGHT_IR, \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_ALSIR_DATA, \ +} + +#define SI1145_TEMP_CHANNEL(_si) { \ + .type = IIO_TEMP, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_AUX_DATA, \ +} + +#define SI1145_UV_CHANNEL(_si) { \ + .type = IIO_UVINDEX, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_AUX_DATA, \ +} + +#define SI1145_PROXIMITY_CHANNEL(_si, _ch) { \ + .type = IIO_PROXIMITY, \ + .indexed = 1, \ + .channel = _ch, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_PS1_DATA + _ch * 2, \ +} + +#define SI1145_VOLTAGE_CHANNEL(_si) { \ + .type = IIO_VOLTAGE, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_AUX_DATA, \ +} + +#define SI1145_CURRENT_CHANNEL(_ch) { \ + .type = IIO_CURRENT, \ + .indexed = 1, \ + .channel = _ch, \ + .output = 1, \ + .scan_index = -1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +} + +static const struct iio_chan_spec si1132_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_TEMP_CHANNEL(2), + SI1145_VOLTAGE_CHANNEL(3), + SI1145_UV_CHANNEL(4), + IIO_CHAN_SOFT_TIMESTAMP(6), +}; + +static const struct iio_chan_spec si1141_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_TEMP_CHANNEL(3), + SI1145_VOLTAGE_CHANNEL(4), + IIO_CHAN_SOFT_TIMESTAMP(5), + SI1145_CURRENT_CHANNEL(0), +}; + +static const struct iio_chan_spec si1142_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_PROXIMITY_CHANNEL(3, 1), + SI1145_TEMP_CHANNEL(4), + SI1145_VOLTAGE_CHANNEL(5), + IIO_CHAN_SOFT_TIMESTAMP(6), + SI1145_CURRENT_CHANNEL(0), + SI1145_CURRENT_CHANNEL(1), +}; + +static const struct iio_chan_spec si1143_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_PROXIMITY_CHANNEL(3, 1), + SI1145_PROXIMITY_CHANNEL(4, 2), + SI1145_TEMP_CHANNEL(5), + SI1145_VOLTAGE_CHANNEL(6), + IIO_CHAN_SOFT_TIMESTAMP(7), + SI1145_CURRENT_CHANNEL(0), + SI1145_CURRENT_CHANNEL(1), + SI1145_CURRENT_CHANNEL(2), +}; + +static const struct iio_chan_spec si1145_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_TEMP_CHANNEL(3), + SI1145_VOLTAGE_CHANNEL(4), + SI1145_UV_CHANNEL(5), + IIO_CHAN_SOFT_TIMESTAMP(6), + SI1145_CURRENT_CHANNEL(0), +}; + +static const struct iio_chan_spec si1146_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_TEMP_CHANNEL(2), + SI1145_VOLTAGE_CHANNEL(3), + SI1145_UV_CHANNEL(4), + SI1145_PROXIMITY_CHANNEL(5, 0), + SI1145_PROXIMITY_CHANNEL(6, 1), + IIO_CHAN_SOFT_TIMESTAMP(7), + SI1145_CURRENT_CHANNEL(0), + SI1145_CURRENT_CHANNEL(1), +}; + +static const struct iio_chan_spec si1147_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_PROXIMITY_CHANNEL(3, 1), + SI1145_PROXIMITY_CHANNEL(4, 2), + SI1145_TEMP_CHANNEL(5), + SI1145_VOLTAGE_CHANNEL(6), + SI1145_UV_CHANNEL(7), + IIO_CHAN_SOFT_TIMESTAMP(8), + SI1145_CURRENT_CHANNEL(0), + SI1145_CURRENT_CHANNEL(1), + SI1145_CURRENT_CHANNEL(2), +}; + +static struct attribute *si1132_attributes[] = { + &iio_const_attr_in_intensity_scale_available.dev_attr.attr, + &iio_const_attr_in_intensity_ir_scale_available.dev_attr.attr, + NULL, +}; + +static struct attribute *si114x_attributes[] = { + &iio_const_attr_in_intensity_scale_available.dev_attr.attr, + &iio_const_attr_in_intensity_ir_scale_available.dev_attr.attr, + &iio_const_attr_in_proximity_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group si1132_attribute_group = { + .attrs = si1132_attributes, +}; + +static const struct attribute_group si114x_attribute_group = { + .attrs = si114x_attributes, +}; + + +static const struct iio_info si1132_info = { + .read_raw = si1145_read_raw, + .write_raw = si1145_write_raw, + .driver_module = THIS_MODULE, + .attrs = &si1132_attribute_group, +}; + +static const struct iio_info si114x_info = { + .read_raw = si1145_read_raw, + .write_raw = si1145_write_raw, + .driver_module = THIS_MODULE, + .attrs = &si114x_attribute_group, +}; + +#define SI1145_PART(id, iio_info, chans, leds, uncompressed_meas_rate) \ + {id, iio_info, chans, ARRAY_SIZE(chans), leds, uncompressed_meas_rate} + +static const struct si1145_part_info si1145_part_info[] = { + [SI1132] = SI1145_PART(0x32, &si1132_info, si1132_channels, 0, true), + [SI1141] = SI1145_PART(0x41, &si114x_info, si1141_channels, 1, false), + [SI1142] = SI1145_PART(0x42, &si114x_info, si1142_channels, 2, false), + [SI1143] = SI1145_PART(0x43, &si114x_info, si1143_channels, 3, false), + [SI1145] = SI1145_PART(0x45, &si114x_info, si1145_channels, 1, true), + [SI1146] = SI1145_PART(0x46, &si114x_info, si1146_channels, 2, true), + [SI1147] = SI1145_PART(0x47, &si114x_info, si1147_channels, 3, true), +}; + +static int si1145_initialize(struct si1145_data *data) +{ + struct i2c_client *client = data->client; + int ret; + + ret = i2c_smbus_write_byte_data(client, SI1145_REG_COMMAND, + SI1145_CMD_RESET); + if (ret < 0) + return ret; + msleep(SI1145_COMMAND_TIMEOUT_MS); + + /* Hardware key, magic value */ + ret = i2c_smbus_write_byte_data(client, SI1145_REG_HW_KEY, 0x17); + if (ret < 0) + return ret; + msleep(SI1145_COMMAND_TIMEOUT_MS); + + /* Turn off autonomous mode */ + ret = si1145_set_meas_rate(data, 0); + if (ret < 0) + return ret; + + /* Initialize sampling freq to 10 Hz */ + ret = si1145_store_samp_freq(data, 10); + if (ret < 0) + return ret; + + /* Set LED currents to 45 mA; have 4 bits, see Table 2 in datasheet */ + switch (data->part_info->num_leds) { + case 3: + ret = i2c_smbus_write_byte_data(client, + SI1145_REG_PS_LED3, + SI1145_LED_CURRENT_45mA); + if (ret < 0) + return ret; + /* fallthrough */ + case 2: + ret = i2c_smbus_write_byte_data(client, + SI1145_REG_PS_LED21, + (SI1145_LED_CURRENT_45mA << 4) | + SI1145_LED_CURRENT_45mA); + break; + case 1: + ret = i2c_smbus_write_byte_data(client, + SI1145_REG_PS_LED21, + SI1145_LED_CURRENT_45mA); + break; + default: + ret = 0; + break; + } + if (ret < 0) + return ret; + + /* Set normal proximity measurement mode */ + ret = si1145_param_set(data, SI1145_PARAM_PS_ADC_MISC, + SI1145_PS_ADC_MODE_NORMAL); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_PS_ADC_GAIN, 0x01); + if (ret < 0) + return ret; + + /* ADC_COUNTER should be one complement of ADC_GAIN */ + ret = si1145_param_set(data, SI1145_PARAM_PS_ADC_COUNTER, 0x06 << 4); + if (ret < 0) + return ret; + + /* Set ALS visible measurement mode */ + ret = si1145_param_set(data, SI1145_PARAM_ALSVIS_ADC_MISC, + SI1145_ADC_MISC_RANGE); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_ALSVIS_ADC_GAIN, 0x03); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_ALSVIS_ADC_COUNTER, + 0x04 << 4); + if (ret < 0) + return ret; + + /* Set ALS IR measurement mode */ + ret = si1145_param_set(data, SI1145_PARAM_ALSIR_ADC_MISC, + SI1145_ADC_MISC_RANGE); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_ALSIR_ADC_GAIN, 0x01); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_ALSIR_ADC_COUNTER, + 0x06 << 4); + if (ret < 0) + return ret; + + /* + * Initialize UCOEF to default values in datasheet + * These registers are normally zero on reset + */ + if (data->part_info == &si1145_part_info[SI1132] || + data->part_info == &si1145_part_info[SI1145] || + data->part_info == &si1145_part_info[SI1146] || + data->part_info == &si1145_part_info[SI1147]) { + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_UCOEF1, + SI1145_UCOEF1_DEFAULT); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_UCOEF2, SI1145_UCOEF2_DEFAULT); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_UCOEF3, SI1145_UCOEF3_DEFAULT); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_UCOEF4, SI1145_UCOEF4_DEFAULT); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + * Program the channels we want to measure with CMD_PSALS_AUTO. No need for + * _postdisable as we stop with CMD_PSALS_PAUSE; single measurement (direct) + * mode reprograms the channels list anyway... + */ +static int si1145_buffer_preenable(struct iio_dev *indio_dev) +{ + struct si1145_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = si1145_set_chlist(indio_dev, *indio_dev->active_scan_mask); + mutex_unlock(&data->lock); + + return ret; +} + +static bool si1145_validate_scan_mask(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct si1145_data *data = iio_priv(indio_dev); + unsigned int count = 0; + int i; + + /* Check that at most one AUX channel is enabled */ + for_each_set_bit(i, scan_mask, data->part_info->num_channels) { + if (indio_dev->channels[i].address == SI1145_REG_AUX_DATA) + count++; + } + + return count <= 1; +} + +static const struct iio_buffer_setup_ops si1145_buffer_setup_ops = { + .preenable = si1145_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .validate_scan_mask = si1145_validate_scan_mask, +}; + +/** + * si1145_trigger_set_state() - Set trigger state + * + * When not using triggers interrupts are disabled and measurement rate is + * set to zero in order to minimize power consumption. + */ +static int si1145_trigger_set_state(struct iio_trigger *trig, bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct si1145_data *data = iio_priv(indio_dev); + int err = 0, ret; + + mutex_lock(&data->lock); + + if (state) { + data->autonomous = true; + err = i2c_smbus_write_byte_data(data->client, + SI1145_REG_INT_CFG, SI1145_INT_CFG_OE); + if (err < 0) + goto disable; + err = i2c_smbus_write_byte_data(data->client, + SI1145_REG_IRQ_ENABLE, SI1145_MASK_ALL_IE); + if (err < 0) + goto disable; + err = si1145_set_meas_rate(data, data->meas_rate); + if (err < 0) + goto disable; + err = si1145_command(data, SI1145_CMD_PSALS_AUTO); + if (err < 0) + goto disable; + } else { +disable: + /* Disable as much as possible skipping errors */ + ret = si1145_command(data, SI1145_CMD_PSALS_PAUSE); + if (ret < 0 && !err) + err = ret; + ret = si1145_set_meas_rate(data, 0); + if (ret < 0 && !err) + err = ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_IRQ_ENABLE, 0); + if (ret < 0 && !err) + err = ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_INT_CFG, 0); + if (ret < 0 && !err) + err = ret; + data->autonomous = false; + } + + mutex_unlock(&data->lock); + return err; +} + +static const struct iio_trigger_ops si1145_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = si1145_trigger_set_state, +}; + +static int si1145_probe_trigger(struct iio_dev *indio_dev) +{ + struct si1145_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + struct iio_trigger *trig; + int ret; + + trig = devm_iio_trigger_alloc(&client->dev, + "%s-dev%d", indio_dev->name, indio_dev->id); + if (!trig) + return -ENOMEM; + + trig->dev.parent = &client->dev; + trig->ops = &si1145_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + + ret = devm_request_irq(&client->dev, client->irq, + iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_FALLING, + "si1145_irq", + trig); + if (ret < 0) { + dev_err(&client->dev, "irq request failed\n"); + return ret; + } + + ret = iio_trigger_register(trig); + if (ret) + return ret; + + data->trig = trig; + indio_dev->trig = iio_trigger_get(data->trig); + + 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) +{ + struct si1145_data *data; + struct iio_dev *indio_dev; + u8 part_id, rev_id, seq_id; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + data->part_info = &si1145_part_info[id->driver_data]; + + part_id = ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_PART_ID); + if (ret < 0) + return ret; + rev_id = ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_REV_ID); + if (ret < 0) + return ret; + seq_id = ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_SEQ_ID); + if (ret < 0) + return ret; + dev_info(&client->dev, "device ID part %#02hhx rev %#02hhx seq %#02hhx\n", + part_id, rev_id, seq_id); + if (part_id != data->part_info->part) { + dev_err(&client->dev, "part ID mismatch got %#02hhx, expected %#02x\n", + part_id, data->part_info->part); + return -ENODEV; + } + + indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; + indio_dev->channels = data->part_info->channels; + indio_dev->num_channels = data->part_info->num_channels; + indio_dev->info = data->part_info->iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + mutex_init(&data->lock); + mutex_init(&data->cmdlock); + + ret = si1145_initialize(data); + if (ret < 0) + return ret; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + si1145_trigger_handler, &si1145_buffer_setup_ops); + if (ret < 0) + return ret; + + if (client->irq) { + ret = si1145_probe_trigger(indio_dev); + if (ret < 0) + goto error_free_buffer; + } 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; +} + +static const struct i2c_device_id si1145_ids[] = { + { "si1132", SI1132 }, + { "si1141", SI1141 }, + { "si1142", SI1142 }, + { "si1143", SI1143 }, + { "si1145", SI1145 }, + { "si1146", SI1146 }, + { "si1147", SI1147 }, + { } +}; +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, +}; + +module_i2c_driver(si1145_driver); + +MODULE_AUTHOR("Peter Meerwald-Stadler "); +MODULE_DESCRIPTION("Silabs SI1132 and SI1141/2/3/5/6/7 proximity, ambient light and UV index sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index 20c40f780964..18cf2e29e4d5 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c @@ -894,7 +894,7 @@ static int us5182d_probe(struct i2c_client *client, goto out_err; if (data->default_continuous) { - pm_runtime_set_active(&client->dev); + ret = pm_runtime_set_active(&client->dev); if (ret < 0) goto out_err; } diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index c9d85bbc9230..360b6e98137a 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -1,6 +1,6 @@ /* - * vcnl4000.c - Support for Vishay VCNL4000 combined ambient light and - * proximity sensor + * vcnl4000.c - Support for Vishay VCNL4000/4010/4020 combined ambient + * light and proximity sensor * * Copyright 2012 Peter Meerwald * @@ -13,6 +13,8 @@ * TODO: * allow to adjust IR current * proximity threshold and event handling + * periodic ALS/proximity measurement (VCNL4010/20) + * interrupts (VCNL4010/20) */ #include @@ -24,6 +26,8 @@ #include #define VCNL4000_DRV_NAME "vcnl4000" +#define VCNL4000_ID 0x01 +#define VCNL4010_ID 0x02 /* for VCNL4020, VCNL4010 */ #define VCNL4000_COMMAND 0x80 /* Command register */ #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ @@ -37,13 +41,14 @@ #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */ /* Bit masks for COMMAND register */ -#define VCNL4000_AL_RDY 0x40 /* ALS data ready? */ -#define VCNL4000_PS_RDY 0x20 /* proximity data ready? */ -#define VCNL4000_AL_OD 0x10 /* start on-demand ALS measurement */ -#define VCNL4000_PS_OD 0x08 /* start on-demand proximity measurement */ +#define VCNL4000_AL_RDY BIT(6) /* ALS data ready? */ +#define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */ +#define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ +#define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ struct vcnl4000_data { struct i2c_client *client; + struct mutex lock; }; static const struct i2c_device_id vcnl4000_id[] = { @@ -59,16 +64,18 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, __be16 buf; int ret; + mutex_lock(&data->lock); + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, req_mask); if (ret < 0) - return ret; + goto fail; /* wait for data to become ready */ while (tries--) { ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); if (ret < 0) - return ret; + goto fail; if (ret & rdy_mask) break; msleep(20); /* measurement takes up to 100 ms */ @@ -77,17 +84,23 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, if (tries < 0) { dev_err(&data->client->dev, "vcnl4000_measure() failed, data not ready\n"); - return -EIO; + ret = -EIO; + goto fail; } ret = i2c_smbus_read_i2c_block_data(data->client, data_reg, sizeof(buf), (u8 *) &buf); if (ret < 0) - return ret; + goto fail; + mutex_unlock(&data->lock); *val = be16_to_cpu(buf); return 0; + +fail: + mutex_unlock(&data->lock); + return ret; } static const struct iio_chan_spec vcnl4000_channels[] = { @@ -105,7 +118,7 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - int ret = -EINVAL; + int ret; struct vcnl4000_data *data = iio_priv(indio_dev); switch (mask) { @@ -117,32 +130,27 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, VCNL4000_AL_RESULT_HI, val); if (ret < 0) return ret; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_PROXIMITY: ret = vcnl4000_measure(data, VCNL4000_PS_OD, VCNL4000_PS_RDY, VCNL4000_PS_RESULT_HI, val); if (ret < 0) return ret; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: - break; + return -EINVAL; } - break; case IIO_CHAN_INFO_SCALE: - if (chan->type == IIO_LIGHT) { - *val = 0; - *val2 = 250000; - ret = IIO_VAL_INT_PLUS_MICRO; - } - break; - default: - break; - } + if (chan->type != IIO_LIGHT) + return -EINVAL; - return ret; + *val = 0; + *val2 = 250000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } } static const struct iio_info vcnl4000_info = { @@ -155,7 +163,7 @@ static int vcnl4000_probe(struct i2c_client *client, { struct vcnl4000_data *data; struct iio_dev *indio_dev; - int ret; + int ret, prod_id; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -164,13 +172,19 @@ static int vcnl4000_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; + mutex_init(&data->lock); ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); if (ret < 0) return ret; - dev_info(&client->dev, "VCNL4000 Ambient light/proximity sensor, Prod %02x, Rev: %02x\n", - ret >> 4, ret & 0xf); + prod_id = ret >> 4; + if (prod_id != VCNL4010_ID && prod_id != VCNL4000_ID) + return -ENODEV; + + dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n", + (prod_id == VCNL4010_ID) ? "VCNL4010/4020" : "VCNL4000", + ret & 0xf); indio_dev->dev.parent = &client->dev; indio_dev->info = &vcnl4000_info; diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 1f842abcb4a4..421ad90a5fbe 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -5,8 +5,22 @@ menu "Magnetometer sensors" +config AK8974 + tristate "Asahi Kasei AK8974 3-Axis Magnetometer" + depends on I2C + depends on OF + select REGMAP_I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Asahi Kasei AK8974 or + AMI305 I2C-based 3-axis magnetometer chips. + + To compile this driver as a module, choose M here: the module + will be called ak8974. + config AK8975 - tristate "Asahi Kasei AK 3-Axis Magnetometer" + tristate "Asahi Kasei AK8975 3-Axis Magnetometer" depends on I2C depends on GPIOLIB || COMPILE_TEST select IIO_BUFFER diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index 92a745c9a6e8..b86d6cb7f285 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AK8974) += ak8974.o obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c new file mode 100644 index 000000000000..217353145676 --- /dev/null +++ b/drivers/iio/magnetometer/ak8974.c @@ -0,0 +1,860 @@ +/* + * Driver for the Asahi Kasei EMD Corporation AK8974 + * and Aichi Steel AMI305 magnetometer chips. + * Based on a patch from Samu Onkalo and the AK8975 IIO driver. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (c) 2010 NVIDIA Corporation. + * Copyright (C) 2016 Linaro Ltd. + * + * Author: Samu Onkalo + * Author: Linus Walleij + */ +#include +#include +#include +#include +#include /* For irq_get_irq_data() */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * 16-bit registers are little-endian. LSB is at the address defined below + * and MSB is at the next higher address. + */ + +/* These registers are common for AK8974 and AMI305 */ +#define AK8974_SELFTEST 0x0C +#define AK8974_SELFTEST_IDLE 0x55 +#define AK8974_SELFTEST_OK 0xAA + +#define AK8974_INFO 0x0D + +#define AK8974_WHOAMI 0x0F +#define AK8974_WHOAMI_VALUE_AMI305 0x47 +#define AK8974_WHOAMI_VALUE_AK8974 0x48 + +#define AK8974_DATA_X 0x10 +#define AK8974_DATA_Y 0x12 +#define AK8974_DATA_Z 0x14 +#define AK8974_INT_SRC 0x16 +#define AK8974_STATUS 0x18 +#define AK8974_INT_CLEAR 0x1A +#define AK8974_CTRL1 0x1B +#define AK8974_CTRL2 0x1C +#define AK8974_CTRL3 0x1D +#define AK8974_INT_CTRL 0x1E +#define AK8974_INT_THRES 0x26 /* Absolute any axis value threshold */ +#define AK8974_PRESET 0x30 + +/* AK8974-specific offsets */ +#define AK8974_OFFSET_X 0x20 +#define AK8974_OFFSET_Y 0x22 +#define AK8974_OFFSET_Z 0x24 +/* AMI305-specific offsets */ +#define AMI305_OFFSET_X 0x6C +#define AMI305_OFFSET_Y 0x72 +#define AMI305_OFFSET_Z 0x78 + +/* Different temperature registers */ +#define AK8974_TEMP 0x31 +#define AMI305_TEMP 0x60 + +#define AK8974_INT_X_HIGH BIT(7) /* Axis over +threshold */ +#define AK8974_INT_Y_HIGH BIT(6) +#define AK8974_INT_Z_HIGH BIT(5) +#define AK8974_INT_X_LOW BIT(4) /* Axis below -threshold */ +#define AK8974_INT_Y_LOW BIT(3) +#define AK8974_INT_Z_LOW BIT(2) +#define AK8974_INT_RANGE BIT(1) /* Range overflow (any axis) */ + +#define AK8974_STATUS_DRDY BIT(6) /* Data ready */ +#define AK8974_STATUS_OVERRUN BIT(5) /* Data overrun */ +#define AK8974_STATUS_INT BIT(4) /* Interrupt occurred */ + +#define AK8974_CTRL1_POWER BIT(7) /* 0 = standby; 1 = active */ +#define AK8974_CTRL1_RATE BIT(4) /* 0 = 10 Hz; 1 = 20 Hz */ +#define AK8974_CTRL1_FORCE_EN BIT(1) /* 0 = normal; 1 = force */ +#define AK8974_CTRL1_MODE2 BIT(0) /* 0 */ + +#define AK8974_CTRL2_INT_EN BIT(4) /* 1 = enable interrupts */ +#define AK8974_CTRL2_DRDY_EN BIT(3) /* 1 = enable data ready signal */ +#define AK8974_CTRL2_DRDY_POL BIT(2) /* 1 = data ready active high */ +#define AK8974_CTRL2_RESDEF (AK8974_CTRL2_DRDY_POL) + +#define AK8974_CTRL3_RESET BIT(7) /* Software reset */ +#define AK8974_CTRL3_FORCE BIT(6) /* Start forced measurement */ +#define AK8974_CTRL3_SELFTEST BIT(4) /* Set selftest register */ +#define AK8974_CTRL3_RESDEF 0x00 + +#define AK8974_INT_CTRL_XEN BIT(7) /* Enable interrupt for this axis */ +#define AK8974_INT_CTRL_YEN BIT(6) +#define AK8974_INT_CTRL_ZEN BIT(5) +#define AK8974_INT_CTRL_XYZEN (BIT(7)|BIT(6)|BIT(5)) +#define AK8974_INT_CTRL_POL BIT(3) /* 0 = active low; 1 = active high */ +#define AK8974_INT_CTRL_PULSE BIT(1) /* 0 = latched; 1 = pulse (50 usec) */ +#define AK8974_INT_CTRL_RESDEF (AK8974_INT_CTRL_XYZEN | AK8974_INT_CTRL_POL) + +/* The AMI305 has elaborate FW version and serial number registers */ +#define AMI305_VER 0xE8 +#define AMI305_SN 0xEA + +#define AK8974_MAX_RANGE 2048 + +#define AK8974_POWERON_DELAY 50 +#define AK8974_ACTIVATE_DELAY 1 +#define AK8974_SELFTEST_DELAY 1 +/* + * Set the autosuspend to two orders of magnitude larger than the poweron + * delay to make sane reasonable power tradeoff savings (5 seconds in + * this case). + */ +#define AK8974_AUTOSUSPEND_DELAY 5000 + +#define AK8974_MEASTIME 3 + +#define AK8974_PWR_ON 1 +#define AK8974_PWR_OFF 0 + +/** + * struct ak8974 - state container for the AK8974 driver + * @i2c: parent I2C client + * @orientation: mounting matrix, flipped axis etc + * @map: regmap to access the AK8974 registers over I2C + * @regs: the avdd and dvdd power regulators + * @name: the name of the part + * @variant: the whoami ID value (for selecting code paths) + * @lock: locks the magnetometer for exclusive use during a measurement + * @drdy_irq: uses the DRDY IRQ line + * @drdy_complete: completion for DRDY + * @drdy_active_low: the DRDY IRQ is active low + */ +struct ak8974 { + struct i2c_client *i2c; + struct iio_mount_matrix orientation; + struct regmap *map; + struct regulator_bulk_data regs[2]; + const char *name; + u8 variant; + struct mutex lock; + bool drdy_irq; + struct completion drdy_complete; + bool drdy_active_low; +}; + +static const char ak8974_reg_avdd[] = "avdd"; +static const char ak8974_reg_dvdd[] = "dvdd"; + +static int ak8974_set_power(struct ak8974 *ak8974, bool mode) +{ + int ret; + u8 val; + + val = mode ? AK8974_CTRL1_POWER : 0; + val |= AK8974_CTRL1_FORCE_EN; + ret = regmap_write(ak8974->map, AK8974_CTRL1, val); + if (ret < 0) + return ret; + + if (mode) + msleep(AK8974_ACTIVATE_DELAY); + + return 0; +} + +static int ak8974_reset(struct ak8974 *ak8974) +{ + int ret; + + /* Power on to get register access. Sets CTRL1 reg to reset state */ + ret = ak8974_set_power(ak8974, AK8974_PWR_ON); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_CTRL2, AK8974_CTRL2_RESDEF); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_RESDEF); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_INT_CTRL, + AK8974_INT_CTRL_RESDEF); + if (ret) + return ret; + + /* After reset, power off is default state */ + return ak8974_set_power(ak8974, AK8974_PWR_OFF); +} + +static int ak8974_configure(struct ak8974 *ak8974) +{ + int ret; + + ret = regmap_write(ak8974->map, AK8974_CTRL2, AK8974_CTRL2_DRDY_EN | + AK8974_CTRL2_INT_EN); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_CTRL3, 0); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_INT_CTRL, AK8974_INT_CTRL_POL); + if (ret) + return ret; + + return regmap_write(ak8974->map, AK8974_PRESET, 0); +} + +static int ak8974_trigmeas(struct ak8974 *ak8974) +{ + unsigned int clear; + u8 mask; + u8 val; + int ret; + + /* Clear any previous measurement overflow status */ + ret = regmap_read(ak8974->map, AK8974_INT_CLEAR, &clear); + if (ret) + return ret; + + /* If we have a DRDY IRQ line, use it */ + if (ak8974->drdy_irq) { + mask = AK8974_CTRL2_INT_EN | + AK8974_CTRL2_DRDY_EN | + AK8974_CTRL2_DRDY_POL; + val = AK8974_CTRL2_DRDY_EN; + + if (!ak8974->drdy_active_low) + val |= AK8974_CTRL2_DRDY_POL; + + init_completion(&ak8974->drdy_complete); + ret = regmap_update_bits(ak8974->map, AK8974_CTRL2, + mask, val); + if (ret) + return ret; + } + + /* Force a measurement */ + return regmap_update_bits(ak8974->map, + AK8974_CTRL3, + AK8974_CTRL3_FORCE, + AK8974_CTRL3_FORCE); +} + +static int ak8974_await_drdy(struct ak8974 *ak8974) +{ + int timeout = 2; + unsigned int val; + int ret; + + if (ak8974->drdy_irq) { + ret = wait_for_completion_timeout(&ak8974->drdy_complete, + 1 + msecs_to_jiffies(1000)); + if (!ret) { + dev_err(&ak8974->i2c->dev, + "timeout waiting for DRDY IRQ\n"); + return -ETIMEDOUT; + } + return 0; + } + + /* Default delay-based poll loop */ + do { + msleep(AK8974_MEASTIME); + ret = regmap_read(ak8974->map, AK8974_STATUS, &val); + if (ret < 0) + return ret; + if (val & AK8974_STATUS_DRDY) + return 0; + } while (--timeout); + if (!timeout) { + dev_err(&ak8974->i2c->dev, + "timeout waiting for DRDY\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int ak8974_getresult(struct ak8974 *ak8974, s16 *result) +{ + unsigned int src; + int ret; + + ret = ak8974_await_drdy(ak8974); + if (ret) + return ret; + ret = regmap_read(ak8974->map, AK8974_INT_SRC, &src); + if (ret < 0) + return ret; + + /* Out of range overflow! Strong magnet close? */ + if (src & AK8974_INT_RANGE) { + dev_err(&ak8974->i2c->dev, + "range overflow in sensor\n"); + return -ERANGE; + } + + ret = regmap_bulk_read(ak8974->map, AK8974_DATA_X, result, 6); + if (ret) + return ret; + + return ret; +} + +static irqreturn_t ak8974_drdy_irq(int irq, void *d) +{ + struct ak8974 *ak8974 = d; + + if (!ak8974->drdy_irq) + return IRQ_NONE; + + /* TODO: timestamp here to get good measurement stamps */ + return IRQ_WAKE_THREAD; +} + +static irqreturn_t ak8974_drdy_irq_thread(int irq, void *d) +{ + struct ak8974 *ak8974 = d; + unsigned int val; + int ret; + + /* Check if this was a DRDY from us */ + ret = regmap_read(ak8974->map, AK8974_STATUS, &val); + if (ret < 0) { + dev_err(&ak8974->i2c->dev, "error reading DRDY status\n"); + return IRQ_HANDLED; + } + if (val & AK8974_STATUS_DRDY) { + /* Yes this was our IRQ */ + complete(&ak8974->drdy_complete); + return IRQ_HANDLED; + } + + /* We may be on a shared IRQ, let the next client check */ + return IRQ_NONE; +} + +static int ak8974_selftest(struct ak8974 *ak8974) +{ + struct device *dev = &ak8974->i2c->dev; + unsigned int val; + int ret; + + ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); + if (ret) + return ret; + if (val != AK8974_SELFTEST_IDLE) { + dev_err(dev, "selftest not idle before test\n"); + return -EIO; + } + + /* Trigger self-test */ + ret = regmap_update_bits(ak8974->map, + AK8974_CTRL3, + AK8974_CTRL3_SELFTEST, + AK8974_CTRL3_SELFTEST); + if (ret) { + dev_err(dev, "could not write CTRL3\n"); + return ret; + } + + msleep(AK8974_SELFTEST_DELAY); + + ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); + if (ret) + return ret; + if (val != AK8974_SELFTEST_OK) { + dev_err(dev, "selftest result NOT OK (%02x)\n", val); + return -EIO; + } + + ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); + if (ret) + return ret; + if (val != AK8974_SELFTEST_IDLE) { + dev_err(dev, "selftest not idle after test (%02x)\n", val); + return -EIO; + } + dev_dbg(dev, "passed self-test\n"); + + return 0; +} + +static int ak8974_get_u16_val(struct ak8974 *ak8974, u8 reg, u16 *val) +{ + int ret; + u16 bulk; + + ret = regmap_bulk_read(ak8974->map, reg, &bulk, 2); + if (ret) + return ret; + *val = le16_to_cpu(bulk); + + return 0; +} + +static int ak8974_detect(struct ak8974 *ak8974) +{ + unsigned int whoami; + const char *name; + int ret; + unsigned int fw; + u16 sn; + + ret = regmap_read(ak8974->map, AK8974_WHOAMI, &whoami); + if (ret) + return ret; + + switch (whoami) { + case AK8974_WHOAMI_VALUE_AMI305: + name = "ami305"; + ret = regmap_read(ak8974->map, AMI305_VER, &fw); + if (ret) + return ret; + fw &= 0x7f; /* only bits 0 thru 6 valid */ + ret = ak8974_get_u16_val(ak8974, AMI305_SN, &sn); + if (ret) + return ret; + dev_info(&ak8974->i2c->dev, + "detected %s, FW ver %02x, S/N: %04x\n", + name, fw, sn); + break; + case AK8974_WHOAMI_VALUE_AK8974: + name = "ak8974"; + dev_info(&ak8974->i2c->dev, "detected AK8974\n"); + break; + default: + dev_err(&ak8974->i2c->dev, "unsupported device (%02x) ", + whoami); + return -ENODEV; + } + + ak8974->name = name; + ak8974->variant = whoami; + + return 0; +} + +static int ak8974_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct ak8974 *ak8974 = iio_priv(indio_dev); + s16 hw_values[3]; + int ret = -EINVAL; + + pm_runtime_get_sync(&ak8974->i2c->dev); + mutex_lock(&ak8974->lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (chan->address > 2) { + dev_err(&ak8974->i2c->dev, "faulty channel address\n"); + ret = -EIO; + goto out_unlock; + } + ret = ak8974_trigmeas(ak8974); + if (ret) + goto out_unlock; + ret = ak8974_getresult(ak8974, hw_values); + if (ret) + goto out_unlock; + + /* + * We read all axes and discard all but one, for optimized + * reading, use the triggered buffer. + */ + *val = le16_to_cpu(hw_values[chan->address]); + + ret = IIO_VAL_INT; + } + + out_unlock: + mutex_unlock(&ak8974->lock); + pm_runtime_mark_last_busy(&ak8974->i2c->dev); + pm_runtime_put_autosuspend(&ak8974->i2c->dev); + + return ret; +} + +static void ak8974_fill_buffer(struct iio_dev *indio_dev) +{ + struct ak8974 *ak8974 = iio_priv(indio_dev); + int ret; + s16 hw_values[8]; /* Three axes + 64bit padding */ + + pm_runtime_get_sync(&ak8974->i2c->dev); + mutex_lock(&ak8974->lock); + + ret = ak8974_trigmeas(ak8974); + if (ret) { + dev_err(&ak8974->i2c->dev, "error triggering measure\n"); + goto out_unlock; + } + ret = ak8974_getresult(ak8974, hw_values); + if (ret) { + dev_err(&ak8974->i2c->dev, "error getting measures\n"); + goto out_unlock; + } + + iio_push_to_buffers_with_timestamp(indio_dev, hw_values, + iio_get_time_ns(indio_dev)); + + out_unlock: + mutex_unlock(&ak8974->lock); + pm_runtime_mark_last_busy(&ak8974->i2c->dev); + pm_runtime_put_autosuspend(&ak8974->i2c->dev); +} + +static irqreturn_t ak8974_handle_trigger(int irq, void *p) +{ + const struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + + ak8974_fill_buffer(indio_dev); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_mount_matrix * +ak8974_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ak8974 *ak8974 = iio_priv(indio_dev); + + return &ak8974->orientation; +} + +static const struct iio_chan_spec_ext_info ak8974_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, ak8974_get_mount_matrix), + { }, +}; + +#define AK8974_AXIS_CHANNEL(axis, index) \ + { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .ext_info = ak8974_ext_info, \ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE \ + }, \ + } + +static const struct iio_chan_spec ak8974_channels[] = { + AK8974_AXIS_CHANNEL(X, 0), + AK8974_AXIS_CHANNEL(Y, 1), + AK8974_AXIS_CHANNEL(Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +static const unsigned long ak8974_scan_masks[] = { 0x7, 0 }; + +static const struct iio_info ak8974_info = { + .read_raw = &ak8974_read_raw, + .driver_module = THIS_MODULE, +}; + +static bool ak8974_writeable_reg(struct device *dev, unsigned int reg) +{ + struct i2c_client *i2c = to_i2c_client(dev); + struct iio_dev *indio_dev = i2c_get_clientdata(i2c); + struct ak8974 *ak8974 = iio_priv(indio_dev); + + switch (reg) { + case AK8974_CTRL1: + case AK8974_CTRL2: + case AK8974_CTRL3: + case AK8974_INT_CTRL: + case AK8974_INT_THRES: + case AK8974_INT_THRES + 1: + case AK8974_PRESET: + case AK8974_PRESET + 1: + return true; + case AK8974_OFFSET_X: + case AK8974_OFFSET_X + 1: + case AK8974_OFFSET_Y: + case AK8974_OFFSET_Y + 1: + case AK8974_OFFSET_Z: + case AK8974_OFFSET_Z + 1: + if (ak8974->variant == AK8974_WHOAMI_VALUE_AK8974) + return true; + return false; + case AMI305_OFFSET_X: + case AMI305_OFFSET_X + 1: + case AMI305_OFFSET_Y: + case AMI305_OFFSET_Y + 1: + case AMI305_OFFSET_Z: + case AMI305_OFFSET_Z + 1: + if (ak8974->variant == AK8974_WHOAMI_VALUE_AMI305) + return true; + return false; + default: + return false; + } +} + +static const struct regmap_config ak8974_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xff, + .writeable_reg = ak8974_writeable_reg, +}; + +static int ak8974_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ak8974 *ak8974; + unsigned long irq_trig; + int irq = i2c->irq; + int ret; + + /* Register with IIO */ + indio_dev = devm_iio_device_alloc(&i2c->dev, sizeof(*ak8974)); + if (indio_dev == NULL) + return -ENOMEM; + + ak8974 = iio_priv(indio_dev); + i2c_set_clientdata(i2c, indio_dev); + ak8974->i2c = i2c; + mutex_init(&ak8974->lock); + + ret = of_iio_read_mount_matrix(&i2c->dev, + "mount-matrix", + &ak8974->orientation); + if (ret) + return ret; + + ak8974->regs[0].supply = ak8974_reg_avdd; + ak8974->regs[1].supply = ak8974_reg_dvdd; + + ret = devm_regulator_bulk_get(&i2c->dev, + ARRAY_SIZE(ak8974->regs), + ak8974->regs); + if (ret < 0) { + dev_err(&i2c->dev, "cannot get regulators\n"); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + if (ret < 0) { + dev_err(&i2c->dev, "cannot enable regulators\n"); + return ret; + } + + /* Take runtime PM online */ + pm_runtime_get_noresume(&i2c->dev); + pm_runtime_set_active(&i2c->dev); + pm_runtime_enable(&i2c->dev); + + ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config); + if (IS_ERR(ak8974->map)) { + dev_err(&i2c->dev, "failed to allocate register map\n"); + return PTR_ERR(ak8974->map); + } + + ret = ak8974_set_power(ak8974, AK8974_PWR_ON); + if (ret) { + dev_err(&i2c->dev, "could not power on\n"); + goto power_off; + } + + ret = ak8974_detect(ak8974); + if (ret) { + dev_err(&i2c->dev, "neither AK8974 nor AMI305 found\n"); + goto power_off; + } + + ret = ak8974_selftest(ak8974); + if (ret) + dev_err(&i2c->dev, "selftest failed (continuing anyway)\n"); + + ret = ak8974_reset(ak8974); + if (ret) { + dev_err(&i2c->dev, "AK8974 reset failed\n"); + goto power_off; + } + + pm_runtime_set_autosuspend_delay(&i2c->dev, + AK8974_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(&i2c->dev); + pm_runtime_put(&i2c->dev); + + indio_dev->dev.parent = &i2c->dev; + indio_dev->channels = ak8974_channels; + indio_dev->num_channels = ARRAY_SIZE(ak8974_channels); + indio_dev->info = &ak8974_info; + indio_dev->available_scan_masks = ak8974_scan_masks; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = ak8974->name; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + ak8974_handle_trigger, + NULL); + if (ret) { + dev_err(&i2c->dev, "triggered buffer setup failed\n"); + goto disable_pm; + } + + /* If we have a valid DRDY IRQ, make use of it */ + if (irq > 0) { + irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); + if (irq_trig == IRQF_TRIGGER_RISING) { + dev_info(&i2c->dev, "enable rising edge DRDY IRQ\n"); + } else if (irq_trig == IRQF_TRIGGER_FALLING) { + ak8974->drdy_active_low = true; + dev_info(&i2c->dev, "enable falling edge DRDY IRQ\n"); + } else { + irq_trig = IRQF_TRIGGER_RISING; + } + irq_trig |= IRQF_ONESHOT; + irq_trig |= IRQF_SHARED; + + ret = devm_request_threaded_irq(&i2c->dev, + irq, + ak8974_drdy_irq, + ak8974_drdy_irq_thread, + irq_trig, + ak8974->name, + ak8974); + if (ret) { + dev_err(&i2c->dev, "unable to request DRDY IRQ " + "- proceeding without IRQ\n"); + goto no_irq; + } + ak8974->drdy_irq = true; + } + +no_irq: + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&i2c->dev, "device register failed\n"); + goto cleanup_buffer; + } + + return 0; + +cleanup_buffer: + iio_triggered_buffer_cleanup(indio_dev); +disable_pm: + pm_runtime_put_noidle(&i2c->dev); + pm_runtime_disable(&i2c->dev); + ak8974_set_power(ak8974, AK8974_PWR_OFF); +power_off: + regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + + return ret; +} + +static int __exit ak8974_remove(struct i2c_client *i2c) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(i2c); + struct ak8974 *ak8974 = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + pm_runtime_get_sync(&i2c->dev); + pm_runtime_put_noidle(&i2c->dev); + pm_runtime_disable(&i2c->dev); + ak8974_set_power(ak8974, AK8974_PWR_OFF); + regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + + return 0; +} + +static int __maybe_unused ak8974_runtime_suspend(struct device *dev) +{ + struct ak8974 *ak8974 = + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + ak8974_set_power(ak8974, AK8974_PWR_OFF); + regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + + return 0; +} + +static int __maybe_unused ak8974_runtime_resume(struct device *dev) +{ + struct ak8974 *ak8974 = + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + if (ret) + return ret; + msleep(AK8974_POWERON_DELAY); + ret = ak8974_set_power(ak8974, AK8974_PWR_ON); + if (ret) + goto out_regulator_disable; + + ret = ak8974_configure(ak8974); + if (ret) + goto out_disable_power; + + return 0; + +out_disable_power: + ak8974_set_power(ak8974, AK8974_PWR_OFF); +out_regulator_disable: + regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + + return ret; +} + +static const struct dev_pm_ops ak8974_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(ak8974_runtime_suspend, + ak8974_runtime_resume, NULL) +}; + +static const struct i2c_device_id ak8974_id[] = { + {"ami305", 0 }, + {"ak8974", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ak8974_id); + +static const struct of_device_id ak8974_of_match[] = { + { .compatible = "asahi-kasei,ak8974", }, + {} +}; +MODULE_DEVICE_TABLE(of, ak8974_of_match); + +static struct i2c_driver ak8974_driver = { + .driver = { + .name = "ak8974", + .pm = &ak8974_dev_pm_ops, + .of_match_table = of_match_ptr(ak8974_of_match), + }, + .probe = ak8974_probe, + .remove = __exit_p(ak8974_remove), + .id_table = ak8974_id, +}; +module_i2c_driver(ak8974_driver); + +MODULE_DESCRIPTION("AK8974 and AMI305 3-axis magnetometer driver"); +MODULE_AUTHOR("Samu Onkalo"); +MODULE_AUTHOR("Linus Walleij"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index f2be4a049056..f2b3bd7bf862 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -154,34 +154,41 @@ static int mag3110_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (chan->type) { case IIO_MAGN: /* in 0.1 uT / LSB */ ret = mag3110_read(data, buffer); if (ret < 0) - return ret; + goto release; *val = sign_extend32( be16_to_cpu(buffer[chan->scan_index]), 15); - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; case IIO_TEMP: /* in 1 C / LSB */ mutex_lock(&data->lock); ret = mag3110_request(data); if (ret < 0) { mutex_unlock(&data->lock); - return ret; + goto release; } ret = i2c_smbus_read_byte_data(data->client, MAG3110_DIE_TEMP); mutex_unlock(&data->lock); if (ret < 0) - return ret; + goto release; *val = sign_extend32(ret, 7); - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; default: - return -EINVAL; + ret = -EINVAL; } +release: + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_MAGN: diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 7fa65ab664fb..15cd416365c1 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -185,4 +185,26 @@ config HP206C This driver can also be built as a module. If so, the module will be called hp206c. +config ZPA2326 + tristate "Murata ZPA2326 pressure sensor driver" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select REGMAP + select ZPA2326_I2C if I2C + select ZPA2326_SPI if SPI_MASTER + help + Say Y here to build support for the Murata ZPA2326 pressure and + temperature sensor. + + To compile this driver as a module, choose M here: the module will + be called zpa2326. + +config ZPA2326_I2C + tristate + select REGMAP_I2C + +config ZPA2326_SPI + tristate + select REGMAP_SPI + endmenu diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 7f395bed5e88..fff77185a5cc 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -22,6 +22,9 @@ st_pressure-y := st_pressure_core.o st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o obj-$(CONFIG_T5403) += t5403.o obj-$(CONFIG_HP206C) += hp206c.o +obj-$(CONFIG_ZPA2326) += zpa2326.o +obj-$(CONFIG_ZPA2326_I2C) += zpa2326_i2c.o +obj-$(CONFIG_ZPA2326_SPI) += zpa2326_spi.o obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index feb41f82c64a..a74ed1f0c880 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -416,8 +416,7 @@ static int ms5611_init(struct iio_dev *indio_dev) return 0; err_regulator_disable: - if (!IS_ERR_OR_NULL(st->vdd)) - regulator_disable(st->vdd); + regulator_disable(st->vdd); return ret; } @@ -425,8 +424,7 @@ static void ms5611_fini(const struct iio_dev *indio_dev) { const struct ms5611_state *st = iio_priv(indio_dev); - if (!IS_ERR_OR_NULL(st->vdd)) - regulator_disable(st->vdd); + regulator_disable(st->vdd); } int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c new file mode 100644 index 000000000000..19d2eb46fda6 --- /dev/null +++ b/drivers/iio/pressure/zpa2326.c @@ -0,0 +1,1735 @@ +/* + * Murata ZPA2326 pressure and temperature sensor IIO driver + * + * Copyright (c) 2016 Parrot S.A. + * + * Author: Gregor Boirie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/** + * DOC: ZPA2326 theory of operations + * + * This driver supports %INDIO_DIRECT_MODE and %INDIO_BUFFER_TRIGGERED IIO + * modes. + * A internal hardware trigger is also implemented to dispatch registered IIO + * trigger consumers upon "sample ready" interrupts. + * + * ZPA2326 hardware supports 2 sampling mode: one shot and continuous. + * + * A complete one shot sampling cycle gets device out of low power mode, + * performs pressure and temperature measurements, then automatically switches + * back to low power mode. It is meant for on demand sampling with optimal power + * saving at the cost of lower sampling rate and higher software overhead. + * This is a natural candidate for IIO read_raw hook implementation + * (%INDIO_DIRECT_MODE). It is also used for triggered buffering support to + * ensure explicit synchronization with external trigger events + * (%INDIO_BUFFER_TRIGGERED). + * + * The continuous mode works according to a periodic hardware measurement + * process continuously pushing samples into an internal hardware FIFO (for + * pressure samples only). Measurement cycle completion may be signaled by a + * "sample ready" interrupt. + * Typical software sequence of operations : + * - get device out of low power mode, + * - setup hardware sampling period, + * - at end of period, upon data ready interrupt: pop pressure samples out of + * hardware FIFO and fetch temperature sample + * - when no longer needed, stop sampling process by putting device into + * low power mode. + * This mode is used to implement %INDIO_BUFFER_TRIGGERED mode if device tree + * declares a valid interrupt line. In this case, the internal hardware trigger + * drives acquisition. + * + * Note that hardware sampling frequency is taken into account only when + * internal hardware trigger is attached as the highest sampling rate seems to + * be the most energy efficient. + * + * TODO: + * preset pressure threshold crossing / IIO events ; + * differential pressure sampling ; + * hardware samples averaging. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "zpa2326.h" + +/* 200 ms should be enough for the longest conversion time in one-shot mode. */ +#define ZPA2326_CONVERSION_JIFFIES (HZ / 5) + +/* There should be a 1 ms delay (Tpup) after getting out of reset. */ +#define ZPA2326_TPUP_USEC_MIN (1000) +#define ZPA2326_TPUP_USEC_MAX (2000) + +/** + * struct zpa2326_frequency - Hardware sampling frequency descriptor + * @hz : Frequency in Hertz. + * @odr: Output Data Rate word as expected by %ZPA2326_CTRL_REG3_REG. + */ +struct zpa2326_frequency { + int hz; + u16 odr; +}; + +/* + * Keep these in strict ascending order: last array entry is expected to + * correspond to the highest sampling frequency. + */ +static const struct zpa2326_frequency zpa2326_sampling_frequencies[] = { + { .hz = 1, .odr = 1 << ZPA2326_CTRL_REG3_ODR_SHIFT }, + { .hz = 5, .odr = 5 << ZPA2326_CTRL_REG3_ODR_SHIFT }, + { .hz = 11, .odr = 6 << ZPA2326_CTRL_REG3_ODR_SHIFT }, + { .hz = 23, .odr = 7 << ZPA2326_CTRL_REG3_ODR_SHIFT }, +}; + +/* Return the highest hardware sampling frequency available. */ +static const struct zpa2326_frequency *zpa2326_highest_frequency(void) +{ + return &zpa2326_sampling_frequencies[ + ARRAY_SIZE(zpa2326_sampling_frequencies) - 1]; +} + +/** + * struct zpa_private - Per-device internal private state + * @timestamp: Buffered samples ready datum. + * @regmap: Underlying I2C / SPI bus adapter used to abstract slave register + * accesses. + * @result: Allows sampling logic to get completion status of operations + * that interrupt handlers perform asynchronously. + * @data_ready: Interrupt handler uses this to wake user context up at sampling + * operation completion. + * @trigger: Optional hardware / interrupt driven trigger used to notify + * external devices a new sample is ready. + * @waken: Flag indicating whether or not device has just been powered on. + * @irq: Optional interrupt line: negative or zero if not declared into + * DT, in which case sampling logic keeps polling status register + * to detect completion. + * @frequency: Current hardware sampling frequency. + * @vref: Power / voltage reference. + * @vdd: Power supply. + */ +struct zpa2326_private { + s64 timestamp; + struct regmap *regmap; + int result; + struct completion data_ready; + struct iio_trigger *trigger; + bool waken; + int irq; + const struct zpa2326_frequency *frequency; + struct regulator *vref; + struct regulator *vdd; +}; + +#define zpa2326_err(_idev, _format, _arg...) \ + dev_err(_idev->dev.parent, _format, ##_arg) + +#define zpa2326_warn(_idev, _format, _arg...) \ + dev_warn(_idev->dev.parent, _format, ##_arg) + +#ifdef DEBUG +#define zpa2326_dbg(_idev, _format, _arg...) \ + dev_dbg(_idev->dev.parent, _format, ##_arg) +#else +#define zpa2326_dbg(_idev, _format, _arg...) +#endif + +bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ZPA2326_REF_P_XL_REG: + case ZPA2326_REF_P_L_REG: + case ZPA2326_REF_P_H_REG: + case ZPA2326_RES_CONF_REG: + case ZPA2326_CTRL_REG0_REG: + case ZPA2326_CTRL_REG1_REG: + case ZPA2326_CTRL_REG2_REG: + case ZPA2326_CTRL_REG3_REG: + case ZPA2326_THS_P_LOW_REG: + case ZPA2326_THS_P_HIGH_REG: + return true; + + default: + return false; + } +} +EXPORT_SYMBOL_GPL(zpa2326_isreg_writeable); + +bool zpa2326_isreg_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ZPA2326_REF_P_XL_REG: + case ZPA2326_REF_P_L_REG: + case ZPA2326_REF_P_H_REG: + case ZPA2326_DEVICE_ID_REG: + case ZPA2326_RES_CONF_REG: + case ZPA2326_CTRL_REG0_REG: + case ZPA2326_CTRL_REG1_REG: + case ZPA2326_CTRL_REG2_REG: + case ZPA2326_CTRL_REG3_REG: + case ZPA2326_INT_SOURCE_REG: + case ZPA2326_THS_P_LOW_REG: + case ZPA2326_THS_P_HIGH_REG: + case ZPA2326_STATUS_REG: + case ZPA2326_PRESS_OUT_XL_REG: + case ZPA2326_PRESS_OUT_L_REG: + case ZPA2326_PRESS_OUT_H_REG: + case ZPA2326_TEMP_OUT_L_REG: + case ZPA2326_TEMP_OUT_H_REG: + return true; + + default: + return false; + } +} +EXPORT_SYMBOL_GPL(zpa2326_isreg_readable); + +bool zpa2326_isreg_precious(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ZPA2326_INT_SOURCE_REG: + case ZPA2326_PRESS_OUT_H_REG: + return true; + + default: + return false; + } +} +EXPORT_SYMBOL_GPL(zpa2326_isreg_precious); + +/** + * zpa2326_enable_device() - Enable device, i.e. get out of low power mode. + * @indio_dev: The IIO device associated with the hardware to enable. + * + * Required to access complete register space and to perform any sampling + * or control operations. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_enable_device(const struct iio_dev *indio_dev) +{ + int err; + + err = regmap_write(((struct zpa2326_private *) + iio_priv(indio_dev))->regmap, + ZPA2326_CTRL_REG0_REG, ZPA2326_CTRL_REG0_ENABLE); + if (err) { + zpa2326_err(indio_dev, "failed to enable device (%d)", err); + return err; + } + + zpa2326_dbg(indio_dev, "enabled"); + + return 0; +} + +/** + * zpa2326_sleep() - Disable device, i.e. switch to low power mode. + * @indio_dev: The IIO device associated with the hardware to disable. + * + * Only %ZPA2326_DEVICE_ID_REG and %ZPA2326_CTRL_REG0_REG registers may be + * accessed once device is in the disabled state. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_sleep(const struct iio_dev *indio_dev) +{ + int err; + + err = regmap_write(((struct zpa2326_private *) + iio_priv(indio_dev))->regmap, + ZPA2326_CTRL_REG0_REG, 0); + if (err) { + zpa2326_err(indio_dev, "failed to sleep (%d)", err); + return err; + } + + zpa2326_dbg(indio_dev, "sleeping"); + + return 0; +} + +/** + * zpa2326_reset_device() - Reset device to default hardware state. + * @indio_dev: The IIO device associated with the hardware to reset. + * + * Disable sampling and empty hardware FIFO. + * Device must be enabled before reset, i.e. not in low power mode. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_reset_device(const struct iio_dev *indio_dev) +{ + int err; + + err = regmap_write(((struct zpa2326_private *) + iio_priv(indio_dev))->regmap, + ZPA2326_CTRL_REG2_REG, ZPA2326_CTRL_REG2_SWRESET); + if (err) { + zpa2326_err(indio_dev, "failed to reset device (%d)", err); + return err; + } + + usleep_range(ZPA2326_TPUP_USEC_MIN, ZPA2326_TPUP_USEC_MAX); + + zpa2326_dbg(indio_dev, "reset"); + + return 0; +} + +/** + * zpa2326_start_oneshot() - Start a single sampling cycle, i.e. in one shot + * mode. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Device must have been previously enabled and configured for one shot mode. + * Device will be switched back to low power mode at end of cycle. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_start_oneshot(const struct iio_dev *indio_dev) +{ + int err; + + err = regmap_write(((struct zpa2326_private *) + iio_priv(indio_dev))->regmap, + ZPA2326_CTRL_REG0_REG, + ZPA2326_CTRL_REG0_ENABLE | + ZPA2326_CTRL_REG0_ONE_SHOT); + if (err) { + zpa2326_err(indio_dev, "failed to start one shot cycle (%d)", + err); + return err; + } + + zpa2326_dbg(indio_dev, "one shot cycle started"); + + return 0; +} + +/** + * zpa2326_power_on() - Power on device to allow subsequent configuration. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * + * Sampling will be disabled, preventing strange things from happening in our + * back. Hardware FIFO content will be cleared. + * When successful, device will be left in the enabled state to allow further + * configuration. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_power_on(const struct iio_dev *indio_dev, + const struct zpa2326_private *private) +{ + int err; + + err = regulator_enable(private->vref); + if (err) + return err; + + err = regulator_enable(private->vdd); + if (err) + goto vref; + + zpa2326_dbg(indio_dev, "powered on"); + + err = zpa2326_enable_device(indio_dev); + if (err) + goto vdd; + + err = zpa2326_reset_device(indio_dev); + if (err) + goto sleep; + + return 0; + +sleep: + zpa2326_sleep(indio_dev); +vdd: + regulator_disable(private->vdd); +vref: + regulator_disable(private->vref); + + zpa2326_dbg(indio_dev, "powered off"); + + return err; +} + +/** + * zpa2326_power_off() - Power off device, i.e. disable attached power + * regulators. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static void zpa2326_power_off(const struct iio_dev *indio_dev, + const struct zpa2326_private *private) +{ + regulator_disable(private->vdd); + regulator_disable(private->vref); + + zpa2326_dbg(indio_dev, "powered off"); +} + +/** + * zpa2326_config_oneshot() - Setup device for one shot / on demand mode. + * @indio_dev: The IIO device associated with the sampling hardware. + * @irq: Optional interrupt line the hardware uses to notify new data + * samples are ready. Negative or zero values indicate no interrupts + * are available, meaning polling is required. + * + * Output Data Rate is configured for the highest possible rate so that + * conversion time and power consumption are reduced to a minimum. + * Note that hardware internal averaging machinery (not implemented in this + * driver) is not applicable in this mode. + * + * Device must have been previously enabled before calling + * zpa2326_config_oneshot(). + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_config_oneshot(const struct iio_dev *indio_dev, + int irq) +{ + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + const struct zpa2326_frequency *freq = zpa2326_highest_frequency(); + int err; + + /* Setup highest available Output Data Rate for one shot mode. */ + err = regmap_write(regs, ZPA2326_CTRL_REG3_REG, freq->odr); + if (err) + return err; + + if (irq > 0) { + /* Request interrupt when new sample is available. */ + err = regmap_write(regs, ZPA2326_CTRL_REG1_REG, + (u8)~ZPA2326_CTRL_REG1_MASK_DATA_READY); + + if (err) { + dev_err(indio_dev->dev.parent, + "failed to setup one shot mode (%d)", err); + return err; + } + } + + zpa2326_dbg(indio_dev, "one shot mode setup @%dHz", freq->hz); + + return 0; +} + +/** + * zpa2326_clear_fifo() - Clear remaining entries in hardware FIFO. + * @indio_dev: The IIO device associated with the sampling hardware. + * @min_count: Number of samples present within hardware FIFO. + * + * @min_count argument is a hint corresponding to the known minimum number of + * samples currently living in the FIFO. This allows to reduce the number of bus + * accesses by skipping status register read operation as long as we know for + * sure there are still entries left. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_clear_fifo(const struct iio_dev *indio_dev, + unsigned int min_count) +{ + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + int err; + unsigned int val; + + if (!min_count) { + /* + * No hint: read status register to determine whether FIFO is + * empty or not. + */ + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + + if (err < 0) + goto err; + + if (val & ZPA2326_STATUS_FIFO_E) + /* Fifo is empty: nothing to trash. */ + return 0; + } + + /* Clear FIFO. */ + do { + /* + * A single fetch from pressure MSB register is enough to pop + * values out of FIFO. + */ + err = regmap_read(regs, ZPA2326_PRESS_OUT_H_REG, &val); + if (err < 0) + goto err; + + if (min_count) { + /* + * We know for sure there are at least min_count entries + * left in FIFO. Skip status register read. + */ + min_count--; + continue; + } + + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + if (err < 0) + goto err; + + } while (!(val & ZPA2326_STATUS_FIFO_E)); + + zpa2326_dbg(indio_dev, "FIFO cleared"); + + return 0; + +err: + zpa2326_err(indio_dev, "failed to clear FIFO (%d)", err); + + return err; +} + +/** + * zpa2326_dequeue_pressure() - Retrieve the most recent pressure sample from + * hardware FIFO. + * @indio_dev: The IIO device associated with the sampling hardware. + * @pressure: Sampled pressure output. + * + * Note that ZPA2326 hardware FIFO stores pressure samples only. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_dequeue_pressure(const struct iio_dev *indio_dev, + u32 *pressure) +{ + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + unsigned int val; + int err; + int cleared = -1; + + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + if (err < 0) + return err; + + *pressure = 0; + + if (val & ZPA2326_STATUS_P_OR) { + /* + * Fifo overrun : first sample dequeued from FIFO is the + * newest. + */ + zpa2326_warn(indio_dev, "FIFO overflow"); + + err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, pressure, + 3); + if (err) + return err; + +#define ZPA2326_FIFO_DEPTH (16U) + /* Hardware FIFO may hold no more than 16 pressure samples. */ + return zpa2326_clear_fifo(indio_dev, ZPA2326_FIFO_DEPTH - 1); + } + + /* + * Fifo has not overflown : retrieve newest sample. We need to pop + * values out until FIFO is empty : last fetched pressure is the newest. + * In nominal cases, we should find a single queued sample only. + */ + do { + err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, pressure, + 3); + if (err) + return err; + + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + if (err < 0) + return err; + + cleared++; + } while (!(val & ZPA2326_STATUS_FIFO_E)); + + if (cleared) + /* + * Samples were pushed by hardware during previous rounds but we + * didn't consume them fast enough: inform user. + */ + zpa2326_dbg(indio_dev, "cleared %d FIFO entries", cleared); + + return 0; +} + +/** + * zpa2326_fill_sample_buffer() - Enqueue new channel samples to IIO buffer. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_fill_sample_buffer(struct iio_dev *indio_dev, + const struct zpa2326_private *private) +{ + struct { + u32 pressure; + u16 temperature; + u64 timestamp; + } sample; + int err; + + if (test_bit(0, indio_dev->active_scan_mask)) { + /* Get current pressure from hardware FIFO. */ + err = zpa2326_dequeue_pressure(indio_dev, &sample.pressure); + if (err) { + zpa2326_warn(indio_dev, "failed to fetch pressure (%d)", + err); + return err; + } + } + + if (test_bit(1, indio_dev->active_scan_mask)) { + /* Get current temperature. */ + err = regmap_bulk_read(private->regmap, ZPA2326_TEMP_OUT_L_REG, + &sample.temperature, 2); + if (err) { + zpa2326_warn(indio_dev, + "failed to fetch temperature (%d)", err); + return err; + } + } + + /* + * Now push samples using timestamp stored either : + * - by hardware interrupt handler if interrupt is available: see + * zpa2326_handle_irq(), + * - or oneshot completion polling machinery : see + * zpa2326_trigger_handler(). + */ + zpa2326_dbg(indio_dev, "filling raw samples buffer"); + + iio_push_to_buffers_with_timestamp(indio_dev, &sample, + private->timestamp); + + return 0; +} + +#ifdef CONFIG_PM +static int zpa2326_runtime_suspend(struct device *parent) +{ + const struct iio_dev *indio_dev = dev_get_drvdata(parent); + + if (pm_runtime_autosuspend_expiration(parent)) + /* Userspace changed autosuspend delay. */ + return -EAGAIN; + + zpa2326_power_off(indio_dev, iio_priv(indio_dev)); + + return 0; +} + +static int zpa2326_runtime_resume(struct device *parent) +{ + const struct iio_dev *indio_dev = dev_get_drvdata(parent); + + return zpa2326_power_on(indio_dev, iio_priv(indio_dev)); +} + +const struct dev_pm_ops zpa2326_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(zpa2326_runtime_suspend, zpa2326_runtime_resume, + NULL) +}; +EXPORT_SYMBOL_GPL(zpa2326_pm_ops); + +/** + * zpa2326_resume() - Request the PM layer to power supply the device. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Return: + * < 0 - a negative error code meaning failure ; + * 0 - success, device has just been powered up ; + * 1 - success, device was already powered. + */ +static int zpa2326_resume(const struct iio_dev *indio_dev) +{ + int err; + + err = pm_runtime_get_sync(indio_dev->dev.parent); + if (err < 0) + return err; + + if (err > 0) { + /* + * Device was already power supplied: get it out of low power + * mode and inform caller. + */ + zpa2326_enable_device(indio_dev); + return 1; + } + + /* Inform caller device has just been brought back to life. */ + return 0; +} + +/** + * zpa2326_suspend() - Schedule a power down using autosuspend feature of PM + * layer. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Device is switched to low power mode at first to save power even when + * attached regulator is a "dummy" one. + */ +static void zpa2326_suspend(struct iio_dev *indio_dev) +{ + struct device *parent = indio_dev->dev.parent; + + zpa2326_sleep(indio_dev); + + pm_runtime_mark_last_busy(parent); + pm_runtime_put_autosuspend(parent); +} + +static void zpa2326_init_runtime(struct device *parent) +{ + pm_runtime_get_noresume(parent); + pm_runtime_set_active(parent); + pm_runtime_enable(parent); + pm_runtime_set_autosuspend_delay(parent, 1000); + pm_runtime_use_autosuspend(parent); + pm_runtime_mark_last_busy(parent); + pm_runtime_put_autosuspend(parent); +} + +static void zpa2326_fini_runtime(struct device *parent) +{ + pm_runtime_disable(parent); + pm_runtime_set_suspended(parent); +} +#else /* !CONFIG_PM */ +static int zpa2326_resume(const struct iio_dev *indio_dev) +{ + zpa2326_enable_device(indio_dev); + + return 0; +} + +static void zpa2326_suspend(struct iio_dev *indio_dev) +{ + zpa2326_sleep(indio_dev); +} + +#define zpa2326_init_runtime(_parent) +#define zpa2326_fini_runtime(_parent) +#endif /* !CONFIG_PM */ + +/** + * zpa2326_handle_irq() - Process hardware interrupts. + * @irq: Interrupt line the hardware uses to notify new data has arrived. + * @data: The IIO device associated with the sampling hardware. + * + * Timestamp buffered samples as soon as possible then schedule threaded bottom + * half. + * + * Return: Always successful. + */ +static irqreturn_t zpa2326_handle_irq(int irq, void *data) +{ + struct iio_dev *indio_dev = (struct iio_dev *)data; + + if (iio_buffer_enabled(indio_dev)) { + /* Timestamping needed for buffered sampling only. */ + ((struct zpa2326_private *) + iio_priv(indio_dev))->timestamp = iio_get_time_ns(indio_dev); + } + + return IRQ_WAKE_THREAD; +} + +/** + * zpa2326_handle_threaded_irq() - Interrupt bottom-half handler. + * @irq: Interrupt line the hardware uses to notify new data has arrived. + * @data: The IIO device associated with the sampling hardware. + * + * Mainly ensures interrupt is caused by a real "new sample available" + * condition. This relies upon the ability to perform blocking / sleeping bus + * accesses to slave's registers. This is why zpa2326_handle_threaded_irq() is + * called from within a thread, i.e. not called from hard interrupt context. + * + * When device is using its own internal hardware trigger in continuous sampling + * mode, data are available into hardware FIFO once interrupt has occurred. All + * we have to do is to dispatch the trigger, which in turn will fetch data and + * fill IIO buffer. + * + * When not using its own internal hardware trigger, the device has been + * configured in one-shot mode either by an external trigger or the IIO read_raw + * hook. This means one of the latter is currently waiting for sampling + * completion, in which case we must simply wake it up. + * + * See zpa2326_trigger_handler(). + * + * Return: + * %IRQ_NONE - no consistent interrupt happened ; + * %IRQ_HANDLED - there was new samples available. + */ +static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data) +{ + struct iio_dev *indio_dev = (struct iio_dev *)data; + struct zpa2326_private *priv = iio_priv(indio_dev); + unsigned int val; + bool cont; + irqreturn_t ret = IRQ_NONE; + + /* + * Are we using our own internal trigger in triggered buffer mode, i.e., + * currently working in continuous sampling mode ? + */ + cont = (iio_buffer_enabled(indio_dev) && + iio_trigger_using_own(indio_dev)); + + /* + * Device works according to a level interrupt scheme: reading interrupt + * status de-asserts interrupt line. + */ + priv->result = regmap_read(priv->regmap, ZPA2326_INT_SOURCE_REG, &val); + if (priv->result < 0) { + if (cont) + return IRQ_NONE; + + goto complete; + } + + /* Data ready is the only interrupt source we requested. */ + if (!(val & ZPA2326_INT_SOURCE_DATA_READY)) { + /* + * Interrupt happened but no new sample available: likely caused + * by spurious interrupts, in which case, returning IRQ_NONE + * allows to benefit from the generic spurious interrupts + * handling. + */ + zpa2326_warn(indio_dev, "unexpected interrupt status %02x", + val); + + if (cont) + return IRQ_NONE; + + priv->result = -ENODATA; + goto complete; + } + + /* New sample available: dispatch internal trigger consumers. */ + iio_trigger_poll_chained(priv->trigger); + + if (cont) + /* + * Internal hardware trigger has been scheduled above : it will + * fetch data on its own. + */ + return IRQ_HANDLED; + + ret = IRQ_HANDLED; + +complete: + /* + * Wake up direct or externaly triggered buffer mode waiters: see + * zpa2326_sample_oneshot() and zpa2326_trigger_handler(). + */ + complete(&priv->data_ready); + + return ret; +} + +/** + * zpa2326_wait_oneshot_completion() - Wait for oneshot data ready interrupt. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, + struct zpa2326_private *private) +{ + int ret; + unsigned int val; + + zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt"); + + ret = wait_for_completion_interruptible_timeout( + &private->data_ready, ZPA2326_CONVERSION_JIFFIES); + if (ret > 0) + /* + * Interrupt handler completed before timeout: return operation + * status. + */ + return private->result; + + /* Clear all interrupts just to be sure. */ + regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, &val); + + if (!ret) + /* Timed out. */ + ret = -ETIME; + + if (ret != -ERESTARTSYS) + zpa2326_warn(indio_dev, "no one shot interrupt occurred (%d)", + ret); + + return ret; +} + +static int zpa2326_init_managed_irq(struct device *parent, + struct iio_dev *indio_dev, + struct zpa2326_private *private, + int irq) +{ + int err; + + private->irq = irq; + + if (irq <= 0) { + /* + * Platform declared no interrupt line: device will be polled + * for data availability. + */ + dev_info(parent, "no interrupt found, running in polling mode"); + return 0; + } + + init_completion(&private->data_ready); + + /* Request handler to be scheduled into threaded interrupt context. */ + err = devm_request_threaded_irq(parent, irq, zpa2326_handle_irq, + zpa2326_handle_threaded_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + dev_name(parent), indio_dev); + if (err) { + dev_err(parent, "failed to request interrupt %d (%d)", irq, + err); + return err; + } + + dev_info(parent, "using interrupt %d", irq); + + return 0; +} + +/** + * zpa2326_poll_oneshot_completion() - Actively poll for one shot data ready. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Loop over registers content to detect end of sampling cycle. Used when DT + * declared no valid interrupt lines. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_poll_oneshot_completion(const struct iio_dev *indio_dev) +{ + unsigned long tmout = jiffies + ZPA2326_CONVERSION_JIFFIES; + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + unsigned int val; + int err; + + zpa2326_dbg(indio_dev, "polling for one shot completion"); + + /* + * At least, 100 ms is needed for the device to complete its one-shot + * cycle. + */ + if (msleep_interruptible(100)) + return -ERESTARTSYS; + + /* Poll for conversion completion in hardware. */ + while (true) { + err = regmap_read(regs, ZPA2326_CTRL_REG0_REG, &val); + if (err < 0) + goto err; + + if (!(val & ZPA2326_CTRL_REG0_ONE_SHOT)) + /* One-shot bit self clears at conversion end. */ + break; + + if (time_after(jiffies, tmout)) { + /* Prevent from waiting forever : let's time out. */ + err = -ETIME; + goto err; + } + + usleep_range(10000, 20000); + } + + /* + * In oneshot mode, pressure sample availability guarantees that + * temperature conversion has also completed : just check pressure + * status bit to keep things simple. + */ + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + if (err < 0) + goto err; + + if (!(val & ZPA2326_STATUS_P_DA)) { + /* No sample available. */ + err = -ENODATA; + goto err; + } + + return 0; + +err: + zpa2326_warn(indio_dev, "failed to poll one shot completion (%d)", err); + + return err; +} + +/** + * zpa2326_fetch_raw_sample() - Retrieve a raw sample and convert it to CPU + * endianness. + * @indio_dev: The IIO device associated with the sampling hardware. + * @type: Type of measurement / channel to fetch from. + * @value: Sample output. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_fetch_raw_sample(const struct iio_dev *indio_dev, + enum iio_chan_type type, + int *value) +{ + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + int err; + + switch (type) { + case IIO_PRESSURE: + zpa2326_dbg(indio_dev, "fetching raw pressure sample"); + + err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, value, + 3); + if (err) { + zpa2326_warn(indio_dev, "failed to fetch pressure (%d)", + err); + return err; + } + + /* Pressure is a 24 bits wide little-endian unsigned int. */ + *value = (((u8 *)value)[2] << 16) | (((u8 *)value)[1] << 8) | + ((u8 *)value)[0]; + + return IIO_VAL_INT; + + case IIO_TEMP: + zpa2326_dbg(indio_dev, "fetching raw temperature sample"); + + err = regmap_bulk_read(regs, ZPA2326_TEMP_OUT_L_REG, value, 2); + if (err) { + zpa2326_warn(indio_dev, + "failed to fetch temperature (%d)", err); + return err; + } + + /* Temperature is a 16 bits wide little-endian signed int. */ + *value = (int)le16_to_cpup((__le16 *)value); + + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +/** + * zpa2326_sample_oneshot() - Perform a complete one shot sampling cycle. + * @indio_dev: The IIO device associated with the sampling hardware. + * @type: Type of measurement / channel to fetch from. + * @value: Sample output. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_sample_oneshot(struct iio_dev *indio_dev, + enum iio_chan_type type, + int *value) +{ + int ret; + struct zpa2326_private *priv; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = zpa2326_resume(indio_dev); + if (ret < 0) + goto release; + + priv = iio_priv(indio_dev); + + if (ret > 0) { + /* + * We were already power supplied. Just clear hardware FIFO to + * get rid of samples acquired during previous rounds (if any). + * Sampling operation always generates both temperature and + * pressure samples. The latter are always enqueued into + * hardware FIFO. This may lead to situations were pressure + * samples still sit into FIFO when previous cycle(s) fetched + * temperature data only. + * Hence, we need to clear hardware FIFO content to prevent from + * getting outdated values at the end of current cycle. + */ + if (type == IIO_PRESSURE) { + ret = zpa2326_clear_fifo(indio_dev, 0); + if (ret) + goto suspend; + } + } else { + /* + * We have just been power supplied, i.e. device is in default + * "out of reset" state, meaning we need to reconfigure it + * entirely. + */ + ret = zpa2326_config_oneshot(indio_dev, priv->irq); + if (ret) + goto suspend; + } + + /* Start a sampling cycle in oneshot mode. */ + ret = zpa2326_start_oneshot(indio_dev); + if (ret) + goto suspend; + + /* Wait for sampling cycle to complete. */ + if (priv->irq > 0) + ret = zpa2326_wait_oneshot_completion(indio_dev, priv); + else + ret = zpa2326_poll_oneshot_completion(indio_dev); + + if (ret) + goto suspend; + + /* Retrieve raw sample value and convert it to CPU endianness. */ + ret = zpa2326_fetch_raw_sample(indio_dev, type, value); + +suspend: + zpa2326_suspend(indio_dev); +release: + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +/** + * zpa2326_trigger_handler() - Perform an IIO buffered sampling round in one + * shot mode. + * @irq: The software interrupt assigned to @data + * @data: The IIO poll function dispatched by external trigger our device is + * attached to. + * + * Bottom-half handler called by the IIO trigger to which our device is + * currently attached. Allows us to synchronize this device buffered sampling + * either with external events (such as timer expiration, external device sample + * ready, etc...) or with its own interrupt (internal hardware trigger). + * + * When using an external trigger, basically run the same sequence of operations + * as for zpa2326_sample_oneshot() with the following hereafter. Hardware FIFO + * is not cleared since already done at buffering enable time and samples + * dequeueing always retrieves the most recent value. + * + * Otherwise, when internal hardware trigger has dispatched us, just fetch data + * from hardware FIFO. + * + * Fetched data will pushed unprocessed to IIO buffer since samples conversion + * is delegated to userspace in buffered mode (endianness, etc...). + * + * Return: + * %IRQ_NONE - no consistent interrupt happened ; + * %IRQ_HANDLED - there was new samples available. + */ +static irqreturn_t zpa2326_trigger_handler(int irq, void *data) +{ + struct iio_dev *indio_dev = ((struct iio_poll_func *) + data)->indio_dev; + struct zpa2326_private *priv = iio_priv(indio_dev); + bool cont; + + /* + * We have been dispatched, meaning we are in triggered buffer mode. + * Using our own internal trigger implies we are currently in continuous + * hardware sampling mode. + */ + cont = iio_trigger_using_own(indio_dev); + + if (!cont) { + /* On demand sampling : start a one shot cycle. */ + if (zpa2326_start_oneshot(indio_dev)) + goto out; + + /* Wait for sampling cycle to complete. */ + if (priv->irq <= 0) { + /* No interrupt available: poll for completion. */ + if (zpa2326_poll_oneshot_completion(indio_dev)) + goto out; + + /* Only timestamp sample once it is ready. */ + priv->timestamp = iio_get_time_ns(indio_dev); + } else { + /* Interrupt handlers will timestamp for us. */ + if (zpa2326_wait_oneshot_completion(indio_dev, priv)) + goto out; + } + } + + /* Enqueue to IIO buffer / userspace. */ + zpa2326_fill_sample_buffer(indio_dev, priv); + +out: + if (!cont) + /* Don't switch to low power if sampling continuously. */ + zpa2326_sleep(indio_dev); + + /* Inform attached trigger we are done. */ + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +/** + * zpa2326_preenable_buffer() - Prepare device for configuring triggered + * sampling + * modes. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Basically power up device. + * Called with IIO device's lock held. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_preenable_buffer(struct iio_dev *indio_dev) +{ + int ret = zpa2326_resume(indio_dev); + + if (ret < 0) + return ret; + + /* Tell zpa2326_postenable_buffer() if we have just been powered on. */ + ((struct zpa2326_private *) + iio_priv(indio_dev))->waken = iio_priv(indio_dev); + + return 0; +} + +/** + * zpa2326_postenable_buffer() - Configure device for triggered sampling. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Basically setup one-shot mode if plugging external trigger. + * Otherwise, let internal trigger configure continuous sampling : + * see zpa2326_set_trigger_state(). + * + * If an error is returned, IIO layer will call our postdisable hook for us, + * i.e. no need to explicitly power device off here. + * Called with IIO device's lock held. + * + * Called with IIO device's lock held. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_postenable_buffer(struct iio_dev *indio_dev) +{ + const struct zpa2326_private *priv = iio_priv(indio_dev); + int err; + + if (!priv->waken) { + /* + * We were already power supplied. Just clear hardware FIFO to + * get rid of samples acquired during previous rounds (if any). + */ + err = zpa2326_clear_fifo(indio_dev, 0); + if (err) + goto err; + } + + if (!iio_trigger_using_own(indio_dev) && priv->waken) { + /* + * We are using an external trigger and we have just been + * powered up: reconfigure one-shot mode. + */ + err = zpa2326_config_oneshot(indio_dev, priv->irq); + if (err) + goto err; + } + + /* Plug our own trigger event handler. */ + err = iio_triggered_buffer_postenable(indio_dev); + if (err) + goto err; + + return 0; + +err: + zpa2326_err(indio_dev, "failed to enable buffering (%d)", err); + + return err; +} + +static int zpa2326_postdisable_buffer(struct iio_dev *indio_dev) +{ + zpa2326_suspend(indio_dev); + + return 0; +} + +static const struct iio_buffer_setup_ops zpa2326_buffer_setup_ops = { + .preenable = zpa2326_preenable_buffer, + .postenable = zpa2326_postenable_buffer, + .predisable = iio_triggered_buffer_predisable, + .postdisable = zpa2326_postdisable_buffer +}; + +/** + * zpa2326_set_trigger_state() - Start / stop continuous sampling. + * @trig: The trigger being attached to IIO device associated with the sampling + * hardware. + * @state: Tell whether to start (true) or stop (false) + * + * Basically enable / disable hardware continuous sampling mode. + * + * Called with IIO device's lock held at postenable() or predisable() time. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_set_trigger_state(struct iio_trigger *trig, bool state) +{ + const struct iio_dev *indio_dev = dev_get_drvdata( + trig->dev.parent); + const struct zpa2326_private *priv = iio_priv(indio_dev); + int err; + + if (!state) { + /* + * Switch trigger off : in case of failure, interrupt is left + * disabled in order to prevent handler from accessing released + * resources. + */ + unsigned int val; + + /* + * As device is working in continuous mode, handlers may be + * accessing resources we are currently freeing... + * Prevent this by disabling interrupt handlers and ensure + * the device will generate no more interrupts unless explicitly + * required to, i.e. by restoring back to default one shot mode. + */ + disable_irq(priv->irq); + + /* + * Disable continuous sampling mode to restore settings for + * one shot / direct sampling operations. + */ + err = regmap_write(priv->regmap, ZPA2326_CTRL_REG3_REG, + zpa2326_highest_frequency()->odr); + if (err) + return err; + + /* + * Now that device won't generate interrupts on its own, + * acknowledge any currently active interrupts (may happen on + * rare occasions while stopping continuous mode). + */ + err = regmap_read(priv->regmap, ZPA2326_INT_SOURCE_REG, &val); + if (err < 0) + return err; + + /* + * Re-enable interrupts only if we can guarantee the device will + * generate no more interrupts to prevent handlers from + * accessing released resources. + */ + enable_irq(priv->irq); + + zpa2326_dbg(indio_dev, "continuous mode stopped"); + } else { + /* + * Switch trigger on : start continuous sampling at required + * frequency. + */ + + if (priv->waken) { + /* Enable interrupt if getting out of reset. */ + err = regmap_write(priv->regmap, ZPA2326_CTRL_REG1_REG, + (u8) + ~ZPA2326_CTRL_REG1_MASK_DATA_READY); + if (err) + return err; + } + + /* Enable continuous sampling at specified frequency. */ + err = regmap_write(priv->regmap, ZPA2326_CTRL_REG3_REG, + ZPA2326_CTRL_REG3_ENABLE_MEAS | + priv->frequency->odr); + if (err) + return err; + + zpa2326_dbg(indio_dev, "continuous mode setup @%dHz", + priv->frequency->hz); + } + + return 0; +} + +static const struct iio_trigger_ops zpa2326_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = zpa2326_set_trigger_state, +}; + +/** + * zpa2326_init_trigger() - Create an interrupt driven / hardware trigger + * allowing to notify external devices a new sample is + * ready. + * @parent: Hardware sampling device @indio_dev is a child of. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * @irq: Optional interrupt line the hardware uses to notify new data + * samples are ready. Negative or zero values indicate no interrupts + * are available, meaning polling is required. + * + * Only relevant when DT declares a valid interrupt line. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_init_managed_trigger(struct device *parent, + struct iio_dev *indio_dev, + struct zpa2326_private *private, + int irq) +{ + struct iio_trigger *trigger; + int ret; + + if (irq <= 0) + return 0; + + trigger = devm_iio_trigger_alloc(parent, "%s-dev%d", + indio_dev->name, indio_dev->id); + if (!trigger) + return -ENOMEM; + + /* Basic setup. */ + trigger->dev.parent = parent; + trigger->ops = &zpa2326_trigger_ops; + + private->trigger = trigger; + + /* Register to triggers space. */ + ret = devm_iio_trigger_register(parent, trigger); + if (ret) + dev_err(parent, "failed to register hardware trigger (%d)", + ret); + + return ret; +} + +static int zpa2326_get_frequency(const struct iio_dev *indio_dev) +{ + return ((struct zpa2326_private *)iio_priv(indio_dev))->frequency->hz; +} + +static int zpa2326_set_frequency(struct iio_dev *indio_dev, int hz) +{ + struct zpa2326_private *priv = iio_priv(indio_dev); + int freq; + int err; + + /* Check if requested frequency is supported. */ + for (freq = 0; freq < ARRAY_SIZE(zpa2326_sampling_frequencies); freq++) + if (zpa2326_sampling_frequencies[freq].hz == hz) + break; + if (freq == ARRAY_SIZE(zpa2326_sampling_frequencies)) + return -EINVAL; + + /* Don't allow changing frequency if buffered sampling is ongoing. */ + err = iio_device_claim_direct_mode(indio_dev); + if (err) + return err; + + priv->frequency = &zpa2326_sampling_frequencies[freq]; + + iio_device_release_direct_mode(indio_dev); + + return 0; +} + +/* Expose supported hardware sampling frequencies (Hz) through sysfs. */ +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1 5 11 23"); + +static struct attribute *zpa2326_attributes[] = { + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group zpa2326_attribute_group = { + .attrs = zpa2326_attributes, +}; + +static int zpa2326_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_RAW: + return zpa2326_sample_oneshot(indio_dev, chan->type, val); + + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_PRESSURE: + /* + * Pressure resolution is 1/64 Pascal. Scale to kPascal + * as required by IIO ABI. + */ + *val = 1; + *val2 = 64000; + return IIO_VAL_FRACTIONAL; + + case IIO_TEMP: + /* + * Temperature follows the equation: + * Temp[degC] = Tempcode * 0.00649 - 176.83 + * where: + * Tempcode is composed the raw sampled 16 bits. + * + * Hence, to produce a temperature in milli-degrees + * Celsius according to IIO ABI, we need to apply the + * following equation to raw samples: + * Temp[milli degC] = (Tempcode + Offset) * Scale + * where: + * Offset = -176.83 / 0.00649 + * Scale = 0.00649 * 1000 + */ + *val = 6; + *val2 = 490000; + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } + + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + *val = -17683000; + *val2 = 649; + return IIO_VAL_FRACTIONAL; + + default: + return -EINVAL; + } + + case IIO_CHAN_INFO_SAMP_FREQ: + *val = zpa2326_get_frequency(indio_dev); + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static int zpa2326_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int val, + int val2, + long mask) +{ + if ((mask != IIO_CHAN_INFO_SAMP_FREQ) || val2) + return -EINVAL; + + return zpa2326_set_frequency(indio_dev, val); +} + +static const struct iio_chan_spec zpa2326_channels[] = { + [0] = { + .type = IIO_PRESSURE, + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 24, + .storagebits = 32, + .endianness = IIO_LE, + }, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + [1] = { + .type = IIO_TEMP, + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .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), + }, + [2] = IIO_CHAN_SOFT_TIMESTAMP(2), +}; + +static const struct iio_info zpa2326_info = { + .driver_module = THIS_MODULE, + .attrs = &zpa2326_attribute_group, + .read_raw = zpa2326_read_raw, + .write_raw = zpa2326_write_raw, +}; + +static struct iio_dev *zpa2326_create_managed_iiodev(struct device *device, + const char *name, + struct regmap *regmap) +{ + struct iio_dev *indio_dev; + + /* Allocate space to hold IIO device internal state. */ + indio_dev = devm_iio_device_alloc(device, + sizeof(struct zpa2326_private)); + if (!indio_dev) + return NULL; + + /* Setup for userspace synchronous on demand sampling. */ + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->dev.parent = device; + indio_dev->channels = zpa2326_channels; + indio_dev->num_channels = ARRAY_SIZE(zpa2326_channels); + indio_dev->name = name; + indio_dev->info = &zpa2326_info; + + return indio_dev; +} + +int zpa2326_probe(struct device *parent, + const char *name, + int irq, + unsigned int hwid, + struct regmap *regmap) +{ + struct iio_dev *indio_dev; + struct zpa2326_private *priv; + int err; + unsigned int id; + + indio_dev = zpa2326_create_managed_iiodev(parent, name, regmap); + if (!indio_dev) + return -ENOMEM; + + priv = iio_priv(indio_dev); + + priv->vref = devm_regulator_get(parent, "vref"); + if (IS_ERR(priv->vref)) + return PTR_ERR(priv->vref); + + priv->vdd = devm_regulator_get(parent, "vdd"); + if (IS_ERR(priv->vdd)) + return PTR_ERR(priv->vdd); + + /* Set default hardware sampling frequency to highest rate supported. */ + priv->frequency = zpa2326_highest_frequency(); + + /* + * Plug device's underlying bus abstraction : this MUST be set before + * registering interrupt handlers since an interrupt might happen if + * power up sequence is not properly applied. + */ + priv->regmap = regmap; + + err = devm_iio_triggered_buffer_setup(parent, indio_dev, NULL, + zpa2326_trigger_handler, + &zpa2326_buffer_setup_ops); + if (err) + return err; + + err = zpa2326_init_managed_trigger(parent, indio_dev, priv, irq); + if (err) + return err; + + err = zpa2326_init_managed_irq(parent, indio_dev, priv, irq); + if (err) + return err; + + /* Power up to check device ID and perform initial hardware setup. */ + err = zpa2326_power_on(indio_dev, priv); + if (err) + return err; + + /* Read id register to check we are talking to the right slave. */ + err = regmap_read(regmap, ZPA2326_DEVICE_ID_REG, &id); + if (err) + goto sleep; + + if (id != hwid) { + dev_err(parent, "found device with unexpected id %02x", id); + err = -ENODEV; + goto sleep; + } + + err = zpa2326_config_oneshot(indio_dev, irq); + if (err) + goto sleep; + + /* Setup done : go sleeping. Device will be awaken upon user request. */ + err = zpa2326_sleep(indio_dev); + if (err) + goto poweroff; + + dev_set_drvdata(parent, indio_dev); + + zpa2326_init_runtime(parent); + + err = iio_device_register(indio_dev); + if (err) { + zpa2326_fini_runtime(parent); + goto poweroff; + } + + return 0; + +sleep: + /* Put to sleep just in case power regulators are "dummy" ones. */ + zpa2326_sleep(indio_dev); +poweroff: + zpa2326_power_off(indio_dev, priv); + + return err; +} +EXPORT_SYMBOL_GPL(zpa2326_probe); + +void zpa2326_remove(const struct device *parent) +{ + struct iio_dev *indio_dev = dev_get_drvdata(parent); + + iio_device_unregister(indio_dev); + zpa2326_fini_runtime(indio_dev->dev.parent); + zpa2326_sleep(indio_dev); + zpa2326_power_off(indio_dev, iio_priv(indio_dev)); +} +EXPORT_SYMBOL_GPL(zpa2326_remove); + +MODULE_AUTHOR("Gregor Boirie "); +MODULE_DESCRIPTION("Core driver for Murata ZPA2326 pressure sensor"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/zpa2326.h b/drivers/iio/pressure/zpa2326.h new file mode 100644 index 000000000000..05d3e1e3a449 --- /dev/null +++ b/drivers/iio/pressure/zpa2326.h @@ -0,0 +1,89 @@ +/* + * Murata ZPA2326 pressure and temperature sensor IIO driver + * + * Copyright (c) 2016 Parrot S.A. + * + * Author: Gregor Boirie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _ZPA2326_H +#define _ZPA2326_H + +/* Register map. */ +#define ZPA2326_REF_P_XL_REG (0x8) +#define ZPA2326_REF_P_L_REG (0x9) +#define ZPA2326_REF_P_H_REG (0xa) +#define ZPA2326_DEVICE_ID_REG (0xf) +#define ZPA2326_DEVICE_ID (0xb9) +#define ZPA2326_RES_CONF_REG (0x10) +#define ZPA2326_CTRL_REG0_REG (0x20) +#define ZPA2326_CTRL_REG0_ONE_SHOT BIT(0) +#define ZPA2326_CTRL_REG0_ENABLE BIT(1) +#define ZPA2326_CTRL_REG1_REG (0x21) +#define ZPA2326_CTRL_REG1_MASK_DATA_READY BIT(2) +#define ZPA2326_CTRL_REG2_REG (0x22) +#define ZPA2326_CTRL_REG2_SWRESET BIT(2) +#define ZPA2326_CTRL_REG3_REG (0x23) +#define ZPA2326_CTRL_REG3_ODR_SHIFT (4) +#define ZPA2326_CTRL_REG3_ENABLE_MEAS BIT(7) +#define ZPA2326_INT_SOURCE_REG (0x24) +#define ZPA2326_INT_SOURCE_DATA_READY BIT(2) +#define ZPA2326_THS_P_LOW_REG (0x25) +#define ZPA2326_THS_P_HIGH_REG (0x26) +#define ZPA2326_STATUS_REG (0x27) +#define ZPA2326_STATUS_P_DA BIT(1) +#define ZPA2326_STATUS_FIFO_E BIT(2) +#define ZPA2326_STATUS_P_OR BIT(5) +#define ZPA2326_PRESS_OUT_XL_REG (0x28) +#define ZPA2326_PRESS_OUT_L_REG (0x29) +#define ZPA2326_PRESS_OUT_H_REG (0x2a) +#define ZPA2326_TEMP_OUT_L_REG (0x2b) +#define ZPA2326_TEMP_OUT_H_REG (0x2c) + +struct device; +struct regmap; + +bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg); +bool zpa2326_isreg_readable(struct device *dev, unsigned int reg); +bool zpa2326_isreg_precious(struct device *dev, unsigned int reg); + +/** + * zpa2326_probe() - Instantiate and register core ZPA2326 IIO device + * @parent: Hardware sampling device the created IIO device will be a child of. + * @name: Arbitrary name to identify the device. + * @irq: Interrupt line, negative if none. + * @hwid: Expected device hardware id. + * @regmap: Registers map used to abstract underlying bus accesses. + * + * Return: Zero when successful, a negative error code otherwise. + */ +int zpa2326_probe(struct device *parent, + const char *name, + int irq, + unsigned int hwid, + struct regmap *regmap); + +/** + * zpa2326_remove() - Unregister and destroy core ZPA2326 IIO device. + * @parent: Hardware sampling device the IIO device to remove is a child of. + */ +void zpa2326_remove(const struct device *parent); + +#ifdef CONFIG_PM +#include +extern const struct dev_pm_ops zpa2326_pm_ops; +#define ZPA2326_PM_OPS (&zpa2326_pm_ops) +#else +#define ZPA2326_PM_OPS (NULL) +#endif + +#endif diff --git a/drivers/iio/pressure/zpa2326_i2c.c b/drivers/iio/pressure/zpa2326_i2c.c new file mode 100644 index 000000000000..e4d27dd4493a --- /dev/null +++ b/drivers/iio/pressure/zpa2326_i2c.c @@ -0,0 +1,99 @@ +/* + * Murata ZPA2326 I2C pressure and temperature sensor driver + * + * Copyright (c) 2016 Parrot S.A. + * + * Author: Gregor Boirie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include "zpa2326.h" + +/* + * read_flag_mask: + * - address bit 7 must be set to request a register read operation + */ +static const struct regmap_config zpa2326_regmap_i2c_config = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = zpa2326_isreg_writeable, + .readable_reg = zpa2326_isreg_readable, + .precious_reg = zpa2326_isreg_precious, + .max_register = ZPA2326_TEMP_OUT_H_REG, + .read_flag_mask = BIT(7), + .cache_type = REGCACHE_NONE, +}; + +static unsigned int zpa2326_i2c_hwid(const struct i2c_client *client) +{ +#define ZPA2326_SA0(_addr) (_addr & BIT(0)) +#define ZPA2326_DEVICE_ID_SA0_SHIFT (1) + + /* Identification register bit 1 mirrors device address bit 0. */ + return (ZPA2326_DEVICE_ID | + (ZPA2326_SA0(client->addr) << ZPA2326_DEVICE_ID_SA0_SHIFT)); +} + +static int zpa2326_probe_i2c(struct i2c_client *client, + const struct i2c_device_id *i2c_id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(client, &zpa2326_regmap_i2c_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "failed to init registers map"); + return PTR_ERR(regmap); + } + + return zpa2326_probe(&client->dev, i2c_id->name, client->irq, + zpa2326_i2c_hwid(client), regmap); +} + +static int zpa2326_remove_i2c(struct i2c_client *client) +{ + zpa2326_remove(&client->dev); + + return 0; +} + +static const struct i2c_device_id zpa2326_i2c_ids[] = { + { "zpa2326", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, zpa2326_i2c_ids); + +#if defined(CONFIG_OF) +static const struct of_device_id zpa2326_i2c_matches[] = { + { .compatible = "murata,zpa2326" }, + { } +}; +MODULE_DEVICE_TABLE(of, zpa2326_i2c_matches); +#endif + +static struct i2c_driver zpa2326_i2c_driver = { + .driver = { + .name = "zpa2326-i2c", + .of_match_table = of_match_ptr(zpa2326_i2c_matches), + .pm = ZPA2326_PM_OPS, + }, + .probe = zpa2326_probe_i2c, + .remove = zpa2326_remove_i2c, + .id_table = zpa2326_i2c_ids, +}; +module_i2c_driver(zpa2326_i2c_driver); + +MODULE_AUTHOR("Gregor Boirie "); +MODULE_DESCRIPTION("I2C driver for Murata ZPA2326 pressure sensor"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/zpa2326_spi.c b/drivers/iio/pressure/zpa2326_spi.c new file mode 100644 index 000000000000..bd2c1c319fca --- /dev/null +++ b/drivers/iio/pressure/zpa2326_spi.c @@ -0,0 +1,103 @@ +/* + * Murata ZPA2326 SPI pressure and temperature sensor driver + * + * Copyright (c) 2016 Parrot S.A. + * + * Author: Gregor Boirie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include "zpa2326.h" + +/* + * read_flag_mask: + * - address bit 7 must be set to request a register read operation + * - address bit 6 must be set to request register address auto increment + */ +static const struct regmap_config zpa2326_regmap_spi_config = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = zpa2326_isreg_writeable, + .readable_reg = zpa2326_isreg_readable, + .precious_reg = zpa2326_isreg_precious, + .max_register = ZPA2326_TEMP_OUT_H_REG, + .read_flag_mask = BIT(7) | BIT(6), + .cache_type = REGCACHE_NONE, +}; + +static int zpa2326_probe_spi(struct spi_device *spi) +{ + struct regmap *regmap; + int err; + + regmap = devm_regmap_init_spi(spi, &zpa2326_regmap_spi_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "failed to init registers map"); + return PTR_ERR(regmap); + } + + /* + * Enforce SPI slave settings to prevent from DT misconfiguration. + * + * Clock is idle high. Sampling happens on trailing edge, i.e., rising + * edge. Maximum bus frequency is 1 MHz. Registers are 8 bits wide. + */ + spi->mode = SPI_MODE_3; + spi->max_speed_hz = min(spi->max_speed_hz, 1000000U); + spi->bits_per_word = 8; + err = spi_setup(spi); + if (err < 0) + return err; + + return zpa2326_probe(&spi->dev, spi_get_device_id(spi)->name, + spi->irq, ZPA2326_DEVICE_ID, regmap); +} + +static int zpa2326_remove_spi(struct spi_device *spi) +{ + zpa2326_remove(&spi->dev); + + return 0; +} + +static const struct spi_device_id zpa2326_spi_ids[] = { + { "zpa2326", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, zpa2326_spi_ids); + +#if defined(CONFIG_OF) +static const struct of_device_id zpa2326_spi_matches[] = { + { .compatible = "murata,zpa2326" }, + { } +}; +MODULE_DEVICE_TABLE(of, zpa2326_spi_matches); +#endif + +static struct spi_driver zpa2326_spi_driver = { + .driver = { + .name = "zpa2326-spi", + .of_match_table = of_match_ptr(zpa2326_spi_matches), + .pm = ZPA2326_PM_OPS, + }, + .probe = zpa2326_probe_spi, + .remove = zpa2326_remove_spi, + .id_table = zpa2326_spi_ids, +}; +module_spi_driver(zpa2326_spi_driver); + +MODULE_AUTHOR("Gregor Boirie "); +MODULE_DESCRIPTION("SPI driver for Murata ZPA2326 pressure sensor"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 1d74b3aafeed..1f06282ec793 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -516,7 +516,7 @@ static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) sx9500_push_events(indio_dev); if (val & SX9500_CONVDONE_IRQ) - complete_all(&data->completion); + complete(&data->completion); out: mutex_unlock(&data->mutex); @@ -1025,6 +1025,12 @@ static const struct acpi_device_id sx9500_acpi_match[] = { }; MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); +static const struct of_device_id sx9500_of_match[] = { + { .compatible = "semtech,sx9500", }, + { } +}; +MODULE_DEVICE_TABLE(of, sx9500_of_match); + static const struct i2c_device_id sx9500_id[] = { {"sx9500", 0}, { }, @@ -1035,6 +1041,7 @@ static struct i2c_driver sx9500_driver = { .driver = { .name = SX9500_DRIVER_NAME, .acpi_match_table = ACPI_PTR(sx9500_acpi_match), + .of_match_table = of_match_ptr(sx9500_of_match), .pm = &sx9500_pm_ops, }, .probe = sx9500_probe, diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index c4664e5de791..5ea77a7e261d 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -3,6 +3,22 @@ # menu "Temperature sensors" +config MAXIM_THERMOCOUPLE + tristate "Maxim thermocouple sensors" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for the Maxim series of + thermocouple sensors connected via SPI. + + Supported sensors: + * MAX6675 + * MAX31855 + + This driver can also be built as a module. If so, the module will + be called maxim_thermocouple. + config MLX90614 tristate "MLX90614 contact-less infrared sensor" depends on I2C diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile index 02bc79d49b24..78c3de0dc3f0 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile @@ -2,6 +2,7 @@ # Makefile for industrial I/O temperature drivers # +obj-$(CONFIG_MAXIM_THERMOCOUPLE) += maxim_thermocouple.o obj-$(CONFIG_MLX90614) += mlx90614.o obj-$(CONFIG_TMP006) += tmp006.o obj-$(CONFIG_TSYS01) += tsys01.o diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c new file mode 100644 index 000000000000..39dd2026ccc9 --- /dev/null +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -0,0 +1,281 @@ +/* + * maxim_thermocouple.c - Support for Maxim thermocouple chips + * + * Copyright (C) 2016 Matt Ranostay + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXIM_THERMOCOUPLE_DRV_NAME "maxim_thermocouple" + +enum { + MAX6675, + MAX31855, +}; + +static const struct iio_chan_spec max6675_channels[] = { + { /* thermocouple temperature */ + .type = IIO_TEMP, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 13, + .storagebits = 16, + .shift = 3, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static const struct iio_chan_spec max31855_channels[] = { + { /* thermocouple temperature */ + .type = IIO_TEMP, + .address = 2, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 14, + .storagebits = 16, + .shift = 2, + .endianness = IIO_BE, + }, + }, + { /* cold junction temperature */ + .type = IIO_TEMP, + .address = 0, + .channel2 = IIO_MOD_TEMP_AMBIENT, + .modified = 1, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 12, + .storagebits = 16, + .shift = 4, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(2), +}; + +static const unsigned long max31855_scan_masks[] = {0x3, 0}; + +struct maxim_thermocouple_chip { + const struct iio_chan_spec *channels; + const unsigned long *scan_masks; + u8 num_channels; + u8 read_size; + + /* bit-check for valid input */ + u32 status_bit; +}; + +static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = { + [MAX6675] = { + .channels = max6675_channels, + .num_channels = ARRAY_SIZE(max6675_channels), + .read_size = 2, + .status_bit = BIT(2), + }, + [MAX31855] = { + .channels = max31855_channels, + .num_channels = ARRAY_SIZE(max31855_channels), + .read_size = 4, + .scan_masks = max31855_scan_masks, + .status_bit = BIT(16), + }, +}; + +struct maxim_thermocouple_data { + struct spi_device *spi; + const struct maxim_thermocouple_chip *chip; + + u8 buffer[16] ____cacheline_aligned; +}; + +static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, + struct iio_chan_spec const *chan, int *val) +{ + unsigned int storage_bytes = data->chip->read_size; + unsigned int shift = chan->scan_type.shift + (chan->address * 8); + unsigned int buf; + int ret; + + ret = spi_read(data->spi, (void *) &buf, storage_bytes); + if (ret) + return ret; + + switch (storage_bytes) { + case 2: + *val = be16_to_cpu(buf); + break; + case 4: + *val = be32_to_cpu(buf); + break; + } + + /* check to be sure this is a valid reading */ + if (*val & data->chip->status_bit) + return -EINVAL; + + *val = sign_extend32(*val >> shift, chan->scan_type.realbits - 1); + + return 0; +} + +static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct maxim_thermocouple_data *data = iio_priv(indio_dev); + int ret; + + ret = spi_read(data->spi, data->buffer, data->chip->read_size); + if (!ret) { + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns(indio_dev)); + } + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct maxim_thermocouple_data *data = iio_priv(indio_dev); + int ret = -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = maxim_thermocouple_read(data, chan, val); + iio_device_release_direct_mode(indio_dev); + + if (!ret) + return IIO_VAL_INT; + + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->channel2) { + case IIO_MOD_TEMP_AMBIENT: + *val = 62; + *val2 = 500000; /* 1000 * 0.0625 */ + ret = IIO_VAL_INT_PLUS_MICRO; + break; + default: + *val = 250; /* 1000 * 0.25 */ + ret = IIO_VAL_INT; + }; + break; + } + + return ret; +} + +static const struct iio_info maxim_thermocouple_info = { + .driver_module = THIS_MODULE, + .read_raw = maxim_thermocouple_read_raw, +}; + +static int maxim_thermocouple_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct iio_dev *indio_dev; + struct maxim_thermocouple_data *data; + const struct maxim_thermocouple_chip *chip = + &maxim_thermocouple_chips[id->driver_data]; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &maxim_thermocouple_info; + indio_dev->name = MAXIM_THERMOCOUPLE_DRV_NAME; + indio_dev->channels = chip->channels; + indio_dev->available_scan_masks = chip->scan_masks; + indio_dev->num_channels = chip->num_channels; + indio_dev->modes = INDIO_DIRECT_MODE; + + data = iio_priv(indio_dev); + data->spi = spi; + data->chip = chip; + + ret = iio_triggered_buffer_setup(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; +} + +static const struct spi_device_id maxim_thermocouple_id[] = { + {"max6675", MAX6675}, + {"max31855", MAX31855}, + {}, +}; +MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); + +static struct spi_driver maxim_thermocouple_driver = { + .driver = { + .name = MAXIM_THERMOCOUPLE_DRV_NAME, + }, + .probe = maxim_thermocouple_probe, + .remove = maxim_thermocouple_remove, + .id_table = maxim_thermocouple_id, +}; +module_spi_driver(maxim_thermocouple_driver); + +MODULE_AUTHOR("Matt Ranostay "); +MODULE_DESCRIPTION("Maxim thermocouple sensors"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index af9476460023..58a7b3504b82 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -40,8 +40,6 @@ source "drivers/staging/rtl8712/Kconfig" source "drivers/staging/rtl8188eu/Kconfig" -source "drivers/staging/rtl8723au/Kconfig" - source "drivers/staging/rts5208/Kconfig" source "drivers/staging/octeon/Kconfig" @@ -104,4 +102,8 @@ source "drivers/staging/i4l/Kconfig" source "drivers/staging/ks7010/Kconfig" +source "drivers/staging/greybus/Kconfig" + +source "drivers/staging/vc04_services/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9f6009dcafa8..2fa9745db614 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ obj-$(CONFIG_R8188EU) += rtl8188eu/ -obj-$(CONFIG_R8723AU) += rtl8723au/ obj-$(CONFIG_RTS5208) += rts5208/ obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ @@ -41,3 +40,5 @@ obj-$(CONFIG_WILC1000) += wilc1000/ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_ISDN_I4L) += i4l/ obj-$(CONFIG_KS7010) += ks7010/ +obj-$(CONFIG_GREYBUS) += greybus/ +obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/ diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 06e41d24ec62..6c00d6f765c6 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -24,19 +24,6 @@ config ANDROID_LOW_MEMORY_KILLER scripts (/init.rc), and it defines priority values with minimum free memory size for each priority. -config SW_SYNC - bool "Software synchronization framework" - default n - depends on SYNC_FILE - depends on DEBUG_FS - ---help--- - A sync object driver that uses a 32bit counter to coordinate - synchronization. Useful when there is no hardware primitive backing - the synchronization. - - WARNING: improper use of this can result in deadlocking kernel - drivers from userspace. Intended for test and debug only. - source "drivers/staging/android/ion/Kconfig" endif # if ANDROID diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 7ca61b77a8d4..7ed1be798909 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -4,4 +4,3 @@ obj-y += ion/ obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o -obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 19c1572f1525..c8fb4134c55d 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -36,7 +36,19 @@ config ION_TEGRA config ION_HISI tristate "Ion for Hisilicon" depends on ARCH_HISI && ION + select ION_OF help Choose this option if you wish to use ion on Hisilicon Platform. source "drivers/staging/android/ion/hisilicon/Kconfig" + +config ION_OF + bool "Devicetree support for Ion" + depends on ION && OF_ADDRESS + help + Provides base support for defining Ion heaps in devicetree + and setting them up. Also includes functions for platforms + to parse the devicetree and expand for their own custom + extensions + + If using Ion and devicetree, you should say Y here diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 18cc2aa593c2..5d630a088381 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,4 +1,5 @@ -obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ +obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ + ion_page_pool.o ion_system_heap.o \ ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o obj-$(CONFIG_ION_TEST) += ion_test.o ifdef CONFIG_COMPAT @@ -8,4 +9,5 @@ endif obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o obj-$(CONFIG_ION_TEGRA) += tegra/ obj-$(CONFIG_ION_HISI) += hisilicon/ +obj-$(CONFIG_ION_OF) += ion_of.o diff --git a/drivers/staging/android/ion/devicetree.txt b/drivers/staging/android/ion/devicetree.txt new file mode 100644 index 000000000000..168715271f06 --- /dev/null +++ b/drivers/staging/android/ion/devicetree.txt @@ -0,0 +1,51 @@ +Ion Memory Manager + +Ion is a memory manager that allows for sharing of buffers via dma-buf. +Ion allows for different types of allocation via an abstraction called +a 'heap'. A heap represents a specific type of memory. Each heap has +a different type. There can be multiple instances of the same heap +type. + +Specific heap instances are tied to heap IDs. Heap IDs are not to be specified +in the devicetree. + +Required properties for Ion + +- compatible: "linux,ion" PLUS a compatible property for the device + +All child nodes of a linux,ion node are interpreted as heaps + +required properties for heaps + +- compatible: compatible string for a heap type PLUS a compatible property +for the specific instance of the heap. Current heap types +-- linux,ion-heap-system +-- linux,ion-heap-system-contig +-- linux,ion-heap-carveout +-- linux,ion-heap-chunk +-- linux,ion-heap-dma +-- linux,ion-heap-custom + +Optional properties +- memory-region: A phandle to a memory region. Required for DMA heap type +(see reserved-memory.txt for details on the reservation) + +Example: + + ion { + compatbile = "hisilicon,ion", "linux,ion"; + + ion-system-heap { + compatbile = "hisilicon,system-heap", "linux,ion-heap-system" + }; + + ion-camera-region { + compatible = "hisilicon,camera-heap", "linux,ion-heap-dma" + memory-region = <&camera_region>; + }; + + ion-fb-region { + compatbile = "hisilicon,fb-heap", "linux,ion-heap-dma" + memory-region = <&fb_region>; + }; + } diff --git a/drivers/staging/android/ion/hisilicon/hi6220_ion.c b/drivers/staging/android/ion/hisilicon/hi6220_ion.c index fe9f0fd210cd..0de7897fd4bf 100644 --- a/drivers/staging/android/ion/hisilicon/hi6220_ion.c +++ b/drivers/staging/android/ion/hisilicon/hi6220_ion.c @@ -19,181 +19,74 @@ #include #include "../ion_priv.h" #include "../ion.h" +#include "../ion_of.h" -struct hi6220_ion_type_table { - const char *name; - enum ion_heap_type type; +struct hisi_ion_dev { + struct ion_heap **heaps; + struct ion_device *idev; + struct ion_platform_data *data; }; -static struct hi6220_ion_type_table ion_type_table[] = { - {"ion_system", ION_HEAP_TYPE_SYSTEM}, - {"ion_system_contig", ION_HEAP_TYPE_SYSTEM_CONTIG}, - {"ion_carveout", ION_HEAP_TYPE_CARVEOUT}, - {"ion_chunk", ION_HEAP_TYPE_CHUNK}, - {"ion_dma", ION_HEAP_TYPE_DMA}, - {"ion_custom", ION_HEAP_TYPE_CUSTOM}, +static struct ion_of_heap hisi_heaps[] = { + PLATFORM_HEAP("hisilicon,sys_user", 0, + ION_HEAP_TYPE_SYSTEM, "sys_user"), + PLATFORM_HEAP("hisilicon,sys_contig", 1, + ION_HEAP_TYPE_SYSTEM_CONTIG, "sys_contig"), + PLATFORM_HEAP("hisilicon,cma", ION_HEAP_TYPE_DMA, ION_HEAP_TYPE_DMA, + "cma"), + {} }; -static struct ion_device *idev; -static int num_heaps; -static struct ion_heap **heaps; -static struct ion_platform_heap **heaps_data; - -static int get_type_by_name(const char *name, enum ion_heap_type *type) +static int hi6220_ion_probe(struct platform_device *pdev) { + struct hisi_ion_dev *ipdev; int i; - for (i = 0; i < ARRAY_SIZE(ion_type_table); i++) { - if (strncmp(name, ion_type_table[i].name, strlen(name))) - continue; - - *type = ion_type_table[i].type; - return 0; - } - - return -EINVAL; -} - -static int hi6220_set_platform_data(struct platform_device *pdev) -{ - unsigned int base; - unsigned int size; - unsigned int id; - const char *heap_name; - const char *type_name; - enum ion_heap_type type; - int ret; - struct device_node *np; - struct ion_platform_heap *p_data; - const struct device_node *dt_node = pdev->dev.of_node; - int index = 0; - - for_each_child_of_node(dt_node, np) - num_heaps++; - - heaps_data = devm_kzalloc(&pdev->dev, - sizeof(struct ion_platform_heap *) * - num_heaps, - GFP_KERNEL); - if (!heaps_data) + ipdev = devm_kzalloc(&pdev->dev, sizeof(*ipdev), GFP_KERNEL); + if (!ipdev) return -ENOMEM; - for_each_child_of_node(dt_node, np) { - ret = of_property_read_string(np, "heap-name", &heap_name); - if (ret < 0) { - pr_err("check the name of node %s\n", np->name); - continue; - } + platform_set_drvdata(pdev, ipdev); - ret = of_property_read_u32(np, "heap-id", &id); - if (ret < 0) { - pr_err("check the id %s\n", np->name); - continue; - } + ipdev->idev = ion_device_create(NULL); + if (IS_ERR(ipdev->idev)) + return PTR_ERR(ipdev->idev); - ret = of_property_read_u32(np, "heap-base", &base); - if (ret < 0) { - pr_err("check the base of node %s\n", np->name); - continue; - } + ipdev->data = ion_parse_dt(pdev, hisi_heaps); + if (IS_ERR(ipdev->data)) + return PTR_ERR(ipdev->data); - ret = of_property_read_u32(np, "heap-size", &size); - if (ret < 0) { - pr_err("check the size of node %s\n", np->name); - continue; - } + ipdev->heaps = devm_kzalloc(&pdev->dev, + sizeof(struct ion_heap) * ipdev->data->nr, + GFP_KERNEL); + if (!ipdev->heaps) { + ion_destroy_platform_data(ipdev->data); + return -ENOMEM; + } - ret = of_property_read_string(np, "heap-type", &type_name); - if (ret < 0) { - pr_err("check the type of node %s\n", np->name); - continue; - } - - ret = get_type_by_name(type_name, &type); - if (ret < 0) { - pr_err("type name error %s!\n", type_name); - continue; - } - pr_info("heap index %d : name %s base 0x%x size 0x%x id %d type %d\n", - index, heap_name, base, size, id, type); - - p_data = devm_kzalloc(&pdev->dev, - sizeof(struct ion_platform_heap), - GFP_KERNEL); - if (!p_data) + for (i = 0; i < ipdev->data->nr; i++) { + ipdev->heaps[i] = ion_heap_create(&ipdev->data->heaps[i]); + if (!ipdev->heaps) { + ion_destroy_platform_data(ipdev->data); return -ENOMEM; - - p_data->name = heap_name; - p_data->base = base; - p_data->size = size; - p_data->id = id; - p_data->type = type; - - heaps_data[index] = p_data; - index++; + } + ion_device_add_heap(ipdev->idev, ipdev->heaps[i]); } return 0; } -static int hi6220_ion_probe(struct platform_device *pdev) -{ - int i; - int err; - static struct ion_platform_heap *p_heap; - - idev = ion_device_create(NULL); - err = hi6220_set_platform_data(pdev); - if (err) { - pr_err("ion set platform data error!\n"); - goto err_free_idev; - } - heaps = devm_kzalloc(&pdev->dev, - sizeof(struct ion_heap *) * num_heaps, - GFP_KERNEL); - if (!heaps) { - err = -ENOMEM; - goto err_free_idev; - } - - /* - * create the heaps as specified in the dts file - */ - for (i = 0; i < num_heaps; i++) { - p_heap = heaps_data[i]; - heaps[i] = ion_heap_create(p_heap); - if (IS_ERR_OR_NULL(heaps[i])) { - err = PTR_ERR(heaps[i]); - goto err_free_heaps; - } - - ion_device_add_heap(idev, heaps[i]); - - pr_info("%s: adding heap %s of type %d with %lx@%lx\n", - __func__, p_heap->name, p_heap->type, - p_heap->base, (unsigned long)p_heap->size); - } - return err; - -err_free_heaps: - for (i = 0; i < num_heaps; ++i) { - ion_heap_destroy(heaps[i]); - heaps[i] = NULL; - } -err_free_idev: - ion_device_destroy(idev); - - return err; -} - static int hi6220_ion_remove(struct platform_device *pdev) { + struct hisi_ion_dev *ipdev; int i; - for (i = 0; i < num_heaps; i++) { - ion_heap_destroy(heaps[i]); - heaps[i] = NULL; - } - ion_device_destroy(idev); + ipdev = platform_get_drvdata(pdev); + + for (i = 0; i < ipdev->data->nr; i++) + ion_heap_destroy(ipdev->heaps[i]); + + ion_destroy_platform_data(ipdev->data); + ion_device_destroy(ipdev->idev); return 0; } diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c new file mode 100644 index 000000000000..7e7431d8d49f --- /dev/null +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -0,0 +1,177 @@ +/* + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include + +#include "ion.h" +#include "ion_priv.h" +#include "compat_ion.h" + +union ion_ioctl_arg { + struct ion_fd_data fd; + struct ion_allocation_data allocation; + struct ion_handle_data handle; + struct ion_custom_data custom; + struct ion_heap_query query; +}; + +static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) +{ + int ret = 0; + + switch (cmd) { + case ION_IOC_HEAP_QUERY: + ret = arg->query.reserved0 != 0; + ret |= arg->query.reserved1 != 0; + ret |= arg->query.reserved2 != 0; + break; + default: + break; + } + + return ret ? -EINVAL : 0; +} + +/* fix up the cases where the ioctl direction bits are incorrect */ +static unsigned int ion_ioctl_dir(unsigned int cmd) +{ + switch (cmd) { + case ION_IOC_SYNC: + case ION_IOC_FREE: + case ION_IOC_CUSTOM: + return _IOC_WRITE; + default: + return _IOC_DIR(cmd); + } +} + +long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct ion_client *client = filp->private_data; + struct ion_device *dev = client->dev; + struct ion_handle *cleanup_handle = NULL; + int ret = 0; + unsigned int dir; + union ion_ioctl_arg data; + + dir = ion_ioctl_dir(cmd); + + if (_IOC_SIZE(cmd) > sizeof(data)) + return -EINVAL; + + /* + * The copy_from_user is unconditional here for both read and write + * to do the validate. If there is no write for the ioctl, the + * buffer is cleared + */ + if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; + + ret = validate_ioctl_arg(cmd, &data); + if (WARN_ON_ONCE(ret)) + return ret; + + if (!(dir & _IOC_WRITE)) + memset(&data, 0, sizeof(data)); + + switch (cmd) { + case ION_IOC_ALLOC: + { + struct ion_handle *handle; + + handle = ion_alloc(client, data.allocation.len, + data.allocation.align, + data.allocation.heap_id_mask, + data.allocation.flags); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + data.allocation.handle = handle->id; + + cleanup_handle = handle; + break; + } + case ION_IOC_FREE: + { + struct ion_handle *handle; + + mutex_lock(&client->lock); + handle = ion_handle_get_by_id_nolock(client, data.handle.handle); + if (IS_ERR(handle)) { + mutex_unlock(&client->lock); + return PTR_ERR(handle); + } + ion_free_nolock(client, handle); + ion_handle_put_nolock(handle); + mutex_unlock(&client->lock); + break; + } + case ION_IOC_SHARE: + case ION_IOC_MAP: + { + struct ion_handle *handle; + + handle = ion_handle_get_by_id(client, data.handle.handle); + if (IS_ERR(handle)) + return PTR_ERR(handle); + data.fd.fd = ion_share_dma_buf_fd(client, handle); + ion_handle_put(handle); + if (data.fd.fd < 0) + ret = data.fd.fd; + break; + } + case ION_IOC_IMPORT: + { + struct ion_handle *handle; + + handle = ion_import_dma_buf_fd(client, data.fd.fd); + if (IS_ERR(handle)) + ret = PTR_ERR(handle); + else + data.handle.handle = handle->id; + break; + } + case ION_IOC_SYNC: + { + ret = ion_sync_for_device(client, data.fd.fd); + break; + } + case ION_IOC_CUSTOM: + { + if (!dev->custom_ioctl) + return -ENOTTY; + ret = dev->custom_ioctl(client, data.custom.cmd, + data.custom.arg); + break; + } + case ION_IOC_HEAP_QUERY: + ret = ion_query_heaps(client, &data.query); + break; + default: + return -ENOTTY; + } + + if (dir & _IOC_READ) { + if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { + if (cleanup_handle) + ion_free(client, cleanup_handle); + return -EFAULT; + } + } + return ret; +} diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a2cf93b59016..396ded52ab70 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -41,80 +41,6 @@ #include "ion_priv.h" #include "compat_ion.h" -/** - * 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 - * @heaps: list of all the heaps in the system - * @user_clients: list of all the clients created from userspace - */ -struct ion_device { - struct miscdevice dev; - struct rb_root buffers; - struct mutex buffer_lock; - struct rw_semaphore lock; - struct plist_head heaps; - long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, - unsigned long arg); - struct rb_root clients; - struct dentry *debug_root; - struct dentry *heaps_debug_root; - struct dentry *clients_debug_root; -}; - -/** - * struct ion_client - a process/hw block local address space - * @node: node in the tree of all clients - * @dev: backpointer to ion device - * @handles: an rb tree of all the handles in this client - * @idr: an idr space for allocating handle ids - * @lock: lock protecting the tree of handles - * @name: used for debugging - * @display_name: used for debugging (unique version of @name) - * @display_serial: used for debugging (to make display_name unique) - * @task: used for debugging - * - * A client represents a list of buffers this client may access. - * The mutex stored here is used to protect both handles tree - * as well as the handles themselves, and should be held while modifying either. - */ -struct ion_client { - struct rb_node node; - struct ion_device *dev; - struct rb_root handles; - struct idr idr; - struct mutex lock; - const char *name; - char *display_name; - int display_serial; - struct task_struct *task; - pid_t pid; - struct dentry *debug_root; -}; - -/** - * ion_handle - a client local reference to a buffer - * @ref: reference count - * @client: back pointer to the client the buffer resides in - * @buffer: pointer to the buffer - * @node: node in the client's handle rbtree - * @kmap_cnt: count of times this client has mapped to kernel - * @id: client-unique id allocated by client->idr - * - * Modifications to node, map_cnt or mapping should be protected by the - * lock in the client. Other fields are never changed after initialization. - */ -struct ion_handle { - struct kref ref; - struct ion_client *client; - struct ion_buffer *buffer; - struct rb_node node; - unsigned int kmap_cnt; - int id; -}; - bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) { return (buffer->flags & ION_FLAG_CACHED) && @@ -174,10 +100,10 @@ static void ion_buffer_add(struct ion_device *dev, /* 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, - unsigned long align, - unsigned long flags) + struct ion_device *dev, + unsigned long len, + unsigned long align, + unsigned long flags) { struct ion_buffer *buffer; struct sg_table *table; @@ -205,19 +131,16 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, goto err2; } - buffer->dev = dev; - buffer->size = len; - - table = heap->ops->map_dma(heap, buffer); - if (WARN_ONCE(table == NULL, - "heap->ops->map_dma should return ERR_PTR on error")) - table = ERR_PTR(-EINVAL); - if (IS_ERR(table)) { + if (buffer->sg_table == NULL) { + WARN_ONCE(1, "This heap needs to set the sgtable"); ret = -EINVAL; goto err1; } - buffer->sg_table = table; + table = buffer->sg_table; + buffer->dev = dev; + buffer->size = len; + if (ion_buffer_fault_user_mappings(buffer)) { int num_pages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; struct scatterlist *sg; @@ -226,7 +149,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->pages = vmalloc(sizeof(struct page *) * num_pages); if (!buffer->pages) { ret = -ENOMEM; - goto err; + goto err1; } for_each_sg(table->sgl, sg, table->nents, i) { @@ -260,8 +183,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, mutex_unlock(&dev->buffer_lock); return buffer; -err: - heap->ops->unmap_dma(heap, buffer); err1: heap->ops->free(buffer); err2: @@ -273,7 +194,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer) { if (WARN_ON(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - buffer->heap->ops->unmap_dma(buffer->heap, buffer); buffer->heap->ops->free(buffer); vfree(buffer->pages); kfree(buffer); @@ -337,7 +257,7 @@ static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) } static struct ion_handle *ion_handle_create(struct ion_client *client, - struct ion_buffer *buffer) + struct ion_buffer *buffer) { struct ion_handle *handle; @@ -377,26 +297,17 @@ static void ion_handle_destroy(struct kref *kref) kfree(handle); } -struct ion_buffer *ion_handle_buffer(struct ion_handle *handle) -{ - return handle->buffer; -} - static void ion_handle_get(struct ion_handle *handle) { kref_get(&handle->ref); } -static int ion_handle_put_nolock(struct ion_handle *handle) +int ion_handle_put_nolock(struct ion_handle *handle) { - int ret; - - ret = kref_put(&handle->ref, ion_handle_destroy); - - return ret; + return kref_put(&handle->ref, ion_handle_destroy); } -static int ion_handle_put(struct ion_handle *handle) +int ion_handle_put(struct ion_handle *handle) { struct ion_client *client = handle->client; int ret; @@ -426,8 +337,8 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, return ERR_PTR(-EINVAL); } -static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, - int id) +struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id) { struct ion_handle *handle; @@ -438,7 +349,7 @@ static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, return handle ? handle : ERR_PTR(-EINVAL); } -static struct ion_handle *ion_handle_get_by_id(struct ion_client *client, +struct ion_handle *ion_handle_get_by_id(struct ion_client *client, int id) { struct ion_handle *handle; @@ -551,15 +462,10 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, } EXPORT_SYMBOL(ion_alloc); -static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) +void ion_free_nolock(struct ion_client *client, + struct ion_handle *handle) { - bool valid_handle; - - BUG_ON(client != handle->client); - - valid_handle = ion_handle_validate(client, handle); - - if (!valid_handle) { + if (!ion_handle_validate(client, handle)) { WARN(1, "%s: invalid handle passed to free.\n", __func__); return; } @@ -576,32 +482,6 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_free); -int ion_phys(struct ion_client *client, struct ion_handle *handle, - ion_phys_addr_t *addr, size_t *len) -{ - struct ion_buffer *buffer; - int ret; - - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - mutex_unlock(&client->lock); - return -EINVAL; - } - - buffer = handle->buffer; - - if (!buffer->heap->ops->phys) { - pr_err("%s: ion_phys is not implemented by this heap (name=%s, type=%d).\n", - __func__, buffer->heap->name, buffer->heap->type); - mutex_unlock(&client->lock); - return -ENODEV; - } - mutex_unlock(&client->lock); - ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len); - return ret; -} -EXPORT_SYMBOL(ion_phys); - static void *ion_buffer_kmap_get(struct ion_buffer *buffer) { void *vaddr; @@ -612,7 +492,7 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer) } vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); if (WARN_ONCE(vaddr == NULL, - "heap->ops->map_kernel should return ERR_PTR on error")) + "heap->ops->map_kernel should return ERR_PTR on error")) return ERR_PTR(-EINVAL); if (IS_ERR(vaddr)) return vaddr; @@ -781,14 +661,14 @@ static const struct file_operations debug_client_fops = { }; static int ion_get_client_serial(const struct rb_root *root, - const unsigned char *name) + const unsigned char *name) { int serial = -1; struct rb_node *node; for (node = rb_first(root); node; node = rb_next(node)) { struct ion_client *client = rb_entry(node, struct ion_client, - node); + node); if (strcmp(client->name, name)) continue; @@ -863,14 +743,14 @@ struct ion_client *ion_client_create(struct ion_device *dev, rb_insert_color(&client->node, &dev->clients); client->debug_root = debugfs_create_file(client->display_name, 0664, - dev->clients_debug_root, - client, &debug_client_fops); + dev->clients_debug_root, + client, &debug_client_fops); if (!client->debug_root) { char buf[256], *path; path = dentry_path(dev->clients_debug_root, buf, 256); pr_err("Failed to create client debugfs at %s/%s\n", - path, client->display_name); + path, client->display_name); } up_write(&dev->lock); @@ -917,26 +797,6 @@ void ion_client_destroy(struct ion_client *client) } EXPORT_SYMBOL(ion_client_destroy); -struct sg_table *ion_sg_table(struct ion_client *client, - struct ion_handle *handle) -{ - struct ion_buffer *buffer; - struct sg_table *table; - - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - pr_err("%s: invalid handle passed to map_dma.\n", - __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-EINVAL); - } - buffer = handle->buffer; - table = buffer->sg_table; - mutex_unlock(&client->lock); - return table; -} -EXPORT_SYMBOL(ion_sg_table); - static void ion_buffer_sync_for_device(struct ion_buffer *buffer, struct device *dev, enum dma_data_direction direction); @@ -958,7 +818,7 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, } void ion_pages_sync_for_device(struct device *dev, struct page *page, - size_t size, enum dma_data_direction dir) + size_t size, enum dma_data_direction dir) { struct scatterlist sg; @@ -998,7 +858,7 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, if (ion_buffer_page_is_dirty(page)) ion_pages_sync_for_device(dev, ion_buffer_page(page), - PAGE_SIZE, dir); + PAGE_SIZE, dir); ion_buffer_page_clean(buffer->pages + i); } @@ -1076,7 +936,7 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) if (!buffer->heap->ops->map_user) { pr_err("%s: this heap does not define a method for mapping to userspace\n", - __func__); + __func__); return -EINVAL; } @@ -1167,7 +1027,7 @@ static struct dma_buf_ops dma_buf_ops = { }; struct dma_buf *ion_share_dma_buf(struct ion_client *client, - struct ion_handle *handle) + struct ion_handle *handle) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); struct ion_buffer *buffer; @@ -1275,7 +1135,7 @@ struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd) } EXPORT_SYMBOL(ion_import_dma_buf_fd); -static int ion_sync_for_device(struct ion_client *client, int fd) +int ion_sync_for_device(struct ion_client *client, int fd) { struct dma_buf *dmabuf; struct ion_buffer *buffer; @@ -1299,124 +1159,45 @@ static int ion_sync_for_device(struct ion_client *client, int fd) return 0; } -/* fix up the cases where the ioctl direction bits are incorrect */ -static unsigned int ion_ioctl_dir(unsigned int cmd) +int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query) { - switch (cmd) { - case ION_IOC_SYNC: - case ION_IOC_FREE: - case ION_IOC_CUSTOM: - return _IOC_WRITE; - default: - return _IOC_DIR(cmd); - } -} - -static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct ion_client *client = filp->private_data; struct ion_device *dev = client->dev; - struct ion_handle *cleanup_handle = NULL; - int ret = 0; - unsigned int dir; + struct ion_heap_data __user *buffer = u64_to_user_ptr(query->heaps); + int ret = -EINVAL, cnt = 0, max_cnt; + struct ion_heap *heap; + struct ion_heap_data hdata; - union { - struct ion_fd_data fd; - struct ion_allocation_data allocation; - struct ion_handle_data handle; - struct ion_custom_data custom; - } data; + memset(&hdata, 0, sizeof(hdata)); - dir = ion_ioctl_dir(cmd); - - if (_IOC_SIZE(cmd) > sizeof(data)) - return -EINVAL; - - if (dir & _IOC_WRITE) - if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) - return -EFAULT; - - switch (cmd) { - case ION_IOC_ALLOC: - { - struct ion_handle *handle; - - handle = ion_alloc(client, data.allocation.len, - data.allocation.align, - data.allocation.heap_id_mask, - data.allocation.flags); - if (IS_ERR(handle)) - return PTR_ERR(handle); - - data.allocation.handle = handle->id; - - cleanup_handle = handle; - break; - } - case ION_IOC_FREE: - { - struct ion_handle *handle; - - mutex_lock(&client->lock); - handle = ion_handle_get_by_id_nolock(client, data.handle.handle); - if (IS_ERR(handle)) { - mutex_unlock(&client->lock); - return PTR_ERR(handle); - } - ion_free_nolock(client, handle); - ion_handle_put_nolock(handle); - mutex_unlock(&client->lock); - break; - } - case ION_IOC_SHARE: - case ION_IOC_MAP: - { - struct ion_handle *handle; - - handle = ion_handle_get_by_id(client, data.handle.handle); - if (IS_ERR(handle)) - return PTR_ERR(handle); - data.fd.fd = ion_share_dma_buf_fd(client, handle); - ion_handle_put(handle); - if (data.fd.fd < 0) - ret = data.fd.fd; - break; - } - case ION_IOC_IMPORT: - { - struct ion_handle *handle; - - handle = ion_import_dma_buf_fd(client, data.fd.fd); - if (IS_ERR(handle)) - ret = PTR_ERR(handle); - else - data.handle.handle = handle->id; - break; - } - case ION_IOC_SYNC: - { - ret = ion_sync_for_device(client, data.fd.fd); - break; - } - case ION_IOC_CUSTOM: - { - if (!dev->custom_ioctl) - return -ENOTTY; - ret = dev->custom_ioctl(client, data.custom.cmd, - data.custom.arg); - break; - } - default: - return -ENOTTY; + down_read(&dev->lock); + if (!buffer) { + query->cnt = dev->heap_cnt; + ret = 0; + goto out; } - if (dir & _IOC_READ) { - if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { - if (cleanup_handle) - ion_free(client, cleanup_handle); - return -EFAULT; - } + if (query->cnt <= 0) + goto out; + + max_cnt = query->cnt; + + plist_for_each_entry(heap, &dev->heaps, node) { + strncpy(hdata.name, heap->name, MAX_HEAP_NAME); + hdata.name[sizeof(hdata.name) - 1] = '\0'; + hdata.type = heap->type; + hdata.heap_id = heap->id; + + ret = copy_to_user(&buffer[cnt], + &hdata, sizeof(hdata)); + + cnt++; + if (cnt >= max_cnt) + break; } + + query->cnt = cnt; +out: + up_read(&dev->lock); return ret; } @@ -1528,7 +1309,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) seq_printf(s, "%16s %16zu\n", "total ", total_size); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) seq_printf(s, "%16s %16zu\n", "deferred free", - heap->free_list_size); + heap->free_list_size); seq_puts(s, "----------------------------------------------------\n"); if (heap->debug_show) @@ -1588,8 +1369,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { struct dentry *debug_file; - if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || - !heap->ops->unmap_dma) + if (!heap->ops->allocate || !heap->ops->free) pr_err("%s: can not add heap with invalid ops struct.\n", __func__); @@ -1611,15 +1391,15 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) plist_node_init(&heap->node, -heap->id); plist_add(&heap->node, &dev->heaps); debug_file = debugfs_create_file(heap->name, 0664, - dev->heaps_debug_root, heap, - &debug_heap_fops); + dev->heaps_debug_root, heap, + &debug_heap_fops); if (!debug_file) { char buf[256], *path; path = dentry_path(dev->heaps_debug_root, buf, 256); pr_err("Failed to create heap debugfs at %s/%s\n", - path, heap->name); + path, heap->name); } if (heap->shrinker.count_objects && heap->shrinker.scan_objects) { @@ -1634,10 +1414,11 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) path = dentry_path(dev->heaps_debug_root, buf, 256); pr_err("Failed to create heap shrinker debugfs at %s/%s\n", - path, debug_name); + path, debug_name); } } + dev->heap_cnt++; up_write(&dev->lock); } EXPORT_SYMBOL(ion_device_add_heap); @@ -1702,38 +1483,3 @@ void ion_device_destroy(struct ion_device *dev) kfree(dev); } EXPORT_SYMBOL(ion_device_destroy); - -void __init ion_reserve(struct ion_platform_data *data) -{ - int i; - - for (i = 0; i < data->nr; i++) { - if (data->heaps[i].size == 0) - continue; - - if (data->heaps[i].base == 0) { - phys_addr_t paddr; - - paddr = memblock_alloc_base(data->heaps[i].size, - data->heaps[i].align, - MEMBLOCK_ALLOC_ANYWHERE); - if (!paddr) { - pr_err("%s: error allocating memblock for heap %d\n", - __func__, i); - continue; - } - data->heaps[i].base = paddr; - } else { - int ret = memblock_reserve(data->heaps[i].base, - data->heaps[i].size); - if (ret) - pr_err("memblock reserve of %zx@%lx failed\n", - data->heaps[i].size, - data->heaps[i].base); - } - pr_info("%s: %s reserved base %lx size %zu\n", __func__, - data->heaps[i].name, - data->heaps[i].base, - data->heaps[i].size); - } -} diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index a1331fc169a1..93dafb4586e4 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -72,17 +72,6 @@ struct ion_platform_data { struct ion_platform_heap *heaps; }; -/** - * ion_reserve() - reserve memory for ion heaps if applicable - * @data: platform data specifying starting physical address and - * size - * - * Calls memblock reserve to set aside memory for heaps that are - * located at specific memory addresses or of specific sizes not - * managed by the kernel - */ -void ion_reserve(struct ion_platform_data *data); - /** * ion_client_create() - allocate a client and returns it * @dev: the global ion device @@ -129,36 +118,6 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, */ void ion_free(struct ion_client *client, struct ion_handle *handle); -/** - * ion_phys - returns the physical address and len of a handle - * @client: the client - * @handle: the handle - * @addr: a pointer to put the address in - * @len: a pointer to put the length in - * - * This function queries the heap for a particular handle to get the - * handle's physical address. It't output is only correct if - * a heap returns physically contiguous memory -- in other cases - * this api should not be implemented -- ion_sg_table should be used - * instead. Returns -EINVAL if the handle is invalid. This has - * no implications on the reference counting of the handle -- - * the returned value may not be valid if the caller is not - * holding a reference. - */ -int ion_phys(struct ion_client *client, struct ion_handle *handle, - ion_phys_addr_t *addr, size_t *len); - -/** - * ion_map_dma - return an sg_table describing a handle - * @client: the client - * @handle: the handle - * - * This function returns the sg_table describing - * a particular ion handle. - */ -struct sg_table *ion_sg_table(struct ion_client *client, - struct ion_handle *handle); - /** * ion_map_kernel - create mapping for the given handle * @client: the client diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 1fb0d81556da..a8ea97391c40 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -25,15 +25,17 @@ #include "ion.h" #include "ion_priv.h" +#define ION_CARVEOUT_ALLOCATE_FAIL -1 + struct ion_carveout_heap { struct ion_heap heap; struct gen_pool *pool; ion_phys_addr_t base; }; -ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, - unsigned long size, - unsigned long align) +static ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, + unsigned long size, + unsigned long align) { struct ion_carveout_heap *carveout_heap = container_of(heap, struct ion_carveout_heap, heap); @@ -45,8 +47,8 @@ ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, return offset; } -void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, - unsigned long size) +static void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, + unsigned long size) { struct ion_carveout_heap *carveout_heap = container_of(heap, struct ion_carveout_heap, heap); @@ -56,19 +58,6 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, gen_pool_free(carveout_heap->pool, addr, size); } -static int ion_carveout_heap_phys(struct ion_heap *heap, - struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - struct sg_table *table = buffer->priv_virt; - struct page *page = sg_page(table->sgl); - ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); - - *addr = paddr; - *len = buffer->size; - return 0; -} - static int ion_carveout_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long size, unsigned long align, @@ -95,7 +84,7 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, } sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), size, 0); - buffer->priv_virt = table; + buffer->sg_table = table; return 0; @@ -109,7 +98,7 @@ err_free: static void ion_carveout_heap_free(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; - struct sg_table *table = buffer->priv_virt; + struct sg_table *table = buffer->sg_table; struct page *page = sg_page(table->sgl); ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); @@ -124,23 +113,9 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer) kfree(table); } -static struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -static void ion_carveout_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static struct ion_heap_ops carveout_heap_ops = { .allocate = ion_carveout_heap_allocate, .free = ion_carveout_heap_free, - .phys = ion_carveout_heap_phys, - .map_dma = ion_carveout_heap_map_dma, - .unmap_dma = ion_carveout_heap_unmap_dma, .map_user = ion_heap_map_user, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index e0553fee9b8a..70495dc645ea 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -34,9 +34,9 @@ struct ion_chunk_heap { }; static int ion_chunk_heap_allocate(struct ion_heap *heap, - struct ion_buffer *buffer, - unsigned long size, unsigned long align, - unsigned long flags) + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) { struct ion_chunk_heap *chunk_heap = container_of(heap, struct ion_chunk_heap, heap); @@ -71,11 +71,11 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, if (!paddr) goto err; sg_set_page(sg, pfn_to_page(PFN_DOWN(paddr)), - chunk_heap->chunk_size, 0); + chunk_heap->chunk_size, 0); sg = sg_next(sg); } - buffer->priv_virt = table; + buffer->sg_table = table; chunk_heap->allocated += allocated_size; return 0; err: @@ -95,7 +95,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) struct ion_heap *heap = buffer->heap; struct ion_chunk_heap *chunk_heap = container_of(heap, struct ion_chunk_heap, heap); - struct sg_table *table = buffer->priv_virt; + struct sg_table *table = buffer->sg_table; struct scatterlist *sg; int i; unsigned long allocated_size; @@ -106,7 +106,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) if (ion_buffer_cached(buffer)) dma_sync_sg_for_device(NULL, table->sgl, table->nents, - DMA_BIDIRECTIONAL); + DMA_BIDIRECTIONAL); for_each_sg(table->sgl, sg, table->nents, i) { gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), @@ -117,22 +117,9 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) kfree(table); } -static struct sg_table *ion_chunk_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -static void ion_chunk_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static struct ion_heap_ops chunk_heap_ops = { .allocate = ion_chunk_heap_allocate, .free = ion_chunk_heap_free, - .map_dma = ion_chunk_heap_map_dma, - .unmap_dma = ion_chunk_heap_unmap_dma, .map_user = ion_heap_map_user, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, @@ -174,7 +161,7 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; pr_debug("%s: base %lu size %zu align %ld\n", __func__, - chunk_heap->base, heap_data->size, heap_data->align); + chunk_heap->base, heap_data->size, heap_data->align); return &chunk_heap->heap; diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index a3446da4fdc2..6c7de74bc7ab 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -78,6 +78,7 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, goto free_table; /* keep this for memory release */ buffer->priv_virt = info; + buffer->sg_table = info->table; dev_dbg(dev, "Allocate buffer %p\n", buffer); return 0; @@ -105,36 +106,6 @@ static void ion_cma_free(struct ion_buffer *buffer) kfree(info); } -/* return physical address in addr */ -static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); - struct device *dev = cma_heap->dev; - struct ion_cma_buffer_info *info = buffer->priv_virt; - - dev_dbg(dev, "Return buffer %p physical address %pa\n", buffer, - &info->handle); - - *addr = info->handle; - *len = buffer->size; - - return 0; -} - -static struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - struct ion_cma_buffer_info *info = buffer->priv_virt; - - return info->table; -} - -static void ion_cma_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma) { @@ -155,16 +126,13 @@ static void *ion_cma_map_kernel(struct ion_heap *heap, } static void ion_cma_unmap_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) + struct ion_buffer *buffer) { } static struct ion_heap_ops ion_cma_ops = { .allocate = ion_cma_allocate, .free = ion_cma_free, - .map_dma = ion_cma_heap_map_dma, - .unmap_dma = ion_cma_heap_unmap_dma, - .phys = ion_cma_phys, .map_user = ion_cma_mmap, .map_kernel = ion_cma_map_kernel, .unmap_kernel = ion_cma_unmap_kernel, diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c index 814a3c92a56e..b23f2c76c753 100644 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -99,7 +99,7 @@ static int __init ion_dummy_init(void) struct ion_platform_heap *heap_data = &dummy_ion_pdata.heaps[i]; if (heap_data->type == ION_HEAP_TYPE_CARVEOUT && - !heap_data->base) + !heap_data->base) continue; if (heap_data->type == ION_HEAP_TYPE_CHUNK && !heap_data->base) @@ -120,12 +120,12 @@ err: if (carveout_ptr) { free_pages_exact(carveout_ptr, - dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); + dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); carveout_ptr = NULL; } if (chunk_ptr) { free_pages_exact(chunk_ptr, - dummy_heaps[ION_HEAP_TYPE_CHUNK].size); + dummy_heaps[ION_HEAP_TYPE_CHUNK].size); chunk_ptr = NULL; } return err; @@ -144,12 +144,12 @@ static void __exit ion_dummy_exit(void) if (carveout_ptr) { free_pages_exact(carveout_ptr, - dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); + dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); carveout_ptr = NULL; } if (chunk_ptr) { free_pages_exact(chunk_ptr, - dummy_heaps[ION_HEAP_TYPE_CHUNK].size); + dummy_heaps[ION_HEAP_TYPE_CHUNK].size); chunk_ptr = NULL; } } diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index ca15a87f6fd3..4e5c0f17f579 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -93,7 +93,7 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, } len = min(len, remainder); ret = remap_pfn_range(vma, addr, page_to_pfn(page), len, - vma->vm_page_prot); + vma->vm_page_prot); if (ret) return ret; addr += len; @@ -116,7 +116,7 @@ static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) } static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, - pgprot_t pgprot) + pgprot_t pgprot) { int p = 0; int ret = 0; @@ -181,7 +181,7 @@ size_t ion_heap_freelist_size(struct ion_heap *heap) } static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, - bool skip_pools) + bool skip_pools) { struct ion_buffer *buffer; size_t total_drained = 0; @@ -266,7 +266,7 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) } static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, - struct shrink_control *sc) + struct shrink_control *sc) { struct ion_heap *heap = container_of(shrinker, struct ion_heap, shrinker); @@ -279,7 +279,7 @@ static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, } static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker, - struct shrink_control *sc) + struct shrink_control *sc) { struct ion_heap *heap = container_of(shrinker, struct ion_heap, shrinker); diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c new file mode 100644 index 000000000000..15bac92b7f04 --- /dev/null +++ b/drivers/staging/android/ion/ion_of.c @@ -0,0 +1,185 @@ +/* + * Based on work from: + * Andrew Andrianov + * Google + * The Linux Foundation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ion.h" +#include "ion_priv.h" +#include "ion_of.h" + +static int ion_parse_dt_heap_common(struct device_node *heap_node, + struct ion_platform_heap *heap, + struct ion_of_heap *compatible) +{ + int i; + + for (i = 0; compatible[i].name; i++) { + if (of_device_is_compatible(heap_node, compatible[i].compat)) + break; + } + + if (!compatible[i].name) + return -ENODEV; + + heap->id = compatible[i].heap_id; + heap->type = compatible[i].type; + heap->name = compatible[i].name; + heap->align = compatible[i].align; + + /* Some kind of callback function pointer? */ + + pr_info("%s: id %d type %d name %s align %lx\n", __func__, + heap->id, heap->type, heap->name, heap->align); + return 0; +} + +static int ion_setup_heap_common(struct platform_device *parent, + struct device_node *heap_node, + struct ion_platform_heap *heap) +{ + int ret = 0; + + switch (heap->type) { + case ION_HEAP_TYPE_CARVEOUT: + case ION_HEAP_TYPE_CHUNK: + if (heap->base && heap->size) + return 0; + + ret = of_reserved_mem_device_init(heap->priv); + break; + default: + break; + } + + return ret; +} + +struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, + struct ion_of_heap *compatible) +{ + int num_heaps, ret; + const struct device_node *dt_node = pdev->dev.of_node; + struct device_node *node; + struct ion_platform_heap *heaps; + struct ion_platform_data *data; + int i = 0; + + num_heaps = of_get_available_child_count(dt_node); + + if (!num_heaps) + return ERR_PTR(-EINVAL); + + heaps = devm_kzalloc(&pdev->dev, + sizeof(struct ion_platform_heap) * num_heaps, + GFP_KERNEL); + if (!heaps) + return ERR_PTR(-ENOMEM); + + data = devm_kzalloc(&pdev->dev, sizeof(struct ion_platform_data), + GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + for_each_available_child_of_node(dt_node, node) { + struct platform_device *heap_pdev; + + ret = ion_parse_dt_heap_common(node, &heaps[i], compatible); + if (ret) + return ERR_PTR(ret); + + heap_pdev = of_platform_device_create(node, heaps[i].name, + &pdev->dev); + if (!pdev) + return ERR_PTR(-ENOMEM); + heap_pdev->dev.platform_data = &heaps[i]; + + heaps[i].priv = &heap_pdev->dev; + + ret = ion_setup_heap_common(pdev, node, &heaps[i]); + if (ret) + goto out_err; + i++; + } + + data->heaps = heaps; + data->nr = num_heaps; + return data; + +out_err: + for ( ; i >= 0; i--) + if (heaps[i].priv) + of_device_unregister(to_platform_device(heaps[i].priv)); + + return ERR_PTR(ret); +} + +void ion_destroy_platform_data(struct ion_platform_data *data) +{ + int i; + + for (i = 0; i < data->nr; i++) + if (data->heaps[i].priv) + of_device_unregister(to_platform_device( + data->heaps[i].priv)); +} + +#ifdef CONFIG_OF_RESERVED_MEM +#include +#include +#include + +static int rmem_ion_device_init(struct reserved_mem *rmem, struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ion_platform_heap *heap = pdev->dev.platform_data; + + heap->base = rmem->base; + heap->base = rmem->size; + pr_debug("%s: heap %s base %pa size %pa dev %p\n", __func__, + heap->name, &rmem->base, &rmem->size, dev); + return 0; +} + +static void rmem_ion_device_release(struct reserved_mem *rmem, + struct device *dev) +{ + return; +} + +static const struct reserved_mem_ops rmem_dma_ops = { + .device_init = rmem_ion_device_init, + .device_release = rmem_ion_device_release, +}; + +static int __init rmem_ion_setup(struct reserved_mem *rmem) +{ + phys_addr_t size = rmem->size; + + size = size / 1024; + + pr_info("Ion memory setup at %pa size %pa MiB\n", + &rmem->base, &size); + rmem->ops = &rmem_dma_ops; + return 0; +} + +RESERVEDMEM_OF_DECLARE(ion, "ion-region", rmem_ion_setup); +#endif diff --git a/drivers/staging/android/ion/ion_of.h b/drivers/staging/android/ion/ion_of.h new file mode 100644 index 000000000000..8241a1770f0a --- /dev/null +++ b/drivers/staging/android/ion/ion_of.h @@ -0,0 +1,37 @@ +/* + * Based on work from: + * Andrew Andrianov + * Google + * The Linux Foundation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _ION_OF_H +#define _ION_OF_H + +struct ion_of_heap { + const char *compat; + int heap_id; + int type; + const char *name; + int align; +}; + +#define PLATFORM_HEAP(_compat, _id, _type, _name) \ +{ \ + .compat = _compat, \ + .heap_id = _id, \ + .type = _type, \ + .name = _name, \ + .align = PAGE_SIZE, \ +} + +struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, + struct ion_of_heap *compatible); + +void ion_destroy_platform_data(struct ion_platform_data *data); + +#endif diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 1fe80165a462..aea89c1ec345 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -30,8 +30,9 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) if (!page) return NULL; - ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order, - DMA_BIDIRECTIONAL); + if (!pool->cached) + ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order, + DMA_BIDIRECTIONAL); return page; } @@ -114,7 +115,7 @@ static int ion_page_pool_total(struct ion_page_pool *pool, bool high) } int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, - int nr_to_scan) + int nr_to_scan) { int freed = 0; bool high; @@ -147,7 +148,8 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, return freed; } -struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) +struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order, + bool cached) { struct ion_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL); @@ -161,6 +163,8 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) pool->order = order; mutex_init(&pool->mutex); plist_node_init(&pool->list, order); + if (cached) + pool->cached = true; return pool; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 0239883bffb7..3c3b3245275d 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -26,11 +26,10 @@ #include #include #include +#include #include "ion.h" -struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); - /** * struct ion_buffer - metadata for a particular buffer * @ref: reference count @@ -42,8 +41,6 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); * @size: size of the buffer * @priv_virt: private data to the buffer representable as * a void * - * @priv_phys: private data to the buffer representable as - * an ion_phys_addr_t (and someday a phys_addr_t) * @lock: protects the buffers cnt fields * @kmap_cnt: number of times the buffer is mapped to the kernel * @vaddr: the kernel mapping if kmap_cnt is not zero @@ -69,10 +66,7 @@ struct ion_buffer { unsigned long flags; unsigned long private_flags; size_t size; - union { - void *priv_virt; - ion_phys_addr_t priv_phys; - }; + void *priv_virt; struct mutex lock; int kmap_cnt; void *vaddr; @@ -87,14 +81,85 @@ struct ion_buffer { }; 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 + * @heaps: list of all the heaps in the system + * @user_clients: list of all the clients created from userspace + */ +struct ion_device { + struct miscdevice dev; + struct rb_root buffers; + struct mutex buffer_lock; + struct rw_semaphore lock; + struct plist_head heaps; + long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, + unsigned long arg); + struct rb_root clients; + struct dentry *debug_root; + struct dentry *heaps_debug_root; + struct dentry *clients_debug_root; + int heap_cnt; +}; + +/** + * struct ion_client - a process/hw block local address space + * @node: node in the tree of all clients + * @dev: backpointer to ion device + * @handles: an rb tree of all the handles in this client + * @idr: an idr space for allocating handle ids + * @lock: lock protecting the tree of handles + * @name: used for debugging + * @display_name: used for debugging (unique version of @name) + * @display_serial: used for debugging (to make display_name unique) + * @task: used for debugging + * + * A client represents a list of buffers this client may access. + * The mutex stored here is used to protect both handles tree + * as well as the handles themselves, and should be held while modifying either. + */ +struct ion_client { + struct rb_node node; + struct ion_device *dev; + struct rb_root handles; + struct idr idr; + struct mutex lock; + const char *name; + char *display_name; + int display_serial; + struct task_struct *task; + pid_t pid; + struct dentry *debug_root; +}; + +/** + * ion_handle - a client local reference to a buffer + * @ref: reference count + * @client: back pointer to the client the buffer resides in + * @buffer: pointer to the buffer + * @node: node in the client's handle rbtree + * @kmap_cnt: count of times this client has mapped to kernel + * @id: client-unique id allocated by client->idr + * + * Modifications to node, map_cnt or mapping should be protected by the + * lock in the client. Other fields are never changed after initialization. + */ +struct ion_handle { + struct kref ref; + struct ion_client *client; + struct ion_buffer *buffer; + struct rb_node node; + unsigned int kmap_cnt; + int id; +}; + /** * struct ion_heap_ops - ops to operate on a given heap * @allocate: allocate memory * @free: free memory - * @phys get physical address of a buffer (only define on - * physically contiguous heaps) - * @map_dma map the memory for dma to a scatterlist - * @unmap_dma unmap the memory for dma * @map_kernel map memory to the kernel * @unmap_kernel unmap memory to the kernel * @map_user map memory to userspace @@ -111,11 +176,6 @@ struct ion_heap_ops { struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags); void (*free)(struct ion_buffer *buffer); - int (*phys)(struct ion_heap *heap, struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len); - struct sg_table * (*map_dma)(struct ion_heap *heap, - struct ion_buffer *buffer); - void (*unmap_dma)(struct ion_heap *heap, struct ion_buffer *buffer); void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, @@ -327,20 +387,6 @@ void ion_chunk_heap_destroy(struct ion_heap *); struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *); void ion_cma_heap_destroy(struct ion_heap *); -/** - * kernel api to allocate/free from carveout -- used when carveout is - * used to back an architecture specific custom heap - */ -ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size, - unsigned long align); -void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, - unsigned long size); -/** - * The carveout heap returns physical addresses, since 0 may be a valid - * physical address, this is used to indicate allocation failed - */ -#define ION_CARVEOUT_ALLOCATE_FAIL -1 - /** * functions for creating and destroying a heap pool -- allows you * to keep a pool of pre allocated memory to use from your heap. Keeping @@ -360,6 +406,7 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, * @gfp_mask: gfp_mask to use from alloc * @order: order of pages in the pool * @list: plist node for list of pools + * @cached: it's cached pool or not * * Allows you to keep a pool of pre allocated pages to use from your heap. * Keeping a pool of pages that is ready for dma, ie any cached mapping have @@ -369,6 +416,7 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, struct ion_page_pool { int high_count; int low_count; + bool cached; struct list_head high_items; struct list_head low_items; struct mutex mutex; @@ -377,7 +425,8 @@ struct ion_page_pool { struct plist_node list; }; -struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); +struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order, + bool cached); void ion_page_pool_destroy(struct ion_page_pool *); struct page *ion_page_pool_alloc(struct ion_page_pool *); void ion_page_pool_free(struct ion_page_pool *, struct page *); @@ -403,4 +452,22 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, void ion_pages_sync_for_device(struct device *dev, struct page *page, size_t size, enum dma_data_direction dir); +long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); + +int ion_sync_for_device(struct ion_client *client, int fd); + +struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id); + +void ion_free_nolock(struct ion_client *client, struct ion_handle *handle); + +int ion_handle_put_nolock(struct ion_handle *handle); + +struct ion_handle *ion_handle_get_by_id(struct ion_client *client, + int id); + +int ion_handle_put(struct ion_handle *handle); + +int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query); + #endif /* _ION_PRIV_H */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index b69dfc706440..7e023d505af8 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -26,16 +26,18 @@ #include "ion.h" #include "ion_priv.h" +#define NUM_ORDERS ARRAY_SIZE(orders) + static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_RECLAIM; -static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN); +static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO); static const unsigned int orders[] = {8, 4, 0}; -static const int num_orders = ARRAY_SIZE(orders); + static int order_to_index(unsigned int order) { int i; - for (i = 0; i < num_orders; i++) + for (i = 0; i < NUM_ORDERS; i++) if (order == orders[i]) return i; BUG(); @@ -49,47 +51,55 @@ static inline unsigned int order_to_size(int order) struct ion_system_heap { struct ion_heap heap; - struct ion_page_pool *pools[0]; + struct ion_page_pool *uncached_pools[NUM_ORDERS]; + struct ion_page_pool *cached_pools[NUM_ORDERS]; }; +/** + * The page from page-pool are all zeroed before. We need do cache + * clean for cached buffer. The uncached buffer are always non-cached + * since it's allocated. So no need for non-cached pages. + */ static struct page *alloc_buffer_page(struct ion_system_heap *heap, struct ion_buffer *buffer, unsigned long order) { bool cached = ion_buffer_cached(buffer); - struct ion_page_pool *pool = heap->pools[order_to_index(order)]; + struct ion_page_pool *pool; struct page *page; - if (!cached) { - page = ion_page_pool_alloc(pool); - } else { - gfp_t gfp_flags = low_order_gfp_flags; + if (!cached) + pool = heap->uncached_pools[order_to_index(order)]; + else + pool = heap->cached_pools[order_to_index(order)]; - if (order > 4) - gfp_flags = high_order_gfp_flags; - page = alloc_pages(gfp_flags | __GFP_COMP, order); - if (!page) - return NULL; + page = ion_page_pool_alloc(pool); + + if (cached) ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, - DMA_BIDIRECTIONAL); - } - + DMA_BIDIRECTIONAL); return page; } static void free_buffer_page(struct ion_system_heap *heap, struct ion_buffer *buffer, struct page *page) { + struct ion_page_pool *pool; unsigned int order = compound_order(page); bool cached = ion_buffer_cached(buffer); - if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) { - struct ion_page_pool *pool = heap->pools[order_to_index(order)]; - - ion_page_pool_free(pool, page); - } else { + /* go to system */ + if (buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE) { __free_pages(page, order); + return; } + + if (!cached) + pool = heap->uncached_pools[order_to_index(order)]; + else + pool = heap->cached_pools[order_to_index(order)]; + + ion_page_pool_free(pool, page); } @@ -101,7 +111,7 @@ static struct page *alloc_largest_available(struct ion_system_heap *heap, struct page *page; int i; - for (i = 0; i < num_orders; i++) { + for (i = 0; i < NUM_ORDERS; i++) { if (size < order_to_size(orders[i])) continue; if (max_order < orders[i]) @@ -118,9 +128,9 @@ static struct page *alloc_largest_available(struct ion_system_heap *heap, } static int ion_system_heap_allocate(struct ion_heap *heap, - struct ion_buffer *buffer, - unsigned long size, unsigned long align, - unsigned long flags) + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) { struct ion_system_heap *sys_heap = container_of(heap, struct ion_system_heap, @@ -142,7 +152,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, INIT_LIST_HEAD(&pages); while (size_remaining > 0) { page = alloc_largest_available(sys_heap, buffer, size_remaining, - max_order); + max_order); if (!page) goto free_pages; list_add_tail(&page->lru, &pages); @@ -164,7 +174,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, list_del(&page->lru); } - buffer->priv_virt = table; + buffer->sg_table = table; return 0; free_table: @@ -181,16 +191,11 @@ static void ion_system_heap_free(struct ion_buffer *buffer) struct ion_system_heap, heap); struct sg_table *table = buffer->sg_table; - bool cached = ion_buffer_cached(buffer); struct scatterlist *sg; int i; - /* - * uncached pages come from the page pools, zero them before returning - * for security purposes (other allocations are zerod at - * alloc time - */ - if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) + /* zero the buffer before goto page pool */ + if (!(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) ion_heap_buffer_zero(buffer); for_each_sg(table->sgl, sg, table->nents, i) @@ -199,20 +204,11 @@ static void ion_system_heap_free(struct ion_buffer *buffer) kfree(table); } -static struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -static void ion_system_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, - int nr_to_scan) + int nr_to_scan) { + struct ion_page_pool *uncached_pool; + struct ion_page_pool *cached_pool; struct ion_system_heap *sys_heap; int nr_total = 0; int i, nr_freed; @@ -223,28 +219,41 @@ static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, if (!nr_to_scan) only_scan = 1; - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; + for (i = 0; i < NUM_ORDERS; i++) { + uncached_pool = sys_heap->uncached_pools[i]; + cached_pool = sys_heap->cached_pools[i]; - nr_freed = ion_page_pool_shrink(pool, gfp_mask, nr_to_scan); - nr_total += nr_freed; + if (only_scan) { + nr_total += ion_page_pool_shrink(uncached_pool, + gfp_mask, + nr_to_scan); - if (!only_scan) { + nr_total += ion_page_pool_shrink(cached_pool, + gfp_mask, + nr_to_scan); + } else { + nr_freed = ion_page_pool_shrink(uncached_pool, + gfp_mask, + nr_to_scan); nr_to_scan -= nr_freed; - /* shrink completed */ + nr_total += nr_freed; + if (nr_to_scan <= 0) + break; + nr_freed = ion_page_pool_shrink(cached_pool, + gfp_mask, + nr_to_scan); + nr_to_scan -= nr_freed; + nr_total += nr_freed; if (nr_to_scan <= 0) break; } } - return nr_total; } static struct ion_heap_ops system_heap_ops = { .allocate = ion_system_heap_allocate, .free = ion_system_heap_free, - .map_dma = ion_system_heap_map_dma, - .unmap_dma = ion_system_heap_unmap_dma, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, .map_user = ion_heap_map_user, @@ -259,52 +268,89 @@ static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, struct ion_system_heap, heap); int i; + struct ion_page_pool *pool; - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; + for (i = 0; i < NUM_ORDERS; i++) { + pool = sys_heap->uncached_pools[i]; - seq_printf(s, "%d order %u highmem pages in pool = %lu total\n", + seq_printf(s, "%d order %u highmem pages uncached %lu total\n", pool->high_count, pool->order, (PAGE_SIZE << pool->order) * pool->high_count); - seq_printf(s, "%d order %u lowmem pages in pool = %lu total\n", + seq_printf(s, "%d order %u lowmem pages uncached %lu total\n", + pool->low_count, pool->order, + (PAGE_SIZE << pool->order) * pool->low_count); + } + + for (i = 0; i < NUM_ORDERS; i++) { + pool = sys_heap->cached_pools[i]; + + seq_printf(s, "%d order %u highmem pages cached %lu total\n", + pool->high_count, pool->order, + (PAGE_SIZE << pool->order) * pool->high_count); + seq_printf(s, "%d order %u lowmem pages cached %lu total\n", pool->low_count, pool->order, (PAGE_SIZE << pool->order) * pool->low_count); } return 0; } +static void ion_system_heap_destroy_pools(struct ion_page_pool **pools) +{ + int i; + + for (i = 0; i < NUM_ORDERS; i++) + if (pools[i]) + ion_page_pool_destroy(pools[i]); +} + +static int ion_system_heap_create_pools(struct ion_page_pool **pools, + bool cached) +{ + int i; + gfp_t gfp_flags = low_order_gfp_flags; + + for (i = 0; i < NUM_ORDERS; i++) { + struct ion_page_pool *pool; + + if (orders[i] > 4) + gfp_flags = high_order_gfp_flags; + + pool = ion_page_pool_create(gfp_flags, orders[i], cached); + if (!pool) + goto err_create_pool; + pools[i] = pool; + } + return 0; + +err_create_pool: + ion_system_heap_destroy_pools(pools); + return -ENOMEM; +} + struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) { struct ion_system_heap *heap; - int i; - heap = kzalloc(sizeof(struct ion_system_heap) + - sizeof(struct ion_page_pool *) * num_orders, - GFP_KERNEL); + heap = kzalloc(sizeof(*heap), GFP_KERNEL); if (!heap) return ERR_PTR(-ENOMEM); heap->heap.ops = &system_heap_ops; heap->heap.type = ION_HEAP_TYPE_SYSTEM; heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool; - gfp_t gfp_flags = low_order_gfp_flags; + if (ion_system_heap_create_pools(heap->uncached_pools, false)) + goto free_heap; - if (orders[i] > 4) - gfp_flags = high_order_gfp_flags; - pool = ion_page_pool_create(gfp_flags, orders[i]); - if (!pool) - goto destroy_pools; - heap->pools[i] = pool; - } + if (ion_system_heap_create_pools(heap->cached_pools, true)) + goto destroy_uncached_pools; heap->heap.debug_show = ion_system_heap_debug_show; return &heap->heap; -destroy_pools: - while (i--) - ion_page_pool_destroy(heap->pools[i]); +destroy_uncached_pools: + ion_system_heap_destroy_pools(heap->uncached_pools); + +free_heap: kfree(heap); return ERR_PTR(-ENOMEM); } @@ -316,8 +362,10 @@ void ion_system_heap_destroy(struct ion_heap *heap) heap); int i; - for (i = 0; i < num_orders; i++) - ion_page_pool_destroy(sys_heap->pools[i]); + for (i = 0; i < NUM_ORDERS; i++) { + ion_page_pool_destroy(sys_heap->uncached_pools[i]); + ion_page_pool_destroy(sys_heap->cached_pools[i]); + } kfree(sys_heap); } @@ -358,7 +406,7 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, sg_set_page(table->sgl, page, len, 0); - buffer->priv_virt = table; + buffer->sg_table = table; ion_pages_sync_for_device(NULL, page, len, DMA_BIDIRECTIONAL); @@ -375,7 +423,7 @@ free_pages: static void ion_system_contig_heap_free(struct ion_buffer *buffer) { - struct sg_table *table = buffer->priv_virt; + struct sg_table *table = buffer->sg_table; struct page *page = sg_page(table->sgl); unsigned long pages = PAGE_ALIGN(buffer->size) >> PAGE_SHIFT; unsigned long i; @@ -386,34 +434,9 @@ static void ion_system_contig_heap_free(struct ion_buffer *buffer) kfree(table); } -static int ion_system_contig_heap_phys(struct ion_heap *heap, - struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - struct sg_table *table = buffer->priv_virt; - struct page *page = sg_page(table->sgl); - *addr = page_to_phys(page); - *len = buffer->size; - return 0; -} - -static struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -static void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static struct ion_heap_ops kmalloc_ops = { .allocate = ion_system_contig_heap_allocate, .free = ion_system_contig_heap_free, - .phys = ion_system_contig_heap_phys, - .map_dma = ion_system_contig_heap_map_dma, - .unmap_dma = ion_system_contig_heap_unmap_dma, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, .map_user = ion_heap_map_user, diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c index 5a396a1a8238..5abf8320a96a 100644 --- a/drivers/staging/android/ion/ion_test.c +++ b/drivers/staging/android/ion/ion_test.c @@ -42,7 +42,8 @@ struct ion_test_data { }; static int ion_handle_test_dma(struct device *dev, struct dma_buf *dma_buf, - void __user *ptr, size_t offset, size_t size, bool write) + void __user *ptr, size_t offset, size_t size, + bool write) { int ret = 0; struct dma_buf_attachment *attach; @@ -98,7 +99,7 @@ err: } static int ion_handle_test_kernel(struct dma_buf *dma_buf, void __user *ptr, - size_t offset, size_t size, bool write) + size_t offset, size_t size, bool write) { int ret; unsigned long page_offset = offset >> PAGE_SHIFT; @@ -144,7 +145,7 @@ err: } static long ion_test_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) + unsigned long arg) { struct ion_test_data *test_data = filp->private_data; int ret = 0; @@ -179,17 +180,19 @@ static long ion_test_ioctl(struct file *filp, unsigned int cmd, case ION_IOC_TEST_DMA_MAPPING: { ret = ion_handle_test_dma(test_data->dev, test_data->dma_buf, - u64_to_uptr(data.test_rw.ptr), - data.test_rw.offset, data.test_rw.size, - data.test_rw.write); + u64_to_uptr(data.test_rw.ptr), + data.test_rw.offset, + data.test_rw.size, + data.test_rw.write); break; } case ION_IOC_TEST_KERNEL_MAPPING: { ret = ion_handle_test_kernel(test_data->dma_buf, - u64_to_uptr(data.test_rw.ptr), - data.test_rw.offset, data.test_rw.size, - data.test_rw.write); + u64_to_uptr(data.test_rw.ptr), + data.test_rw.offset, + data.test_rw.size, + data.test_rw.write); break; } default: @@ -242,7 +245,7 @@ static int __init ion_test_probe(struct platform_device *pdev) struct ion_test_device *testdev; testdev = devm_kzalloc(&pdev->dev, sizeof(struct ion_test_device), - GFP_KERNEL); + GFP_KERNEL); if (!testdev) return -ENOMEM; diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 45a1b4ec4ca3..ec3b66561412 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -92,8 +92,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) int array_size = ARRAY_SIZE(lowmem_adj); int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages; int other_file = global_node_page_state(NR_FILE_PAGES) - - global_node_page_state(NR_SHMEM) - - total_swapcache_pages(); + global_node_page_state(NR_SHMEM) - + total_swapcache_pages(); if (lowmem_adj_size < array_size) array_size = lowmem_adj_size; @@ -204,10 +204,9 @@ device_initcall(lowmem_init); * not really modular, but the easiest way to keep compat with existing * bootargs behaviour is to continue using module_param here. */ -module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR); -module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, - S_IRUGO | S_IWUSR); +module_param_named(cost, lowmem_shrinker.seeks, int, 0644); +module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644); module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, - S_IRUGO | S_IWUSR); -module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR); + 0644); +module_param_named(debug_level, lowmem_debug_level, uint, 0644); diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index 0a8e40f92cd7..14cd8738ecfc 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -44,32 +44,26 @@ enum ion_heap_type { * must be last so device specific heaps always * are at the end of this enum */ - ION_NUM_HEAPS = 16, }; -#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM) -#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) -#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) -#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA) - #define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8) /** * allocation flags - the lower 16 bits are used by core ion, the upper 16 * bits are reserved for use by the heaps themselves. */ -#define ION_FLAG_CACHED 1 /* - * mappings of this buffer should be - * cached, ion will do cache - * maintenance when the buffer is - * mapped for dma - */ -#define ION_FLAG_CACHED_NEEDS_SYNC 2 /* - * mappings of this buffer will created - * at mmap time, if this is set - * caches must be managed - * manually - */ + +/* + * mappings of this buffer should be cached, ion will do cache maintenance + * when the buffer is mapped for dma + */ +#define ION_FLAG_CACHED 1 + +/* + * mappings of this buffer will created at mmap time, if this is set + * caches must be managed manually + */ +#define ION_FLAG_CACHED_NEEDS_SYNC 2 /** * DOC: Ion Userspace API @@ -134,6 +128,36 @@ struct ion_custom_data { unsigned long arg; }; +#define MAX_HEAP_NAME 32 + +/** + * struct ion_heap_data - data about a heap + * @name - first 32 characters of the heap name + * @type - heap type + * @heap_id - heap id for the heap + */ +struct ion_heap_data { + char name[MAX_HEAP_NAME]; + __u32 type; + __u32 heap_id; + __u32 reserved0; + __u32 reserved1; + __u32 reserved2; +}; + +/** + * struct ion_heap_query - collection of data about all heaps + * @cnt - total number of heaps to be copied + * @heaps - buffer to copy heap data + */ +struct ion_heap_query { + __u32 cnt; /* Total number of heaps to be copied */ + __u32 reserved0; /* align to 64bits */ + __u64 heaps; /* buffer to be populated */ + __u32 reserved1; + __u32 reserved2; +}; + #define ION_IOC_MAGIC 'I' /** @@ -200,4 +224,13 @@ struct ion_custom_data { */ #define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data) +/** + * DOC: ION_IOC_HEAP_QUERY - information about available heaps + * + * Takes an ion_heap_query structure and populates information about + * available Ion heaps. + */ +#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, \ + struct ion_heap_query) + #endif /* _UAPI_LINUX_ION_H */ diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 1999eed4f4c5..64b3966c5f1f 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -81,20 +81,20 @@ struct comedi_file { (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS) static int comedi_num_legacy_minors; -module_param(comedi_num_legacy_minors, int, S_IRUGO); +module_param(comedi_num_legacy_minors, int, 0444); MODULE_PARM_DESC(comedi_num_legacy_minors, "number of comedi minor devices to reserve for non-auto-configured devices (default 0)" ); unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB; -module_param(comedi_default_buf_size_kb, uint, S_IRUGO | S_IWUSR); +module_param(comedi_default_buf_size_kb, uint, 0644); MODULE_PARM_DESC(comedi_default_buf_size_kb, "default asynchronous buffer size in KiB (default " __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")"); unsigned int comedi_default_buf_maxsize_kb = CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB; -module_param(comedi_default_buf_maxsize_kb, uint, S_IRUGO | S_IWUSR); +module_param(comedi_default_buf_maxsize_kb, uint, 0644); MODULE_PARM_DESC(comedi_default_buf_maxsize_kb, "default maximum size of asynchronous buffer in KiB (default " __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")"); @@ -2233,7 +2233,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) goto done; } - n_pages = size >> PAGE_SHIFT; + n_pages = vma_pages(vma); /* get reference to current buf map (if any) */ bm = comedi_buf_map_from_subdev_get(s); diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 44511d729450..a5bf2cc165c0 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -15,7 +15,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -*/ + */ #include #include diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c deleted file mode 100644 index 375707497896..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Watchdog Related Defines */ - -#define ADDIDATA_TIMER 0 -#define ADDIDATA_WATCHDOG 2 - -/* - * (*insn_config) for the timer subdevice - * - * Configures The Timer, Counter or Watchdog - * Data Pointer contains configuration parameters as below - * data[0] : 0 Configure As Timer - * 1 Configure As Counter - * 2 Configure As Watchdog - * data[1] : 1 Enable Interrupt - * 0 Disable Interrupt - * data[2] : Time Unit - * data[3] : Reload Value - */ -static int apci3501_config_insn_timer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci3501_private *devpriv = dev->private; - unsigned int ctrl; - - if (data[0] != ADDIDATA_WATCHDOG && - data[0] != ADDIDATA_TIMER) - return -EINVAL; - - devpriv->tsk_Current = current; - - devpriv->timer_mode = data[0]; - - /* first, disable the watchdog or stop the timer */ - if (devpriv->timer_mode == ADDIDATA_WATCHDOG) { - ctrl = 0; - } else { - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | - ADDI_TCW_CTRL_ENA); - } - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - - /* enable/disable the timer interrupt */ - ctrl = (data[1] == 1) ? ADDI_TCW_CTRL_IRQ_ENA : 0; - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - - outl(data[2], devpriv->tcw + ADDI_TCW_TIMEBASE_REG); - outl(data[3], devpriv->tcw + ADDI_TCW_RELOAD_REG); - - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - if (devpriv->timer_mode == ADDIDATA_WATCHDOG) { - /* Set the mode (e2->e0) NOTE: this doesn't look correct */ - ctrl |= ~(ADDI_TCW_CTRL_CNT_UP | ADDI_TCW_CTRL_EXT_CLK_MASK | - ADDI_TCW_CTRL_MODE_MASK | ADDI_TCW_CTRL_GATE | - ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_TIMER_ENA | - ADDI_TCW_CTRL_RESET_ENA | ADDI_TCW_CTRL_WARN_ENA | - ADDI_TCW_CTRL_IRQ_ENA | ADDI_TCW_CTRL_ENA); - } else { - /* mode 2 */ - ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK | - ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | - ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA | - ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA); - ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA; - } - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - - return insn->n; -} - -/* - * (*insn_write) for the timer subdevice - * - * Start / Stop The Selected Timer , Counter or Watchdog - * Data Pointer contains configuration parameters as below - * data[0] : 0 Timer - * 1 Counter - * 2 Watchdog - * data[1] : 1 Start - * 0 Stop - * 2 Trigger - */ -static int apci3501_write_insn_timer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci3501_private *devpriv = dev->private; - unsigned int ctrl; - - if (devpriv->timer_mode == ADDIDATA_WATCHDOG || - devpriv->timer_mode == ADDIDATA_TIMER) { - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG); - - if (data[1] == 1) { /* enable */ - ctrl |= ADDI_TCW_CTRL_ENA; - } else if (data[1] == 0) { /* stop */ - if (devpriv->timer_mode == ADDIDATA_WATCHDOG) - ctrl = 0; - else - ctrl &= ~ADDI_TCW_CTRL_ENA; - } else if (data[1] == 2) { /* trigger */ - ctrl |= ADDI_TCW_CTRL_TRIG; - } - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - } - - inl(devpriv->tcw + ADDI_TCW_STATUS_REG); - return insn->n; -} - -/* - * (*insn_read) for the timer subdevice - * - * Read The Selected Timer, Counter or Watchdog - * Data Pointer contains configuration parameters as below - * data[0] : 0 Timer - * 1 Counter - * 2 Watchdog - * data[1] : Timer Counter Watchdog Number - */ -static int apci3501_read_insn_timer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci3501_private *devpriv = dev->private; - - if (devpriv->timer_mode != ADDIDATA_TIMER && - devpriv->timer_mode != ADDIDATA_WATCHDOG) - return -EINVAL; - - data[0] = inl(devpriv->tcw + ADDI_TCW_STATUS_REG) & - ADDI_TCW_STATUS_OVERFLOW; - data[1] = inl(devpriv->tcw + ADDI_TCW_VAL_REG); - - return insn->n; -} diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 40ff91411139..57f0f46de0be 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -22,12 +22,36 @@ * more details. */ +/* + * Driver: addi_apci_3501 + * Description: ADDI-DATA APCI-3501 Analog output board + * Devices: [ADDI-DATA] APCI-3501 (addi_apci_3501) + * Author: H Hartley Sweeten + * Updated: Mon, 20 Jun 2016 10:57:01 -0700 + * Status: untested + * + * Configuration Options: not applicable, uses comedi PCI auto config + * + * This board has the following features: + * - 4 or 8 analog output channels + * - 2 optically isolated digital inputs + * - 2 optically isolated digital outputs + * - 1 12-bit watchdog/timer + * + * There are 2 versions of the APCI-3501: + * - APCI-3501-4 4 analog output channels + * - APCI-3501-8 8 analog output channels + * + * These boards use the same PCI Vendor/Device IDs. The number of output + * channels used by this driver is determined by reading the EEPROM on + * the board. + * + * The watchdog/timer subdevice is not currently supported. + */ + #include -#include -#include #include "../comedi_pci.h" -#include "addi_tcw.h" #include "amcc_s5933.h" /* @@ -67,8 +91,6 @@ struct apci3501_private { unsigned long amcc; - unsigned long tcw; - struct task_struct *tsk_Current; unsigned char timer_mode; }; @@ -139,8 +161,6 @@ static int apci3501_ao_insn_write(struct comedi_device *dev, return insn->n; } -#include "addi-data/hwdrv_apci3501.c" - static int apci3501_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -253,37 +273,6 @@ static int apci3501_eeprom_insn_read(struct comedi_device *dev, return insn->n; } -static irqreturn_t apci3501_interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct apci3501_private *devpriv = dev->private; - unsigned int status; - unsigned int ctrl; - - /* Disable Interrupt */ - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | - ADDI_TCW_CTRL_IRQ_ENA); - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - - status = inl(devpriv->tcw + ADDI_TCW_IRQ_REG); - if (!(status & ADDI_TCW_IRQ)) { - dev_err(dev->class_dev, "IRQ from unknown source\n"); - return IRQ_NONE; - } - - /* Enable Interrupt Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | - ADDI_TCW_CTRL_IRQ_ENA); - ctrl |= ADDI_TCW_CTRL_IRQ_ENA; - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - inl(devpriv->tcw + ADDI_TCW_STATUS_REG); - - return IRQ_HANDLED; -} - static int apci3501_reset(struct comedi_device *dev) { unsigned int val; @@ -333,17 +322,9 @@ static int apci3501_auto_attach(struct comedi_device *dev, devpriv->amcc = pci_resource_start(pcidev, 0); dev->iobase = pci_resource_start(pcidev, 1); - devpriv->tcw = dev->iobase + APCI3501_TIMER_BASE; ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev); - if (pcidev->irq > 0) { - ret = request_irq(pcidev->irq, apci3501_interrupt, IRQF_SHARED, - dev->board_name, dev); - if (ret == 0) - dev->irq = pcidev->irq; - } - ret = comedi_alloc_subdevices(dev, 5); if (ret) return ret; @@ -383,17 +364,9 @@ static int apci3501_auto_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = apci3501_do_insn_bits; - /* Initialize the timer/watchdog subdevice */ + /* Timer/Watchdog subdevice */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_TIMER; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 1; - s->maxdata = 0; - s->len_chanlist = 1; - s->range_table = &range_digital; - s->insn_write = apci3501_write_insn_timer; - s->insn_read = apci3501_read_insn_timer; - s->insn_config = apci3501_config_insn_timer; + s->type = COMEDI_SUBD_UNUSED; /* Initialize the eeprom subdevice */ s = &dev->subdevices[4]; diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index be70bd333807..86450c08f291 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1693,8 +1693,7 @@ static void pci9118_detach(struct comedi_device *dev) pci9118_reset(dev); comedi_pci_detach(dev); pci9118_free_dma(dev); - if (pcidev) - pci_dev_put(pcidev); + pci_dev_put(pcidev); } static struct comedi_driver adl_pci9118_driver = { diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 1f9c08a845b6..cb9c2699277e 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1,34 +1,34 @@ /* - comedi/drivers/cb_pcidas64.c - This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS - 64xx, 60xx, and 4020 cards. - - Author: Frank Mori Hess - Copyright (C) 2001, 2002 Frank Mori Hess - - Thanks also go to the following people: - - Steve Rosenbluth, for providing the source code for - his pci-das6402 driver, and source code for working QNX pci-6402 - drivers by Greg Laird and Mariusz Bogacz. None of the code was - used directly here, but it was useful as an additional source of - documentation on how to program the boards. - - John Sims, for much testing and feedback on pcidas-4020 support. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-8 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/drivers/cb_pcidas64.c + * This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS + * 64xx, 60xx, and 4020 cards. + * + * Author: Frank Mori Hess + * Copyright (C) 2001, 2002 Frank Mori Hess + * + * Thanks also go to the following people: + * + * Steve Rosenbluth, for providing the source code for + * his pci-das6402 driver, and source code for working QNX pci-6402 + * drivers by Greg Laird and Mariusz Bogacz. None of the code was + * used directly here, but it was useful as an additional source of + * documentation on how to program the boards. + * + * John Sims, for much testing and feedback on pcidas-4020 support. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-8 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* * Driver: cb_pcidas64 @@ -66,19 +66,18 @@ */ /* - -TODO: - make it return error if user attempts an ai command that uses the - external queue, and an ao command simultaneously user counter subdevice - there are a number of boards this driver will support when they are - fully released, but does not yet since the pci device id numbers - are not yet available. - - support prescaled 100khz clock for slow pacing (not available on 6000 - series?) - - make ao fifo size adjustable like ai fifo -*/ + * TODO: + * make it return error if user attempts an ai command that uses the + * external queue, and an ao command simultaneously user counter subdevice + * there are a number of boards this driver will support when they are + * fully released, but does not yet since the pci device id numbers + * are not yet available. + * + * support prescaled 100khz clock for slow pacing (not available on 6000 + * series?) + * + * make ao fifo size adjustable like ai fifo + */ #include #include @@ -90,53 +89,56 @@ TODO: #include "plx9080.h" #define TIMER_BASE 25 /* 40MHz master clock */ -/* 100kHz 'prescaled' clock for slow acquisition, - * maybe I'll support this someday */ +/* + * 100kHz 'prescaled' clock for slow acquisition, + * maybe I'll support this someday + */ #define PRESCALED_TIMER_BASE 10000 -#define DMA_BUFFER_SIZE 0x1000 +#define DMA_BUFFER_SIZE 0x1000 +#define DAC_FIFO_SIZE 0x2000 -/* maximum value that can be loaded into board's 24-bit counters*/ +/* maximum value that can be loaded into board's 24-bit counters */ static const int max_counter_value = 0xffffff; /* PCI-DAS64xxx base addresses */ /* devpriv->main_iobase registers */ enum write_only_registers { - INTR_ENABLE_REG = 0x0, /* interrupt enable register */ - HW_CONFIG_REG = 0x2, /* hardware config register */ + INTR_ENABLE_REG = 0x0, /* interrupt enable register */ + HW_CONFIG_REG = 0x2, /* hardware config register */ DAQ_SYNC_REG = 0xc, DAQ_ATRIG_LOW_4020_REG = 0xc, - ADC_CONTROL0_REG = 0x10, /* adc control register 0 */ - ADC_CONTROL1_REG = 0x12, /* adc control register 1 */ + ADC_CONTROL0_REG = 0x10, /* adc control register 0 */ + ADC_CONTROL1_REG = 0x12, /* adc control register 1 */ CALIBRATION_REG = 0x14, - /* lower 16 bits of adc sample interval counter */ + /* lower 16 bits of adc sample interval counter */ ADC_SAMPLE_INTERVAL_LOWER_REG = 0x16, - /* upper 8 bits of adc sample interval counter */ + /* upper 8 bits of adc sample interval counter */ ADC_SAMPLE_INTERVAL_UPPER_REG = 0x18, - /* lower 16 bits of delay interval counter */ + /* lower 16 bits of delay interval counter */ ADC_DELAY_INTERVAL_LOWER_REG = 0x1a, - /* upper 8 bits of delay interval counter */ + /* upper 8 bits of delay interval counter */ ADC_DELAY_INTERVAL_UPPER_REG = 0x1c, - /* lower 16 bits of hardware conversion/scan counter */ + /* lower 16 bits of hardware conversion/scan counter */ ADC_COUNT_LOWER_REG = 0x1e, - /* upper 8 bits of hardware conversion/scan counter */ + /* upper 8 bits of hardware conversion/scan counter */ ADC_COUNT_UPPER_REG = 0x20, - ADC_START_REG = 0x22, /* software trigger to start acquisition */ - ADC_CONVERT_REG = 0x24, /* initiates single conversion */ - ADC_QUEUE_CLEAR_REG = 0x26, /* clears adc queue */ - ADC_QUEUE_LOAD_REG = 0x28, /* loads adc queue */ + ADC_START_REG = 0x22, /* software trigger to start acquisition */ + ADC_CONVERT_REG = 0x24, /* initiates single conversion */ + ADC_QUEUE_CLEAR_REG = 0x26, /* clears adc queue */ + ADC_QUEUE_LOAD_REG = 0x28, /* loads adc queue */ ADC_BUFFER_CLEAR_REG = 0x2a, - /* high channel for internal queue, use adc_chan_bits() inline above */ + /* high channel for internal queue, use adc_chan_bits() inline above */ ADC_QUEUE_HIGH_REG = 0x2c, - DAC_CONTROL0_REG = 0x50, /* dac control register 0 */ - DAC_CONTROL1_REG = 0x52, /* dac control register 0 */ - /* lower 16 bits of dac sample interval counter */ + DAC_CONTROL0_REG = 0x50, /* dac control register 0 */ + DAC_CONTROL1_REG = 0x52, /* dac control register 0 */ + /* lower 16 bits of dac sample interval counter */ DAC_SAMPLE_INTERVAL_LOWER_REG = 0x54, - /* upper 8 bits of dac sample interval counter */ + /* upper 8 bits of dac sample interval counter */ DAC_SAMPLE_INTERVAL_UPPER_REG = 0x56, DAC_SELECT_REG = 0x60, DAC_START_REG = 0x64, - DAC_BUFFER_CLEAR_REG = 0x66, /* clear dac buffer */ + DAC_BUFFER_CLEAR_REG = 0x66, /* clear dac buffer */ }; static inline unsigned int dac_convert_reg(unsigned int channel) @@ -168,8 +170,8 @@ enum read_only_registers { }; enum read_write_registers { - I8255_4020_REG = 0x48, /* 8255 offset, for 4020 only */ - /* external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG */ + I8255_4020_REG = 0x48, /* 8255 offset, for 4020 only */ + /* external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG */ ADC_QUEUE_FIFO_REG = 0x100, ADC_FIFO_REG = 0x200, /* adc data fifo */ /* dac data fifo, has weird interactions with external channel queue */ @@ -188,50 +190,51 @@ enum dio_counter_registers { /* bit definitions for write-only registers */ enum intr_enable_contents { - ADC_INTR_SRC_MASK = 0x3, /* adc interrupt source mask */ - ADC_INTR_QFULL_BITS = 0x0, /* interrupt fifo quarter full */ - ADC_INTR_EOC_BITS = 0x1, /* interrupt end of conversion */ - ADC_INTR_EOSCAN_BITS = 0x2, /* interrupt end of scan */ - ADC_INTR_EOSEQ_BITS = 0x3, /* interrupt end of sequence mask */ - EN_ADC_INTR_SRC_BIT = 0x4, /* enable adc interrupt source */ - EN_ADC_DONE_INTR_BIT = 0x8, /* enable adc acquisition done intr */ + ADC_INTR_SRC_MASK = 0x3, /* adc interrupt source mask */ + ADC_INTR_QFULL_BITS = 0x0, /* interrupt fifo quarter full */ + ADC_INTR_EOC_BITS = 0x1, /* interrupt end of conversion */ + ADC_INTR_EOSCAN_BITS = 0x2, /* interrupt end of scan */ + ADC_INTR_EOSEQ_BITS = 0x3, /* interrupt end of sequence mask */ + EN_ADC_INTR_SRC_BIT = 0x4, /* enable adc interrupt source */ + EN_ADC_DONE_INTR_BIT = 0x8, /* enable adc acquisition done intr */ DAC_INTR_SRC_MASK = 0x30, DAC_INTR_QEMPTY_BITS = 0x0, DAC_INTR_HIGH_CHAN_BITS = 0x10, - EN_DAC_INTR_SRC_BIT = 0x40, /* enable dac interrupt source */ + EN_DAC_INTR_SRC_BIT = 0x40, /* enable dac interrupt source */ EN_DAC_DONE_INTR_BIT = 0x80, - EN_ADC_ACTIVE_INTR_BIT = 0x200, /* enable adc active interrupt */ - EN_ADC_STOP_INTR_BIT = 0x400, /* enable adc stop trigger interrupt */ - EN_DAC_ACTIVE_INTR_BIT = 0x800, /* enable dac active interrupt */ - EN_DAC_UNDERRUN_BIT = 0x4000, /* enable dac underrun status bit */ - EN_ADC_OVERRUN_BIT = 0x8000, /* enable adc overrun status bit */ + EN_ADC_ACTIVE_INTR_BIT = 0x200, /* enable adc active interrupt */ + EN_ADC_STOP_INTR_BIT = 0x400, /* enable adc stop trigger interrupt */ + EN_DAC_ACTIVE_INTR_BIT = 0x800, /* enable dac active interrupt */ + EN_DAC_UNDERRUN_BIT = 0x4000, /* enable dac underrun status bit */ + EN_ADC_OVERRUN_BIT = 0x8000, /* enable adc overrun status bit */ }; enum hw_config_contents { - MASTER_CLOCK_4020_MASK = 0x3, /* master clock source mask for 4020 */ - INTERNAL_CLOCK_4020_BITS = 0x1, /* use 40 MHz internal master clock */ - BNC_CLOCK_4020_BITS = 0x2, /* use BNC input for master clock */ - EXT_CLOCK_4020_BITS = 0x3, /* use dio input for master clock */ - EXT_QUEUE_BIT = 0x200, /* use external channel/gain queue */ - /* use 225 nanosec strobe when loading dac instead of 50 nanosec */ + MASTER_CLOCK_4020_MASK = 0x3, /* master clock source mask for 4020 */ + INTERNAL_CLOCK_4020_BITS = 0x1, /* use 40 MHz internal master clock */ + BNC_CLOCK_4020_BITS = 0x2, /* use BNC input for master clock */ + EXT_CLOCK_4020_BITS = 0x3, /* use dio input for master clock */ + EXT_QUEUE_BIT = 0x200, /* use external channel/gain queue */ + /* use 225 nanosec strobe when loading dac instead of 50 nanosec */ SLOW_DAC_BIT = 0x400, - /* bit with unknown function yet given as default value in pci-das64 - * manual */ + /* + * bit with unknown function yet given as default value in pci-das64 + * manual + */ HW_CONFIG_DUMMY_BITS = 0x2000, - /* bit selects channels 1/0 for analog input/output, otherwise 0/1 */ + /* bit selects channels 1/0 for analog input/output, otherwise 0/1 */ DMA_CH_SELECT_BIT = 0x8000, - FIFO_SIZE_REG = 0x4, /* allows adjustment of fifo sizes */ - DAC_FIFO_SIZE_MASK = 0xff00, /* bits that set dac fifo size */ - DAC_FIFO_BITS = 0xf800, /* 8k sample ao fifo */ + FIFO_SIZE_REG = 0x4, /* allows adjustment of fifo sizes */ + DAC_FIFO_SIZE_MASK = 0xff00, /* bits that set dac fifo size */ + DAC_FIFO_BITS = 0xf800, /* 8k sample ao fifo */ }; -#define DAC_FIFO_SIZE 0x2000 enum daq_atrig_low_4020_contents { - /* use trig/ext clk bnc input for analog gate signal */ + /* use trig/ext clk bnc input for analog gate signal */ EXT_AGATE_BNC_BIT = 0x8000, - /* use trig/ext clk bnc input for external stop trigger signal */ + /* use trig/ext clk bnc input for external stop trigger signal */ EXT_STOP_TRIG_BNC_BIT = 0x4000, - /* use trig/ext clk bnc input for external start trigger signal */ + /* use trig/ext clk bnc input for external start trigger signal */ EXT_START_TRIG_BNC_BIT = 0x2000, }; @@ -241,38 +244,38 @@ static inline uint16_t analog_trig_low_threshold_bits(uint16_t threshold) } enum adc_control0_contents { - ADC_GATE_SRC_MASK = 0x3, /* bits that select gate */ - ADC_SOFT_GATE_BITS = 0x1, /* software gate */ - ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ - ADC_ANALOG_GATE_BITS = 0x3, /* analog level gate */ - /* level-sensitive gate (for digital) */ + ADC_GATE_SRC_MASK = 0x3, /* bits that select gate */ + ADC_SOFT_GATE_BITS = 0x1, /* software gate */ + ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ + ADC_ANALOG_GATE_BITS = 0x3, /* analog level gate */ + /* level-sensitive gate (for digital) */ ADC_GATE_LEVEL_BIT = 0x4, - ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ + ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ ADC_START_TRIG_SOFT_BITS = 0x10, ADC_START_TRIG_EXT_BITS = 0x20, ADC_START_TRIG_ANALOG_BITS = 0x30, ADC_START_TRIG_MASK = 0x30, - ADC_START_TRIG_FALLING_BIT = 0x40, /* trig 1 uses falling edge */ - /* external pacing uses falling edge */ + ADC_START_TRIG_FALLING_BIT = 0x40, /* trig 1 uses falling edge */ + /* external pacing uses falling edge */ ADC_EXT_CONV_FALLING_BIT = 0x800, - /* enable hardware scan counter */ + /* enable hardware scan counter */ ADC_SAMPLE_COUNTER_EN_BIT = 0x1000, - ADC_DMA_DISABLE_BIT = 0x4000, /* disables dma */ - ADC_ENABLE_BIT = 0x8000, /* master adc enable */ + ADC_DMA_DISABLE_BIT = 0x4000, /* disables dma */ + ADC_ENABLE_BIT = 0x8000, /* master adc enable */ }; enum adc_control1_contents { - /* should be set for boards with > 16 channels */ + /* should be set for boards with > 16 channels */ ADC_QUEUE_CONFIG_BIT = 0x1, CONVERT_POLARITY_BIT = 0x10, EOC_POLARITY_BIT = 0x20, - ADC_SW_GATE_BIT = 0x40, /* software gate of adc */ - ADC_DITHER_BIT = 0x200, /* turn on extra noise for dithering */ + ADC_SW_GATE_BIT = 0x40, /* software gate of adc */ + ADC_DITHER_BIT = 0x200, /* turn on extra noise for dithering */ RETRIGGER_BIT = 0x800, ADC_LO_CHANNEL_4020_MASK = 0x300, ADC_HI_CHANNEL_4020_MASK = 0xc00, - TWO_CHANNEL_4020_BITS = 0x1000, /* two channel mode for 4020 */ - FOUR_CHANNEL_4020_BITS = 0x2000, /* four channel mode for 4020 */ + TWO_CHANNEL_4020_BITS = 0x1000, /* two channel mode for 4020 */ + FOUR_CHANNEL_4020_BITS = 0x2000, /* four channel mode for 4020 */ CHANNEL_MODE_4020_MASK = 0x3000, ADC_MODE_MASK = 0xf000, }; @@ -296,10 +299,10 @@ enum calibration_contents { SELECT_8800_BIT = 0x1, SELECT_8402_64XX_BIT = 0x2, SELECT_1590_60XX_BIT = 0x2, - CAL_EN_64XX_BIT = 0x40, /* calibration enable for 64xx series */ + CAL_EN_64XX_BIT = 0x40, /* calibration enable for 64xx series */ SERIAL_DATA_IN_BIT = 0x80, SERIAL_CLOCK_BIT = 0x100, - CAL_EN_60XX_BIT = 0x200, /* calibration enable for 60xx series */ + CAL_EN_60XX_BIT = 0x200, /* calibration enable for 60xx series */ CAL_GAIN_BIT = 0x800, }; @@ -326,12 +329,12 @@ static inline uint16_t adc_convert_chan_4020_bits(unsigned int channel) }; enum adc_queue_load_contents { - UNIP_BIT = 0x800, /* unipolar/bipolar bit */ - ADC_SE_DIFF_BIT = 0x1000, /* single-ended/ differential bit */ - /* non-referenced single-ended (common-mode input) */ + UNIP_BIT = 0x800, /* unipolar/bipolar bit */ + ADC_SE_DIFF_BIT = 0x1000, /* single-ended/ differential bit */ + /* non-referenced single-ended (common-mode input) */ ADC_COMMON_BIT = 0x2000, - QUEUE_EOSEQ_BIT = 0x4000, /* queue end of sequence */ - QUEUE_EOSCAN_BIT = 0x8000, /* queue end of scan */ + QUEUE_EOSEQ_BIT = 0x4000, /* queue end of sequence */ + QUEUE_EOSCAN_BIT = 0x8000, /* queue end of scan */ }; static inline uint16_t adc_chan_bits(unsigned int channel) @@ -340,7 +343,7 @@ static inline uint16_t adc_chan_bits(unsigned int channel) }; enum dac_control0_contents { - DAC_ENABLE_BIT = 0x8000, /* dac controller enable bit */ + DAC_ENABLE_BIT = 0x8000, /* dac controller enable bit */ DAC_CYCLIC_STOP_BIT = 0x4000, DAC_WAVEFORM_MODE_BIT = 0x100, DAC_EXT_UPDATE_FALLING_BIT = 0x80, @@ -360,7 +363,7 @@ enum dac_control1_contents { DAC_WRITE_POLARITY_BIT = 0x800, /* board-dependent setting */ DAC1_EXT_REF_BIT = 0x200, DAC0_EXT_REF_BIT = 0x100, - DAC_OUTPUT_ENABLE_BIT = 0x80, /* dac output enable bit */ + DAC_OUTPUT_ENABLE_BIT = 0x80, /* dac output enable bit */ DAC_UPDATE_POLARITY_BIT = 0x40, /* board-dependent setting */ DAC_SW_GATE_BIT = 0x20, DAC1_UNIPOLAR_BIT = 0x8, @@ -409,9 +412,9 @@ enum i2c_addresses { }; enum range_cal_i2c_contents { - /* bits that set what source the adc converter measures */ + /* bits that set what source the adc converter measures */ ADC_SRC_4020_MASK = 0x70, - /* make bnc trig/ext clock threshold 0V instead of 2.5V */ + /* make bnc trig/ext clock threshold 0V instead of 2.5V */ BNC_TRIG_THRESHOLD_0V_BIT = 0x80, }; @@ -422,7 +425,7 @@ static inline uint8_t adc_src_4020_bits(unsigned int source) static inline uint8_t attenuate_bit(unsigned int channel) { - /* attenuate channel (+-5V input range) */ + /* attenuate channel (+-5V input range) */ return 1 << (channel & 0x3); }; @@ -627,18 +630,18 @@ enum pcidas64_boardid { struct pcidas64_board { const char *name; - int ai_se_chans; /* number of ai inputs in single-ended mode */ - int ai_bits; /* analog input resolution */ - int ai_speed; /* fastest conversion period in ns */ + int ai_se_chans; /* number of ai inputs in single-ended mode */ + int ai_bits; /* analog input resolution */ + int ai_speed; /* fastest conversion period in ns */ const struct comedi_lrange *ai_range_table; const uint8_t *ai_range_code; - int ao_nchan; /* number of analog out channels */ - int ao_bits; /* analog output resolution */ - int ao_scan_speed; /* analog output scan speed */ + int ao_nchan; /* number of analog out channels */ + int ao_bits; /* analog output resolution */ + int ao_scan_speed; /* analog output scan speed */ const struct comedi_lrange *ao_range_table; const int *ao_range_code; const struct hw_fifo_info *const ai_fifo; - /* different board families have slightly different registers */ + /* different board families have slightly different registers */ enum register_layout layout; unsigned has_8255:1; }; @@ -699,7 +702,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .has_8255 = 1, }, [BOARD_PCIDAS6402_12] = { - .name = "pci-das6402/12", /* XXX check */ + .name = "pci-das6402/12", /* XXX check */ .ai_se_chans = 64, .ai_bits = 12, .ai_speed = 5000, @@ -996,7 +999,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ai_speed = 50, .ao_bits = 12, .ao_nchan = 2, - .ao_scan_speed = 0, /* no hardware pacing on ao */ + .ao_scan_speed = 0, /* no hardware pacing on ao */ .layout = LAYOUT_4020, .ai_range_table = &ai_ranges_4020, .ao_range_table = &ao_ranges_4020, @@ -1005,9 +1008,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .has_8255 = 1, }, #if 0 - /* - * The device id for these boards is unknown - */ + /* The device id for these boards is unknown */ [BOARD_PCIDAS6402_16_JR] = { .name = "pci-das6402/16/jr", @@ -1116,62 +1117,66 @@ static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev, } struct ext_clock_info { - /* master clock divisor to use for scans with external master clock */ + /* master clock divisor to use for scans with external master clock */ unsigned int divisor; - /* chanspec for master clock input when used as scan begin src */ + /* chanspec for master clock input when used as scan begin src */ unsigned int chanspec; }; /* this structure is for data unique to this hardware driver. */ struct pcidas64_private { - /* base addresses (physical) */ + /* base addresses (physical) */ resource_size_t main_phys_iobase; resource_size_t dio_counter_phys_iobase; - /* base addresses (ioremapped) */ + /* base addresses (ioremapped) */ void __iomem *plx9080_iobase; void __iomem *main_iobase; - /* local address (used by dma controller) */ + /* local address (used by dma controller) */ uint32_t local0_iobase; uint32_t local1_iobase; - /* dma buffers for analog input */ + /* dma buffers for analog input */ uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT]; - /* physical addresses of ai dma buffers */ + /* physical addresses of ai dma buffers */ dma_addr_t ai_buffer_bus_addr[MAX_AI_DMA_RING_COUNT]; - /* array of ai dma descriptors read by plx9080, - * allocated to get proper alignment */ + /* + * array of ai dma descriptors read by plx9080, + * allocated to get proper alignment + */ struct plx_dma_desc *ai_dma_desc; - /* physical address of ai dma descriptor array */ + /* physical address of ai dma descriptor array */ dma_addr_t ai_dma_desc_bus_addr; - /* index of the ai dma descriptor/buffer - * that is currently being used */ + /* + * index of the ai dma descriptor/buffer + * that is currently being used + */ unsigned int ai_dma_index; - /* dma buffers for analog output */ + /* dma buffers for analog output */ uint16_t *ao_buffer[AO_DMA_RING_COUNT]; - /* physical addresses of ao dma buffers */ + /* physical addresses of ao dma buffers */ dma_addr_t ao_buffer_bus_addr[AO_DMA_RING_COUNT]; struct plx_dma_desc *ao_dma_desc; dma_addr_t ao_dma_desc_bus_addr; - /* keeps track of buffer where the next ao sample should go */ + /* keeps track of buffer where the next ao sample should go */ unsigned int ao_dma_index; - unsigned int hw_revision; /* stc chip hardware revision number */ - /* last bits sent to INTR_ENABLE_REG register */ + unsigned int hw_revision; /* stc chip hardware revision number */ + /* last bits sent to INTR_ENABLE_REG register */ unsigned int intr_enable_bits; - /* last bits sent to ADC_CONTROL1_REG register */ + /* last bits sent to ADC_CONTROL1_REG register */ uint16_t adc_control1_bits; - /* last bits sent to FIFO_SIZE_REG register */ + /* last bits sent to FIFO_SIZE_REG register */ uint16_t fifo_size_bits; - /* last bits sent to HW_CONFIG_REG register */ + /* last bits sent to HW_CONFIG_REG register */ uint16_t hw_config_bits; uint16_t dac_control1_bits; - /* last bits written to plx9080 control register */ + /* last bits written to plx9080 control register */ uint32_t plx_control_bits; - /* last bits written to plx interrupt control and status register */ + /* last bits written to plx interrupt control and status register */ uint32_t plx_intcsr_bits; - /* index of calibration source readable through ai ch0 */ + /* index of calibration source readable through ai ch0 */ int calibration_source; - /* bits written to i2c calibration/range register */ + /* bits written to i2c calibration/range register */ uint8_t i2c_cal_range_bits; - /* configure digital triggers to trigger on falling edge */ + /* configure digital triggers to trigger on falling edge */ unsigned int ext_trig_falling; short ai_cmd_running; unsigned int ai_fifo_segment_length; @@ -1224,7 +1229,7 @@ static void abort_dma(struct comedi_device *dev, unsigned int channel) struct pcidas64_private *devpriv = dev->private; unsigned long flags; - /* spinlock for plx dma control/status reg */ + /* spinlock for plx dma control/status reg */ spin_lock_irqsave(&dev->spinlock, flags); plx9080_abort_dma(devpriv->plx9080_iobase, channel); @@ -1271,7 +1276,7 @@ static void enable_ai_interrupts(struct comedi_device *dev, * if CMDF_WAKE_EOS flag is set. */ if (cmd->flags & CMDF_WAKE_EOS) { - /* 4020 doesn't support pio transfers except for fifo dregs */ + /* 4020 doesn't support pio transfers except for fifo dregs */ if (board->layout != LAYOUT_4020) bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT; } @@ -1305,36 +1310,40 @@ static void init_plx9080(struct comedi_device *dev) abort_dma(dev, 0); abort_dma(dev, 1); - /* configure dma0 mode */ + /* configure dma0 mode */ bits = 0; - /* enable ready input, not sure if this is necessary */ + /* enable ready input, not sure if this is necessary */ bits |= PLX_DMAMODE_READYIEN; - /* enable bterm, not sure if this is necessary */ + /* enable bterm, not sure if this is necessary */ bits |= PLX_DMAMODE_BTERMIEN; - /* enable dma chaining */ + /* enable dma chaining */ bits |= PLX_DMAMODE_CHAINEN; - /* enable interrupt on dma done - * (probably don't need this, since chain never finishes) */ + /* + * enable interrupt on dma done + * (probably don't need this, since chain never finishes) + */ bits |= PLX_DMAMODE_DONEIEN; - /* don't increment local address during transfers - * (we are transferring from a fixed fifo register) */ + /* + * don't increment local address during transfers + * (we are transferring from a fixed fifo register) + */ bits |= PLX_DMAMODE_LACONST; - /* route dma interrupt to pci bus */ + /* route dma interrupt to pci bus */ bits |= PLX_DMAMODE_INTRPCI; - /* enable demand mode */ + /* enable demand mode */ bits |= PLX_DMAMODE_DEMAND; - /* enable local burst mode */ + /* enable local burst mode */ bits |= PLX_DMAMODE_BURSTEN; - /* 4020 uses 32 bit dma */ + /* 4020 uses 32 bit dma */ if (board->layout == LAYOUT_4020) - bits |= PLX_DMAMODE_WIDTH32; - else /* localspace0 bus is 16 bits wide */ - bits |= PLX_DMAMODE_WIDTH16; + bits |= PLX_DMAMODE_WIDTH_32; + else /* localspace0 bus is 16 bits wide */ + bits |= PLX_DMAMODE_WIDTH_16; writel(bits, plx_iobase + PLX_REG_DMAMODE1); if (ao_cmd_is_supported(board)) writel(bits, plx_iobase + PLX_REG_DMAMODE0); - /* enable interrupts on plx 9080 */ + /* enable interrupts on plx 9080 */ devpriv->plx_intcsr_bits |= PLX_INTCSR_LSEABORTEN | PLX_INTCSR_LSEPARITYEN | PLX_INTCSR_PIEN | PLX_INTCSR_PLIEN | PLX_INTCSR_PABORTIEN | PLX_INTCSR_LIOEN | @@ -1376,7 +1385,7 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev, if (num_entries > fifo->max_segment_length) num_entries = fifo->max_segment_length; - /* 1 == 256 entries, 2 == 512 entries, etc */ + /* 1 == 256 entries, 2 == 512 entries, etc */ num_increments = DIV_ROUND_CLOSEST(num_entries, increment_size); bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask; @@ -1442,7 +1451,7 @@ static void init_stc_registers(struct comedi_device *dev) writew(devpriv->adc_control1_bits, devpriv->main_iobase + ADC_CONTROL1_REG); - /* 6402/16 manual says this register must be initialized to 0xff? */ + /* 6402/16 manual says this register must be initialized to 0xff? */ writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT; @@ -1457,7 +1466,7 @@ static void init_stc_registers(struct comedi_device *dev) spin_unlock_irqrestore(&dev->spinlock, flags); - /* set fifos to maximum size */ + /* set fifos to maximum size */ devpriv->fifo_size_bits |= DAC_FIFO_BITS; set_ai_fifo_segment_length(dev, board->ai_fifo->max_segment_length); @@ -1478,7 +1487,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) struct pcidas64_private *devpriv = dev->private; int i; - /* allocate pci dma buffers */ + /* allocate pci dma buffers */ for (i = 0; i < ai_dma_ring_count(board); i++) { devpriv->ai_buffer[i] = dma_alloc_coherent(&pcidev->dev, DMA_BUFFER_SIZE, @@ -1499,7 +1508,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) return -ENOMEM; } } - /* allocate dma descriptors */ + /* allocate dma descriptors */ devpriv->ai_dma_desc = dma_alloc_coherent(&pcidev->dev, sizeof(struct plx_dma_desc) * ai_dma_ring_count(board), @@ -1517,7 +1526,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) if (!devpriv->ao_dma_desc) return -ENOMEM; } - /* initialize dma descriptors */ + /* initialize dma descriptors */ for (i = 0; i < ai_dma_ring_count(board); i++) { devpriv->ai_dma_desc[i].pci_start_addr = cpu_to_le32(devpriv->ai_buffer_bus_addr[i]); @@ -1618,13 +1627,11 @@ static void i2c_set_sda(struct comedi_device *dev, int state) void __iomem *plx_control_addr = devpriv->plx9080_iobase + PLX_REG_CNTRL; - if (state) { - /* set data line high */ + if (state) { /* set data line high */ devpriv->plx_control_bits &= ~data_bit; writel(devpriv->plx_control_bits, plx_control_addr); udelay(i2c_high_udelay); - } else { /* set data line low */ - + } else { /* set data line low */ devpriv->plx_control_bits |= data_bit; writel(devpriv->plx_control_bits, plx_control_addr); udelay(i2c_low_udelay); @@ -1639,13 +1646,11 @@ static void i2c_set_scl(struct comedi_device *dev, int state) void __iomem *plx_control_addr = devpriv->plx9080_iobase + PLX_REG_CNTRL; - if (state) { - /* set clock line high */ + if (state) { /* set clock line high */ devpriv->plx_control_bits &= ~clock_bit; writel(devpriv->plx_control_bits, plx_control_addr); udelay(i2c_high_udelay); - } else { /* set clock line low */ - + } else { /* set clock line low */ devpriv->plx_control_bits |= clock_bit; writel(devpriv->plx_control_bits, plx_control_addr); udelay(i2c_low_udelay); @@ -1674,7 +1679,7 @@ static int i2c_read_ack(struct comedi_device *dev) i2c_set_sda(dev, 1); i2c_set_scl(dev, 1); - return 0; /* return fake acknowledge bit */ + return 0; /* return fake acknowledge bit */ } /* send start bit */ @@ -1707,23 +1712,23 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, * eeprom and i2c bus */ - /* make sure we dont send anything to eeprom */ + /* make sure we dont send anything to eeprom */ devpriv->plx_control_bits &= ~PLX_CNTRL_EECS; i2c_stop(dev); i2c_start(dev); - /* send address and write bit */ + /* send address and write bit */ bitstream = (address << 1) & ~read_bit; i2c_write_byte(dev, bitstream); - /* get acknowledge */ + /* get acknowledge */ if (i2c_read_ack(dev) != 0) { dev_err(dev->class_dev, "failed: no acknowledge\n"); i2c_stop(dev); return; } - /* write data bytes */ + /* write data bytes */ for (i = 0; i < length; i++) { i2c_write_byte(dev, data[i]); if (i2c_read_ack(dev) != 0) { @@ -1770,8 +1775,8 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, range = CR_RANGE(insn->chanspec); aref = CR_AREF(insn->chanspec); - /* disable card's analog input interrupt sources and pacing */ - /* 4020 generates dac done interrupts even though they are disabled */ + /* disable card's analog input interrupt sources and pacing */ + /* 4020 generates dac done interrupts even though they are disabled */ disable_ai_pacing(dev); spin_lock_irqsave(&dev->spinlock, flags); @@ -1784,12 +1789,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, spin_unlock_irqrestore(&dev->spinlock, flags); if (board->layout != LAYOUT_4020) { - /* use internal queue */ + /* use internal queue */ devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; writew(devpriv->hw_config_bits, devpriv->main_iobase + HW_CONFIG_REG); - /* ALT_SOURCE is internal calibration reference */ + /* ALT_SOURCE is internal calibration reference */ if (insn->chanspec & CR_ALT_SOURCE) { unsigned int cal_en_bit; @@ -1811,19 +1816,19 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, */ writew(0, devpriv->main_iobase + CALIBRATION_REG); } - /* load internal queue */ + /* load internal queue */ bits = 0; - /* set gain */ + /* set gain */ bits |= ai_range_bits_6xxx(dev, CR_RANGE(insn->chanspec)); - /* set single-ended / differential */ + /* set single-ended / differential */ bits |= se_diff_bit_6xxx(dev, aref == AREF_DIFF); if (aref == AREF_COMMON) bits |= ADC_COMMON_BIT; bits |= adc_chan_bits(channel); - /* set stop channel */ + /* set stop channel */ writew(adc_chan_bits(channel), devpriv->main_iobase + ADC_QUEUE_HIGH_REG); - /* set start channel, and rest of settings */ + /* set start channel, and rest of settings */ writew(bits, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); } else { uint8_t old_cal_range_bits = devpriv->i2c_cal_range_bits; @@ -1835,7 +1840,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, } else { /* select BNC inputs */ devpriv->i2c_cal_range_bits |= adc_src_4020_bits(4); } - /* select range */ + /* select range */ if (range == 0) devpriv->i2c_cal_range_bits |= attenuate_bit(channel); else @@ -1862,14 +1867,14 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, } for (n = 0; n < insn->n; n++) { - /* clear adc buffer (inside loop for 4020 sake) */ + /* clear adc buffer (inside loop for 4020 sake) */ writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); /* trigger conversion, bits sent only matter for 4020 */ writew(adc_convert_chan_4020_bits(CR_CHAN(insn->chanspec)), devpriv->main_iobase + ADC_CONVERT_REG); - /* wait for data */ + /* wait for data */ ret = comedi_timeout(dev, s, insn, cb_pcidas64_ai_eoc, 0); if (ret) return ret; @@ -2249,7 +2254,7 @@ static void setup_sample_counters(struct comedi_device *dev, { struct pcidas64_private *devpriv = dev->private; - /* load hardware conversion counter */ + /* load hardware conversion counter */ if (use_hw_sample_counter(cmd)) { writew(cmd->stop_arg & 0xffff, devpriv->main_iobase + ADC_COUNT_LOWER_REG); @@ -2277,7 +2282,7 @@ static inline unsigned int dma_transfer_size(struct comedi_device *dev) static uint32_t ai_convert_counter_6xxx(const struct comedi_device *dev, const struct comedi_cmd *cmd) { - /* supposed to load counter with desired divisor minus 3 */ + /* supposed to load counter with desired divisor minus 3 */ return cmd->convert_arg / TIMER_BASE - 3; } @@ -2286,7 +2291,7 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device *dev, { uint32_t count; - /* figure out how long we need to delay at end of scan */ + /* figure out how long we need to delay at end of scan */ switch (cmd->scan_begin_src) { case TRIG_TIMER: count = (cmd->scan_begin_arg - @@ -2315,13 +2320,13 @@ static uint32_t ai_convert_counter_4020(struct comedi_device *dev, case TRIG_OTHER: divisor = devpriv->ext_clock.divisor; break; - default: /* should never happen */ + default: /* should never happen */ dev_err(dev->class_dev, "bug! failed to set ai pacing!\n"); divisor = 1000; break; } - /* supposed to load counter with desired divisor minus 2 for 4020 */ + /* supposed to load counter with desired divisor minus 2 for 4020 */ return divisor - 2; } @@ -2330,7 +2335,7 @@ static void select_master_clock_4020(struct comedi_device *dev, { struct pcidas64_private *devpriv = dev->private; - /* select internal/external master clock */ + /* select internal/external master clock */ devpriv->hw_config_bits &= ~MASTER_CLOCK_4020_MASK; if (cmd->scan_begin_src == TRIG_OTHER) { int chanspec = devpriv->ext_clock.chanspec; @@ -2366,7 +2371,7 @@ static inline void dma_start_sync(struct comedi_device *dev, struct pcidas64_private *devpriv = dev->private; unsigned long flags; - /* spinlock for plx dma control/status reg */ + /* spinlock for plx dma control/status reg */ spin_lock_irqsave(&dev->spinlock, flags); writeb(PLX_DMACSR_ENABLE | PLX_DMACSR_START | PLX_DMACSR_CLEARINTR, devpriv->plx9080_iobase + PLX_REG_DMACSR(channel)); @@ -2390,16 +2395,16 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) scan_counter = ai_scan_counter_6xxx(dev, cmd); } - /* load lower 16 bits of convert interval */ + /* load lower 16 bits of convert interval */ writew(convert_counter & 0xffff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); - /* load upper 8 bits of convert interval */ + /* load upper 8 bits of convert interval */ writew((convert_counter >> 16) & 0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); - /* load lower 16 bits of scan delay */ + /* load lower 16 bits of scan delay */ writew(scan_counter & 0xffff, devpriv->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG); - /* load upper 8 bits of scan delay */ + /* load upper 8 bits of scan delay */ writew((scan_counter >> 16) & 0xff, devpriv->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG); } @@ -2435,26 +2440,26 @@ static int setup_channel_queue(struct comedi_device *dev, writew(devpriv->hw_config_bits, devpriv->main_iobase + HW_CONFIG_REG); bits = 0; - /* set channel */ + /* set channel */ bits |= adc_chan_bits(CR_CHAN(cmd->chanlist[0])); - /* set gain */ + /* set gain */ bits |= ai_range_bits_6xxx(dev, CR_RANGE(cmd->chanlist[0])); - /* set single-ended / differential */ + /* set single-ended / differential */ bits |= se_diff_bit_6xxx(dev, CR_AREF(cmd->chanlist[0]) == AREF_DIFF); if (CR_AREF(cmd->chanlist[0]) == AREF_COMMON) bits |= ADC_COMMON_BIT; - /* set stop channel */ + /* set stop channel */ writew(adc_chan_bits (CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])), devpriv->main_iobase + ADC_QUEUE_HIGH_REG); - /* set start channel, and rest of settings */ + /* set start channel, and rest of settings */ writew(bits, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); } else { - /* use external queue */ + /* use external queue */ if (dev->write_subdev && dev->write_subdev->busy) { warn_external_queue(dev); return -EBUSY; @@ -2462,30 +2467,30 @@ static int setup_channel_queue(struct comedi_device *dev, devpriv->hw_config_bits |= EXT_QUEUE_BIT; writew(devpriv->hw_config_bits, devpriv->main_iobase + HW_CONFIG_REG); - /* clear DAC buffer to prevent weird interactions */ + /* clear DAC buffer to prevent weird interactions */ writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG); - /* clear queue pointer */ + /* clear queue pointer */ writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); - /* load external queue */ + /* load external queue */ for (i = 0; i < cmd->chanlist_len; i++) { bits = 0; - /* set channel */ + /* set channel */ bits |= adc_chan_bits(CR_CHAN(cmd-> chanlist[i])); - /* set gain */ + /* set gain */ bits |= ai_range_bits_6xxx(dev, CR_RANGE(cmd-> chanlist [i])); - /* set single-ended / differential */ + /* set single-ended / differential */ bits |= se_diff_bit_6xxx(dev, CR_AREF(cmd-> chanlist[i]) == AREF_DIFF); if (CR_AREF(cmd->chanlist[i]) == AREF_COMMON) bits |= ADC_COMMON_BIT; - /* mark end of queue */ + /* mark end of queue */ if (i == cmd->chanlist_len - 1) bits |= QUEUE_EOSCAN_BIT | QUEUE_EOSEQ_BIT; @@ -2498,7 +2503,7 @@ static int setup_channel_queue(struct comedi_device *dev, * but required for reliable operation */ writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); - /* prime queue holding register */ + /* prime queue holding register */ writew(0, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); } } else { @@ -2507,7 +2512,7 @@ static int setup_channel_queue(struct comedi_device *dev, devpriv->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK; /* select BNC inputs */ devpriv->i2c_cal_range_bits |= adc_src_4020_bits(4); - /* select ranges */ + /* select ranges */ for (i = 0; i < cmd->chanlist_len; i++) { unsigned int channel = CR_CHAN(cmd->chanlist[i]); unsigned int range = CR_RANGE(cmd->chanlist[i]); @@ -2579,7 +2584,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (retval < 0) return retval; - /* make sure internal calibration source is turned off */ + /* make sure internal calibration source is turned off */ writew(0, devpriv->main_iobase + CALIBRATION_REG); set_ai_pacing(dev, cmd); @@ -2595,10 +2600,10 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (board->layout != LAYOUT_4020) { devpriv->adc_control1_bits &= ~ADC_MODE_MASK; if (cmd->convert_src == TRIG_EXT) - /* good old mode 13 */ + /* good old mode 13 */ devpriv->adc_control1_bits |= adc_mode_bits(13); else - /* mode 8. What else could you need? */ + /* mode 8. What else could you need? */ devpriv->adc_control1_bits |= adc_mode_bits(8); } else { devpriv->adc_control1_bits &= ~CHANNEL_MODE_4020_MASK; @@ -2618,20 +2623,20 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->main_iobase + ADC_CONTROL1_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - /* clear adc buffer */ + /* clear adc buffer */ writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); if ((cmd->flags & CMDF_WAKE_EOS) == 0 || board->layout == LAYOUT_4020) { devpriv->ai_dma_index = 0; - /* set dma transfer size */ + /* set dma transfer size */ for (i = 0; i < ai_dma_ring_count(board); i++) devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(dma_transfer_size(dev) * sizeof(uint16_t)); - /* give location of first dma descriptor */ + /* give location of first dma descriptor */ load_first_dma_descriptor(dev, 1, devpriv->ai_dma_desc_bus_addr | PLX_DMADPR_DESCPCI | @@ -2657,7 +2662,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) bits = ADC_ENABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT; if (cmd->flags & CMDF_WAKE_EOS) bits |= ADC_DMA_DISABLE_BIT; - /* set start trigger */ + /* set start trigger */ if (cmd->start_src == TRIG_EXT) { bits |= ADC_START_TRIG_EXT_BITS; if (cmd->start_arg & CR_INVERT) @@ -2673,7 +2678,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) spin_unlock_irqrestore(&dev->spinlock, flags); - /* start acquisition */ + /* start acquisition */ if (cmd->start_src == TRIG_NOW) writew(0, devpriv->main_iobase + ADC_START_REG); @@ -2691,7 +2696,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) int num_samples; do { - /* get least significant 15 bits */ + /* get least significant 15 bits */ read_index = readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff; write_index = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & @@ -2796,14 +2801,14 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) pci_addr_reg = devpriv->plx9080_iobase + PLX_REG_DMAPADR(channel); - /* loop until we have read all the full buffers */ + /* loop until we have read all the full buffers */ for (j = 0, next_transfer_addr = readl(pci_addr_reg); (next_transfer_addr < devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] || next_transfer_addr >= devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] + DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board); j++) { - /* transfer data from dma buffer to comedi buffer */ + /* transfer data from dma buffer to comedi buffer */ num_samples = comedi_nsamples_left(s, dma_transfer_size(dev)); comedi_buf_write_samples(s, devpriv->ai_buffer[devpriv->ai_dma_index], @@ -2829,15 +2834,15 @@ static void handle_ai_interrupt(struct comedi_device *dev, uint8_t dma1_status; unsigned long flags; - /* check for fifo overrun */ + /* check for fifo overrun */ if (status & ADC_OVERRUN_BIT) { dev_err(dev->class_dev, "fifo overrun\n"); async->events |= COMEDI_CB_ERROR; } - /* spin lock makes sure no one else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma1_status = readb(devpriv->plx9080_iobase + PLX_REG_DMACSR1); - if (plx_status & PLX_INTCSR_DMA1IA) { /* dma chan 1 interrupt */ + if (plx_status & PLX_INTCSR_DMA1IA) { /* dma chan 1 interrupt */ writeb((dma1_status & PLX_DMACSR_ENABLE) | PLX_DMACSR_CLEARINTR, devpriv->plx9080_iobase + PLX_REG_DMACSR1); @@ -2846,7 +2851,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, } spin_unlock_irqrestore(&dev->spinlock, flags); - /* drain fifo with pio */ + /* drain fifo with pio */ if ((status & ADC_DONE_BIT) || ((cmd->flags & CMDF_WAKE_EOS) && (status & ADC_INTR_PENDING_BIT) && @@ -2859,7 +2864,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, spin_unlock_irqrestore(&dev->spinlock, flags); } } - /* if we are have all the data, then quit */ + /* if we are have all the data, then quit */ if ((cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) || (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) @@ -3012,7 +3017,7 @@ static void handle_ao_interrupt(struct comedi_device *dev, async = s->async; cmd = &async->cmd; - /* spin lock makes sure no one else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma0_status = readb(devpriv->plx9080_iobase + PLX_REG_DMACSR0); if (plx_status & PLX_INTCSR_DMA0IA) { /* dma chan 0 interrupt */ @@ -3106,15 +3111,15 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, int chan = CR_CHAN(insn->chanspec); int range = CR_RANGE(insn->chanspec); - /* do some initializing */ + /* do some initializing */ writew(0, devpriv->main_iobase + DAC_CONTROL0_REG); - /* set range */ + /* set range */ set_dac_range_bits(dev, &devpriv->dac_control1_bits, chan, range); writew(devpriv->dac_control1_bits, devpriv->main_iobase + DAC_CONTROL1_REG); - /* write to channel */ + /* write to channel */ if (board->layout == LAYOUT_4020) { writew(data[0] & 0xff, devpriv->main_iobase + dac_lsb_4020_reg(chan)); @@ -3124,7 +3129,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, writew(data[0], devpriv->main_iobase + dac_convert_reg(chan)); } - /* remember output value */ + /* remember output value */ s->readback[chan] = data[0]; return 1; @@ -3556,7 +3561,7 @@ static int caldac_i2c_write(struct comedi_device *dev, uint8_t serial_bytes[3]; uint8_t i2c_addr; enum pointer_bits { - /* manual has gain and offset bits switched */ + /* manual has gain and offset bits switched */ OFFSET_0_2 = 0x1, GAIN_0_2 = 0x2, OFFSET_1_3 = 0x4, @@ -3567,35 +3572,35 @@ static int caldac_i2c_write(struct comedi_device *dev, }; switch (caldac_channel) { - case 0: /* chan 0 offset */ + case 0: /* chan 0 offset */ i2c_addr = CALDAC0_I2C_ADDR; serial_bytes[0] = OFFSET_0_2; break; - case 1: /* chan 1 offset */ + case 1: /* chan 1 offset */ i2c_addr = CALDAC0_I2C_ADDR; serial_bytes[0] = OFFSET_1_3; break; - case 2: /* chan 2 offset */ + case 2: /* chan 2 offset */ i2c_addr = CALDAC1_I2C_ADDR; serial_bytes[0] = OFFSET_0_2; break; - case 3: /* chan 3 offset */ + case 3: /* chan 3 offset */ i2c_addr = CALDAC1_I2C_ADDR; serial_bytes[0] = OFFSET_1_3; break; - case 4: /* chan 0 gain */ + case 4: /* chan 0 gain */ i2c_addr = CALDAC0_I2C_ADDR; serial_bytes[0] = GAIN_0_2; break; - case 5: /* chan 1 gain */ + case 5: /* chan 1 gain */ i2c_addr = CALDAC0_I2C_ADDR; serial_bytes[0] = GAIN_1_3; break; - case 6: /* chan 2 gain */ + case 6: /* chan 2 gain */ i2c_addr = CALDAC1_I2C_ADDR; serial_bytes[0] = GAIN_0_2; break; - case 7: /* chan 3 gain */ + case 7: /* chan 3 gain */ i2c_addr = CALDAC1_I2C_ADDR; serial_bytes[0] = GAIN_1_3; break; @@ -3718,24 +3723,24 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address) udelay(eeprom_udelay); devpriv->plx_control_bits &= ~PLX_CNTRL_EESK & ~PLX_CNTRL_EECS; - /* make sure we don't send anything to the i2c bus on 4020 */ + /* make sure we don't send anything to the i2c bus on 4020 */ devpriv->plx_control_bits |= PLX_CNTRL_USERO; writel(devpriv->plx_control_bits, plx_control_addr); - /* activate serial eeprom */ + /* activate serial eeprom */ udelay(eeprom_udelay); devpriv->plx_control_bits |= PLX_CNTRL_EECS; writel(devpriv->plx_control_bits, plx_control_addr); - /* write read command and desired memory address */ + /* write read command and desired memory address */ for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { - /* set bit to be written */ + /* set bit to be written */ udelay(eeprom_udelay); if (bitstream & bit) devpriv->plx_control_bits |= PLX_CNTRL_EEWB; else devpriv->plx_control_bits &= ~PLX_CNTRL_EEWB; writel(devpriv->plx_control_bits, plx_control_addr); - /* clock in bit */ + /* clock in bit */ udelay(eeprom_udelay); devpriv->plx_control_bits |= PLX_CNTRL_EESK; writel(devpriv->plx_control_bits, plx_control_addr); @@ -3743,10 +3748,10 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address) devpriv->plx_control_bits &= ~PLX_CNTRL_EESK; writel(devpriv->plx_control_bits, plx_control_addr); } - /* read back value from eeprom memory location */ + /* read back value from eeprom memory location */ value = 0; for (bit = 1 << (value_length - 1); bit; bit >>= 1) { - /* clock out bit */ + /* clock out bit */ udelay(eeprom_udelay); devpriv->plx_control_bits |= PLX_CNTRL_EESK; writel(devpriv->plx_control_bits, plx_control_addr); @@ -3758,7 +3763,7 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address) value |= bit; } - /* deactivate eeprom serial input */ + /* deactivate eeprom serial input */ udelay(eeprom_udelay); devpriv->plx_control_bits &= ~PLX_CNTRL_EECS; writel(devpriv->plx_control_bits, plx_control_addr); @@ -3775,9 +3780,7 @@ static int eeprom_read_insn(struct comedi_device *dev, return 1; } -/* - * Allocate and initialize the subdevice structures. - */ +/* Allocate and initialize the subdevice structures. */ static int setup_subdevices(struct comedi_device *dev) { const struct pcidas64_board *board = dev->board_ptr; @@ -3816,7 +3819,7 @@ static int setup_subdevices(struct comedi_device *dev) * (not internal calibration sources) */ devpriv->i2c_cal_range_bits = adc_src_4020_bits(4); - /* set channels to +-5 volt input ranges */ + /* set channels to +-5 volt input ranges */ for (i = 0; i < s->n_chan; i++) devpriv->i2c_cal_range_bits |= attenuate_bit(i); data = devpriv->i2c_cal_range_bits; @@ -3849,7 +3852,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* digital input */ + /* digital input */ s = &dev->subdevices[2]; if (board->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_DI; @@ -3862,7 +3865,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* digital output */ + /* digital output */ if (board->layout == LAYOUT_64XX) { s = &dev->subdevices[3]; s->type = COMEDI_SUBD_DO; @@ -3891,7 +3894,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* 8 channel dio for 60xx */ + /* 8 channel dio for 60xx */ s = &dev->subdevices[5]; if (board->layout == LAYOUT_60XX) { s->type = COMEDI_SUBD_DIO; @@ -3905,7 +3908,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* caldac */ + /* caldac */ s = &dev->subdevices[6]; s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; @@ -3925,7 +3928,7 @@ static int setup_subdevices(struct comedi_device *dev) s->readback[i] = s->maxdata / 2; } - /* 2 channel ad8402 potentiometer */ + /* 2 channel ad8402 potentiometer */ s = &dev->subdevices[7]; if (board->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_CALIB; @@ -3959,7 +3962,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* user counter subd XXX */ + /* user counter subd XXX */ s = &dev->subdevices[9]; s->type = COMEDI_SUBD_UNUSED; @@ -4005,7 +4008,7 @@ static int auto_attach(struct comedi_device *dev, return -ENOMEM; } - /* figure out what local addresses are */ + /* figure out what local addresses are */ local_range = readl(devpriv->plx9080_iobase + PLX_REG_LAS0RR) & PLX_LASRR_MEM_MASK; local_decode = readl(devpriv->plx9080_iobase + PLX_REG_LAS0BA) & diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 9c02b17a2834..317a9b5e4a3b 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -1,43 +1,42 @@ /* - comedi/drivers/das08_cs.c - DAS08 driver + * Comedi driver for DAS008 PCMCIA boards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * Copyright (C) 2001,2002,2003 Frank Mori Hess + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * PCMCIA support code for this driver is adapted from the dummy_cs.c + * driver of the Linux PCMCIA Card Services package. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef - Copyright (C) 2001,2002,2003 Frank Mori Hess - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - PCMCIA support code for this driver is adapted from the dummy_cs.c - driver of the Linux PCMCIA Card Services package. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. -*/ /* -Driver: das08_cs -Description: DAS-08 PCMCIA boards -Author: Warren Jasper, ds, Frank Hess -Devices: [ComputerBoards] PCM-DAS08 (pcm-das08) -Status: works - -This is the PCMCIA-specific support split off from the -das08 driver. - -Options (for pcm-das08): - NONE - -Command support does not exist, but could be added for this board. -*/ + * Driver: das08_cs + * Description: DAS-08 PCMCIA boards + * Author: Warren Jasper, ds, Frank Hess + * Devices: [ComputerBoards] PCM-DAS08 (pcm-das08) + * Status: works + * + * This is the PCMCIA-specific support split off from the + * das08 driver. + * + * Configuration Options: none, uses PCMCIA auto config + * + * Command support does not exist, but could be added for this board. + */ #include diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 8bbd93814340..fcd85475e429 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -96,11 +96,11 @@ * 6 6 100 kHz 6 1000000 * 7 12 50 kHz 7 10000000 */ -const unsigned int dt2811_clk_dividers[] = { +static const unsigned int dt2811_clk_dividers[] = { 1, 10, 2, 3, 4, 5, 6, 12 }; -const unsigned int dt2811_clk_multipliers[] = { +static const unsigned int dt2811_clk_multipliers[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 }; diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 3295bb4ac8c4..7ebca862ecaa 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -660,12 +660,12 @@ static int dt9812_find_endpoints(struct comedi_device *dev) case 1: dir = USB_DIR_OUT; devpriv->cmd_wr.addr = ep->bEndpointAddress; - devpriv->cmd_wr.size = le16_to_cpu(ep->wMaxPacketSize); + devpriv->cmd_wr.size = usb_endpoint_maxp(ep); break; case 2: dir = USB_DIR_IN; devpriv->cmd_rd.addr = ep->bEndpointAddress; - devpriv->cmd_rd.size = le16_to_cpu(ep->wMaxPacketSize); + devpriv->cmd_rd.size = usb_endpoint_maxp(ep); break; case 3: /* unused write stream */ diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index af4b4175af4d..e5b948405fd9 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -582,7 +582,7 @@ static void gsc_hpdi_init_plx9080(struct comedi_device *dev) bits |= PLX_DMAMODE_DEMAND; /* enable local burst mode */ bits |= PLX_DMAMODE_BURSTEN; - bits |= PLX_DMAMODE_WIDTH32; + bits |= PLX_DMAMODE_WIDTH_32; writel(bits, plx_iobase + PLX_REG_DMAMODE0); } diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 6c4ff023717f..70390de66e0e 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -141,7 +141,7 @@ static void set_transforms(struct jr3_channel __iomem *channel, { int i; - num &= 0x000f; /* Make sure that 0 <= num <= 15 */ + num &= 0x000f; /* Make sure that 0 <= num <= 15 */ for (i = 0; i < 8; i++) { set_u16(&channel->transforms[num].link[i].link_type, transf.link[i].link_type); @@ -323,10 +323,10 @@ static int read_idm_word(const u8 *data, size_t size, int *pos, int value; if (pos && val) { - /* Skip over non hex */ + /* Skip over non hex */ for (; *pos < size && !isxdigit(data[*pos]); (*pos)++) ; - /* Collect value */ + /* Collect value */ *val = 0; for (; *pos < size; (*pos)++) { value = hex_to_bin(data[*pos]); @@ -448,7 +448,8 @@ static int jr3_download_firmware(struct comedi_device *dev, return 0; } -static struct jr3_pci_poll_delay jr3_pci_poll_subdevice(struct comedi_subdevice *s) +static struct jr3_pci_poll_delay +jr3_pci_poll_subdevice(struct comedi_subdevice *s) { struct jr3_pci_subdev_private *spriv = s->private; struct jr3_pci_poll_delay result = poll_delay_min_max(1000, 2000); @@ -733,13 +734,13 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, } } - /* Reset DSP card */ + /* Reset DSP card */ writel(0, &devpriv->iobase->channel[0].reset); ret = comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev, "comedi/jr3pci.idm", jr3_download_firmware, 0); - dev_dbg(dev->class_dev, "Firmare load %d\n", ret); + dev_dbg(dev->class_dev, "Firmware load %d\n", ret); if (ret < 0) return ret; /* @@ -763,7 +764,7 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, data.copyright[i]) >> 8); } - /* Start card timer */ + /* Start card timer */ for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; spriv = s->private; diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h index 356811defaf4..f10a84fb6c14 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.h +++ b/drivers/staging/comedi/drivers/jr3_pci.h @@ -1,4 +1,5 @@ -/* Helper types to take care of the fact that the DSP card memory +/* + * Helper types to take care of the fact that the DSP card memory * is 16 bits, but aligned on a 32 bit PCI boundary */ @@ -22,7 +23,8 @@ static inline void set_s16(s32 __iomem *p, s16 val) writel(val, p); } -/* The raw data is stored in a format which facilitates rapid +/* + * The raw data is stored in a format which facilitates rapid * processing by the JR3 DSP chip. The raw_channel structure shows the * format for a single channel of data. Each channel takes four, * two-byte words. @@ -47,7 +49,8 @@ struct raw_channel { s32 reserved[2]; }; -/* The force_array structure shows the layout for the decoupled and +/* + * The force_array structure shows the layout for the decoupled and * filtered force data. */ struct force_array { @@ -61,7 +64,8 @@ struct force_array { s32 v2; }; -/* The six_axis_array structure shows the layout for the offsets and +/* + * The six_axis_array structure shows the layout for the offsets and * the full scales. */ struct six_axis_array { @@ -74,7 +78,8 @@ struct six_axis_array { }; /* VECT_BITS */ -/* The vect_bits structure shows the layout for indicating +/* + * The vect_bits structure shows the layout for indicating * which axes to use in computing the vectors. Each bit signifies * selection of a single axis. The V1x axis bit corresponds to a hex * value of 0x0001 and the V2z bit corresponds to a hex value of @@ -100,12 +105,14 @@ enum { }; /* WARNING_BITS */ -/* The warning_bits structure shows the bit pattern for the warning +/* + * The warning_bits structure shows the bit pattern for the warning * word. The bit fields are shown from bit 0 (lsb) to bit 15 (msb). */ -/* XX_NEAR_SET */ -/* The xx_near_sat bits signify that the indicated axis has reached or +/* XX_NEAR_SET */ +/* + * The xx_near_sat bits signify that the indicated axis has reached or * exceeded the near saturation value. */ @@ -118,12 +125,13 @@ enum { mz_near_sat = 0x0020 }; -/* ERROR_BITS */ -/* XX_SAT */ -/* MEMORY_ERROR */ -/* SENSOR_CHANGE */ +/* ERROR_BITS */ +/* XX_SAT */ +/* MEMORY_ERROR */ +/* SENSOR_CHANGE */ -/* The error_bits structure shows the bit pattern for the error word. +/* + * The error_bits structure shows the bit pattern for the error word. * The bit fields are shown from bit 0 (lsb) to bit 15 (msb). The * xx_sat bits signify that the indicated axis has reached or exceeded * the saturation value. The memory_error bit indicates that a problem @@ -134,9 +142,10 @@ enum { * */ -/* SYSTEM_BUSY */ +/* SYSTEM_BUSY */ -/* The system_busy bit indicates that the JR3 DSP is currently busy +/* + * The system_busy bit indicates that the JR3 DSP is currently busy * and is not calculating force data. This occurs when a new * coordinate transformation, or new sensor full scale is set by the * user. A very fast system using the force data for feedback might @@ -146,9 +155,10 @@ enum { * calibration CRC. */ -/* CAL_CRC_BAD */ +/* CAL_CRC_BAD */ -/* The cal_crc_bad bit indicates that the calibration CRC has not +/* + * The cal_crc_bad bit indicates that the calibration CRC has not * calculated to zero. CRC is short for cyclic redundancy code. It is * a method for determining the integrity of messages in data * communication. The calibration data stored inside the sensor is @@ -168,7 +178,8 @@ enum { /* WATCH_DOG */ /* WATCH_DOG2 */ -/* The watch_dog and watch_dog2 bits are sensor, not processor, watch +/* + * The watch_dog and watch_dog2 bits are sensor, not processor, watch * dog bits. Watch_dog indicates that the sensor data line seems to be * acting correctly, while watch_dog2 indicates that sensor data and * clock are being received. It is possible for watch_dog2 to go off @@ -192,9 +203,10 @@ enum error_bits_t { watch_dog = 0x8000 }; -/* THRESH_STRUCT */ +/* THRESH_STRUCT */ -/* This structure shows the layout for a single threshold packet inside of a +/* + * This structure shows the layout for a single threshold packet inside of a * load envelope. Each load envelope can contain several threshold structures. * 1. data_address contains the address of the data for that threshold. This * includes filtered, unfiltered, raw, rate, counters, error and warning data @@ -210,9 +222,10 @@ struct thresh_struct { s32 bit_pattern; }; -/* LE_STRUCT */ +/* LE_STRUCT */ -/* Layout of a load enveloped packet. Four thresholds are showed ... for more +/* + * Layout of a load enveloped packet. Four thresholds are showed ... for more * see manual (pag.25) * 1. latch_bits is a bit pattern that show which bits the user wants to latch. * The latched bits will not be reset once the threshold which set them is @@ -228,8 +241,9 @@ struct le_struct { s32 reserved; }; -/* LINK_TYPES */ -/* Link types is an enumerated value showing the different possible transform +/* LINK_TYPES */ +/* + * Link types is an enumerated value showing the different possible transform * link types. * 0 - end transform packet * 1 - translate along X axis (TX) @@ -252,8 +266,8 @@ enum link_types { neg }; -/* TRANSFORM */ -/* Structure used to describe a transform. */ +/* TRANSFORM */ +/* Structure used to describe a transform. */ struct intern_transform { struct { u32 link_type; @@ -261,23 +275,29 @@ struct intern_transform { } link[8]; }; -/* JR3 force/torque sensor data definition. For more information see sensor - * and hardware manuals. +/* + * JR3 force/torque sensor data definition. For more information see sensor + * and hardware manuals. */ struct jr3_channel { - /* Raw_channels is the area used to store the raw data coming from */ - /* the sensor. */ + /* + * Raw_channels is the area used to store the raw data coming from + * the sensor. + */ struct raw_channel raw_channels[16]; /* offset 0x0000 */ - /* Copyright is a null terminated ASCII string containing the JR3 */ - /* copyright notice. */ + /* + * Copyright is a null terminated ASCII string containing the JR3 + * copyright notice. + */ u32 copyright[0x0018]; /* offset 0x0040 */ s32 reserved1[0x0008]; /* offset 0x0058 */ - /* Shunts contains the sensor shunt readings. Some JR3 sensors have + /* + * Shunts contains the sensor shunt readings. Some JR3 sensors have * the ability to have their gains adjusted. This allows the * hardware full scales to be adjusted to potentially allow * better resolution or dynamic range. For sensors that have @@ -298,25 +318,29 @@ struct jr3_channel { * command (10) set new full scales (pg. 38). */ - struct six_axis_array shunts; /* offset 0x0060 */ - s32 reserved2[2]; /* offset 0x0066 */ + struct six_axis_array shunts; /* offset 0x0060 */ + s32 reserved2[2]; /* offset 0x0066 */ - /* Default_FS contains the full scale that is used if the user does */ - /* not set a full scale. */ + /* + * Default_FS contains the full scale that is used if the user does + * not set a full scale. + */ struct six_axis_array default_FS; /* offset 0x0068 */ - s32 reserved3; /* offset 0x006e */ + s32 reserved3; /* offset 0x006e */ - /* Load_envelope_num is the load envelope number that is currently + /* + * Load_envelope_num is the load envelope number that is currently * in use. This value is set by the user after one of the load * envelopes has been initialized. */ - s32 load_envelope_num; /* offset 0x006f */ + s32 load_envelope_num; /* offset 0x006f */ /* Min_full_scale is the recommend minimum full scale. */ - /* These values in conjunction with max_full_scale (pg. 9) helps + /* + * These values in conjunction with max_full_scale (pg. 9) helps * determine the appropriate value for setting the full scales. The * software allows the user to set the sensor full scale to an * arbitrary value. But setting the full scales has some hazards. If @@ -342,30 +366,35 @@ struct jr3_channel { */ struct six_axis_array min_full_scale; /* offset 0x0070 */ - s32 reserved4; /* offset 0x0076 */ + s32 reserved4; /* offset 0x0076 */ - /* Transform_num is the transform number that is currently in use. + /* + * Transform_num is the transform number that is currently in use. * This value is set by the JR3 DSP after the user has used command * (5) use transform # (pg. 33). */ - s32 transform_num; /* offset 0x0077 */ + s32 transform_num; /* offset 0x0077 */ - /* Max_full_scale is the recommended maximum full scale. See */ - /* min_full_scale (pg. 9) for more details. */ + /* + * Max_full_scale is the recommended maximum full scale. + * See min_full_scale (pg. 9) for more details. + */ struct six_axis_array max_full_scale; /* offset 0x0078 */ - s32 reserved5; /* offset 0x007e */ + s32 reserved5; /* offset 0x007e */ - /* Peak_address is the address of the data which will be monitored + /* + * Peak_address is the address of the data which will be monitored * by the peak routine. This value is set by the user. The peak * routine will monitor any 8 contiguous addresses for peak values. * (ex. to watch filter3 data for peaks, set this value to 0x00a8). */ - s32 peak_address; /* offset 0x007f */ + s32 peak_address; /* offset 0x007f */ - /* Full_scale is the sensor full scales which are currently in use. + /* + * Full_scale is the sensor full scales which are currently in use. * Decoupled and filtered data is scaled so that +/- 16384 is equal * to the full scales. The engineering units used are indicated by * the units value discussed on page 16. The full scales for Fx, Fy, @@ -377,9 +406,10 @@ struct jr3_channel { * axes used for each vector respectively. */ - struct force_array full_scale; /* offset 0x0080 */ + struct force_array full_scale; /* offset 0x0080 */ - /* Offsets contains the sensor offsets. These values are subtracted from + /* + * Offsets contains the sensor offsets. These values are subtracted from * the sensor data to obtain the decoupled data. The offsets are set a * few seconds (< 10) after the calibration data has been received. * They are set so that the output data will be zero. These values @@ -392,23 +422,26 @@ struct jr3_channel { * about Z by 90 degrees, FY would be 5 and all others would be zero. */ - struct six_axis_array offsets; /* offset 0x0088 */ + struct six_axis_array offsets; /* offset 0x0088 */ - /* Offset_num is the number of the offset currently in use. This + /* + * Offset_num is the number of the offset currently in use. This * value is set by the JR3 DSP after the user has executed the use * offset # command (pg. 34). It can vary between 0 and 15. */ - s32 offset_num; /* offset 0x008e */ + s32 offset_num; /* offset 0x008e */ - /* Vect_axes is a bit map showing which of the axes are being used + /* + * Vect_axes is a bit map showing which of the axes are being used * in the vector calculations. This value is set by the JR3 DSP * after the user has executed the set vector axes command (pg. 37). */ - u32 vect_axes; /* offset 0x008f */ + u32 vect_axes; /* offset 0x008f */ - /* Filter0 is the decoupled, unfiltered data from the JR3 sensor. + /* + * Filter0 is the decoupled, unfiltered data from the JR3 sensor. * This data has had the offsets removed. * * These force_arrays hold the filtered data. The decoupled data is @@ -420,23 +453,27 @@ struct jr3_channel { * cutoff at 125 Hz, 31.25 Hz, 7.813 Hz, 1.953 Hz and 0.4883 Hz. */ - struct force_array filter[7]; /* offset 0x0090, - offset 0x0098, - offset 0x00a0, - offset 0x00a8, - offset 0x00b0, - offset 0x00b8 , - offset 0x00c0 */ + struct force_array filter[7]; /* + * offset 0x0090, + * offset 0x0098, + * offset 0x00a0, + * offset 0x00a8, + * offset 0x00b0, + * offset 0x00b8, + * offset 0x00c0 + */ - /* Rate_data is the calculated rate data. It is a first derivative + /* + * Rate_data is the calculated rate data. It is a first derivative * calculation. It is calculated at a frequency specified by the * variable rate_divisor (pg. 12). The data on which the rate is * calculated is specified by the variable rate_address (pg. 12). */ - struct force_array rate_data; /* offset 0x00c8 */ + struct force_array rate_data; /* offset 0x00c8 */ - /* Minimum_data & maximum_data are the minimum and maximum (peak) + /* + * Minimum_data & maximum_data are the minimum and maximum (peak) * data values. The JR3 DSP can monitor any 8 contiguous data items * for minimums and maximums at full sensor bandwidth. This area is * only updated at user request. This is done so that the user does @@ -451,7 +488,8 @@ struct jr3_channel { struct force_array minimum_data; /* offset 0x00d0 */ struct force_array maximum_data; /* offset 0x00d8 */ - /* Near_sat_value & sat_value contain the value used to determine if + /* + * Near_sat_value & sat_value contain the value used to determine if * the raw sensor is saturated. Because of decoupling and offset * removal, it is difficult to tell from the processed data if the * sensor is saturated. These values, in conjunction with the error @@ -465,10 +503,11 @@ struct jr3_channel { * sat_value = 32768 - 2^(16 - ADC bits) */ - s32 near_sat_value; /* offset 0x00e0 */ - s32 sat_value; /* offset 0x00e1 */ + s32 near_sat_value; /* offset 0x00e0 */ + s32 sat_value; /* offset 0x00e1 */ - /* Rate_address, rate_divisor & rate_count contain the data used to + /* + * Rate_address, rate_divisor & rate_count contain the data used to * control the calculations of the rates. Rate_address is the * address of the data used for the rate calculation. The JR3 DSP * will calculate rates for any 8 contiguous values (ex. to @@ -485,11 +524,12 @@ struct jr3_channel { * will minimize the time necessary to start the rate calculations. */ - s32 rate_address; /* offset 0x00e2 */ - u32 rate_divisor; /* offset 0x00e3 */ - u32 rate_count; /* offset 0x00e4 */ + s32 rate_address; /* offset 0x00e2 */ + u32 rate_divisor; /* offset 0x00e3 */ + u32 rate_count; /* offset 0x00e4 */ - /* Command_word2 through command_word0 are the locations used to + /* + * Command_word2 through command_word0 are the locations used to * send commands to the JR3 DSP. Their usage varies with the command * and is detailed later in the Command Definitions section (pg. * 29). In general the user places values into various memory @@ -502,11 +542,12 @@ struct jr3_channel { * command_word1). */ - s32 command_word2; /* offset 0x00e5 */ - s32 command_word1; /* offset 0x00e6 */ - s32 command_word0; /* offset 0x00e7 */ + s32 command_word2; /* offset 0x00e5 */ + s32 command_word1; /* offset 0x00e6 */ + s32 command_word0; /* offset 0x00e7 */ - /* Count1 through count6 are unsigned counters which are incremented + /* + * Count1 through count6 are unsigned counters which are incremented * every time the matching filters are calculated. Filter1 is * calculated at the sensor data bandwidth. So this counter would * increment at 8 kHz for a typical sensor. The rest of the counters @@ -518,14 +559,15 @@ struct jr3_channel { * once. */ - u32 count1; /* offset 0x00e8 */ - u32 count2; /* offset 0x00e9 */ - u32 count3; /* offset 0x00ea */ - u32 count4; /* offset 0x00eb */ - u32 count5; /* offset 0x00ec */ - u32 count6; /* offset 0x00ed */ + u32 count1; /* offset 0x00e8 */ + u32 count2; /* offset 0x00e9 */ + u32 count3; /* offset 0x00ea */ + u32 count4; /* offset 0x00eb */ + u32 count5; /* offset 0x00ec */ + u32 count6; /* offset 0x00ed */ - /* Error_count is a running count of data reception errors. If this + /* + * Error_count is a running count of data reception errors. If this * counter is changing rapidly, it probably indicates a bad sensor * cable connection or other hardware problem. In most installations * error_count should not change at all. But it is possible in an @@ -535,75 +577,84 @@ struct jr3_channel { * where this counter counts a bad sample, that sample is ignored. */ - u32 error_count; /* offset 0x00ee */ + u32 error_count; /* offset 0x00ee */ - /* Count_x is a counter which is incremented every time the JR3 DSP + /* + * Count_x is a counter which is incremented every time the JR3 DSP * searches its job queues and finds nothing to do. It indicates the * amount of idle time the JR3 DSP has available. It can also be * used to determine if the JR3 DSP is alive. See the Performance * Issues section on pg. 49 for more details. */ - u32 count_x; /* offset 0x00ef */ + u32 count_x; /* offset 0x00ef */ - /* Warnings & errors contain the warning and error bits + /* + * Warnings & errors contain the warning and error bits * respectively. The format of these two words is discussed on page * 21 under the headings warnings_bits and error_bits. */ - u32 warnings; /* offset 0x00f0 */ - u32 errors; /* offset 0x00f1 */ + u32 warnings; /* offset 0x00f0 */ + u32 errors; /* offset 0x00f1 */ - /* Threshold_bits is a word containing the bits that are set by the + /* + * Threshold_bits is a word containing the bits that are set by the * load envelopes. See load_envelopes (pg. 17) and thresh_struct * (pg. 23) for more details. */ - s32 threshold_bits; /* offset 0x00f2 */ + s32 threshold_bits; /* offset 0x00f2 */ - /* Last_crc is the value that shows the actual calculated CRC. CRC + /* + * Last_crc is the value that shows the actual calculated CRC. CRC * is short for cyclic redundancy code. It should be zero. See the * description for cal_crc_bad (pg. 21) for more information. */ - s32 last_CRC; /* offset 0x00f3 */ + s32 last_CRC; /* offset 0x00f3 */ - /* EEProm_ver_no contains the version number of the sensor EEProm. + /* + * EEProm_ver_no contains the version number of the sensor EEProm. * EEProm version numbers can vary between 0 and 255. * Software_ver_no contains the software version number. Version * 3.02 would be stored as 302. */ - s32 eeprom_ver_no; /* offset 0x00f4 */ - s32 software_ver_no; /* offset 0x00f5 */ + s32 eeprom_ver_no; /* offset 0x00f4 */ + s32 software_ver_no; /* offset 0x00f5 */ - /* Software_day & software_year are the release date of the software + /* + * Software_day & software_year are the release date of the software * the JR3 DSP is currently running. Day is the day of the year, * with January 1 being 1, and December 31, being 365 for non leap * years. */ - s32 software_day; /* offset 0x00f6 */ - s32 software_year; /* offset 0x00f7 */ + s32 software_day; /* offset 0x00f6 */ + s32 software_year; /* offset 0x00f7 */ - /* Serial_no & model_no are the two values which uniquely identify a + /* + * Serial_no & model_no are the two values which uniquely identify a * sensor. This model number does not directly correspond to the JR3 * model number, but it will provide a unique identifier for * different sensor configurations. */ - u32 serial_no; /* offset 0x00f8 */ - u32 model_no; /* offset 0x00f9 */ + u32 serial_no; /* offset 0x00f8 */ + u32 model_no; /* offset 0x00f9 */ - /* Cal_day & cal_year are the sensor calibration date. Day is the + /* + * Cal_day & cal_year are the sensor calibration date. Day is the * day of the year, with January 1 being 1, and December 31, being * 366 for leap years. */ - s32 cal_day; /* offset 0x00fa */ - s32 cal_year; /* offset 0x00fb */ + s32 cal_day; /* offset 0x00fa */ + s32 cal_year; /* offset 0x00fb */ - /* Units is an enumerated read only value defining the engineering + /* + * Units is an enumerated read only value defining the engineering * units used in the sensor full scale. The meanings of particular * values are discussed in the section detailing the force_units * structure on page 22. The engineering units are setto customer @@ -626,20 +677,22 @@ struct jr3_channel { * received. */ - u32 units; /* offset 0x00fc */ - s32 bits; /* offset 0x00fd */ - s32 channels; /* offset 0x00fe */ + u32 units; /* offset 0x00fc */ + s32 bits; /* offset 0x00fd */ + s32 channels; /* offset 0x00fe */ - /* Thickness specifies the overall thickness of the sensor from + /* + * Thickness specifies the overall thickness of the sensor from * flange to flange. The engineering units for this value are * contained in units (pg. 16). The sensor calibration is relative * to the center of the sensor. This value allows easy coordinate * transformation from the center of the sensor to either flange. */ - s32 thickness; /* offset 0x00ff */ + s32 thickness; /* offset 0x00ff */ - /* Load_envelopes is a table containing the load envelope + /* + * Load_envelopes is a table containing the load envelope * descriptions. There are 16 possible load envelope slots in the * table. The slots are on 16 word boundaries and are numbered 0-15. * Each load envelope needs to start at the beginning of a slot but @@ -655,7 +708,8 @@ struct jr3_channel { struct le_struct load_envelopes[0x10]; /* offset 0x0100 */ - /* Transforms is a table containing the transform descriptions. + /* + * Transforms is a table containing the transform descriptions. * There are 16 possible transform slots in the table. The slots are * on 16 word boundaries and are numbered 0-15. Each transform needs * to start at the beginning of a slot but need not be fully diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 3e72718801a9..74911dbb2561 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -1,40 +1,34 @@ /* - comedi/drivers/ni_670x.c - Hardware driver for NI 670x devices - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2001 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: ni_670x -Description: National Instruments 670x -Author: Bart Joris -Updated: Wed, 11 Dec 2002 18:25:35 -0800 -Devices: [National Instruments] PCI-6703 (ni_670x), PCI-6704 -Status: unknown - -Commands are not supported. -*/ + * Comedi driver for NI 670x devices + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2001 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* - Bart Joris Last updated on 20/08/2001 - - Manuals: - - 322110a.pdf PCI/PXI-6704 User Manual - 322110b.pdf PCI/PXI-6703/6704 User Manual - -*/ + * Driver: ni_670x + * Description: National Instruments 670x + * Author: Bart Joris + * Updated: Wed, 11 Dec 2002 18:25:35 -0800 + * Devices: [National Instruments] PCI-6703 (ni_670x), PCI-6704 + * Status: unknown + * + * Commands are not supported. + * + * Manuals: + * 322110a.pdf PCI/PXI-6704 User Manual + * 322110b.pdf PCI/PXI-6703/6704 User Manual + */ #include #include diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 9b444f8c4e33..5a4dcc6e61d8 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -1,62 +1,47 @@ /* - comedi/drivers/ni_at_a2150.c - Driver for National Instruments AT-A2150 boards - Copyright (C) 2001, 2002 Frank Mori Hess + * Comedi driver for National Instruments AT-A2150 boards + * Copyright (C) 2001, 2002 Frank Mori Hess + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: ni_at_a2150 -Description: National Instruments AT-A2150 -Author: Frank Mori Hess -Status: works -Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s) - -If you want to ac couple the board's inputs, use AREF_OTHER. - -Configuration options: - [0] - I/O port base address - [1] - IRQ (optional, required for timed conversions) - [2] - DMA (optional, required for timed conversions) - -*/ -/* -Yet another driver for obsolete hardware brought to you by Frank Hess. -Testing and debugging help provided by Dave Andruczyk. - -This driver supports the boards: - -AT-A2150C -AT-A2150S - -The only difference is their master clock frequencies. - -Options: - [0] - base io address - [1] - irq - [2] - dma channel - -References (from ftp://ftp.natinst.com/support/manuals): - - 320360.pdf AT-A2150 User Manual - -TODO: - -analog level triggering -TRIG_WAKE_EOS - -*/ + * Driver: ni_at_a2150 + * Description: National Instruments AT-A2150 + * Author: Frank Mori Hess + * Status: works + * Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s) + * + * Configuration options: + * [0] - I/O port base address + * [1] - IRQ (optional, required for timed conversions) + * [2] - DMA (optional, required for timed conversions) + * + * Yet another driver for obsolete hardware brought to you by Frank Hess. + * Testing and debugging help provided by Dave Andruczyk. + * + * If you want to ac couple the board's inputs, use AREF_OTHER. + * + * The only difference in the boards is their master clock frequencies. + * + * References (from ftp://ftp.natinst.com/support/manuals): + * 320360.pdf AT-A2150 User Manual + * + * TODO: + * - analog level triggering + * - TRIG_WAKE_EOS + */ #include #include @@ -73,48 +58,52 @@ TRIG_WAKE_EOS /* Registers and bits */ #define CONFIG_REG 0x0 -#define CHANNEL_BITS(x) ((x) & 0x7) +#define CHANNEL_BITS(x) ((x) & 0x7) #define CHANNEL_MASK 0x7 -#define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3) -#define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5) +#define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3) +#define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5) #define CLOCK_MASK (0xf << 3) -#define ENABLE0_BIT 0x80 /* enable (don't internally ground) channels 0 and 1 */ -#define ENABLE1_BIT 0x100 /* enable (don't internally ground) channels 2 and 3 */ -#define AC0_BIT 0x200 /* ac couple channels 0,1 */ -#define AC1_BIT 0x400 /* ac couple channels 2,3 */ -#define APD_BIT 0x800 /* analog power down */ -#define DPD_BIT 0x1000 /* digital power down */ -#define TRIGGER_REG 0x2 /* trigger config register */ -#define POST_TRIGGER_BITS 0x2 -#define DELAY_TRIGGER_BITS 0x3 -#define HW_TRIG_EN 0x10 /* enable hardware trigger */ -#define FIFO_START_REG 0x6 /* software start aquistion trigger */ -#define FIFO_RESET_REG 0x8 /* clears fifo + fifo flags */ -#define FIFO_DATA_REG 0xa /* read data */ -#define DMA_TC_CLEAR_REG 0xe /* clear dma terminal count interrupt */ -#define STATUS_REG 0x12 /* read only */ -#define FNE_BIT 0x1 /* fifo not empty */ -#define OVFL_BIT 0x8 /* fifo overflow */ -#define EDAQ_BIT 0x10 /* end of acquisition interrupt */ -#define DCAL_BIT 0x20 /* offset calibration in progress */ -#define INTR_BIT 0x40 /* interrupt has occurred */ -#define DMA_TC_BIT 0x80 /* dma terminal count interrupt has occurred */ -#define ID_BITS(x) (((x) >> 8) & 0x3) -#define IRQ_DMA_CNTRL_REG 0x12 /* write only */ -#define DMA_CHAN_BITS(x) ((x) & 0x7) /* sets dma channel */ -#define DMA_EN_BIT 0x8 /* enables dma */ -#define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */ -#define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */ -#define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */ -#define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */ -#define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */ +/* enable (don't internally ground) channels 0 and 1 */ +#define ENABLE0_BIT 0x80 +/* enable (don't internally ground) channels 2 and 3 */ +#define ENABLE1_BIT 0x100 +#define AC0_BIT 0x200 /* ac couple channels 0,1 */ +#define AC1_BIT 0x400 /* ac couple channels 2,3 */ +#define APD_BIT 0x800 /* analog power down */ +#define DPD_BIT 0x1000 /* digital power down */ +#define TRIGGER_REG 0x2 /* trigger config register */ +#define POST_TRIGGER_BITS 0x2 +#define DELAY_TRIGGER_BITS 0x3 +#define HW_TRIG_EN 0x10 /* enable hardware trigger */ +#define FIFO_START_REG 0x6 /* software start aquistion trigger */ +#define FIFO_RESET_REG 0x8 /* clears fifo + fifo flags */ +#define FIFO_DATA_REG 0xa /* read data */ +#define DMA_TC_CLEAR_REG 0xe /* clear dma terminal count interrupt */ +#define STATUS_REG 0x12 /* read only */ +#define FNE_BIT 0x1 /* fifo not empty */ +#define OVFL_BIT 0x8 /* fifo overflow */ +#define EDAQ_BIT 0x10 /* end of acquisition interrupt */ +#define DCAL_BIT 0x20 /* offset calibration in progress */ +#define INTR_BIT 0x40 /* interrupt has occurred */ +/* dma terminal count interrupt has occurred */ +#define DMA_TC_BIT 0x80 +#define ID_BITS(x) (((x) >> 8) & 0x3) +#define IRQ_DMA_CNTRL_REG 0x12 /* write only */ +#define DMA_CHAN_BITS(x) ((x) & 0x7) /* sets dma channel */ +#define DMA_EN_BIT 0x8 /* enables dma */ +#define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */ +#define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */ +#define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */ +/* enable interrupt on dma terminal count */ +#define DMA_INTR_EN_BIT 0x800 +#define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */ #define I8253_BASE_REG 0x14 struct a2150_board { const char *name; - int clock[4]; /* master clock periods, in nanoseconds */ - int num_clocks; /* number of available master clock speeds */ - int ai_speed; /* maximum conversion rate in nanoseconds */ + int clock[4]; /* master clock periods, in nanoseconds */ + int num_clocks; /* number of available master clock speeds */ + int ai_speed; /* maximum conversion rate in nanoseconds */ }; /* analog input range */ @@ -144,8 +133,8 @@ static const struct a2150_board a2150_boards[] = { struct a2150_private { struct comedi_isadma *dma; unsigned int count; /* number of data points left to be taken */ - int irq_dma_bits; /* irq/dma register bits */ - int config_bits; /* config register bits */ + int irq_dma_bits; /* irq/dma register bits */ + int config_bits; /* config register bits */ }; /* interrupt service routine */ @@ -189,13 +178,13 @@ static irqreturn_t a2150_interrupt(int irq, void *d) */ residue = comedi_isadma_disable(desc->chan); - /* figure out how many points to read */ + /* figure out how many points to read */ max_points = comedi_bytes_to_samples(s, desc->size); num_points = max_points - comedi_bytes_to_samples(s, residue); if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT) num_points = devpriv->count; - /* figure out how many points will be stored next time */ + /* figure out how many points will be stored next time */ leftover = 0; if (cmd->stop_src == TRIG_NONE) { leftover = comedi_bytes_to_samples(s, desc->size); @@ -204,7 +193,8 @@ static irqreturn_t a2150_interrupt(int irq, void *d) if (leftover > max_points) leftover = max_points; } - /* there should only be a residue if collection was stopped by having + /* + * There should only be a residue if collection was stopped by having * the stop_src set to an external trigger, in which case there * will be no more data */ @@ -214,7 +204,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) for (i = 0; i < num_points; i++) { /* write data point to comedi buffer */ dpnt = buf[i]; - /* convert from 2's complement to unsigned coding */ + /* convert from 2's complement to unsigned coding */ dpnt ^= 0x8000; comedi_buf_write_samples(s, &dpnt, 1); if (cmd->stop_src == TRIG_COUNT) { @@ -244,14 +234,14 @@ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_isadma *dma = devpriv->dma; struct comedi_isadma_desc *desc = &dma->desc[0]; - /* disable dma on card */ + /* disable dma on card */ devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); - /* disable computer's dma */ + /* disable computer's dma */ comedi_isadma_disable(desc->chan); - /* clear fifo and reset triggering circuitry */ + /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); return 0; @@ -270,7 +260,7 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index; int i, j; - /* initialize greatest lower and least upper bounds */ + /* initialize greatest lower and least upper bounds */ lub_divisor_shift = 3; lub_index = 0; lub = board->clock[lub_index] * (1 << lub_divisor_shift); @@ -278,19 +268,19 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, glb_index = board->num_clocks - 1; glb = board->clock[glb_index] * (1 << glb_divisor_shift); - /* make sure period is in available range */ + /* make sure period is in available range */ if (*period < glb) *period = glb; if (*period > lub) *period = lub; - /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */ + /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */ for (i = 0; i < 4; i++) { - /* there are a maximum of 4 master clocks */ + /* there are a maximum of 4 master clocks */ for (j = 0; j < board->num_clocks; j++) { - /* temp is the period in nanosec we are evaluating */ + /* temp is the period in nanosec we are evaluating */ temp = board->clock[j] * (1 << i); - /* if it is the best match yet */ + /* if it is the best match yet */ if (temp < lub && temp >= *period) { lub_divisor_shift = i; lub_index = j; @@ -306,7 +296,7 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, switch (flags & CMDF_ROUND_MASK) { case CMDF_ROUND_NEAREST: default: - /* if least upper bound is better approximation */ + /* if least upper bound is better approximation */ if (lub - *period < *period - glb) *period = lub; else @@ -320,7 +310,7 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, break; } - /* set clock bits for config register appropriately */ + /* set clock bits for config register appropriately */ devpriv->config_bits &= ~CLOCK_MASK; if (*period == lub) { devpriv->config_bits |= @@ -495,7 +485,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) "dma incompatible with hard real-time interrupt (CMDF_PRIORITY), aborting\n"); return -1; } - /* clear fifo and reset triggering circuitry */ + /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); /* setup chanlist */ @@ -503,7 +493,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) cmd->chanlist_len) < 0) return -1; - /* setup ac/dc coupling */ + /* setup ac/dc coupling */ if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER) devpriv->config_bits |= AC0_BIT; else @@ -513,18 +503,18 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else devpriv->config_bits &= ~AC1_BIT; - /* setup timing */ + /* setup timing */ a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags); - /* send timing, channel, config bits */ + /* send timing, channel, config bits */ outw(devpriv->config_bits, dev->iobase + CONFIG_REG); - /* initialize number of samples remaining */ + /* initialize number of samples remaining */ devpriv->count = cmd->stop_arg * cmd->chanlist_len; comedi_isadma_disable(desc->chan); - /* set size of transfer to fill in 1/3 second */ + /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 desc->size = comedi_bytes_per_sample(s) * cmd->chanlist_len * ONE_THIRD_SECOND / cmd->scan_begin_arg; @@ -536,40 +526,45 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) comedi_isadma_program(desc); - /* clear dma interrupt before enabling it, to try and get rid of that - * one spurious interrupt that has been happening */ + /* + * Clear dma interrupt before enabling it, to try and get rid of + * that one spurious interrupt that has been happening. + */ outw(0x00, dev->iobase + DMA_TC_CLEAR_REG); - /* enable dma on card */ + /* enable dma on card */ devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); - /* may need to wait 72 sampling periods if timing was changed */ + /* may need to wait 72 sampling periods if timing was changed */ comedi_8254_load(dev->pacer, 2, 72, I8254_MODE0 | I8254_BINARY); - /* setup start triggering */ + /* setup start triggering */ trigger_bits = 0; - /* decide if we need to wait 72 periods for valid data */ + /* decide if we need to wait 72 periods for valid data */ if (cmd->start_src == TRIG_NOW && (old_config_bits & CLOCK_MASK) != (devpriv->config_bits & CLOCK_MASK)) { - /* set trigger source to delay trigger */ + /* set trigger source to delay trigger */ trigger_bits |= DELAY_TRIGGER_BITS; } else { - /* otherwise no delay */ + /* otherwise no delay */ trigger_bits |= POST_TRIGGER_BITS; } - /* enable external hardware trigger */ + /* enable external hardware trigger */ if (cmd->start_src == TRIG_EXT) { trigger_bits |= HW_TRIG_EN; } else if (cmd->start_src == TRIG_OTHER) { - /* XXX add support for level/slope start trigger using TRIG_OTHER */ + /* + * XXX add support for level/slope start trigger + * using TRIG_OTHER + */ dev_err(dev->class_dev, "you shouldn't see this?\n"); } - /* send trigger config bits */ + /* send trigger config bits */ outw(trigger_bits, dev->iobase + TRIGGER_REG); - /* start acquisition for soft trigger */ + /* start acquisition for soft trigger */ if (cmd->start_src == TRIG_NOW) outw(0, dev->iobase + FIFO_START_REG); @@ -596,28 +591,28 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int n; int ret; - /* clear fifo and reset triggering circuitry */ + /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); /* setup chanlist */ if (a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0) return -1; - /* set dc coupling */ + /* set dc coupling */ devpriv->config_bits &= ~AC0_BIT; devpriv->config_bits &= ~AC1_BIT; - /* send timing, channel, config bits */ + /* send timing, channel, config bits */ outw(devpriv->config_bits, dev->iobase + CONFIG_REG); - /* disable dma on card */ + /* disable dma on card */ devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); - /* setup start triggering */ + /* setup start triggering */ outw(0, dev->iobase + TRIGGER_REG); - /* start acquisition for soft trigger */ + /* start acquisition for soft trigger */ outw(0, dev->iobase + FIFO_START_REG); /* @@ -632,7 +627,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, inw(dev->iobase + FIFO_DATA_REG); } - /* read data */ + /* read data */ for (n = 0; n < insn->n; n++) { ret = comedi_timeout(dev, s, insn, a2150_ai_eoc, 0); if (ret) @@ -642,7 +637,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, data[n] ^= 0x8000; } - /* clear fifo and reset triggering circuitry */ + /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); return n; @@ -749,16 +744,16 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->cancel = a2150_cancel; } - /* set card's irq and dma levels */ + /* set card's irq and dma levels */ outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); - /* reset and sync adc clock circuitry */ + /* reset and sync adc clock circuitry */ outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG); outw_p(DPD_BIT, dev->iobase + CONFIG_REG); - /* initialize configuration register */ + /* initialize configuration register */ devpriv->config_bits = 0; outw(devpriv->config_bits, dev->iobase + CONFIG_REG); - /* wait until offset calibration is done, then enable analog inputs */ + /* wait until offset calibration is done, then enable analog inputs */ for (i = 0; i < timeout; i++) { if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0) break; diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 95435b81aa55..ffcf7afce684 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -1,93 +1,84 @@ /* - comedi/drivers/ni_atmio.c - Hardware driver for NI AT-MIO E series cards + * Comedi driver for NI AT-MIO E series cards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2001 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2001 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: ni_atmio -Description: National Instruments AT-MIO-E series -Author: ds -Devices: [National Instruments] AT-MIO-16E-1 (ni_atmio), - AT-MIO-16E-2, AT-MIO-16E-10, AT-MIO-16DE-10, AT-MIO-64E-3, - AT-MIO-16XE-50, AT-MIO-16XE-10, AT-AI-16XE-10 -Status: works -Updated: Thu May 1 20:03:02 CDT 2003 + * Driver: ni_atmio + * Description: National Instruments AT-MIO-E series + * Author: ds + * Devices: [National Instruments] AT-MIO-16E-1 (ni_atmio), + * AT-MIO-16E-2, AT-MIO-16E-10, AT-MIO-16DE-10, AT-MIO-64E-3, + * AT-MIO-16XE-50, AT-MIO-16XE-10, AT-AI-16XE-10 + * Status: works + * Updated: Thu May 1 20:03:02 CDT 2003 + * + * The driver has 2.6 kernel isapnp support, and will automatically probe for + * a supported board if the I/O base is left unspecified with comedi_config. + * However, many of the isapnp id numbers are unknown. If your board is not + * recognized, please send the output of 'cat /proc/isapnp' (you may need to + * modprobe the isa-pnp module for /proc/isapnp to exist) so the id numbers + * for your board can be added to the driver. + * + * Otherwise, you can use the isapnptools package to configure your board. + * Use isapnp to configure the I/O base and IRQ for the board, and then pass + * the same values as parameters in comedi_config. A sample isapnp.conf file + * is included in the etc/ directory of Comedilib. + * + * Comedilib includes a utility to autocalibrate these boards. The boards + * seem to boot into a state where the all calibration DACs are at one + * extreme of their range, thus the default calibration is terrible. + * Calibration at boot is strongly encouraged. + * + * To use the extended digital I/O on some of the boards, enable the + * 8255 driver when configuring the Comedi source tree. + * + * External triggering is supported for some events. The channel index + * (scan_begin_arg, etc.) maps to PFI0 - PFI9. + * + * Some of the more esoteric triggering possibilities of these boards are + * not supported. + */ -The driver has 2.6 kernel isapnp support, and -will automatically probe for a supported board if the -I/O base is left unspecified with comedi_config. -However, many of -the isapnp id numbers are unknown. If your board is not -recognized, please send the output of 'cat /proc/isapnp' -(you may need to modprobe the isa-pnp module for -/proc/isapnp to exist) so the -id numbers for your board can be added to the driver. - -Otherwise, you can use the isapnptools package to configure -your board. Use isapnp to -configure the I/O base and IRQ for the board, and then pass -the same values as -parameters in comedi_config. A sample isapnp.conf file is included -in the etc/ directory of Comedilib. - -Comedilib includes a utility to autocalibrate these boards. The -boards seem to boot into a state where the all calibration DACs -are at one extreme of their range, thus the default calibration -is terrible. Calibration at boot is strongly encouraged. - -To use the extended digital I/O on some of the boards, enable the -8255 driver when configuring the Comedi source tree. - -External triggering is supported for some events. The channel index -(scan_begin_arg, etc.) maps to PFI0 - PFI9. - -Some of the more esoteric triggering possibilities of these boards -are not supported. -*/ /* - The real guts of the driver is in ni_mio_common.c, which is included - both here and in ni_pcimio.c - - Interrupt support added by Truxton Fulton - - References for specifications: - - 340747b.pdf Register Level Programmer Manual (obsolete) - 340747c.pdf Register Level Programmer Manual (new) - DAQ-STC reference manual - - Other possibly relevant info: - - 320517c.pdf User manual (obsolete) - 320517f.pdf User manual (new) - 320889a.pdf delete - 320906c.pdf maximum signal ratings - 321066a.pdf about 16x - 321791a.pdf discontinuation of at-mio-16e-10 rev. c - 321808a.pdf about at-mio-16e-10 rev P - 321837a.pdf discontinuation of at-mio-16de-10 rev d - 321838a.pdf about at-mio-16de-10 rev N - - ISSUES: - - need to deal with external reference for DAC, and other DAC - properties in board properties - - deal with at-mio-16de-10 revision D to N changes, etc. - -*/ + * The real guts of the driver is in ni_mio_common.c, which is included + * both here and in ni_pcimio.c + * + * Interrupt support added by Truxton Fulton + * + * References for specifications: + * 340747b.pdf Register Level Programmer Manual (obsolete) + * 340747c.pdf Register Level Programmer Manual (new) + * DAQ-STC reference manual + * + * Other possibly relevant info: + * 320517c.pdf User manual (obsolete) + * 320517f.pdf User manual (new) + * 320889a.pdf delete + * 320906c.pdf maximum signal ratings + * 321066a.pdf about 16x + * 321791a.pdf discontinuation of at-mio-16e-10 rev. c + * 321808a.pdf about at-mio-16e-10 rev P + * 321837a.pdf discontinuation of at-mio-16de-10 rev d + * 321838a.pdf about at-mio-16de-10 rev N + * + * ISSUES: + * - need to deal with external reference for DAC, and other DAC + * properties in board properties + * - deal with at-mio-16de-10 revision D to N changes, etc. + */ #include #include @@ -98,10 +89,7 @@ are not supported. #include "ni_stc.h" #include "8255.h" -/* - * AT specific setup - */ - +/* AT specific setup */ static const struct ni_board_struct ni_boards[] = { { .name = "at-mio-16e-1", @@ -215,7 +203,7 @@ static const struct ni_board_struct ni_boards[] = { .n_adchan = 16, .ai_maxdata = 0xffff, .ai_fifo_depth = 512, - .alwaysdither = 1, /* unknown */ + .alwaysdither = 1, /* unknown */ .gainlkup = ai_gain_14, .ai_speed = 10000, .caldac = { dac8800, dac8043, ad8522 }, @@ -287,10 +275,10 @@ static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev) } if (device_id == 255) dev_err(dev->class_dev, "can't find board\n"); - else if (device_id == 0) + else if (device_id == 0) dev_err(dev->class_dev, "EEPROM read error (?) or device not found\n"); - else + else dev_err(dev->class_dev, "unknown device ID %d -- contact author\n", device_id); diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index c3eb54622bc3..fb59b0ffbba6 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -1,25 +1,41 @@ /* - comedi/drivers/ni_atmio16d.c - Hardware driver for National Instruments AT-MIO16D board - Copyright (C) 2000 Chris R. Baugher - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * Comedi driver for National Instruments AT-MIO16D board + * Copyright (C) 2000 Chris R. Baugher + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ + /* -Driver: ni_atmio16d -Description: National Instruments AT-MIO-16D -Author: Chris R. Baugher -Status: unknown -Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) -*/ + * Driver: ni_atmio16d + * Description: National Instruments AT-MIO-16D + * Author: Chris R. Baugher + * Status: unknown + * Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) + * + * Configuration options: + * [0] - I/O port + * [1] - MIO irq (0 == no irq; or 3,4,5,6,7,9,10,11,12,14,15) + * [2] - DIO irq (0 == no irq; or 3,4,5,6,7,9) + * [3] - DMA1 channel (0 == no DMA; or 5,6,7) + * [4] - DMA2 channel (0 == no DMA; or 5,6,7) + * [5] - a/d mux (0=differential; 1=single) + * [6] - a/d range (0=bipolar10; 1=bipolar5; 2=unipolar10) + * [7] - dac0 range (0=bipolar; 1=unipolar) + * [8] - dac0 reference (0=internal; 1=external) + * [9] - dac0 coding (0=2's comp; 1=straight binary) + * [10] - dac1 range (same as dac0 options) + * [11] - dac1 reference (same as dac0 options) + * [12] - dac1 coding (same as dac0 options) + */ + /* * I must give credit here to Michal Dobes who * wrote the driver for Advantec's pcl812 boards. I used the interrupt @@ -295,8 +311,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, unsigned int sample_count, tmp, chan, gain; int i; - /* This is slowly becoming a working command interface. * - * It is still uber-experimental */ + /* + * This is slowly becoming a working command interface. + * It is still uber-experimental + */ reset_counters(dev); @@ -322,9 +340,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, outw(tmp, dev->iobase + MUX_GAIN_REG); } - /* Now program the sample interval timer */ - /* Figure out which clock to use then get an - * appropriate timer value */ + /* + * Now program the sample interval timer. + * Figure out which clock to use then get an appropriate timer value. + */ if (cmd->convert_arg < 65536000) { base_clock = CLOCK_1_MHZ; timer = cmd->convert_arg / 1000; @@ -386,9 +405,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); } - /* Program the scan interval timer ONLY IF SCANNING IS ENABLED */ - /* Figure out which clock to use then get an - * appropriate timer value */ + /* + * Program the scan interval timer ONLY IF SCANNING IS ENABLED. + * Figure out which clock to use then get an appropriate timer value. + */ if (cmd->chanlist_len > 1) { if (cmd->scan_begin_arg < 65536000) { base_clock = CLOCK_1_MHZ; @@ -566,38 +586,6 @@ static int atmio16d_dio_insn_config(struct comedi_device *dev, return insn->n; } -/* - options[0] - I/O port - options[1] - MIO irq - 0 == no irq - N == irq N {3,4,5,6,7,9,10,11,12,14,15} - options[2] - DIO irq - 0 == no irq - N == irq N {3,4,5,6,7,9} - options[3] - DMA1 channel - 0 == no DMA - N == DMA N {5,6,7} - options[4] - DMA2 channel - 0 == no DMA - N == DMA N {5,6,7} - - options[5] - a/d mux - 0=differential, 1=single - options[6] - a/d range - 0=bipolar10, 1=bipolar5, 2=unipolar10 - - options[7] - dac0 range - 0=bipolar, 1=unipolar - options[8] - dac0 reference - 0=internal, 1=external - options[9] - dac0 coding - 0=2's comp, 1=straight binary - - options[10] - dac1 range - options[11] - dac1 reference - options[12] - dac1 coding - */ - static int atmio16d_attach(struct comedi_device *dev, struct comedi_devconfig *it) { diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index d9de83ab0267..733d3fbafa4d 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -1,35 +1,35 @@ /* - comedi/drivers/ni_daq_dio24.c - Driver for National Instruments PCMCIA DAQ-Card DIO-24 - Copyright (C) 2002 Daniel Vecino Castel + * Comedi driver for National Instruments PCMCIA DAQ-Card DIO-24 + * Copyright (C) 2002 Daniel Vecino Castel + * + * PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 + * 2001/08/24 12:13:13 from the pcmcia package. + * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 - 2001/08/24 12:13:13 from the pcmcia package. - The initial developer of the pcmcia dummy_cs.c code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: ni_daq_dio24 -Description: National Instruments PCMCIA DAQ-Card DIO-24 -Author: Daniel Vecino Castel -Devices: [National Instruments] PCMCIA DAQ-Card DIO-24 (ni_daq_dio24) -Status: ? -Updated: Thu, 07 Nov 2002 21:53:06 -0800 - -This is just a wrapper around the 8255.o driver to properly handle -the PCMCIA interface. -*/ + * Driver: ni_daq_dio24 + * Description: National Instruments PCMCIA DAQ-Card DIO-24 + * Author: Daniel Vecino Castel + * Devices: [National Instruments] PCMCIA DAQ-Card DIO-24 (ni_daq_dio24) + * Status: ? + * Updated: Thu, 07 Nov 2002 21:53:06 -0800 + * + * This is just a wrapper around the 8255.o driver to properly handle + * the PCMCIA interface. + */ #include #include "../comedi_pcmcia.h" diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index e3d821bf2d6a..21f823179356 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -1,40 +1,39 @@ /* - comedi/drivers/ni_mio_cs.c - Hardware driver for NI PCMCIA MIO E series cards + * Comedi driver for NI PCMCIA MIO E series cards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2000 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: ni_mio_cs -Description: National Instruments DAQCard E series -Author: ds -Status: works -Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs), - DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E -Updated: Thu Oct 23 19:43:17 CDT 2003 + * Driver: ni_mio_cs + * Description: National Instruments DAQCard E series + * Author: ds + * Status: works + * Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs), + * DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E + * Updated: Thu Oct 23 19:43:17 CDT 2003 + * + * See the notes in the ni_atmio.o driver. + */ -See the notes in the ni_atmio.o driver. -*/ /* - The real guts of the driver is in ni_mio_common.c, which is - included by all the E series drivers. - - References for specifications: - - 341080a.pdf DAQCard E Series Register Level Programmer Manual - -*/ + * The real guts of the driver is in ni_mio_common.c, which is + * included by all the E series drivers. + * + * References for specifications: + * 341080a.pdf DAQCard E Series Register Level Programmer Manual + */ #include #include diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 35ef1925703f..daeb4ad7a75f 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1,50 +1,49 @@ /* - comedi/drivers/ni_pcidio.c - driver for National Instruments PCI-DIO-32HS + * Comedi driver for National Instruments PCI-DIO-32HS + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1999,2002 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999,2002 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: ni_pcidio -Description: National Instruments PCI-DIO32HS, PCI-6533 -Author: ds -Status: works -Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio) - [National Instruments] PXI-6533, PCI-6533 (pxi-6533) - [National Instruments] PCI-6534 (pci-6534) -Updated: Mon, 09 Jan 2012 14:27:23 +0000 - -The DIO32HS board appears as one subdevice, with 32 channels. -Each channel is individually I/O configurable. The channel order -is 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only -supports simple digital I/O; no handshaking is supported. - -DMA mostly works for the PCI-DIO32HS, but only in timed input mode. - -The PCI-DIO-32HS/PCI-6533 has a configurable external trigger. Setting -scan_begin_arg to 0 or CR_EDGE triggers on the leading edge. Setting -scan_begin_arg to CR_INVERT or (CR_EDGE | CR_INVERT) triggers on the -trailing edge. - -This driver could be easily modified to support AT-MIO32HS and -AT-MIO96. - -The PCI-6534 requires a firmware upload after power-up to work, the -firmware data and instructions for loading it with comedi_config -it are contained in the -comedi_nonfree_firmware tarball available from http://www.comedi.org -*/ + * Driver: ni_pcidio + * Description: National Instruments PCI-DIO32HS, PCI-6533 + * Author: ds + * Status: works + * Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio) + * [National Instruments] PXI-6533, PCI-6533 (pxi-6533) + * [National Instruments] PCI-6534 (pci-6534) + * Updated: Mon, 09 Jan 2012 14:27:23 +0000 + * + * The DIO32HS board appears as one subdevice, with 32 channels. Each + * channel is individually I/O configurable. The channel order is 0=A0, + * 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only supports simple + * digital I/O; no handshaking is supported. + * + * DMA mostly works for the PCI-DIO32HS, but only in timed input mode. + * + * The PCI-DIO-32HS/PCI-6533 has a configurable external trigger. Setting + * scan_begin_arg to 0 or CR_EDGE triggers on the leading edge. Setting + * scan_begin_arg to CR_INVERT or (CR_EDGE | CR_INVERT) triggers on the + * trailing edge. + * + * This driver could be easily modified to support AT-MIO32HS and AT-MIO96. + * + * The PCI-6534 requires a firmware upload after power-up to work, the + * firmware data and instructions for loading it with comedi_config + * it are contained in the comedi_nonfree_firmware tarball available from + * http://www.comedi.org + */ #define USE_DMA @@ -61,36 +60,36 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org #define Window_Address 4 /* W */ #define Interrupt_And_Window_Status 4 /* R */ -#define IntStatus1 (1<<0) -#define IntStatus2 (1<<1) +#define IntStatus1 BIT(0) +#define IntStatus2 BIT(1) #define WindowAddressStatus_mask 0x7c #define Master_DMA_And_Interrupt_Control 5 /* W */ #define InterruptLine(x) ((x)&3) -#define OpenInt (1<<2) +#define OpenInt BIT(2) #define Group_Status 5 /* R */ -#define DataLeft (1<<0) -#define Req (1<<2) -#define StopTrig (1<<3) +#define DataLeft BIT(0) +#define Req BIT(2) +#define StopTrig BIT(3) #define Group_1_Flags 6 /* R */ #define Group_2_Flags 7 /* R */ -#define TransferReady (1<<0) -#define CountExpired (1<<1) -#define Waited (1<<5) -#define PrimaryTC (1<<6) -#define SecondaryTC (1<<7) +#define TransferReady BIT(0) +#define CountExpired BIT(1) +#define Waited BIT(5) +#define PrimaryTC BIT(6) +#define SecondaryTC BIT(7) /* #define SerialRose */ /* #define ReqRose */ /* #define Paused */ #define Group_1_First_Clear 6 /* W */ #define Group_2_First_Clear 7 /* W */ -#define ClearWaited (1<<3) -#define ClearPrimaryTC (1<<4) -#define ClearSecondaryTC (1<<5) -#define DMAReset (1<<6) -#define FIFOReset (1<<7) +#define ClearWaited BIT(3) +#define ClearPrimaryTC BIT(4) +#define ClearSecondaryTC BIT(5) +#define DMAReset BIT(6) +#define FIFOReset BIT(7) #define ClearAll 0xf8 #define Group_1_FIFO 8 /* W */ @@ -111,27 +110,27 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org #define Group_1_Second_Clear 46 /* W */ #define Group_2_Second_Clear 47 /* W */ -#define ClearExpired (1<<0) +#define ClearExpired BIT(0) #define Port_Pattern(x) (48+(x)) #define Data_Path 64 -#define FIFOEnableA (1<<0) -#define FIFOEnableB (1<<1) -#define FIFOEnableC (1<<2) -#define FIFOEnableD (1<<3) +#define FIFOEnableA BIT(0) +#define FIFOEnableB BIT(1) +#define FIFOEnableC BIT(2) +#define FIFOEnableD BIT(3) #define Funneling(x) (((x)&3)<<4) -#define GroupDirection (1<<7) +#define GroupDirection BIT(7) #define Protocol_Register_1 65 #define OpMode Protocol_Register_1 #define RunMode(x) ((x)&7) -#define Numbered (1<<3) +#define Numbered BIT(3) #define Protocol_Register_2 66 #define ClockReg Protocol_Register_2 #define ClockLine(x) (((x)&3)<<5) -#define InvertStopTrig (1<<7) +#define InvertStopTrig BIT(7) #define DataLatching(x) (((x)&3)<<5) #define Protocol_Register_3 67 @@ -152,17 +151,17 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org #define Protocol_Register_6 73 #define LinePolarities Protocol_Register_6 -#define InvertAck (1<<0) -#define InvertReq (1<<1) -#define InvertClock (1<<2) -#define InvertSerial (1<<3) -#define OpenAck (1<<4) -#define OpenClock (1<<5) +#define InvertAck BIT(0) +#define InvertReq BIT(1) +#define InvertClock BIT(2) +#define InvertSerial BIT(3) +#define OpenAck BIT(4) +#define OpenClock BIT(5) #define Protocol_Register_7 74 #define AckSer Protocol_Register_7 #define AckLine(x) (((x)&3)<<2) -#define ExchangePins (1<<7) +#define ExchangePins BIT(7) #define Interrupt_Control 75 /* bits same as flags */ @@ -183,20 +182,20 @@ static inline unsigned int secondary_DMAChannel_bits(unsigned int channel) #define Transfer_Size_Control 77 #define TransferWidth(x) ((x)&3) #define TransferLength(x) (((x)&3)<<3) -#define RequireRLevel (1<<5) +#define RequireRLevel BIT(5) #define Protocol_Register_15 79 #define DAQOptions Protocol_Register_15 #define StartSource(x) ((x)&0x3) -#define InvertStart (1<<2) +#define InvertStart BIT(2) #define StopSource(x) (((x)&0x3)<<3) -#define ReqStart (1<<6) -#define PreStart (1<<7) +#define ReqStart BIT(6) +#define PreStart BIT(7) #define Pattern_Detection 81 -#define DetectionMethod (1<<0) -#define InvertMatch (1<<1) -#define IE_Pattern_Detection (1<<2) +#define DetectionMethod BIT(0) +#define InvertMatch BIT(1) +#define IE_Pattern_Detection BIT(2) #define Protocol_Register_9 82 #define ReqDelay Protocol_Register_9 @@ -649,8 +648,10 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) writeb(1, dev->mmio + AckDelay); writeb(0x0b, dev->mmio + AckNotDelay); writeb(0x01, dev->mmio + Data1Delay); - /* manual, page 4-5: ClockSpeed comment is incorrectly listed - * on DAQOptions */ + /* + * manual, page 4-5: + * ClockSpeed comment is incorrectly listed on DAQOptions + */ writew(0, dev->mmio + ClockSpeed); writeb(0, dev->mmio + DAQOptions); } else { diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index d8917392b9f9..f13a2f7360b3 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1,111 +1,106 @@ /* - comedi/drivers/ni_pcimio.c - Hardware driver for NI PCI-MIO E series cards + * Comedi driver for NI PCI-MIO E series cards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-8 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-8 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: ni_pcimio -Description: National Instruments PCI-MIO-E series and M series (all boards) -Author: ds, John Hallen, Frank Mori Hess, Rolf Mueller, Herbert Peremans, - Herman Bruyninckx, Terry Barnaby -Status: works -Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio), - PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, PCI-6040E, - PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E, - PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E, - PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, - PCI-6225, PXI-6225, PCI-6229, PCI-6250, - PCI-6251, PXI-6251, PCIe-6251, PXIe-6251, - PCI-6254, PCI-6259, PCIe-6259, - PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, - PCI-6711, PXI-6711, PCI-6713, PXI-6713, - PXI-6071E, PCI-6070E, PXI-6070E, - PXI-6052E, PCI-6036E, PCI-6731, PCI-6733, PXI-6733, - PCI-6143, PXI-6143 -Updated: Mon, 09 Jan 2012 14:52:48 +0000 + * Driver: ni_pcimio + * Description: National Instruments PCI-MIO-E series and M series (all boards) + * Author: ds, John Hallen, Frank Mori Hess, Rolf Mueller, Herbert Peremans, + * Herman Bruyninckx, Terry Barnaby + * Status: works + * Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio), + * PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, + * PCI-6040E, PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, + * PCI-6071E, PCI-6023E, PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, + * PCI-6035E, PCI-6052E, + * PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, + * PCI-6225, PXI-6225, PCI-6229, PCI-6250, + * PCI-6251, PXI-6251, PCIe-6251, PXIe-6251, + * PCI-6254, PCI-6259, PCIe-6259, + * PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, + * PCI-6711, PXI-6711, PCI-6713, PXI-6713, + * PXI-6071E, PCI-6070E, PXI-6070E, + * PXI-6052E, PCI-6036E, PCI-6731, PCI-6733, PXI-6733, + * PCI-6143, PXI-6143 + * Updated: Mon, 09 Jan 2012 14:52:48 +0000 + * + * These boards are almost identical to the AT-MIO E series, except that + * they use the PCI bus instead of ISA (i.e., AT). See the notes for the + * ni_atmio.o driver for additional information about these boards. + * + * Autocalibration is supported on many of the devices, using the + * comedi_calibrate (or comedi_soft_calibrate for m-series) utility. + * M-Series boards do analog input and analog output calibration entirely + * in software. The software calibration corrects the analog input for + * offset, gain and nonlinearity. The analog outputs are corrected for + * offset and gain. See the comedilib documentation on + * comedi_get_softcal_converter() for more information. + * + * By default, the driver uses DMA to transfer analog input data to + * memory. When DMA is enabled, not all triggering features are + * supported. + * + * Digital I/O may not work on 673x. + * + * Note that the PCI-6143 is a simultaineous sampling device with 8 + * convertors. With this board all of the convertors perform one + * simultaineous sample during a scan interval. The period for a scan + * is used for the convert time in a Comedi cmd. The convert trigger + * source is normally set to TRIG_NOW by default. + * + * The RTSI trigger bus is supported on these cards on subdevice 10. + * See the comedilib documentation for details. + * + * Information (number of channels, bits, etc.) for some devices may be + * incorrect. Please check this and submit a bug if there are problems + * for your device. + * + * SCXI is probably broken for m-series boards. + * + * Bugs: + * - When DMA is enabled, COMEDI_EV_CONVERT does not work correctly. + */ -These boards are almost identical to the AT-MIO E series, except that -they use the PCI bus instead of ISA (i.e., AT). See the notes for -the ni_atmio.o driver for additional information about these boards. - -Autocalibration is supported on many of the devices, using the -comedi_calibrate (or comedi_soft_calibrate for m-series) utility. -M-Series boards do analog input and analog output calibration entirely -in software. The software calibration corrects -the analog input for offset, gain and -nonlinearity. The analog outputs are corrected for offset and gain. -See the comedilib documentation on comedi_get_softcal_converter() for -more information. - -By default, the driver uses DMA to transfer analog input data to -memory. When DMA is enabled, not all triggering features are -supported. - -Digital I/O may not work on 673x. - -Note that the PCI-6143 is a simultaineous sampling device with 8 convertors. -With this board all of the convertors perform one simultaineous sample during -a scan interval. The period for a scan is used for the convert time in a -Comedi cmd. The convert trigger source is normally set to TRIG_NOW by default. - -The RTSI trigger bus is supported on these cards on -subdevice 10. See the comedilib documentation for details. - -Information (number of channels, bits, etc.) for some devices may be -incorrect. Please check this and submit a bug if there are problems -for your device. - -SCXI is probably broken for m-series boards. - -Bugs: - - When DMA is enabled, COMEDI_EV_CONVERT does - not work correctly. - -*/ /* - The PCI-MIO E series driver was originally written by - Tomasz Motylewski <...>, and ported to comedi by ds. - - References: - - 341079b.pdf PCI E Series Register-Level Programmer Manual - 340934b.pdf DAQ-STC reference manual - - 322080b.pdf 6711/6713/6715 User Manual - - 320945c.pdf PCI E Series User Manual - 322138a.pdf PCI-6052E and DAQPad-6052E User Manual - - ISSUES: - - need to deal with external reference for DAC, and other DAC - properties in board properties - - deal with at-mio-16de-10 revision D to N changes, etc. - - need to add other CALDAC type - - need to slow down DAC loading. I don't trust NI's claim that - two writes to the PCI bus slows IO enough. I would prefer to - use udelay(). Timing specs: (clock) - AD8522 30ns - DAC8043 120ns - DAC8800 60ns - MB88341 ? - -*/ + * The PCI-MIO E series driver was originally written by + * Tomasz Motylewski <...>, and ported to comedi by ds. + * + * References: + * 341079b.pdf PCI E Series Register-Level Programmer Manual + * 340934b.pdf DAQ-STC reference manual + * + * 322080b.pdf 6711/6713/6715 User Manual + * + * 320945c.pdf PCI E Series User Manual + * 322138a.pdf PCI-6052E and DAQPad-6052E User Manual + * + * ISSUES: + * - need to deal with external reference for DAC, and other DAC + * properties in board properties + * - deal with at-mio-16de-10 revision D to N changes, etc. + * - need to add other CALDAC type + * - need to slow down DAC loading. I don't trust NI's claim that + * two writes to the PCI bus slows IO enough. I would prefer to + * use udelay(). + * Timing specs: (clock) + * AD8522 30ns + * DAC8043 120ns + * DAC8800 60ns + * MB88341 ? + */ #include #include @@ -119,13 +114,14 @@ Bugs: #define PCIDMA -/* These are not all the possible ao ranges for 628x boards. - They can do OFFSET +- REFERENCE where OFFSET can be - 0V, 5V, APFI<0,1>, or AO<0...3> and RANGE can - be 10V, 5V, 2V, 1V, APFI<0,1>, AO<0...3>. That's - 63 different possibilities. An AO channel - can not act as it's own OFFSET or REFERENCE. -*/ +/* + * These are not all the possible ao ranges for 628x boards. + * They can do OFFSET +- REFERENCE where OFFSET can be + * 0V, 5V, APFI<0,1>, or AO<0...3> and RANGE can + * be 10V, 5V, 2V, 1V, APFI<0,1>, AO<0...3>. That's + * 63 different possibilities. An AO channel + * can not act as it's own OFFSET or REFERENCE. + */ static const struct comedi_lrange range_ni_M_628x_ao = { 8, { BIP_RANGE(10), diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c index 95b537a8ecdb..5036eebb9162 100644 --- a/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/drivers/staging/comedi/drivers/ni_usb6501.c @@ -465,12 +465,12 @@ static int ni6501_alloc_usb_buffers(struct comedi_device *dev) struct ni6501_private *devpriv = dev->private; size_t size; - size = le16_to_cpu(devpriv->ep_rx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_rx); devpriv->usb_rx_buf = kzalloc(size, GFP_KERNEL); if (!devpriv->usb_rx_buf) return -ENOMEM; - size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_tx); devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL); if (!devpriv->usb_tx_buf) { kfree(devpriv->usb_rx_buf); diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index 0e20cc5c9a69..e23e63a097b5 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -60,9 +60,9 @@ struct plx_dma_desc { #define PLX_REG_LAS1RR 0x00f0 #define PLX_LASRR_IO BIT(0) /* Map to: 1=I/O, 0=Mem */ -#define PLX_LASRR_ANY32 (BIT(1) * 0) /* Locate anywhere in 32 bit */ -#define PLX_LASRR_LT1MB (BIT(1) * 1) /* Locate in 1st meg */ -#define PLX_LASRR_ANY64 (BIT(1) * 2) /* Locate anywhere in 64 bit */ +#define PLX_LASRR_MLOC_ANY32 (BIT(1) * 0) /* Locate anywhere in 32 bit */ +#define PLX_LASRR_MLOC_LT1MB (BIT(1) * 1) /* Locate in 1st meg */ +#define PLX_LASRR_MLOC_ANY64 (BIT(1) * 2) /* Locate anywhere in 64 bit */ #define PLX_LASRR_MLOC_MASK GENMASK(2, 1) /* Memory location bits */ #define PLX_LASRR_PREFETCH BIT(3) /* Memory is prefetchable */ /* bits that specify range for memory space decode bits */ @@ -89,11 +89,11 @@ struct plx_dma_desc { /* Local Bus Latency Timer */ #define PLX_MARBR_LT(x) (BIT(0) * ((x) & 0xff)) #define PLX_MARBR_LT_MASK GENMASK(7, 0) -#define PLX_MARBR_LT_SHIFT 0 +#define PLX_MARBR_TO_LT(r) ((r) & PLX_MARBR_LT_MASK) /* Local Bus Pause Timer */ #define PLX_MARBR_PT(x) (BIT(8) * ((x) & 0xff)) #define PLX_MARBR_PT_MASK GENMASK(15, 8) -#define PLX_MARBR_PT_SHIFT 8 +#define PLX_MARBR_TO_PT(r) (((r) & PLX_MARBR_PT_MASK) >> 8) /* Local Bus Latency Timer Enable */ #define PLX_MARBR_LTEN BIT(16) /* Local Bus Pause Timer Enable */ @@ -166,16 +166,15 @@ struct plx_dma_desc { #define PLX_REG_LBRD1 0x00f8 /* Memory Space Local Bus Width */ -#define PLX_LBRD_MSWIDTH8 (BIT(0) * 0) /* 8 bits wide */ -#define PLX_LBRD_MSWIDTH16 (BIT(0) * 1) /* 16 bits wide */ -#define PLX_LBRD_MSWIDTH32 (BIT(0) * 2) /* 32 bits wide */ -#define PLX_LBRD_MSWIDTH32A (BIT(0) * 3) /* 32 bits wide */ +#define PLX_LBRD_MSWIDTH_8 (BIT(0) * 0) /* 8 bits wide */ +#define PLX_LBRD_MSWIDTH_16 (BIT(0) * 1) /* 16 bits wide */ +#define PLX_LBRD_MSWIDTH_32 (BIT(0) * 2) /* 32 bits wide */ +#define PLX_LBRD_MSWIDTH_32A (BIT(0) * 3) /* 32 bits wide */ #define PLX_LBRD_MSWIDTH_MASK GENMASK(1, 0) -#define PLX_LBRD_MSWIDTH_SHIFT 0 /* Memory Space Internal Wait States */ #define PLX_LBRD_MSIWS(x) (BIT(2) * ((x) & 0xf)) #define PLX_LBRD_MSIWS_MASK GENMASK(5, 2) -#define PLX_LBRD_MSIWS_SHIFT 2 +#define PLX_LBRD_TO_MSIWS(r) (((r) & PLS_LBRD_MSIWS_MASK) >> 2) /* Memory Space Ready Input Enable */ #define PLX_LBRD_MSREADYIEN BIT(6) /* Memory Space BTERM# Input Enable */ @@ -193,18 +192,17 @@ struct plx_dma_desc { /* Prefetch Counter */ #define PLX_LBRD_PFCOUNT(x) (BIT(11) * ((x) & 0xf)) #define PLX_LBRD_PFCOUNT_MASK GENMASK(14, 11) -#define PLX_LBRD_PFCOUNT_SHIFT 11 +#define PLX_LBRD_TO_PFCOUNT(r) (((r) & PLX_LBRD_PFCOUNT_MASK) >> 11) /* Expansion ROM Space Local Bus Width (LBRD0 only) */ -#define PLX_LBRD0_EROMWIDTH8 (BIT(16) * 0) /* 8 bits wide */ -#define PLX_LBRD0_EROMWIDTH16 (BIT(16) * 1) /* 16 bits wide */ -#define PLX_LBRD0_EROMWIDTH32 (BIT(16) * 2) /* 32 bits wide */ -#define PLX_LBRD0_EROMWIDTH32A (BIT(16) * 3) /* 32 bits wide */ +#define PLX_LBRD0_EROMWIDTH_8 (BIT(16) * 0) /* 8 bits wide */ +#define PLX_LBRD0_EROMWIDTH_16 (BIT(16) * 1) /* 16 bits wide */ +#define PLX_LBRD0_EROMWIDTH_32 (BIT(16) * 2) /* 32 bits wide */ +#define PLX_LBRD0_EROMWIDTH_32A (BIT(16) * 3) /* 32 bits wide */ #define PLX_LBRD0_EROMWIDTH_MASK GENMASK(17, 16) -#define PLX_LBRD0_EROMWIDTH_SHIFT 16 /* Expansion ROM Space Internal Wait States (LBRD0 only) */ #define PLX_LBRD0_EROMIWS(x) (BIT(18) * ((x) & 0xf)) #define PLX_LBRD0_EROMIWS_MASK GENMASK(21, 18) -#define PLX_LBRD0_EROMIWS_SHIFT 18 +#define PLX_LBRD0_TO_EROMIWS(r) (((r) & PLX_LBRD0_EROMIWS_MASK) >> 18) /* Expansion ROM Space Ready Input Enable (LBDR0 only) */ #define PLX_LBRD0_EROMREADYIEN BIT(22) /* Expansion ROM Space BTERM# Input Enable (LBRD0 only) */ @@ -220,7 +218,7 @@ struct plx_dma_desc { /* PCI Target Retry Delay Clocks / 8 (LBRD0 only) */ #define PLX_LBRD0_TRDELAY(x) (BIT(28) * ((x) & 0xF)) #define PLX_LBRD0_TRDELAY_MASK GENMASK(31, 28) -#define PLX_LBRD0_TRDELAY_SHIFT 28 +#define PLX_LBRD0_TO_TRDELAY(r) (((r) & PLX_LBRD0_TRDELAY_MASK) >> 28) /* Local Range Register for Direct Master to PCI */ #define PLX_REG_DMRR 0x001c @@ -241,10 +239,10 @@ struct plx_dma_desc { /* LLOCK# Input Enable */ #define PLX_DMPBAM_LLOCKIEN BIT(2) /* Direct Master Read Prefetch Size Control (bits 12, 3) */ -#define PLX_DMPBAM_RPSIZECONT ((BIT(12) * 0) | (BIT(3) * 0)) -#define PLX_DMPBAM_RPSIZE4 ((BIT(12) * 0) | (BIT(3) * 1)) -#define PLX_DMPBAM_RPSIZE8 ((BIT(12) * 1) | (BIT(3) * 0)) -#define PLX_DMPBAM_RPSIZE16 ((BIT(12) * 1) | (BIT(3) * 1)) +#define PLX_DMPBAM_RPSIZE_CONT ((BIT(12) * 0) | (BIT(3) * 0)) +#define PLX_DMPBAM_RPSIZE_4 ((BIT(12) * 0) | (BIT(3) * 1)) +#define PLX_DMPBAM_RPSIZE_8 ((BIT(12) * 1) | (BIT(3) * 0)) +#define PLX_DMPBAM_RPSIZE_16 ((BIT(12) * 1) | (BIT(3) * 1)) #define PLX_DMPBAM_RPSIZE_MASK (BIT(12) | BIT(3)) /* Direct Master PCI Read Mode - deassert IRDY when FIFO full */ #define PLX_DMPBAM_RMIRDY BIT(4) @@ -261,10 +259,10 @@ struct plx_dma_desc { /* I/O Remap Select */ #define PLX_DMPBAM_IOREMAPSEL BIT(13) /* Direct Master Write Delay */ -#define PLX_DMPBAM_WDELAYNONE (BIT(14) * 0) -#define PLX_DMPBAM_WDELAY4 (BIT(14) * 1) -#define PLX_DMPBAM_WDELAY8 (BIT(14) * 2) -#define PLX_DMPBAM_WDELAY16 (BIT(14) * 3) +#define PLX_DMPBAM_WDELAY_NONE (BIT(14) * 0) +#define PLX_DMPBAM_WDELAY_4 (BIT(14) * 1) +#define PLX_DMPBAM_WDELAY_8 (BIT(14) * 2) +#define PLX_DMPBAM_WDELAY_16 (BIT(14) * 3) #define PLX_DMPBAM_WDELAY_MASK GENMASK(15, 14) /* Remap of Local-to-PCI Space Into PCI Address Space */ #define PLX_DMPBAM_REMAP_MASK GENMASK(31, 16) @@ -279,19 +277,19 @@ struct plx_dma_desc { /* Register Number */ #define PLX_DMCFGA_REGNUM(x) (BIT(2) * ((x) & 0x3f)) #define PLX_DMCFGA_REGNUM_MASK GENMASK(7, 2) -#define PLX_DMCFGA_REGNUM_SHIFT 2 +#define PLX_DMCFGA_TO_REGNUM(r) (((r) & PLX_DMCFGA_REGNUM_MASK) >> 2) /* Function Number */ #define PLX_DMCFGA_FUNCNUM(x) (BIT(8) * ((x) & 0x7)) #define PLX_DMCFGA_FUNCNUM_MASK GENMASK(10, 8) -#define PLX_DMCFGA_FUNCNUM_SHIFT 8 +#define PLX_DMCFGA_TO_FUNCNUM(r) (((r) & PLX_DMCFGA_FUNCNUM_MASK) >> 8) /* Device Number */ #define PLX_DMCFGA_DEVNUM(x) (BIT(11) * ((x) & 0x1f)) #define PLX_DMCFGA_DEVNUM_MASK GENMASK(15, 11) -#define PLX_DMCFGA_DEVNUM_SHIFT 11 +#define PLX_DMCFGA_TO_DEVNUM(r) (((r) & PLX_DMCFGA_DEVNUM_MASK) >> 11) /* Bus Number */ #define PLX_DMCFGA_BUSNUM(x) (BIT(16) * ((x) & 0xff)) #define PLX_DMCFGA_BUSNUM_MASK GENMASK(23, 16) -#define PLX_DMCFGA_BUSNUM_SHIFT 16 +#define PLX_DMCFGA_TO_BUSNUM(r) (((r) & PLX_DMCFGA_BUSNUM_MASK) >> 16) /* Configuration Enable */ #define PLX_DMCFGA_CONFIGEN BIT(31) @@ -402,22 +400,22 @@ struct plx_dma_desc { /* PCI Read Command Code For DMA */ #define PLX_CNTRL_CCRDMA(x) (BIT(0) * ((x) & 0xf)) #define PLX_CNTRL_CCRDMA_MASK GENMASK(3, 0) -#define PLX_CNTRL_CCRDMA_SHIFT 0 +#define PLX_CNTRL_TO_CCRDMA(r) ((r) & PLX_CNTRL_CCRDMA_MASK) #define PLX_CNTRL_CCRDMA_NORMAL PLX_CNTRL_CCRDMA(14) /* value after reset */ /* PCI Write Command Code For DMA 0 */ #define PLX_CNTRL_CCWDMA(x) (BIT(4) * ((x) & 0xf)) #define PLX_CNTRL_CCWDMA_MASK GENMASK(7, 4) -#define PLX_CNTRL_CCWDMA_SHIFT 4 +#define PLX_CNTRL_TO_CCWDMA(r) (((r) & PLX_CNTRL_CCWDMA_MASK) >> 4) #define PLX_CNTRL_CCWDMA_NORMAL PLX_CNTRL_CCWDMA(7) /* value after reset */ /* PCI Memory Read Command Code For Direct Master */ #define PLX_CNTRL_CCRDM(x) (BIT(8) * ((x) & 0xf)) #define PLX_CNTRL_CCRDM_MASK GENMASK(11, 8) -#define PLX_CNTRL_CCRDM_SHIFT 8 +#define PLX_CNTRL_TO_CCRDM(r) (((r) & PLX_CNTRL_CCRDM_MASK) >> 8) #define PLX_CNTRL_CCRDM_NORMAL PLX_CNTRL_CCRDM(6) /* value after reset */ /* PCI Memory Write Command Code For Direct Master */ #define PLX_CNTRL_CCWDM(x) (BIT(12) * ((x) & 0xf)) #define PLX_CNTRL_CCWDM_MASK GENMASK(15, 12) -#define PLX_CNTRL_CCWDM_SHIFT 12 +#define PLX_CNTRL_TO_CCWDM(r) (((r) & PLX_CNTRL_CCWDM_MASK) >> 12) #define PLX_CNTRL_CCWDM_NORMAL PLX_CNTRL_CCWDM(7) /* value after reset */ /* General Purpose Output (USERO) */ #define PLX_CNTRL_USERO BIT(16) @@ -464,16 +462,15 @@ struct plx_dma_desc { #define PLX_REG_DMAMODE1 0x0094 /* Local Bus Width */ -#define PLX_DMAMODE_WIDTH8 (BIT(0) * 0) /* 8 bits wide */ -#define PLX_DMAMODE_WIDTH16 (BIT(0) * 1) /* 16 bits wide */ -#define PLX_DMAMODE_WIDTH32 (BIT(0) * 2) /* 32 bits wide */ -#define PLX_DMAMODE_WIDTH32A (BIT(0) * 3) /* 32 bits wide */ +#define PLX_DMAMODE_WIDTH_8 (BIT(0) * 0) /* 8 bits wide */ +#define PLX_DMAMODE_WIDTH_16 (BIT(0) * 1) /* 16 bits wide */ +#define PLX_DMAMODE_WIDTH_32 (BIT(0) * 2) /* 32 bits wide */ +#define PLX_DMAMODE_WIDTH_32A (BIT(0) * 3) /* 32 bits wide */ #define PLX_DMAMODE_WIDTH_MASK GENMASK(1, 0) -#define PLX_DMAMODE_WIDTH_SHIFT 0 /* Internal Wait States */ #define PLX_DMAMODE_IWS(x) (BIT(2) * ((x) & 0xf)) #define PLX_DMAMODE_IWS_MASK GENMASK(5, 2) -#define PLX_DMAMODE_SHIFT 2 +#define PLX_DMAMODE_TO_IWS(r) (((r) & PLX_DMAMODE_IWS_MASK) >> 2) /* Ready Input Enable */ #define PLX_DMAMODE_READYIEN BIT(6) /* BTERM# Input Enable */ @@ -560,35 +557,35 @@ struct plx_dma_desc { /* DMA Channel 0 PCI-to-Local Almost Full (divided by 2, minus 1) */ #define PLX_DMATHR_C0PLAF(x) (BIT(0) * ((x) & 0xf)) #define PLX_DMATHR_C0PLAF_MASK GENMASK(3, 0) -#define PLX_DMATHR_C0PLAF_SHIFT 0 +#define PLX_DMATHR_TO_C0PLAF(r) ((r) & PLX_DMATHR_C0PLAF_MASK) /* DMA Channel 0 Local-to-PCI Almost Empty (divided by 2, minus 1) */ #define PLX_DMATHR_C0LPAE(x) (BIT(4) * ((x) & 0xf)) #define PLX_DMATHR_C0LPAE_MASK GENMASK(7, 4) -#define PLX_DMATHR_C0LPAE_SHIFT 4 +#define PLX_DMATHR_TO_C0LPAE(r) (((r) & PLX_DMATHR_C0LPAE_MASK) >> 4) /* DMA Channel 0 Local-to-PCI Almost Full (divided by 2, minus 1) */ #define PLX_DMATHR_C0LPAF(x) (BIT(8) * ((x) & 0xf)) #define PLX_DMATHR_C0LPAF_MASK GENMASK(11, 8) -#define PLX_DMATHR_C0LPAF_SHIFT 8 +#define PLX_DMATHR_TO_C0LPAF(r) (((r) & PLX_DMATHR_C0LPAF_MASK) >> 8) /* DMA Channel 0 PCI-to-Local Almost Empty (divided by 2, minus 1) */ #define PLX_DMATHR_C0PLAE(x) (BIT(12) * ((x) & 0xf)) #define PLX_DMATHR_C0PLAE_MASK GENMASK(15, 12) -#define PLX_DMATHR_C0PLAE_SHIFT 12 +#define PLX_DMATHR_TO_C0PLAE(r) (((r) & PLX_DMATHR_C0PLAE_MASK) >> 12) /* DMA Channel 1 PCI-to-Local Almost Full (divided by 2, minus 1) */ #define PLX_DMATHR_C1PLAF(x) (BIT(16) * ((x) & 0xf)) #define PLX_DMATHR_C1PLAF_MASK GENMASK(19, 16) -#define PLX_DMATHR_C1PLAF_SHIFT 16 +#define PLX_DMATHR_TO_C1PLAF(r) (((r) & PLX_DMATHR_C1PLAF_MASK) >> 16) /* DMA Channel 1 Local-to-PCI Almost Empty (divided by 2, minus 1) */ #define PLX_DMATHR_C1LPAE(x) (BIT(20) * ((x) & 0xf)) #define PLX_DMATHR_C1LPAE_MASK GENMASK(23, 20) -#define PLX_DMATHR_C1LPAE_SHIFT 20 +#define PLX_DMATHR_TO_C1LPAE(r) (((r) & PLX_DMATHR_C1LPAE_MASK) >> 20) /* DMA Channel 1 Local-to-PCI Almost Full (divided by 2, minus 1) */ #define PLX_DMATHR_C1LPAF(x) (BIT(24) * ((x) & 0xf)) #define PLX_DMATHR_C1LPAF_MASK GENMASK(27, 24) -#define PLX_DMATHR_C1LPAF_SHIFT 24 +#define PLX_DMATHR_TO_C1LPAF(r) (((r) & PLX_DMATHR_C1LPAF_MASK) >> 24) /* DMA Channel 1 PCI-to-Local Almost Empty (divided by 2, minus 1) */ #define PLX_DMATHR_C1PLAE(x) (BIT(28) * ((x) & 0xf)) #define PLX_DMATHR_C1PLAE_MASK GENMASK(31, 28) -#define PLX_DMATHR_C1PLAE_SHIFT 28 +#define PLX_DMATHR_TO_C1PLAE(r) (((r) & PLX_DMATHR_C1PLAE_MASK) >> 28) /* * Messaging Queue Registers OPLFIS, OPLFIM, IQP, OQP, MQCR, QBAR, IFHPR, diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 4a87b4b52400..c14a02564432 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -697,134 +697,6 @@ static void s626_reset_cap_flags(struct comedi_device *dev, s626_debi_replace(dev, S626_LP_CRB(chan), ~S626_CRBMSK_INTCTRL, set); } -#ifdef unused -/* - * Return counter setup in a format (COUNTER_SETUP) that is consistent - * for both A and B counters. - */ -static uint16_t s626_get_mode_a(struct comedi_device *dev, - unsigned int chan) -{ - uint16_t cra; - uint16_t crb; - uint16_t setup; - unsigned int cntsrc, clkmult, clkpol, encmode; - - /* Fetch CRA and CRB register images. */ - cra = s626_debi_read(dev, S626_LP_CRA(chan)); - crb = s626_debi_read(dev, S626_LP_CRB(chan)); - - /* - * Populate the standardized counter setup bit fields. - */ - setup = - /* LoadSrc = LoadSrcA. */ - S626_SET_STD_LOADSRC(S626_GET_CRA_LOADSRC_A(cra)) | - /* LatchSrc = LatchSrcA. */ - S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) | - /* IntSrc = IntSrcA. */ - S626_SET_STD_INTSRC(S626_GET_CRA_INTSRC_A(cra)) | - /* IndxSrc = IndxSrcA. */ - S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_A(cra)) | - /* IndxPol = IndxPolA. */ - S626_SET_STD_INDXPOL(S626_GET_CRA_INDXPOL_A(cra)) | - /* ClkEnab = ClkEnabA. */ - S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_A(crb)); - - /* Adjust mode-dependent parameters. */ - cntsrc = S626_GET_CRA_CNTSRC_A(cra); - if (cntsrc & S626_CNTSRC_SYSCLK) { - /* Timer mode (CntSrcA<1> == 1): */ - encmode = S626_ENCMODE_TIMER; - /* Set ClkPol to indicate count direction (CntSrcA<0>). */ - clkpol = cntsrc & 1; - /* ClkMult must be 1x in Timer mode. */ - clkmult = S626_CLKMULT_1X; - } else { - /* Counter mode (CntSrcA<1> == 0): */ - encmode = S626_ENCMODE_COUNTER; - /* Pass through ClkPol. */ - clkpol = S626_GET_CRA_CLKPOL_A(cra); - /* Force ClkMult to 1x if not legal, else pass through. */ - clkmult = S626_GET_CRA_CLKMULT_A(cra); - if (clkmult == S626_CLKMULT_SPECIAL) - clkmult = S626_CLKMULT_1X; - } - setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) | - S626_SET_STD_CLKPOL(clkpol); - - /* Return adjusted counter setup. */ - return setup; -} - -static uint16_t s626_get_mode_b(struct comedi_device *dev, - unsigned int chan) -{ - uint16_t cra; - uint16_t crb; - uint16_t setup; - unsigned int cntsrc, clkmult, clkpol, encmode; - - /* Fetch CRA and CRB register images. */ - cra = s626_debi_read(dev, S626_LP_CRA(chan)); - crb = s626_debi_read(dev, S626_LP_CRB(chan)); - - /* - * Populate the standardized counter setup bit fields. - */ - setup = - /* IntSrc = IntSrcB. */ - S626_SET_STD_INTSRC(S626_GET_CRB_INTSRC_B(crb)) | - /* LatchSrc = LatchSrcB. */ - S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) | - /* LoadSrc = LoadSrcB. */ - S626_SET_STD_LOADSRC(S626_GET_CRB_LOADSRC_B(crb)) | - /* IndxPol = IndxPolB. */ - S626_SET_STD_INDXPOL(S626_GET_CRB_INDXPOL_B(crb)) | - /* ClkEnab = ClkEnabB. */ - S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_B(crb)) | - /* IndxSrc = IndxSrcB. */ - S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_B(cra)); - - /* Adjust mode-dependent parameters. */ - cntsrc = S626_GET_CRA_CNTSRC_B(cra); - clkmult = S626_GET_CRB_CLKMULT_B(crb); - if (clkmult == S626_CLKMULT_SPECIAL) { - /* Extender mode (ClkMultB == S626_CLKMULT_SPECIAL): */ - encmode = S626_ENCMODE_EXTENDER; - /* Indicate multiplier is 1x. */ - clkmult = S626_CLKMULT_1X; - /* Set ClkPol equal to Timer count direction (CntSrcB<0>). */ - clkpol = cntsrc & 1; - } else if (cntsrc & S626_CNTSRC_SYSCLK) { - /* Timer mode (CntSrcB<1> == 1): */ - encmode = S626_ENCMODE_TIMER; - /* Indicate multiplier is 1x. */ - clkmult = S626_CLKMULT_1X; - /* Set ClkPol equal to Timer count direction (CntSrcB<0>). */ - clkpol = cntsrc & 1; - } else { - /* If Counter mode (CntSrcB<1> == 0): */ - encmode = S626_ENCMODE_COUNTER; - /* Clock multiplier is passed through. */ - /* Clock polarity is passed through. */ - clkpol = S626_GET_CRB_CLKPOL_B(crb); - } - setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) | - S626_SET_STD_CLKPOL(clkpol); - - /* Return adjusted counter setup. */ - return setup; -} - -static uint16_t s626_get_mode(struct comedi_device *dev, - unsigned int chan) -{ - return (chan < 3) ? s626_get_mode_a(dev, chan) - : s626_get_mode_b(dev, chan); -} -#endif - /* * Set the operating mode for the specified counter. The setup * parameter is treated as a COUNTER_SETUP data type. The following @@ -1023,25 +895,6 @@ static void s626_set_enable(struct comedi_device *dev, s626_debi_replace(dev, S626_LP_CRB(chan), ~mask, set); } -#ifdef unused -static uint16_t s626_get_enable(struct comedi_device *dev, - unsigned int chan) -{ - uint16_t crb = s626_debi_read(dev, S626_LP_CRB(chan)); - - return (chan < 3) ? S626_GET_CRB_CLKENAB_A(crb) - : S626_GET_CRB_CLKENAB_B(crb); -} -#endif - -#ifdef unused -static uint16_t s626_get_latch_source(struct comedi_device *dev, - unsigned int chan) -{ - return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, S626_LP_CRB(chan))); -} -#endif - /* * Return/set the event that will trigger transfer of the preload * register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow, @@ -1066,19 +919,6 @@ static void s626_set_load_trig(struct comedi_device *dev, s626_debi_replace(dev, reg, ~mask, set); } -#ifdef unused -static uint16_t s626_get_load_trig(struct comedi_device *dev, - unsigned int chan) -{ - if (chan < 3) - return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev, - S626_LP_CRA(chan))); - else - return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev, - S626_LP_CRB(chan))); -} -#endif - /* * Return/set counter interrupt source and clear any captured * index/overflow events. int_source: 0=Disabled, 1=OverflowOnly, @@ -1138,93 +978,6 @@ static void s626_set_int_src(struct comedi_device *dev, } } -#ifdef unused -static uint16_t s626_get_int_src(struct comedi_device *dev, - unsigned int chan) -{ - if (chan < 3) - return S626_GET_CRA_INTSRC_A(s626_debi_read(dev, - S626_LP_CRA(chan))); - else - return S626_GET_CRB_INTSRC_B(s626_debi_read(dev, - S626_LP_CRB(chan))); -} -#endif - -#ifdef unused -/* - * Return/set the clock multiplier. - */ -static void s626_set_clk_mult(struct comedi_device *dev, - unsigned int chan, uint16_t value) -{ - uint16_t mode; - - mode = s626_get_mode(dev, chan); - mode &= ~S626_STDMSK_CLKMULT; - mode |= S626_SET_STD_CLKMULT(value); - - s626_set_mode(dev, chan, mode, false); -} - -/* - * Return/set the clock polarity. - */ -static void s626_set_clk_pol(struct comedi_device *dev, - unsigned int chan, uint16_t value) -{ - uint16_t mode; - - mode = s626_get_mode(dev, chan); - mode &= ~S626_STDMSK_CLKPOL; - mode |= S626_SET_STD_CLKPOL(value); - - s626_set_mode(dev, chan, mode, false); -} - -/* - * Return/set the encoder mode. - */ -static void s626_set_enc_mode(struct comedi_device *dev, - unsigned int chan, uint16_t value) -{ - uint16_t mode; - - mode = s626_get_mode(dev, chan); - mode &= ~S626_STDMSK_ENCMODE; - mode |= S626_SET_STD_ENCMODE(value); - - s626_set_mode(dev, chan, mode, false); -} - -static uint16_t s626_get_index_pol(struct comedi_device *dev, - unsigned int chan) -{ - return S626_GET_STD_INDXPOL(s626_get_mode(dev, chan)); -} - -/* - * Return/set the index source. - */ -static void s626_set_index_src(struct comedi_device *dev, - unsigned int chan, uint16_t value) -{ - uint16_t mode; - - mode = s626_get_mode(dev, chan); - mode &= ~S626_STDMSK_INDXSRC; - mode |= S626_SET_STD_INDXSRC(value != 0); - - s626_set_mode(dev, chan, mode, false); -} - -static uint16_t s626_get_index_src(struct comedi_device *dev, - unsigned int chan) -{ - return S626_GET_STD_INDXSRC(s626_get_mode(dev, chan)); -} -#endif - /* * Generate an index pulse. */ @@ -1717,43 +1470,6 @@ static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl) /* End of RPS program build */ } -#ifdef unused_code -static int s626_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct s626_private *devpriv = dev->private; - uint8_t i; - int32_t *readaddr; - - /* Trigger ADC scan loop start */ - s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); - - /* Wait until ADC scan loop is finished (RPS Signal 0 reset) */ - while (s626_mc_test(dev, S626_MC2_ADC_RPS, S626_P_MC2)) - ; - - /* - * Init ptr to DMA buffer that holds new ADC data. We skip the - * first uint16_t in the buffer because it contains junk data from - * the final ADC of the previous poll list scan. - */ - readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1; - - /* - * Convert ADC data to 16-bit integer values and - * copy to application buffer. - */ - for (i = 0; i < devpriv->adc_items; i++) { - *data = s626_ai_reg_to_uint(*readaddr++); - data++; - } - - return i; -} -#endif - static int s626_ai_eoc(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -2500,7 +2216,8 @@ static int s626_initialize(struct comedi_device *dev) for (i = 0; i < 2; i++) { writel(S626_I2C_CLKSEL, dev->mmio + S626_P_I2CSTAT); s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); - ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0); + ret = comedi_timeout(dev, NULL, + NULL, s626_i2c_handshake_eoc, 0); if (ret) return ret; } diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 6a00a64c6f3a..4cef45263267 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -79,7 +79,7 @@ /* Address offsets, in DWORDS, from base of DMA buffer. */ #define S626_DAC_WDMABUF_OS S626_ADC_DMABUF_DWORDS -/* Interrupt enable bit in ISR and IER. */ +/* Interrupt enable bit in ISR and IER. */ #define S626_IRQ_GPIO3 0x00000040 /* IRQ enable for GPIO3. */ #define S626_IRQ_RPS1 0x10000000 #define S626_ISR_AFOU 0x00000800 @@ -329,7 +329,7 @@ * WS1-WS4 = CS* outputs. */ -#if S626_PLATFORM == S626_INTEL /* +#if (S626_PLATFORM == S626_INTEL) /* * Base ACON1 config: always run * A1 based on TSL1. */ diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 10f94ec34536..608403c7586b 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -946,10 +946,8 @@ static int usbduxfast_auto_attach(struct comedi_device *dev, } devpriv->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!devpriv->urb) { - dev_err(dev->class_dev, "Could not alloc. urb\n"); + if (!devpriv->urb) return -ENOMEM; - } devpriv->inbuf = kmalloc(SIZEINBUF, GFP_KERNEL); if (!devpriv->inbuf) diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 8c7393ef762d..a004aed0147a 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -177,7 +177,7 @@ static void vmk80xx_do_bulk_msg(struct comedi_device *dev) * The max packet size attributes of the K8061 * input/output endpoints are identical */ - size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_tx); usb_bulk_msg(usb, tx_pipe, devpriv->usb_tx_buf, size, NULL, devpriv->ep_tx->bInterval); @@ -199,7 +199,7 @@ static int vmk80xx_read_packet(struct comedi_device *dev) ep = devpriv->ep_rx; pipe = usb_rcvintpipe(usb, ep->bEndpointAddress); return usb_interrupt_msg(usb, pipe, devpriv->usb_rx_buf, - le16_to_cpu(ep->wMaxPacketSize), NULL, + usb_endpoint_maxp(ep), NULL, HZ * 10); } @@ -220,7 +220,7 @@ static int vmk80xx_write_packet(struct comedi_device *dev, int cmd) ep = devpriv->ep_tx; pipe = usb_sndintpipe(usb, ep->bEndpointAddress); return usb_interrupt_msg(usb, pipe, devpriv->usb_tx_buf, - le16_to_cpu(ep->wMaxPacketSize), NULL, + usb_endpoint_maxp(ep), NULL, HZ * 10); } @@ -230,7 +230,7 @@ static int vmk80xx_reset_device(struct comedi_device *dev) size_t size; int retval; - size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_tx); memset(devpriv->usb_tx_buf, 0, size); retval = vmk80xx_write_packet(dev, VMK8055_CMD_RST); if (retval) @@ -684,12 +684,12 @@ static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev) struct vmk80xx_private *devpriv = dev->private; size_t size; - size = le16_to_cpu(devpriv->ep_rx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_rx); devpriv->usb_rx_buf = kzalloc(size, GFP_KERNEL); if (!devpriv->usb_rx_buf) return -ENOMEM; - size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_tx); devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL); if (!devpriv->usb_tx_buf) { kfree(devpriv->usb_rx_buf); diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 46c050cc7dbe..aedca66cbe41 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -26,56 +26,6 @@ #include "dgnc_cls.h" #include "dgnc_tty.h" -static inline void cls_parse_isr(struct dgnc_board *brd, uint port); -static inline void cls_clear_break(struct channel_t *ch, int force); -static inline void cls_set_cts_flow_control(struct channel_t *ch); -static inline void cls_set_rts_flow_control(struct channel_t *ch); -static inline void cls_set_ixon_flow_control(struct channel_t *ch); -static inline void cls_set_ixoff_flow_control(struct channel_t *ch); -static inline void cls_set_no_output_flow_control(struct channel_t *ch); -static inline void cls_set_no_input_flow_control(struct channel_t *ch); -static void cls_parse_modem(struct channel_t *ch, unsigned char signals); -static void cls_tasklet(unsigned long data); -static void cls_vpd(struct dgnc_board *brd); -static void cls_uart_init(struct channel_t *ch); -static void cls_uart_off(struct channel_t *ch); -static int cls_drain(struct tty_struct *tty, uint seconds); -static void cls_param(struct tty_struct *tty); -static void cls_assert_modem_signals(struct channel_t *ch); -static void cls_flush_uart_write(struct channel_t *ch); -static void cls_flush_uart_read(struct channel_t *ch); -static void cls_disable_receiver(struct channel_t *ch); -static void cls_enable_receiver(struct channel_t *ch); -static void cls_send_break(struct channel_t *ch, int msecs); -static void cls_send_start_character(struct channel_t *ch); -static void cls_send_stop_character(struct channel_t *ch); -static void cls_copy_data_from_uart_to_queue(struct channel_t *ch); -static void cls_copy_data_from_queue_to_uart(struct channel_t *ch); -static uint cls_get_uart_bytes_left(struct channel_t *ch); -static void cls_send_immediate_char(struct channel_t *ch, unsigned char); -static irqreturn_t cls_intr(int irq, void *voidbrd); - -struct board_ops dgnc_cls_ops = { - .tasklet = cls_tasklet, - .intr = cls_intr, - .uart_init = cls_uart_init, - .uart_off = cls_uart_off, - .drain = cls_drain, - .param = cls_param, - .vpd = cls_vpd, - .assert_modem_signals = cls_assert_modem_signals, - .flush_uart_write = cls_flush_uart_write, - .flush_uart_read = cls_flush_uart_read, - .disable_receiver = cls_disable_receiver, - .enable_receiver = cls_enable_receiver, - .send_break = cls_send_break, - .send_start_character = cls_send_start_character, - .send_stop_character = cls_send_stop_character, - .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart, - .get_uart_bytes_left = cls_get_uart_bytes_left, - .send_immediate_char = cls_send_immediate_char -}; - static inline void cls_set_cts_flow_control(struct channel_t *ch) { unsigned char lcrb = readb(&ch->ch_cls_uart->lcr); @@ -357,6 +307,253 @@ static inline void cls_clear_break(struct channel_t *ch, int force) spin_unlock_irqrestore(&ch->ch_lock, flags); } +static void cls_copy_data_from_uart_to_queue(struct channel_t *ch) +{ + int qleft = 0; + unsigned char linestatus = 0; + unsigned char error_mask = 0; + ushort head; + ushort tail; + unsigned long flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + spin_lock_irqsave(&ch->ch_lock, flags); + + /* cache head and tail of queue */ + head = ch->ch_r_head; + tail = ch->ch_r_tail; + + /* Store how much space we have left in the queue */ + qleft = tail - head - 1; + if (qleft < 0) + qleft += RQUEUEMASK + 1; + + /* + * Create a mask to determine whether we should + * insert the character (if any) into our queue. + */ + if (ch->ch_c_iflag & IGNBRK) + error_mask |= UART_LSR_BI; + + while (1) { + linestatus = readb(&ch->ch_cls_uart->lsr); + + if (!(linestatus & (UART_LSR_DR))) + break; + + /* + * Discard character if we are ignoring the error mask. + */ + if (linestatus & error_mask) { + linestatus = 0; + readb(&ch->ch_cls_uart->txrx); + continue; + } + + /* + * If our queue is full, we have no choice but to drop some + * data. The assumption is that HWFLOW or SWFLOW should have + * stopped things way way before we got to this point. + * + * I decided that I wanted to ditch the oldest data first, + * I hope thats okay with everyone? Yes? Good. + */ + while (qleft < 1) { + tail = (tail + 1) & RQUEUEMASK; + ch->ch_r_tail = tail; + ch->ch_err_overrun++; + qleft++; + } + + ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE + | UART_LSR_FE); + ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx); + + qleft--; + + if (ch->ch_equeue[head] & UART_LSR_PE) + ch->ch_err_parity++; + if (ch->ch_equeue[head] & UART_LSR_BI) + ch->ch_err_break++; + if (ch->ch_equeue[head] & UART_LSR_FE) + ch->ch_err_frame++; + + /* Add to, and flip head if needed */ + head = (head + 1) & RQUEUEMASK; + ch->ch_rxcount++; + } + + /* + * Write new final heads to channel structure. + */ + ch->ch_r_head = head & RQUEUEMASK; + ch->ch_e_head = head & EQUEUEMASK; + + spin_unlock_irqrestore(&ch->ch_lock, flags); +} + +/* Make the UART raise any of the output signals we want up */ +static void cls_assert_modem_signals(struct channel_t *ch) +{ + unsigned char out; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + out = ch->ch_mostat; + + if (ch->ch_flags & CH_LOOPBACK) + out |= UART_MCR_LOOP; + + writeb(out, &ch->ch_cls_uart->mcr); + + /* Give time for the UART to actually drop the signals */ + udelay(10); +} + +static void cls_copy_data_from_queue_to_uart(struct channel_t *ch) +{ + ushort head; + ushort tail; + int n; + int qlen; + uint len_written = 0; + unsigned long flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + spin_lock_irqsave(&ch->ch_lock, flags); + + /* No data to write to the UART */ + if (ch->ch_w_tail == ch->ch_w_head) + goto exit_unlock; + + /* If port is "stopped", don't send any data to the UART */ + if ((ch->ch_flags & CH_FORCED_STOP) || + (ch->ch_flags & CH_BREAK_SENDING)) + goto exit_unlock; + + if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) + goto exit_unlock; + + n = 32; + + /* cache head and tail of queue */ + head = ch->ch_w_head & WQUEUEMASK; + tail = ch->ch_w_tail & WQUEUEMASK; + qlen = (head - tail) & WQUEUEMASK; + + /* Find minimum of the FIFO space, versus queue length */ + n = min(n, qlen); + + while (n > 0) { + /* + * If RTS Toggle mode is on, turn on RTS now if not already set, + * and make sure we get an event when the data transfer has + * completed. + */ + if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_RTS)) { + ch->ch_mostat |= (UART_MCR_RTS); + cls_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + + /* + * If DTR Toggle mode is on, turn on DTR now if not already set, + * and make sure we get an event when the data transfer has + * completed. + */ + if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_DTR)) { + ch->ch_mostat |= (UART_MCR_DTR); + cls_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_cls_uart->txrx); + ch->ch_w_tail++; + ch->ch_w_tail &= WQUEUEMASK; + ch->ch_txcount++; + len_written++; + n--; + } + + if (len_written > 0) + ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + +exit_unlock: + spin_unlock_irqrestore(&ch->ch_lock, flags); +} + +static void cls_parse_modem(struct channel_t *ch, unsigned char signals) +{ + unsigned char msignals = signals; + unsigned long flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + /* + * Do altpin switching. Altpin switches DCD and DSR. + * This prolly breaks DSRPACE, so we should be more clever here. + */ + spin_lock_irqsave(&ch->ch_lock, flags); + if (ch->ch_digi.digi_flags & DIGI_ALTPIN) { + unsigned char mswap = signals; + + if (mswap & UART_MSR_DDCD) { + msignals &= ~UART_MSR_DDCD; + msignals |= UART_MSR_DDSR; + } + if (mswap & UART_MSR_DDSR) { + msignals &= ~UART_MSR_DDSR; + msignals |= UART_MSR_DDCD; + } + if (mswap & UART_MSR_DCD) { + msignals &= ~UART_MSR_DCD; + msignals |= UART_MSR_DSR; + } + if (mswap & UART_MSR_DSR) { + msignals &= ~UART_MSR_DSR; + msignals |= UART_MSR_DCD; + } + } + spin_unlock_irqrestore(&ch->ch_lock, flags); + + /* + * Scrub off lower bits. They signify delta's, which I don't + * care about + */ + signals &= 0xf0; + + spin_lock_irqsave(&ch->ch_lock, flags); + if (msignals & UART_MSR_DCD) + ch->ch_mistat |= UART_MSR_DCD; + else + ch->ch_mistat &= ~UART_MSR_DCD; + + if (msignals & UART_MSR_DSR) + ch->ch_mistat |= UART_MSR_DSR; + else + ch->ch_mistat &= ~UART_MSR_DSR; + + if (msignals & UART_MSR_RI) + ch->ch_mistat |= UART_MSR_RI; + else + ch->ch_mistat &= ~UART_MSR_RI; + + if (msignals & UART_MSR_CTS) + ch->ch_mistat |= UART_MSR_CTS; + else + ch->ch_mistat &= ~UART_MSR_CTS; + spin_unlock_irqrestore(&ch->ch_lock, flags); +} + /* Parse the ISR register for the specific port */ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) { @@ -387,8 +584,6 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) /* Receive Interrupt pending */ if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) { /* Read data from uart -> queue */ - brd->intr_rx++; - ch->ch_intr_rx++; cls_copy_data_from_uart_to_queue(ch); dgnc_check_queue_flow_control(ch); } @@ -398,27 +593,48 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); - brd->intr_tx++; - ch->ch_intr_tx++; spin_unlock_irqrestore(&ch->ch_lock, flags); cls_copy_data_from_queue_to_uart(ch); } - /* CTS/RTS change of state */ - if (isr & UART_IIR_CTSRTS) { - brd->intr_modem++; - ch->ch_intr_modem++; - /* - * Don't need to do anything, the cls_parse_modem - * below will grab the updated modem signals. - */ - } - /* Parse any modem signal changes */ cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr)); } } +/* Channel lock MUST be held before calling this function! */ +static void cls_flush_uart_write(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), + &ch->ch_cls_uart->isr_fcr); + usleep_range(10, 20); + + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); +} + +/* Channel lock MUST be held before calling this function! */ +static void cls_flush_uart_read(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + /* + * For complete POSIX compatibility, we should be purging the + * read FIFO in the UART here. + * + * However, clearing the read FIFO (UART_FCR_CLEAR_RCVR) also + * incorrectly flushes write data as well as just basically trashing the + * FIFO. + * + * Presumably, this is a bug in this UART. + */ + + udelay(10); +} + /* * cls_param() * Send any/all changes to the line to the UART. @@ -760,8 +976,6 @@ static irqreturn_t cls_intr(int irq, void *voidbrd) spin_lock_irqsave(&brd->bd_intr_lock, flags); - brd->intr_count++; - /* * Check the board's global interrupt offset to see if we * we actually do have an interrupt pending for us. @@ -804,93 +1018,6 @@ static void cls_enable_receiver(struct channel_t *ch) writeb(tmp, &ch->ch_cls_uart->ier); } -static void cls_copy_data_from_uart_to_queue(struct channel_t *ch) -{ - int qleft = 0; - unsigned char linestatus = 0; - unsigned char error_mask = 0; - ushort head; - ushort tail; - unsigned long flags; - - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - spin_lock_irqsave(&ch->ch_lock, flags); - - /* cache head and tail of queue */ - head = ch->ch_r_head; - tail = ch->ch_r_tail; - - /* Store how much space we have left in the queue */ - qleft = tail - head - 1; - if (qleft < 0) - qleft += RQUEUEMASK + 1; - - /* - * Create a mask to determine whether we should - * insert the character (if any) into our queue. - */ - if (ch->ch_c_iflag & IGNBRK) - error_mask |= UART_LSR_BI; - - while (1) { - linestatus = readb(&ch->ch_cls_uart->lsr); - - if (!(linestatus & (UART_LSR_DR))) - break; - - /* - * Discard character if we are ignoring the error mask. - */ - if (linestatus & error_mask) { - linestatus = 0; - readb(&ch->ch_cls_uart->txrx); - continue; - } - - /* - * If our queue is full, we have no choice but to drop some - * data. The assumption is that HWFLOW or SWFLOW should have - * stopped things way way before we got to this point. - * - * I decided that I wanted to ditch the oldest data first, - * I hope thats okay with everyone? Yes? Good. - */ - while (qleft < 1) { - tail = (tail + 1) & RQUEUEMASK; - ch->ch_r_tail = tail; - ch->ch_err_overrun++; - qleft++; - } - - ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE - | UART_LSR_FE); - ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx); - - qleft--; - - if (ch->ch_equeue[head] & UART_LSR_PE) - ch->ch_err_parity++; - if (ch->ch_equeue[head] & UART_LSR_BI) - ch->ch_err_break++; - if (ch->ch_equeue[head] & UART_LSR_FE) - ch->ch_err_frame++; - - /* Add to, and flip head if needed */ - head = (head + 1) & RQUEUEMASK; - ch->ch_rxcount++; - } - - /* - * Write new final heads to channel structure. - */ - ch->ch_r_head = head & RQUEUEMASK; - ch->ch_e_head = head & EQUEUEMASK; - - spin_unlock_irqrestore(&ch->ch_lock, flags); -} - /* * This function basically goes to sleep for secs, or until * it gets signalled that the port has fully drained. @@ -926,199 +1053,6 @@ static int cls_drain(struct tty_struct *tty, uint seconds) ((un->un_flags & UN_EMPTY) == 0)); } -/* Channel lock MUST be held before calling this function! */ -static void cls_flush_uart_write(struct channel_t *ch) -{ - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), - &ch->ch_cls_uart->isr_fcr); - usleep_range(10, 20); - - ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); -} - -/* Channel lock MUST be held before calling this function! */ -static void cls_flush_uart_read(struct channel_t *ch) -{ - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - /* - * For complete POSIX compatibility, we should be purging the - * read FIFO in the UART here. - * - * However, clearing the read FIFO (UART_FCR_CLEAR_RCVR) also - * incorrectly flushes write data as well as just basically trashing the - * FIFO. - * - * Presumably, this is a bug in this UART. - */ - - udelay(10); -} - -static void cls_copy_data_from_queue_to_uart(struct channel_t *ch) -{ - ushort head; - ushort tail; - int n; - int qlen; - uint len_written = 0; - unsigned long flags; - - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - spin_lock_irqsave(&ch->ch_lock, flags); - - /* No data to write to the UART */ - if (ch->ch_w_tail == ch->ch_w_head) - goto exit_unlock; - - /* If port is "stopped", don't send any data to the UART */ - if ((ch->ch_flags & CH_FORCED_STOP) || - (ch->ch_flags & CH_BREAK_SENDING)) - goto exit_unlock; - - if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) - goto exit_unlock; - - n = 32; - - /* cache head and tail of queue */ - head = ch->ch_w_head & WQUEUEMASK; - tail = ch->ch_w_tail & WQUEUEMASK; - qlen = (head - tail) & WQUEUEMASK; - - /* Find minimum of the FIFO space, versus queue length */ - n = min(n, qlen); - - while (n > 0) { - /* - * If RTS Toggle mode is on, turn on RTS now if not already set, - * and make sure we get an event when the data transfer has - * completed. - */ - if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { - if (!(ch->ch_mostat & UART_MCR_RTS)) { - ch->ch_mostat |= (UART_MCR_RTS); - cls_assert_modem_signals(ch); - } - ch->ch_tun.un_flags |= (UN_EMPTY); - } - - /* - * If DTR Toggle mode is on, turn on DTR now if not already set, - * and make sure we get an event when the data transfer has - * completed. - */ - if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { - if (!(ch->ch_mostat & UART_MCR_DTR)) { - ch->ch_mostat |= (UART_MCR_DTR); - cls_assert_modem_signals(ch); - } - ch->ch_tun.un_flags |= (UN_EMPTY); - } - writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_cls_uart->txrx); - ch->ch_w_tail++; - ch->ch_w_tail &= WQUEUEMASK; - ch->ch_txcount++; - len_written++; - n--; - } - - if (len_written > 0) - ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); - -exit_unlock: - spin_unlock_irqrestore(&ch->ch_lock, flags); -} - -static void cls_parse_modem(struct channel_t *ch, unsigned char signals) -{ - unsigned char msignals = signals; - unsigned long flags; - - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - /* - * Do altpin switching. Altpin switches DCD and DSR. - * This prolly breaks DSRPACE, so we should be more clever here. - */ - spin_lock_irqsave(&ch->ch_lock, flags); - if (ch->ch_digi.digi_flags & DIGI_ALTPIN) { - unsigned char mswap = signals; - - if (mswap & UART_MSR_DDCD) { - msignals &= ~UART_MSR_DDCD; - msignals |= UART_MSR_DDSR; - } - if (mswap & UART_MSR_DDSR) { - msignals &= ~UART_MSR_DDSR; - msignals |= UART_MSR_DDCD; - } - if (mswap & UART_MSR_DCD) { - msignals &= ~UART_MSR_DCD; - msignals |= UART_MSR_DSR; - } - if (mswap & UART_MSR_DSR) { - msignals &= ~UART_MSR_DSR; - msignals |= UART_MSR_DCD; - } - } - spin_unlock_irqrestore(&ch->ch_lock, flags); - - /* - * Scrub off lower bits. They signify delta's, which I don't - * care about - */ - signals &= 0xf0; - - spin_lock_irqsave(&ch->ch_lock, flags); - if (msignals & UART_MSR_DCD) - ch->ch_mistat |= UART_MSR_DCD; - else - ch->ch_mistat &= ~UART_MSR_DCD; - - if (msignals & UART_MSR_DSR) - ch->ch_mistat |= UART_MSR_DSR; - else - ch->ch_mistat &= ~UART_MSR_DSR; - - if (msignals & UART_MSR_RI) - ch->ch_mistat |= UART_MSR_RI; - else - ch->ch_mistat &= ~UART_MSR_RI; - - if (msignals & UART_MSR_CTS) - ch->ch_mistat |= UART_MSR_CTS; - else - ch->ch_mistat &= ~UART_MSR_CTS; - spin_unlock_irqrestore(&ch->ch_lock, flags); -} - -/* Make the UART raise any of the output signals we want up */ -static void cls_assert_modem_signals(struct channel_t *ch) -{ - unsigned char out; - - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - out = ch->ch_mostat; - - if (ch->ch_flags & CH_LOOPBACK) - out |= UART_MCR_LOOP; - - writeb(out, &ch->ch_cls_uart->mcr); - - /* Give time for the UART to actually drop the signals */ - udelay(10); -} - static void cls_send_start_character(struct channel_t *ch) { if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) @@ -1298,3 +1232,24 @@ static void cls_vpd(struct dgnc_board *brd) iounmap(re_map_vpdbase); } + +struct board_ops dgnc_cls_ops = { + .tasklet = cls_tasklet, + .intr = cls_intr, + .uart_init = cls_uart_init, + .uart_off = cls_uart_off, + .drain = cls_drain, + .param = cls_param, + .vpd = cls_vpd, + .assert_modem_signals = cls_assert_modem_signals, + .flush_uart_write = cls_flush_uart_write, + .flush_uart_read = cls_flush_uart_read, + .disable_receiver = cls_disable_receiver, + .enable_receiver = cls_enable_receiver, + .send_break = cls_send_break, + .send_start_character = cls_send_start_character, + .send_stop_character = cls_send_stop_character, + .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart, + .get_uart_bytes_left = cls_get_uart_bytes_left, + .send_immediate_char = cls_send_immediate_char +}; diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index af2e835efa1b..fd372d3afa46 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -37,13 +37,14 @@ MODULE_SUPPORTED_DEVICE("dgnc"); * */ static int dgnc_start(void); -static int dgnc_finalize_board_init(struct dgnc_board *brd); -static int dgnc_found_board(struct pci_dev *pdev, int id); +static int dgnc_request_irq(struct dgnc_board *brd); +static void dgnc_free_irq(struct dgnc_board *brd); +static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id); static void dgnc_cleanup_board(struct dgnc_board *brd); static void dgnc_poll_handler(ulong dummy); static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static void dgnc_do_remap(struct dgnc_board *brd); +static int dgnc_do_remap(struct dgnc_board *brd); /* * File operations permitted on Control/Management major. @@ -146,7 +147,7 @@ static void cleanup(bool sysfiles) for (i = 0; i < dgnc_num_boards; ++i) { dgnc_remove_ports_sysfiles(dgnc_board[i]); - dgnc_tty_uninit(dgnc_board[i]); + dgnc_cleanup_tty(dgnc_board[i]); dgnc_cleanup_board(dgnc_board[i]); } @@ -158,7 +159,7 @@ static void cleanup(bool sysfiles) * * Module unload. This is where it all ends. */ -static void dgnc_cleanup_module(void) +static void __exit dgnc_cleanup_module(void) { cleanup(true); pci_unregister_driver(&dgnc_driver); @@ -274,6 +275,7 @@ failed_class: static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; + struct dgnc_board *brd; /* wake up and enable device */ rc = pci_enable_device(pdev); @@ -281,9 +283,48 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return -EIO; - rc = dgnc_found_board(pdev, ent->driver_data); - if (rc == 0) - dgnc_num_boards++; + brd = dgnc_found_board(pdev, ent->driver_data); + if (IS_ERR(brd)) + return PTR_ERR(brd); + + /* + * Do tty device initialization. + */ + + rc = dgnc_tty_register(brd); + if (rc < 0) { + pr_err(DRVSTR ": Can't register tty devices (%d)\n", rc); + goto failed; + } + + rc = dgnc_request_irq(brd); + if (rc < 0) { + pr_err(DRVSTR ": Can't finalize board init (%d)\n", rc); + goto unregister_tty; + } + + rc = dgnc_tty_init(brd); + if (rc < 0) { + pr_err(DRVSTR ": Can't init tty devices (%d)\n", rc); + goto free_irq; + } + + brd->state = BOARD_READY; + brd->dpastatus = BD_RUNNING; + + dgnc_create_ports_sysfiles(brd); + + dgnc_board[dgnc_num_boards++] = brd; + + return 0; + +free_irq: + dgnc_free_irq(brd); +unregister_tty: + dgnc_tty_unregister(brd); + +failed: + kfree(brd); return rc; } @@ -324,17 +365,6 @@ static void dgnc_cleanup_board(struct dgnc_board *brd) brd->re_map_membase = NULL; } - if (brd->msgbuf_head) { - unsigned long flags; - - spin_lock_irqsave(&dgnc_global_lock, flags); - brd->msgbuf = NULL; - dev_dbg(&brd->pdev->dev, "%s\n", brd->msgbuf_head); - kfree(brd->msgbuf_head); - brd->msgbuf_head = NULL; - spin_unlock_irqrestore(&dgnc_global_lock, flags); - } - /* Free all allocated channels structs */ for (i = 0; i < MAXPORTS ; i++) { if (brd->channels[i]) { @@ -356,29 +386,17 @@ static void dgnc_cleanup_board(struct dgnc_board *brd) * * A board has been found, init it. */ -static int dgnc_found_board(struct pci_dev *pdev, int id) +static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id) { struct dgnc_board *brd; unsigned int pci_irq; int i = 0; int rc = 0; - unsigned long flags; /* get the board structure and prep it */ - dgnc_board[dgnc_num_boards] = kzalloc(sizeof(*brd), GFP_KERNEL); - brd = dgnc_board[dgnc_num_boards]; - + brd = kzalloc(sizeof(*brd), GFP_KERNEL); if (!brd) - return -ENOMEM; - - /* make a temporary message buffer for the boot messages */ - brd->msgbuf_head = kcalloc(8192, sizeof(u8), GFP_KERNEL); - brd->msgbuf = brd->msgbuf_head; - - if (!brd->msgbuf) { - kfree(brd); - return -ENOMEM; - } + return ERR_PTR(-ENOMEM); /* store the info for the board we've found */ brd->magic = DGNC_BOARD_MAGIC; @@ -400,9 +418,6 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) brd->state = BOARD_FOUND; - for (i = 0; i < MAXPORTS; i++) - brd->channels[i] = NULL; - /* store which card & revision we have */ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor); pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice); @@ -435,7 +450,8 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) if (!brd->membase) { dev_err(&brd->pdev->dev, "Card has no PCI IO resources, failing.\n"); - return -ENODEV; + rc = -ENODEV; + goto failed; } brd->membase_end = pci_resource_end(pdev, 4); @@ -455,7 +471,10 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) brd->bd_uart_offset = 0x8; brd->bd_dividend = 921600; - dgnc_do_remap(brd); + rc = dgnc_do_remap(brd); + + if (rc < 0) + goto failed; /* Get and store the board VPD, if it exists */ brd->bd_ops->vpd(brd); @@ -507,81 +526,45 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) brd->bd_uart_offset = 0x200; brd->bd_dividend = 921600; - dgnc_do_remap(brd); + rc = dgnc_do_remap(brd); - if (brd->re_map_membase) { - /* Read and store the dvid after remapping */ - brd->dvid = readb(brd->re_map_membase + 0x8D); + if (rc < 0) + goto failed; + + /* Read and store the dvid after remapping */ + brd->dvid = readb(brd->re_map_membase + 0x8D); + + /* Get and store the board VPD, if it exists */ + brd->bd_ops->vpd(brd); - /* Get and store the board VPD, if it exists */ - brd->bd_ops->vpd(brd); - } break; default: dev_err(&brd->pdev->dev, "Didn't find any compatible Neo/Classic PCI boards.\n"); - return -ENXIO; - } - - /* - * Do tty device initialization. - */ - - rc = dgnc_tty_register(brd); - if (rc < 0) { - pr_err(DRVSTR ": Can't register tty devices (%d)\n", rc); + rc = -ENXIO; goto failed; } - rc = dgnc_finalize_board_init(brd); - if (rc < 0) { - pr_err(DRVSTR ": Can't finalize board init (%d)\n", rc); - goto failed; - } - - rc = dgnc_tty_init(brd); - if (rc < 0) { - pr_err(DRVSTR ": Can't init tty devices (%d)\n", rc); - goto failed; - } - - brd->state = BOARD_READY; - brd->dpastatus = BD_RUNNING; - - dgnc_create_ports_sysfiles(brd); - /* init our poll helper tasklet */ tasklet_init(&brd->helper_tasklet, brd->bd_ops->tasklet, (unsigned long)brd); - spin_lock_irqsave(&dgnc_global_lock, flags); - brd->msgbuf = NULL; - dev_dbg(&brd->pdev->dev, "%s\n", brd->msgbuf_head); - kfree(brd->msgbuf_head); - brd->msgbuf_head = NULL; - spin_unlock_irqrestore(&dgnc_global_lock, flags); - wake_up_interruptible(&brd->state_wait); - return 0; + return brd; failed: - dgnc_tty_uninit(brd); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; + kfree(brd); - return -ENXIO; + return ERR_PTR(rc); } -static int dgnc_finalize_board_init(struct dgnc_board *brd) +static int dgnc_request_irq(struct dgnc_board *brd) { int rc = 0; - if (!brd || brd->magic != DGNC_BOARD_MAGIC) - return -ENODEV; - if (brd->irq) { rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "DGNC", brd); @@ -597,42 +580,51 @@ static int dgnc_finalize_board_init(struct dgnc_board *brd) return rc; } +static void dgnc_free_irq(struct dgnc_board *brd) +{ + if (brd->irq) + free_irq(brd->irq, brd); +} + /* * Remap PCI memory. */ -static void dgnc_do_remap(struct dgnc_board *brd) +static int dgnc_do_remap(struct dgnc_board *brd) { - if (!brd || brd->magic != DGNC_BOARD_MAGIC) - return; + int rc = 0; brd->re_map_membase = ioremap(brd->membase, 0x1000); + if (!brd->re_map_membase) + rc = -ENOMEM; + + return rc; } -/***************************************************************************** -* -* Function: -* -* dgnc_poll_handler -* -* Author: -* -* Scott H Kilau -* -* Parameters: -* -* dummy -- ignored -* -* Return Values: -* -* none -* -* Description: -* -* As each timer expires, it determines (a) whether the "transmit" -* waiter needs to be woken up, and (b) whether the poller needs to -* be rescheduled. -* -******************************************************************************/ +/* + * + * Function: + * + * dgnc_poll_handler + * + * Author: + * + * Scott H Kilau + * + * Parameters: + * + * dummy -- ignored + * + * Return Values: + * + * none + * + * Description: + * + * As each timer expires, it determines (a) whether the "transmit" + * waiter needs to be woken up, and (b) whether the poller needs to + * be rescheduled. + * + */ static void dgnc_poll_handler(ulong dummy) { diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 95ec729fae38..879202663a98 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -183,10 +183,6 @@ struct dgnc_board { uint nasync; /* Number of ports on card */ uint irq; /* Interrupt request number */ - ulong intr_count; /* Count of interrupts */ - ulong intr_modem; /* Count of interrupts */ - ulong intr_tx; /* Count of interrupts */ - ulong intr_rx; /* Count of interrupts */ ulong membase; /* Start of base memory of the card */ ulong membase_end; /* End of base memory of the card */ @@ -207,9 +203,6 @@ struct dgnc_board { struct tty_driver *print_driver; char print_name[200]; - bool dgnc_major_serial_registered; - bool dgnc_major_transparent_print_registered; - u16 dpatype; /* The board "type", * as defined by DPA */ @@ -217,12 +210,6 @@ struct dgnc_board { * as defined by DPA */ - /* - * Mgmt data. - */ - char *msgbuf_head; - char *msgbuf; - uint bd_dividend; /* Board/UARTs specific dividend */ struct board_ops *bd_ops; @@ -381,10 +368,6 @@ struct channel_t { ulong ch_xon_sends; /* Count of xons transmitted */ ulong ch_xoff_sends; /* Count of xoffs transmitted */ - ulong ch_intr_modem; /* Count of interrupts */ - ulong ch_intr_tx; /* Count of interrupts */ - ulong ch_intr_rx; /* Count of interrupts */ - /* /proc// entries */ struct proc_dir_entry *proc_entry_pointer; struct dgnc_proc_entry *dgnc_channel_table; @@ -398,7 +381,7 @@ extern uint dgnc_major; /* Our driver/mgmt major */ extern int dgnc_poll_tick; /* Poll interval - 20 ms */ extern spinlock_t dgnc_global_lock; /* Driver global spinlock */ extern spinlock_t dgnc_poll_lock; /* Poll scheduling lock */ -extern uint dgnc_num_boards; /* Total number of boards */ +extern uint dgnc_num_boards; /* Total number of boards */ extern struct dgnc_board *dgnc_board[MAXBOARDS]; /* Array of board * structs */ diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index ba57e9546f72..5becb3741b67 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -107,7 +107,9 @@ static inline void neo_set_cts_flow_control(struct channel_t *ch) /* Turn off auto Xon flow control */ efr &= ~UART_17158_EFR_IXON; - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -143,7 +145,9 @@ static inline void neo_set_rts_flow_control(struct channel_t *ch) ier &= ~UART_17158_IER_XOFF; efr &= ~UART_17158_EFR_IXOFF; - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -181,7 +185,9 @@ static inline void neo_set_ixon_flow_control(struct channel_t *ch) /* Turn on auto Xon flow control */ efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON); - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -219,7 +225,9 @@ static inline void neo_set_ixoff_flow_control(struct channel_t *ch) ier |= UART_17158_IER_XOFF; efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF); - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -260,7 +268,9 @@ static inline void neo_set_no_input_flow_control(struct channel_t *ch) else efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF); - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero + * it out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -298,7 +308,9 @@ static inline void neo_set_no_output_flow_control(struct channel_t *ch) else efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON); - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -399,19 +411,17 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) { /* Read data from uart -> queue */ - brd->intr_rx++; - ch->ch_intr_rx++; neo_copy_data_from_uart_to_queue(ch); - /* Call our tty layer to enforce queue flow control if needed. */ + /* Call our tty layer to enforce queue + * flow control if needed. + */ spin_lock_irqsave(&ch->ch_lock, flags); dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, flags); } if (isr & UART_IIR_THRI) { - brd->intr_tx++; - ch->ch_intr_tx++; /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); @@ -428,7 +438,9 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) * one it was, so we can suspend or resume data flow. */ if (cause == UART_17158_XON_DETECT) { - /* Is output stopped right now, if so, resume it */ + /* Is output stopped right now, if so, + * resume it + */ if (brd->channels[port]->ch_flags & CH_STOP) { spin_lock_irqsave(&ch->ch_lock, flags); @@ -437,7 +449,8 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) flags); } } else if (cause == UART_17158_XOFF_DETECT) { - if (!(brd->channels[port]->ch_flags & CH_STOP)) { + if (!(brd->channels[port]->ch_flags & + CH_STOP)) { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= CH_STOP; @@ -449,11 +462,10 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) { /* - * If we get here, this means the hardware is doing auto flow control. - * Check to see whether RTS/DTR or CTS/DSR caused this interrupt. + * If we get here, this means the hardware is + * doing auto flow control. Check to see whether + * RTS/DTR or CTS/DSR caused this interrupt. */ - brd->intr_modem++; - ch->ch_intr_modem++; cause = readb(&ch->ch_neo_uart->mcr); /* Which pin is doing auto flow? RTS or DTR? */ if ((cause & 0x4) == 0) { @@ -517,8 +529,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) ch->ch_cached_lsr |= linestatus; if (ch->ch_cached_lsr & UART_LSR_DR) { - brd->intr_rx++; - ch->ch_intr_rx++; /* Read data from uart -> queue */ neo_copy_data_from_uart_to_queue(ch); spin_lock_irqsave(&ch->ch_lock, flags); @@ -545,14 +555,13 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) * Rx Oruns. Exar says that an orun will NOT corrupt * the FIFO. It will just replace the holding register * with this new data byte. So basically just ignore this. - * Probably we should eventually have an orun stat in our driver... + * Probably we should eventually have an orun stat in our + * driver... */ ch->ch_err_overrun++; } if (linestatus & UART_LSR_THRE) { - brd->intr_tx++; - ch->ch_intr_tx++; spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -560,8 +569,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) /* Transfer data (if any) from Write Queue -> UART. */ neo_copy_data_from_queue_to_uart(ch); } else if (linestatus & UART_17158_TX_AND_FIFO_CLR) { - brd->intr_tx++; - ch->ch_intr_tx++; spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -665,7 +672,9 @@ static void neo_param(struct tty_struct *tty) 4800, 9600, 19200, 38400 } }; - /* Only use the TXPrint baud rate if the terminal unit is NOT open */ + /* Only use the TXPrint baud rate if the terminal unit + * is NOT open + */ if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT)) baud = C_BAUD(ch->ch_pun.un_tty) & 0xff; @@ -788,7 +797,9 @@ static void neo_param(struct tty_struct *tty) if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) { neo_set_cts_flow_control(ch); } else if (ch->ch_c_iflag & IXON) { - /* If start/stop is set to disable, then we should disable flow control */ + /* If start/stop is set to disable, then we should + * disable flow control + */ if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) neo_set_no_output_flow_control(ch); @@ -801,7 +812,9 @@ static void neo_param(struct tty_struct *tty) if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) { neo_set_rts_flow_control(ch); } else if (ch->ch_c_iflag & IXOFF) { - /* If start/stop is set to disable, then we should disable flow control */ + /* If start/stop is set to disable, then we should + * disable flow control + */ if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) neo_set_no_input_flow_control(ch); @@ -926,8 +939,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) if (!brd || brd->magic != DGNC_BOARD_MAGIC) return IRQ_NONE; - brd->intr_count++; - /* Lock out the slow poller from running on this board. */ spin_lock_irqsave(&brd->bd_intr_lock, flags); @@ -940,14 +951,18 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) /* * If 0, no interrupts pending. - * This can happen if the IRQ is shared among a couple Neo/Classic boards. + * This can happen if the IRQ is shared among a couple Neo/Classic + * boards. */ if (!uart_poll) { spin_unlock_irqrestore(&brd->bd_intr_lock, flags); return IRQ_NONE; } - /* At this point, we have at least SOMETHING to service, dig further... */ + /* + * At this point, we have at least SOMETHING to service, dig + * further... + */ /* Loop on each port */ while ((uart_poll & 0xff) != 0) { @@ -971,7 +986,10 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) ch = brd->channels[port]; neo_copy_data_from_uart_to_queue(ch); - /* Call our tty layer to enforce queue flow control if needed. */ + /* + * Call our tty layer to enforce queue flow control if + * needed. + */ spin_lock_irqsave(&ch->ch_lock, flags2); dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, flags2); @@ -987,16 +1005,18 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) case UART_17158_TXRDY: /* - * TXRDY interrupt clears after reading ISR register for the UART channel. + * TXRDY interrupt clears after reading ISR register + * for the UART channel. */ /* * Yes, this is odd... * Why would I check EVERY possibility of type of * interrupt, when we know its TXRDY??? - * Becuz for some reason, even tho we got triggered for TXRDY, - * it seems to be occasionally wrong. Instead of TX, which - * it should be, I was getting things like RXDY too. Weird. + * Becuz for some reason, even tho we got triggered for + * TXRDY, it seems to be occasionally wrong. Instead of + * TX, which it should be, I was getting things like + * RXDY too. Weird. */ neo_parse_isr(brd, port); break; @@ -1011,8 +1031,8 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) default: /* * The UART triggered us with a bogus interrupt type. - * It appears the Exar chip, when REALLY bogged down, will throw - * these once and awhile. + * It appears the Exar chip, when REALLY bogged down, + * will throw these once and awhile. * Its harmless, just ignore it and move on. */ break; @@ -1230,7 +1250,8 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) } /* - * If our queue is full, we have no choice but to drop some data. + * If our queue is full, we have no choice but to drop some + * data. * The assumption is that HWFLOW or SWFLOW should have stopped * things way way before we got to this point. * @@ -1323,7 +1344,10 @@ static void neo_flush_uart_write(struct channel_t *ch) neo_pci_posting_flush(ch->ch_bd); for (i = 0; i < 10; i++) { - /* Check to see if the UART feels it completely flushed the FIFO. */ + /* + * Check to see if the UART feels it completely flushed the + * FIFO. + */ tmp = readb(&ch->ch_neo_uart->isr_fcr); if (tmp & 4) udelay(10); @@ -1352,7 +1376,10 @@ static void neo_flush_uart_read(struct channel_t *ch) neo_pci_posting_flush(ch->ch_bd); for (i = 0; i < 10; i++) { - /* Check to see if the UART feels it completely flushed the FIFO. */ + /* + * Check to see if the UART feels it completely flushed the + * FIFO. + */ tmp = readb(&ch->ch_neo_uart->isr_fcr); if (tmp & 2) udelay(10); @@ -1397,8 +1424,9 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) ch->ch_cached_lsr &= ~(UART_LSR_THRE); /* - * If RTS Toggle mode is on, turn on RTS now if not already set, - * and make sure we get an event when the data transfer has completed. + * If RTS Toggle mode is on, turn on RTS now if not + * already set, and make sure we get an event when the + * data transfer has completed. */ if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { if (!(ch->ch_mostat & UART_MCR_RTS)) { @@ -1408,8 +1436,9 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) ch->ch_tun.un_flags |= (UN_EMPTY); } /* - * If DTR Toggle mode is on, turn on DTR now if not already set, - * and make sure we get an event when the data transfer has completed. + * If DTR Toggle mode is on, turn on DTR now if not + * already set, and make sure we get an event when the + * data transfer has completed. */ if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { if (!(ch->ch_mostat & UART_MCR_DTR)) { @@ -1465,7 +1494,8 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) /* * If RTS Toggle mode is on, turn on RTS now if not already set, - * and make sure we get an event when the data transfer has completed. + * and make sure we get an event when the data transfer has + * completed. */ if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { if (!(ch->ch_mostat & UART_MCR_RTS)) { @@ -1477,7 +1507,8 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) /* * If DTR Toggle mode is on, turn on DTR now if not already set, - * and make sure we get an event when the data transfer has completed. + * and make sure we get an event when the data transfer has + * completed. */ if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { if (!(ch->ch_mostat & UART_MCR_DTR)) { @@ -1541,7 +1572,10 @@ static void neo_parse_modem(struct channel_t *ch, unsigned char signals) } } - /* Scrub off lower bits. They signify delta's, which I don't care about */ + /* + * Scrub off lower bits. They signify delta's, which I don't care + * about + */ msignals &= 0xf0; if (msignals & UART_MSR_DCD) diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c index b8d41c5617e2..290bf6e226ac 100644 --- a/drivers/staging/dgnc/dgnc_sysfs.c +++ b/drivers/staging/dgnc/dgnc_sysfs.c @@ -25,31 +25,31 @@ #include "dgnc_driver.h" #include "dgnc_mgmt.h" -static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf) +static ssize_t version_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART); } -static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL); +static DRIVER_ATTR_RO(version); -static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf) +static ssize_t boards_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_num_boards); } -static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL); +static DRIVER_ATTR_RO(boards); -static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf) +static ssize_t maxboards_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS); } -static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL); +static DRIVER_ATTR_RO(maxboards); -static ssize_t dgnc_driver_pollrate_show(struct device_driver *ddp, char *buf) +static ssize_t pollrate_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%dms\n", dgnc_poll_tick); } -static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, - const char *buf, size_t count) +static ssize_t pollrate_store(struct device_driver *ddp, + const char *buf, size_t count) { unsigned long flags; int tick; @@ -65,8 +65,7 @@ static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, return count; } -static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, - dgnc_driver_pollrate_store); +static DRIVER_ATTR_RW(pollrate); void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver) { @@ -103,8 +102,8 @@ void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver) return 0; \ } while (0) -static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, - char *buf) +static ssize_t vpd_show(struct device *p, struct device_attribute *attr, + char *buf) { struct dgnc_board *bd; int count = 0; @@ -123,10 +122,10 @@ static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, return count; } -static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL); +static DEVICE_ATTR_RO(vpd); -static ssize_t dgnc_serial_number_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t serial_number_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -140,10 +139,10 @@ static ssize_t dgnc_serial_number_show(struct device *p, return count; } -static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL); +static DEVICE_ATTR_RO(serial_number); -static ssize_t dgnc_ports_state_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_state_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -158,10 +157,10 @@ static ssize_t dgnc_ports_state_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL); +static DEVICE_ATTR_RO(ports_state); -static ssize_t dgnc_ports_baud_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_baud_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -176,11 +175,10 @@ static ssize_t dgnc_ports_baud_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL); +static DEVICE_ATTR_RO(ports_baud); -static ssize_t dgnc_ports_msignals_show(struct device *p, - struct device_attribute *attr, - char *buf) +static ssize_t ports_msignals_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -208,10 +206,10 @@ static ssize_t dgnc_ports_msignals_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL); +static DEVICE_ATTR_RO(ports_msignals); -static ssize_t dgnc_ports_iflag_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_iflag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -226,10 +224,10 @@ static ssize_t dgnc_ports_iflag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL); +static DEVICE_ATTR_RO(ports_iflag); -static ssize_t dgnc_ports_cflag_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_cflag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -244,10 +242,10 @@ static ssize_t dgnc_ports_cflag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL); +static DEVICE_ATTR_RO(ports_cflag); -static ssize_t dgnc_ports_oflag_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_oflag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -262,10 +260,10 @@ static ssize_t dgnc_ports_oflag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL); +static DEVICE_ATTR_RO(ports_oflag); -static ssize_t dgnc_ports_lflag_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_lflag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -280,11 +278,10 @@ static ssize_t dgnc_ports_lflag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL); +static DEVICE_ATTR_RO(ports_lflag); -static ssize_t dgnc_ports_digi_flag_show(struct device *p, - struct device_attribute *attr, - char *buf) +static ssize_t ports_digi_flag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -299,10 +296,10 @@ static ssize_t dgnc_ports_digi_flag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL); +static DEVICE_ATTR_RO(ports_digi_flag); -static ssize_t dgnc_ports_rxcount_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_rxcount_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -317,10 +314,10 @@ static ssize_t dgnc_ports_rxcount_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL); +static DEVICE_ATTR_RO(ports_rxcount); -static ssize_t dgnc_ports_txcount_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_txcount_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -335,7 +332,7 @@ static ssize_t dgnc_ports_txcount_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL); +static DEVICE_ATTR_RO(ports_txcount); /* this function creates the sys files that will export each signal status * to sysfs each value will be put in a separate filename @@ -378,8 +375,8 @@ void dgnc_remove_ports_sysfiles(struct dgnc_board *bd) device_remove_file(&bd->pdev->dev, &dev_attr_serial_number); } -static ssize_t dgnc_tty_state_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_state_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -402,10 +399,10 @@ static ssize_t dgnc_tty_state_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed"); } -static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL); +static DEVICE_ATTR_RO(tty_state); -static ssize_t dgnc_tty_baud_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_baud_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -427,10 +424,10 @@ static ssize_t dgnc_tty_baud_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud); } -static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL); +static DEVICE_ATTR_RO(tty_baud); -static ssize_t dgnc_tty_msignals_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_msignals_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -461,10 +458,10 @@ static ssize_t dgnc_tty_msignals_show(struct device *d, } return 0; } -static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL); +static DEVICE_ATTR_RO(tty_msignals); -static ssize_t dgnc_tty_iflag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_iflag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -486,10 +483,10 @@ static ssize_t dgnc_tty_iflag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag); } -static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL); +static DEVICE_ATTR_RO(tty_iflag); -static ssize_t dgnc_tty_cflag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_cflag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -511,10 +508,10 @@ static ssize_t dgnc_tty_cflag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag); } -static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL); +static DEVICE_ATTR_RO(tty_cflag); -static ssize_t dgnc_tty_oflag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_oflag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -536,10 +533,10 @@ static ssize_t dgnc_tty_oflag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag); } -static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL); +static DEVICE_ATTR_RO(tty_oflag); -static ssize_t dgnc_tty_lflag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_lflag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -561,10 +558,10 @@ static ssize_t dgnc_tty_lflag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag); } -static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL); +static DEVICE_ATTR_RO(tty_lflag); -static ssize_t dgnc_tty_digi_flag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_digi_flag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -586,10 +583,10 @@ static ssize_t dgnc_tty_digi_flag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags); } -static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL); +static DEVICE_ATTR_RO(tty_digi_flag); -static ssize_t dgnc_tty_rxcount_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_rxcount_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -611,10 +608,10 @@ static ssize_t dgnc_tty_rxcount_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount); } -static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL); +static DEVICE_ATTR_RO(tty_rxcount); -static ssize_t dgnc_tty_txcount_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_txcount_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -636,10 +633,10 @@ static ssize_t dgnc_tty_txcount_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount); } -static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL); +static DEVICE_ATTR_RO(tty_txcount); -static ssize_t dgnc_tty_name_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_custom_name_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -663,24 +660,24 @@ static ssize_t dgnc_tty_name_show(struct device *d, (un->un_type == DGNC_PRINT) ? "pr" : "tty", bd->boardnum + 1, 'a' + ch->ch_portnum); } -static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL); +static DEVICE_ATTR_RO(tty_custom_name); static struct attribute *dgnc_sysfs_tty_entries[] = { - &dev_attr_state.attr, - &dev_attr_baud.attr, - &dev_attr_msignals.attr, - &dev_attr_iflag.attr, - &dev_attr_cflag.attr, - &dev_attr_oflag.attr, - &dev_attr_lflag.attr, - &dev_attr_digi_flag.attr, - &dev_attr_rxcount.attr, - &dev_attr_txcount.attr, - &dev_attr_custom_name.attr, + &dev_attr_tty_state.attr, + &dev_attr_tty_baud.attr, + &dev_attr_tty_msignals.attr, + &dev_attr_tty_iflag.attr, + &dev_attr_tty_cflag.attr, + &dev_attr_tty_oflag.attr, + &dev_attr_tty_lflag.attr, + &dev_attr_tty_digi_flag.attr, + &dev_attr_tty_rxcount.attr, + &dev_attr_tty_txcount.attr, + &dev_attr_tty_custom_name.attr, NULL }; -static struct attribute_group dgnc_tty_attribute_group = { +static const struct attribute_group dgnc_tty_attribute_group = { .name = NULL, .attrs = dgnc_sysfs_tty_entries, }; diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 4eeecc992a02..953d9310fa74 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -45,7 +45,6 @@ /* * internal variables */ -static struct dgnc_board *dgnc_BoardsByMajor[256]; static unsigned char *dgnc_TmpWriteBuf; /* @@ -100,7 +99,7 @@ static void dgnc_tty_unthrottle(struct tty_struct *tty); static void dgnc_tty_flush_chars(struct tty_struct *tty); static void dgnc_tty_flush_buffer(struct tty_struct *tty); static void dgnc_tty_hangup(struct tty_struct *tty); -static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, +static int dgnc_set_modem_info(struct channel_t *ch, unsigned int command, unsigned int __user *value); static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value); @@ -186,7 +185,8 @@ int dgnc_tty_register(struct dgnc_board *brd) if (IS_ERR(brd->serial_driver)) return PTR_ERR(brd->serial_driver); - snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum); + snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgnc_%d_", + brd->boardnum); brd->serial_driver->name = brd->serial_name; brd->serial_driver->name_base = 0; @@ -203,15 +203,11 @@ int dgnc_tty_register(struct dgnc_board *brd) */ tty_set_operations(brd->serial_driver, &dgnc_tty_ops); - if (!brd->dgnc_major_serial_registered) { - /* Register tty devices */ - rc = tty_register_driver(brd->serial_driver); - if (rc < 0) { - dev_dbg(&brd->pdev->dev, - "Can't register tty device (%d)\n", rc); - goto free_serial_driver; - } - brd->dgnc_major_serial_registered = true; + rc = tty_register_driver(brd->serial_driver); + if (rc < 0) { + dev_dbg(&brd->pdev->dev, + "Can't register tty device (%d)\n", rc); + goto free_serial_driver; } /* @@ -246,20 +242,14 @@ int dgnc_tty_register(struct dgnc_board *brd) */ tty_set_operations(brd->print_driver, &dgnc_tty_ops); - if (!brd->dgnc_major_transparent_print_registered) { - /* Register Transparent Print devices */ - rc = tty_register_driver(brd->print_driver); - if (rc < 0) { - dev_dbg(&brd->pdev->dev, - "Can't register Transparent Print device(%d)\n", - rc); - goto free_print_driver; - } - brd->dgnc_major_transparent_print_registered = true; + rc = tty_register_driver(brd->print_driver); + if (rc < 0) { + dev_dbg(&brd->pdev->dev, + "Can't register Transparent Print device(%d)\n", + rc); + goto free_print_driver; } - dgnc_BoardsByMajor[brd->serial_driver->major] = brd; - return 0; free_print_driver: @@ -272,6 +262,14 @@ free_serial_driver: return rc; } +void dgnc_tty_unregister(struct dgnc_board *brd) +{ + tty_unregister_driver(brd->print_driver); + tty_unregister_driver(brd->serial_driver); + put_tty_driver(brd->print_driver); + put_tty_driver(brd->serial_driver); +} + /* * dgnc_tty_init() * @@ -378,38 +376,30 @@ void dgnc_tty_post_uninit(void) } /* - * dgnc_tty_uninit() + * dgnc_cleanup_tty() * * Uninitialize the TTY portion of this driver. Free all memory and * resources. */ -void dgnc_tty_uninit(struct dgnc_board *brd) +void dgnc_cleanup_tty(struct dgnc_board *brd) { int i = 0; - if (brd->dgnc_major_serial_registered) { - dgnc_BoardsByMajor[brd->serial_driver->major] = NULL; - for (i = 0; i < brd->nasync; i++) { - if (brd->channels[i]) - dgnc_remove_tty_sysfs(brd->channels[i]-> - ch_tun.un_sysfs); - tty_unregister_device(brd->serial_driver, i); - } - tty_unregister_driver(brd->serial_driver); - brd->dgnc_major_serial_registered = false; + for (i = 0; i < brd->nasync; i++) { + if (brd->channels[i]) + dgnc_remove_tty_sysfs(brd->channels[i]-> + ch_tun.un_sysfs); + tty_unregister_device(brd->serial_driver, i); } + tty_unregister_driver(brd->serial_driver); - if (brd->dgnc_major_transparent_print_registered) { - dgnc_BoardsByMajor[brd->print_driver->major] = NULL; - for (i = 0; i < brd->nasync; i++) { - if (brd->channels[i]) - dgnc_remove_tty_sysfs(brd->channels[i]-> - ch_pun.un_sysfs); - tty_unregister_device(brd->print_driver, i); - } - tty_unregister_driver(brd->print_driver); - brd->dgnc_major_transparent_print_registered = false; + for (i = 0; i < brd->nasync; i++) { + if (brd->channels[i]) + dgnc_remove_tty_sysfs(brd->channels[i]-> + ch_pun.un_sysfs); + tty_unregister_device(brd->print_driver, i); } + tty_unregister_driver(brd->print_driver); put_tty_driver(brd->serial_driver); put_tty_driver(brd->print_driver); @@ -640,19 +630,12 @@ exit_unlock: ************************************************************************/ void dgnc_carrier(struct channel_t *ch) { - struct dgnc_board *bd; - int virt_carrier = 0; int phys_carrier = 0; if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - bd = ch->ch_bd; - - if (!bd || bd->magic != DGNC_BOARD_MAGIC) - return; - if (ch->ch_mistat & UART_MSR_DCD) phys_carrier = 1; @@ -947,6 +930,24 @@ void dgnc_wakeup_writes(struct channel_t *ch) spin_unlock_irqrestore(&ch->ch_lock, flags); } +struct dgnc_board *find_board_by_major(unsigned int major) +{ + int i; + + for (i = 0; i < MAXBOARDS; i++) { + struct dgnc_board *brd = dgnc_board[i]; + + if (!brd) + return NULL; + + if (major == brd->serial_driver->major || + major == brd->print_driver->major) + return brd; + } + + return NULL; +} + /************************************************************************ * * TTY Entry points and helper functions @@ -976,7 +977,7 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) return -ENXIO; /* Get board pointer from our array of majors we have allocated */ - brd = dgnc_BoardsByMajor[major]; + brd = find_board_by_major(major); if (!brd) return -ENXIO; @@ -1172,17 +1173,12 @@ static int dgnc_block_til_ready(struct tty_struct *tty, struct channel_t *ch) { int retval = 0; - struct un_t *un = NULL; + struct un_t *un = tty->driver_data; unsigned long flags; uint old_flags = 0; int sleep_on_un_flags = 0; - if (!tty || tty->magic != TTY_MAGIC || !file || !ch || - ch->magic != DGNC_CHANNEL_MAGIC) - return -ENXIO; - - un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!file) return -ENXIO; spin_lock_irqsave(&ch->ch_lock, flags); @@ -1301,15 +1297,9 @@ static int dgnc_block_til_ready(struct tty_struct *tty, */ static void dgnc_tty_hangup(struct tty_struct *tty) { - struct un_t *un; - if (!tty || tty->magic != TTY_MAGIC) return; - un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) - return; - /* flush the transmit queues */ dgnc_tty_flush_buffer(tty); } @@ -1510,18 +1500,8 @@ static int dgnc_tty_chars_in_buffer(struct tty_struct *tty) * returns the new bytes_available. This only affects printer * output. */ -static int dgnc_maxcps_room(struct tty_struct *tty, int bytes_available) +static int dgnc_maxcps_room(struct channel_t *ch, int bytes_available) { - struct un_t *un = tty->driver_data; - struct channel_t *ch = un->un_ch; - - /* - * If its not the Transparent print device, return - * the full data amount. - */ - if (un->un_type != DGNC_PRINT) - return bytes_available; - if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) { int cps_limit = 0; unsigned long current_time = jiffies; @@ -1585,7 +1565,8 @@ static int dgnc_tty_write_room(struct tty_struct *tty) ret += WQUEUESIZE; /* Limit printer to maxcps */ - ret = dgnc_maxcps_room(tty, ret); + if (un->un_type != DGNC_PRINT) + ret = dgnc_maxcps_room(ch, ret); /* * If we are printer device, leave space for @@ -1677,7 +1658,8 @@ static int dgnc_tty_write(struct tty_struct *tty, * Limit printer output to maxcps overall, with bursts allowed * up to bufsize characters. */ - bufcount = dgnc_maxcps_room(tty, bufcount); + if (un->un_type != DGNC_PRINT) + bufcount = dgnc_maxcps_room(ch, bufcount); /* * Take minimum of what the user wants to send, and the @@ -1984,7 +1966,7 @@ static void dgnc_tty_send_xchar(struct tty_struct *tty, char c) static inline int dgnc_get_mstat(struct channel_t *ch) { unsigned char mstat; - int result = -EIO; + int result = 0; unsigned long flags; if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) @@ -1996,8 +1978,6 @@ static inline int dgnc_get_mstat(struct channel_t *ch) spin_unlock_irqrestore(&ch->ch_lock, flags); - result = 0; - if (mstat & UART_MCR_DTR) result |= TIOCM_DTR; if (mstat & UART_MCR_RTS) @@ -2028,32 +2008,14 @@ static int dgnc_get_modem_info(struct channel_t *ch, * * Set modem signals, called by ld. */ -static int dgnc_set_modem_info(struct tty_struct *tty, +static int dgnc_set_modem_info(struct channel_t *ch, unsigned int command, unsigned int __user *value) { - struct dgnc_board *bd; - struct channel_t *ch; - struct un_t *un; int ret = -ENXIO; unsigned int arg = 0; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) - return ret; - - un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) - return ret; - - ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return ret; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) - return ret; - ret = get_user(arg, value); if (ret) return ret; @@ -2593,9 +2555,8 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long __user *)arg); - return rc; + return put_user(C_CLOCAL(tty) ? 1 : 0, + (unsigned long __user *)arg); case TIOCSSOFTCAR: @@ -2620,7 +2581,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case TIOCMBIC: case TIOCMSET: spin_unlock_irqrestore(&ch->ch_lock, flags); - return dgnc_set_modem_info(tty, cmd, uarg); + return dgnc_set_modem_info(ch, cmd, uarg); /* * Here are any additional ioctl's that we want to implement @@ -2766,8 +2727,8 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case DIGI_GETCUSTOMBAUD: spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = put_user(ch->ch_custom_speed, (unsigned int __user *)arg); - return rc; + return put_user(ch->ch_custom_speed, + (unsigned int __user *)arg); case DIGI_SETCUSTOMBAUD: { @@ -2853,8 +2814,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, events |= (EV_IPU | EV_IPS); spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = put_user(events, (unsigned int __user *)arg); - return rc; + return put_user(events, (unsigned int __user *)arg); } /* diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h index 21d3369b875c..24c9a412211e 100644 --- a/drivers/staging/dgnc/dgnc_tty.h +++ b/drivers/staging/dgnc/dgnc_tty.h @@ -19,12 +19,13 @@ #include "dgnc_driver.h" int dgnc_tty_register(struct dgnc_board *brd); +void dgnc_tty_unregister(struct dgnc_board *brd); int dgnc_tty_preinit(void); int dgnc_tty_init(struct dgnc_board *); void dgnc_tty_post_uninit(void); -void dgnc_tty_uninit(struct dgnc_board *); +void dgnc_cleanup_tty(struct dgnc_board *); void dgnc_input(struct channel_t *ch); void dgnc_carrier(struct channel_t *ch); diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 3b56b2826263..c3e298843b43 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -131,7 +131,6 @@ static void _nbu2ss_dump_register(struct nbu2ss_udc *udc) reg_data = _nbu2ss_readl( (u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i + 12)); dev_dbg(&udc->dev, " %08x\n", (int)reg_data); - } spin_lock(&udc->lock); @@ -478,9 +477,9 @@ static void _nbu2ss_dma_map_single( ) { if (req->req.dma == DMA_ADDR_INVALID) { - if (req->unaligned) + if (req->unaligned) { req->req.dma = ep->phys_buf; - else { + } else { req->req.dma = dma_map_single( udc->gadget.dev.parent, req->req.buf, @@ -1236,9 +1235,9 @@ static int _nbu2ss_start_transfer( req->dma_flag = FALSE; req->div_len = 0; - if (req->req.length == 0) + if (req->req.length == 0) { req->zero = false; - else { + } else { if ((req->req.length % ep->ep.maxpacket) == 0) req->zero = req->req.zero; else @@ -1941,9 +1940,9 @@ static void _nbu2ss_ep_done( if (likely(req->req.status == -EINPROGRESS)) req->req.status = status; - if (ep->stalled) + if (ep->stalled) { _nbu2ss_epn_set_stall(udc, ep); - else { + } else { if (!list_empty(&ep->queue)) _nbu2ss_restert_transfer(ep); } @@ -2264,9 +2263,7 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc) if (udc->udc_enabled) return 0; - /* - Reset - */ + /* Reset */ _nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST)); udelay(EPC_RST_DISABLE_TIME); /* 1us wait */ @@ -2476,8 +2473,9 @@ static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc) _nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW); _nbu2ss_writel(&preg->USB_INT_ENA, 0); status = 0; - } else + } else { status = _nbu2ss_readl(&preg->USB_INT_STA); + } if (status == 0) break; diff --git a/drivers/staging/emxx_udc/emxx_udc.h b/drivers/staging/emxx_udc/emxx_udc.h index 39769e3a801c..789bfb97143c 100644 --- a/drivers/staging/emxx_udc/emxx_udc.h +++ b/drivers/staging/emxx_udc/emxx_udc.h @@ -586,7 +586,7 @@ struct nbu2ss_udc { unsigned remote_wakeup:1; unsigned udc_enabled:1; - unsigned mA; + unsigned int mA; u32 curr_config; /* Current Configuration Number */ diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c index 82b46cd27ca7..7561385761e9 100644 --- a/drivers/staging/fbtft/fb_agm1264k-fl.c +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -350,8 +350,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) } } - /* 1 string = 2 pages */ - for (y = addr_win.ys_page; y <= addr_win.ye_page; ++y) { + /* 1 string = 2 pages */ + for (y = addr_win.ys_page; y <= addr_win.ye_page; ++y) { /* left half of display */ if (addr_win.xs < par->info->var.xres / 2) { construct_line_bitmap(par, buf, convert_buf, diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index 6ff222d6d6d6..278e4c7e95e5 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -29,7 +29,7 @@ #define DEFAULT_GAMMA "07 07 6 0 0 0 5 5 4 0\n" \ "07 08 4 7 5 1 2 0 7 7" -static unsigned read_devicecode(struct fbtft_par *par) +static unsigned int read_devicecode(struct fbtft_par *par) { int ret; u8 rxbuf[8] = {0, }; @@ -41,7 +41,7 @@ static unsigned read_devicecode(struct fbtft_par *par) static int init_display(struct fbtft_par *par) { - unsigned devcode; + unsigned int devcode; par->fbtftops.reset(par); diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index fdf98d37550e..c31e2e051d4a 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -32,26 +32,26 @@ #define DEFAULT_GAMMA "0F 00 7 2 0 0 6 5 4 1\n" \ "04 16 2 7 6 3 2 1 7 7" -static unsigned bt = 6; /* VGL=Vci*4 , VGH=Vci*4 */ +static unsigned int bt = 6; /* VGL=Vci*4 , VGH=Vci*4 */ module_param(bt, uint, 0); MODULE_PARM_DESC(bt, "Sets the factor used in the step-up circuits"); -static unsigned vc = 0x03; /* Vci1=Vci*0.80 */ +static unsigned int vc = 0x03; /* Vci1=Vci*0.80 */ module_param(vc, uint, 0); MODULE_PARM_DESC(vc, "Sets the ratio factor of Vci to generate the reference voltages Vci1"); -static unsigned vrh = 0x0d; /* VREG1OUT=Vci*1.85 */ +static unsigned int vrh = 0x0d; /* VREG1OUT=Vci*1.85 */ module_param(vrh, uint, 0); MODULE_PARM_DESC(vrh, "Set the amplifying rate (1.6 ~ 1.9) of Vci applied to output the VREG1OUT"); -static unsigned vdv = 0x12; /* VCOMH amplitude=VREG1OUT*0.98 */ +static unsigned int vdv = 0x12; /* VCOMH amplitude=VREG1OUT*0.98 */ module_param(vdv, uint, 0); MODULE_PARM_DESC(vdv, "Select the factor of VREG1OUT to set the amplitude of Vcom"); -static unsigned vcm = 0x0a; /* VCOMH=VREG1OUT*0.735 */ +static unsigned int vcm = 0x0a; /* VCOMH=VREG1OUT*0.735 */ module_param(vcm, uint, 0); MODULE_PARM_DESC(vcm, "Set the internal VcomH voltage"); diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index a6b43323f29a..a4710dc067ef 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -32,11 +32,11 @@ #define TXBUFLEN (84 * 6) #define DEFAULT_GAMMA "40" /* gamma controls the contrast in this driver */ -static unsigned tc; +static unsigned int tc; module_param(tc, uint, 0); MODULE_PARM_DESC(tc, "TC[1:0] Temperature coefficient: 0-3 (default: 0)"); -static unsigned bs = 4; +static unsigned int bs = 4; module_param(bs, uint, 0); MODULE_PARM_DESC(bs, "BS[2:0] Bias voltage level: 0-7 (default: 4)"); diff --git a/drivers/staging/fbtft/fb_s6d02a1.c b/drivers/staging/fbtft/fb_s6d02a1.c index 3113355062fc..774b0ff69e6d 100644 --- a/drivers/staging/fbtft/fb_s6d02a1.c +++ b/drivers/staging/fbtft/fb_s6d02a1.c @@ -113,12 +113,14 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) #define MV BIT(5) static int set_var(struct fbtft_par *par) { - /* Memory data access control (0x36h) - RGB/BGR: - 1. Mode selection pin SRGB - RGB H/W pin for color filter setting: 0=RGB, 1=BGR - 2. MADCTL RGB bit - RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + /* + * Memory data access control (0x36h) + * RGB/BGR: + * 1. Mode selection pin SRGB + * RGB H/W pin for color filter setting: 0=RGB, 1=BGR + * 2. MADCTL RGB bit + * RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR + */ switch (par->info->var.rotate) { case 0: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c index d6ae76b318ad..9b1d70b218df 100644 --- a/drivers/staging/fbtft/fb_s6d1121.c +++ b/drivers/staging/fbtft/fb_s6d1121.c @@ -125,10 +125,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1 - PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1 -*/ + * Gamma string format: + * PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1 + * PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1 + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c index 1162c08613fa..25f9fbe1e76f 100644 --- a/drivers/staging/fbtft/fb_ssd1289.c +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -29,7 +29,7 @@ #define DEFAULT_GAMMA "02 03 2 5 7 7 4 2 4 2\n" \ "02 03 2 5 7 5 4 2 4 2" -static unsigned reg11 = 0x6040; +static unsigned int reg11 = 0x6040; module_param(reg11, uint, 0); MODULE_PARM_DESC(reg11, "Register 11h value"); @@ -131,10 +131,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - VRP0 VRP1 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 - VRN0 VRN1 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 -*/ + * Gamma string format: + * VRP0 VRP1 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 + * VRN0 VRN1 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { diff --git a/drivers/staging/fbtft/fb_ssd1306.c b/drivers/staging/fbtft/fb_ssd1306.c index e0b34a42c9c6..80fc57029fee 100644 --- a/drivers/staging/fbtft/fb_ssd1306.c +++ b/drivers/staging/fbtft/fb_ssd1306.c @@ -27,15 +27,15 @@ #define HEIGHT 64 /* - write_reg() caveat: - - This doesn't work because D/C has to be LOW for both values: - write_reg(par, val1, val2); - - Do it like this: - write_reg(par, val1); - write_reg(par, val2); -*/ + * write_reg() caveat: + * + * This doesn't work because D/C has to be LOW for both values: + * write_reg(par, val1, val2); + * + * Do it like this: + * write_reg(par, val1); + * write_reg(par, val2); + */ /* Init sequence taken from the Adafruit SSD1306 Arduino library */ static int init_display(struct fbtft_par *par) @@ -113,8 +113,9 @@ static int init_display(struct fbtft_par *par) write_reg(par, 0xA4); /* Set Normal Display - 0 in RAM: OFF in display panel - 1 in RAM: ON in display panel */ + * 0 in RAM: OFF in display panel + * 1 in RAM: ON in display panel + */ write_reg(par, 0xA6); /* Set Display ON */ diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c index bd294f886c5f..1d74ac1343a8 100644 --- a/drivers/staging/fbtft/fb_ssd1331.c +++ b/drivers/staging/fbtft/fb_ssd1331.c @@ -102,26 +102,26 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) } /* - Grayscale Lookup Table - GS1 - GS63 - The driver Gamma curve contains the relative values between the entries - in the Lookup table. - - From datasheet: - 8.8 Gray Scale Decoder - - there are total 180 Gamma Settings (Setting 0 to Setting 180) - available for the Gray Scale table. - - The gray scale is defined in incremental way, with reference - to the length of previous table entry: - Setting of GS1 has to be >= 0 - Setting of GS2 has to be > Setting of GS1 +1 - Setting of GS3 has to be > Setting of GS2 +1 - : - Setting of GS63 has to be > Setting of GS62 +1 - -*/ + * Grayscale Lookup Table + * GS1 - GS63 + * The driver Gamma curve contains the relative values between the entries + * in the Lookup table. + * + * From datasheet: + * 8.8 Gray Scale Decoder + * + * there are total 180 Gamma Settings (Setting 0 to Setting 180) + * available for the Gray Scale table. + * + * The gray scale is defined in incremental way, with reference + * to the length of previous table entry: + * Setting of GS1 has to be >= 0 + * Setting of GS2 has to be > Setting of GS1 +1 + * Setting of GS3 has to be > Setting of GS2 +1 + * : + * Setting of GS63 has to be > Setting of GS62 +1 + * + */ static int set_gamma(struct fbtft_par *par, unsigned long *curves) { unsigned long tmp[GAMMA_NUM * GAMMA_LEN]; diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c index cef33e439f46..200aa9ba98f9 100644 --- a/drivers/staging/fbtft/fb_ssd1351.c +++ b/drivers/staging/fbtft/fb_ssd1351.c @@ -25,8 +25,8 @@ static void register_onboard_backlight(struct fbtft_par *par); static int init_display(struct fbtft_par *par) { - if (par->pdata - && par->pdata->display.backlight == FBTFT_ONBOARD_BACKLIGHT) { + if (par->pdata && + par->pdata->display.backlight == FBTFT_ONBOARD_BACKLIGHT) { /* module uses onboard GPIO for panel power */ par->fbtftops.register_backlight = register_onboard_backlight; } @@ -66,7 +66,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) static int set_var(struct fbtft_par *par) { - unsigned remap; + unsigned int remap; if (par->fbtftops.init_display != init_display) { /* don't risk messing up register A0h */ @@ -80,10 +80,10 @@ static int set_var(struct fbtft_par *par) switch (par->info->var.rotate) { case 0: - write_reg(par, 0xA0, remap | 0x00 | 1<<4); + write_reg(par, 0xA0, remap | 0x00 | 1 << 4); break; case 270: - write_reg(par, 0xA0, remap | 0x03 | 1<<4); + write_reg(par, 0xA0, remap | 0x03 | 1 << 4); break; case 180: write_reg(par, 0xA0, remap | 0x02); @@ -189,8 +189,8 @@ static int update_onboard_backlight(struct backlight_device *bd) "%s: power=%d, fb_blank=%d\n", __func__, bd->props.power, bd->props.fb_blank); - on = (bd->props.power == FB_BLANK_UNBLANK) - && (bd->props.fb_blank == FB_BLANK_UNBLANK); + on = (bd->props.power == FB_BLANK_UNBLANK) && + (bd->props.fb_blank == FB_BLANK_UNBLANK); /* Onboard backlight connected to GPIO0 on SSD1351, GPIO1 unused */ write_reg(par, 0xB5, on ? 0x03 : 0x02); diff --git a/drivers/staging/fbtft/fb_st7735r.c b/drivers/staging/fbtft/fb_st7735r.c index c5e51fe1aad5..6670f2bb62ec 100644 --- a/drivers/staging/fbtft/fb_st7735r.c +++ b/drivers/staging/fbtft/fb_st7735r.c @@ -33,35 +33,43 @@ static int default_init_sequence[] = { -2, 500, /* delay */ /* FRMCTR1 - frame rate control: normal mode - frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ + * frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) + */ -1, 0xB1, 0x01, 0x2C, 0x2D, /* FRMCTR2 - frame rate control: idle mode - frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ + * frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) + */ -1, 0xB2, 0x01, 0x2C, 0x2D, /* FRMCTR3 - frame rate control - partial mode - dot inversion mode, line inversion mode */ + * dot inversion mode, line inversion mode + */ -1, 0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, /* INVCTR - display inversion control - no inversion */ + * no inversion + */ -1, 0xB4, 0x07, /* PWCTR1 - Power Control - -4.6V, AUTO mode */ + * -4.6V, AUTO mode + */ -1, 0xC0, 0xA2, 0x02, 0x84, /* PWCTR2 - Power Control - VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD */ + * VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD + */ -1, 0xC1, 0xC5, /* PWCTR3 - Power Control - Opamp current small, Boost frequency */ + * Opamp current small, Boost frequency + */ -1, 0xC2, 0x0A, 0x00, /* PWCTR4 - Power Control - BCLK/2, Opamp current small & Medium low */ + * BCLK/2, Opamp current small & Medium low + */ -1, 0xC3, 0x8A, 0x2A, /* PWCTR5 - Power Control */ @@ -101,11 +109,12 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) static int set_var(struct fbtft_par *par) { /* MADCTL - Memory data access control - RGB/BGR: - 1. Mode selection pin SRGB - RGB H/W pin for color filter setting: 0=RGB, 1=BGR - 2. MADCTL RGB bit - RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + * RGB/BGR: + * 1. Mode selection pin SRGB + * RGB H/W pin for color filter setting: 0=RGB, 1=BGR + * 2. MADCTL RGB bit + * RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR + */ switch (par->info->var.rotate) { case 0: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, @@ -129,10 +138,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - VRF0P VOS0P PK0P PK1P PK2P PK3P PK4P PK5P PK6P PK7P PK8P PK9P SELV0P SELV1P SELV62P SELV63P - VRF0N VOS0N PK0N PK1N PK2N PK3N PK4N PK5N PK6N PK7N PK8N PK9N SELV0N SELV1N SELV62N SELV63N -*/ + * Gamma string format: + * VRF0P VOS0P PK0P PK1P PK2P PK3P PK4P PK5P PK6P PK7P PK8P PK9P SELV0P SELV1P SELV62P SELV63P + * VRF0N VOS0N PK0N PK1N PK2N PK3N PK4N PK5N PK6N PK7N PK8N PK9N SELV0N SELV1N SELV62N SELV63N + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { diff --git a/drivers/staging/fbtft/fb_tls8204.c b/drivers/staging/fbtft/fb_tls8204.c index 2183f98c8315..ea2ddacb9468 100644 --- a/drivers/staging/fbtft/fb_tls8204.c +++ b/drivers/staging/fbtft/fb_tls8204.c @@ -35,7 +35,7 @@ /* gamma is used to control contrast in this driver */ #define DEFAULT_GAMMA "40" -static unsigned bs = 4; +static unsigned int bs = 4; module_param(bs, uint, 0); MODULE_PARM_DESC(bs, "BS[2:0] Bias voltage level: 0-7 (default: 4)"); @@ -44,21 +44,21 @@ static int init_display(struct fbtft_par *par) par->fbtftops.reset(par); /* Enter extended command mode */ - write_reg(par, 0x21); /* 5:1 1 - 2:0 PD - Powerdown control: chip is active - 1:0 V - Entry mode: horizontal addressing - 0:1 H - Extended instruction set control: - extended - */ + write_reg(par, 0x21); /* 5:1 1 + * 2:0 PD - Powerdown control: chip is active + * 1:0 V - Entry mode: horizontal addressing + * 0:1 H - Extended instruction set control: + * extended + */ /* H=1 Bias system */ - write_reg(par, 0x10 | (bs & 0x7)); /* - 4:1 1 - 3:0 0 - 2:x BS2 - Bias System - 1:x BS1 - 0:x BS0 - */ + write_reg(par, 0x10 | (bs & 0x7)); + /* 4:1 1 + * 3:0 0 + * 2:x BS2 - Bias System + * 1:x BS1 + * 0:x BS0 + */ /* Set the address of the first display line. */ write_reg(par, 0x04 | (64 >> 6)); @@ -68,12 +68,12 @@ static int init_display(struct fbtft_par *par) write_reg(par, 0x20); /* H=0 Display control */ - write_reg(par, 0x08 | 4); /* - 3:1 1 - 2:1 D - DE: 10=normal mode - 1:0 0 - 0:0 E - */ + write_reg(par, 0x08 | 4); + /* 3:1 1 + * 2:1 D - DE: 10=normal mode + * 1:0 0 + * 0:0 E + */ return 0; } @@ -81,15 +81,15 @@ static int init_display(struct fbtft_par *par) static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) { /* H=0 Set X address of RAM */ - write_reg(par, 0x80); /* 7:1 1 - 6-0: X[6:0] - 0x00 - */ + write_reg(par, 0x80); /* 7:1 1 + * 6-0: X[6:0] - 0x00 + */ /* H=0 Set Y address of RAM */ - write_reg(par, 0x40); /* 7:0 0 - 6:1 1 - 2-0: Y[2:0] - 0x0 - */ + write_reg(par, 0x40); /* 7:0 0 + * 6:1 1 + * 2-0: Y[2:0] - 0x0 + */ } static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) @@ -100,8 +100,9 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) for (y = 0; y < HEIGHT / 8; y++) { u8 *buf = par->txbuf.buf; - /* The display is 102x68 but the LCD is 84x48. Set - the write pointer at the start of each row. */ + /* The display is 102x68 but the LCD is 84x48. + * Set the write pointer at the start of each row. + */ gpio_set_value(par->gpio.dc, 0); write_reg(par, 0x80 | 0); write_reg(par, 0x40 | y); diff --git a/drivers/staging/fbtft/fb_uc1611.c b/drivers/staging/fbtft/fb_uc1611.c index e87401aacfb3..b33b73f17da4 100644 --- a/drivers/staging/fbtft/fb_uc1611.c +++ b/drivers/staging/fbtft/fb_uc1611.c @@ -41,30 +41,30 @@ */ /* BR -> actual ratio: 0-3 -> 5, 10, 11, 13 */ -static unsigned ratio = 2; +static unsigned int ratio = 2; module_param(ratio, uint, 0); MODULE_PARM_DESC(ratio, "BR[1:0] Bias voltage ratio: 0-3 (default: 2)"); -static unsigned gain = 3; +static unsigned int gain = 3; module_param(gain, uint, 0); MODULE_PARM_DESC(gain, "GN[1:0] Bias voltage gain: 0-3 (default: 3)"); -static unsigned pot = 16; +static unsigned int pot = 16; module_param(pot, uint, 0); MODULE_PARM_DESC(pot, "PM[6:0] Bias voltage pot.: 0-63 (default: 16)"); /* TC -> % compensation per deg C: 0-3 -> -.05, -.10, -.015, -.20 */ -static unsigned temp; +static unsigned int temp; module_param(temp, uint, 0); MODULE_PARM_DESC(temp, "TC[1:0] Temperature compensation: 0-3 (default: 0)"); /* PC[1:0] -> LCD capacitance: 0-3 -> <20nF, 20-28 nF, 29-40 nF, 40-56 nF */ -static unsigned load = 1; +static unsigned int load = 1; module_param(load, uint, 0); MODULE_PARM_DESC(load, "PC[1:0] Panel Loading: 0-3 (default: 1)"); /* PC[3:2] -> V_LCD: 0, 1, 3 -> ext., int. with ratio = 5, int. standard */ -static unsigned pump = 3; +static unsigned int pump = 3; module_param(pump, uint, 0); MODULE_PARM_DESC(pump, "PC[3:2] Pump control: 0,1,3 (default: 3)"); diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c index f8cb610a7b69..a52e28a48825 100644 --- a/drivers/staging/fbtft/fb_watterott.c +++ b/drivers/staging/fbtft/fb_watterott.c @@ -67,7 +67,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) { - unsigned start_line, end_line; + unsigned int start_line, end_line; u16 *vmem16 = (u16 *)(par->info->screen_buffer + offset); u16 *pos = par->txbuf.buf + 1; u16 *buf16 = par->txbuf.buf + 10; @@ -104,7 +104,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) static int write_vmem_8bit(struct fbtft_par *par, size_t offset, size_t len) { - unsigned start_line, end_line; + unsigned int start_line, end_line; u16 *vmem16 = (u16 *)(par->info->screen_buffer + offset); u16 *pos = par->txbuf.buf + 1; u8 *buf8 = par->txbuf.buf + 10; @@ -137,7 +137,7 @@ static int write_vmem_8bit(struct fbtft_par *par, size_t offset, size_t len) return 0; } -static unsigned firmware_version(struct fbtft_par *par) +static unsigned int firmware_version(struct fbtft_par *par) { u8 rxbuf[4] = {0, }; @@ -152,7 +152,7 @@ static unsigned firmware_version(struct fbtft_par *par) static int init_display(struct fbtft_par *par) { int ret; - unsigned version; + unsigned int version; u8 save_mode; /* enable SPI interface by having CS and MOSI low during reset */ diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c index 83505bce628a..ec45043c0830 100644 --- a/drivers/staging/fbtft/fbtft-bus.c +++ b/drivers/staging/fbtft/fbtft-bus.c @@ -92,7 +92,8 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...) if (par->spi && (par->spi->bits_per_word == 8)) { /* we're emulating 9-bit, pad start of buffer with no-ops - (assuming here that zero is a no-op) */ + * (assuming here that zero is a no-op) + */ pad = (len % 4) ? 4 - (len % 4) : 0; for (i = 0; i < pad; i++) *buf++ = 0x000; diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 0c1a77cafe14..587f68aa466c 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -341,8 +341,8 @@ static void fbtft_reset(struct fbtft_par *par) mdelay(120); } -static void fbtft_update_display(struct fbtft_par *par, unsigned start_line, - unsigned end_line) +static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line, + unsigned int end_line) { size_t offset, len; ktime_t ts_start, ts_end; @@ -391,11 +391,11 @@ static void fbtft_update_display(struct fbtft_par *par, unsigned start_line, if (unlikely(timeit)) { ts_end = ktime_get(); - if (ktime_to_ns(par->update_time)) + if (!ktime_to_ns(par->update_time)) par->update_time = ts_start; - par->update_time = ts_start; fps = ktime_us_delta(ts_start, par->update_time); + par->update_time = ts_start; fps = fps ? 1000000 / fps : 0; throughput = ktime_us_delta(ts_end, ts_start); @@ -435,10 +435,10 @@ static void fbtft_mkdirty(struct fb_info *info, int y, int height) static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist) { struct fbtft_par *par = info->par; - unsigned dirty_lines_start, dirty_lines_end; + unsigned int dirty_lines_start, dirty_lines_end; struct page *page; unsigned long index; - unsigned y_low = 0, y_high = 0; + unsigned int y_low = 0, y_high = 0; int count = 0; spin_lock(&par->dirty_lock); @@ -526,18 +526,18 @@ static ssize_t fbtft_fb_write(struct fb_info *info, const char __user *buf, } /* from pxafb.c */ -static unsigned int chan_to_field(unsigned chan, struct fb_bitfield *bf) +static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) { chan &= 0xffff; chan >>= 16 - bf->length; return chan << bf->offset; } -static int fbtft_fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, +static int fbtft_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, + unsigned int blue, unsigned int transp, struct fb_info *info) { - unsigned val; + unsigned int val; int ret = 1; dev_dbg(info->dev, @@ -654,11 +654,11 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, u8 *vmem = NULL; void *txbuf = NULL; void *buf = NULL; - unsigned width; - unsigned height; + unsigned int width; + unsigned int height; int txbuflen = display->txbuflen; - unsigned bpp = display->bpp; - unsigned fps = display->fps; + unsigned int bpp = display->bpp; + unsigned int fps = display->fps; int vmem_size, i; int *init_sequence = display->init_sequence; char *gamma = display->gamma; @@ -820,6 +820,8 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, /* Transmit buffer */ if (txbuflen == -1) txbuflen = vmem_size + 2; /* add in case startbyte is used */ + if (txbuflen >= vmem_size + 2) + txbuflen = 0; #ifdef __LITTLE_ENDIAN if ((!txbuflen) && (bpp > 8)) diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h index d3bc3943a983..89c4b5b76ce6 100644 --- a/drivers/staging/fbtft/fbtft.h +++ b/drivers/staging/fbtft/fbtft.h @@ -38,7 +38,7 @@ */ struct fbtft_gpio { char name[FBTFT_GPIO_NAME_SIZE]; - unsigned gpio; + unsigned int gpio; }; struct fbtft_par; @@ -79,7 +79,7 @@ struct fbtft_ops { void (*reset)(struct fbtft_par *par); void (*mkdirty)(struct fb_info *info, int from, int to); void (*update_display)(struct fbtft_par *par, - unsigned start_line, unsigned end_line); + unsigned int start_line, unsigned int end_line); int (*init_display)(struct fbtft_par *par); int (*blank)(struct fbtft_par *par, bool on); @@ -115,14 +115,14 @@ struct fbtft_ops { * This structure is not stored by FBTFT except for init_sequence. */ struct fbtft_display { - unsigned width; - unsigned height; - unsigned regwidth; - unsigned buswidth; - unsigned backlight; + unsigned int width; + unsigned int height; + unsigned int regwidth; + unsigned int buswidth; + unsigned int backlight; struct fbtft_ops fbtftops; - unsigned bpp; - unsigned fps; + unsigned int bpp; + unsigned int fps; int txbuflen; int *init_sequence; char *gamma; @@ -146,9 +146,9 @@ struct fbtft_display { struct fbtft_platform_data { struct fbtft_display display; const struct fbtft_gpio *gpios; - unsigned rotate; + unsigned int rotate; bool bgr; - unsigned fps; + unsigned int fps; int txbuflen; u8 startbyte; char *gamma; @@ -216,8 +216,8 @@ struct fbtft_par { u8 startbyte; struct fbtft_ops fbtftops; spinlock_t dirty_lock; - unsigned dirty_lines_start; - unsigned dirty_lines_end; + unsigned int dirty_lines_start; + unsigned int dirty_lines_end; struct { int reset; int dc; diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c index e4a355aefb25..e9211831b6a1 100644 --- a/drivers/staging/fbtft/fbtft_device.c +++ b/drivers/staging/fbtft/fbtft_device.c @@ -32,20 +32,20 @@ static char *name; module_param(name, charp, 0); MODULE_PARM_DESC(name, "Devicename (required). name=list => list all supported devices."); -static unsigned rotate; +static unsigned int rotate; module_param(rotate, uint, 0); MODULE_PARM_DESC(rotate, "Angle to rotate display counter clockwise: 0, 90, 180, 270"); -static unsigned busnum; +static unsigned int busnum; module_param(busnum, uint, 0); MODULE_PARM_DESC(busnum, "SPI bus number (default=0)"); -static unsigned cs; +static unsigned int cs; module_param(cs, uint, 0); MODULE_PARM_DESC(cs, "SPI chip select (default=0)"); -static unsigned speed; +static unsigned int speed; module_param(speed, uint, 0); MODULE_PARM_DESC(speed, "SPI speed (override device default)"); @@ -58,7 +58,7 @@ module_param(gpios, charp, 0); MODULE_PARM_DESC(gpios, "List of gpios. Comma separated with the form: reset:23,dc:24 (when overriding the default, all gpios must be specified)"); -static unsigned fps; +static unsigned int fps; module_param(fps, uint, 0); MODULE_PARM_DESC(fps, "Frames per second (override driver default)"); @@ -76,7 +76,7 @@ module_param(bgr, int, 0); MODULE_PARM_DESC(bgr, "BGR bit (supported by some drivers)."); -static unsigned startbyte; +static unsigned int startbyte; module_param(startbyte, uint, 0); MODULE_PARM_DESC(startbyte, "Sets the Start byte used by some SPI displays."); @@ -84,15 +84,15 @@ static bool custom; module_param(custom, bool, 0); MODULE_PARM_DESC(custom, "Add a custom display device. Use speed= argument to make it a SPI device, else platform_device"); -static unsigned width; +static unsigned int width; module_param(width, uint, 0); MODULE_PARM_DESC(width, "Display width, used with the custom argument"); -static unsigned height; +static unsigned int height; module_param(height, uint, 0); MODULE_PARM_DESC(height, "Display height, used with the custom argument"); -static unsigned buswidth = 8; +static unsigned int buswidth = 8; module_param(buswidth, uint, 0); MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument"); @@ -106,7 +106,7 @@ module_param(debug, ulong, 0); MODULE_PARM_DESC(debug, "level: 0-7 (the remaining 29 bits is for advanced usage)"); -static unsigned verbose = 3; +static unsigned int verbose = 3; module_param(verbose, uint, 0); MODULE_PARM_DESC(verbose, "0 silent, >0 show gpios, >1 show devices, >2 show devices before (default=3)"); @@ -1215,7 +1215,8 @@ static struct fbtft_device_display displays[] = { } }, { /* This should be the last item. - Used with the custom argument */ + * Used with the custom argument + */ .name = "", .spi = &(struct spi_board_info) { .modalias = "", @@ -1306,8 +1307,9 @@ static struct fbtft_gpio fbtft_device_param_gpios[MAX_GPIOS + 1] = { }; static void fbtft_device_pdev_release(struct device *dev) { /* Needed to silence this message: -Device 'xxx' does not have a release() function, it is broken and must be fixed -*/ + * Device 'xxx' does not have a release() function, + * it is broken and must be fixed + */ } static int spi_device_found(struct device *dev, void *data) @@ -1346,7 +1348,7 @@ static void pr_p_devices(void) } #ifdef MODULE -static void fbtft_device_spi_delete(struct spi_master *master, unsigned cs) +static void fbtft_device_spi_delete(struct spi_master *master, unsigned int cs) { struct device *dev; char str[32]; @@ -1399,7 +1401,7 @@ static int __init fbtft_device_init(void) long val; int ret = 0; - if (name == NULL) { + if (!name) { #ifdef MODULE pr_err("missing module parameter: 'name'\n"); return -EINVAL; @@ -1416,14 +1418,14 @@ static int __init fbtft_device_init(void) /* parse module parameter: gpios */ while ((p_gpio = strsep(&gpios, ","))) { - if (strchr(p_gpio, ':') == NULL) { + if (!strchr(p_gpio, ':')) { pr_err("error: missing ':' in gpios parameter: %s\n", p_gpio); return -EINVAL; } p_num = p_gpio; p_name = strsep(&p_num, ":"); - if (p_name == NULL || p_num == NULL) { + if (!p_name || !p_num) { pr_err("something bad happened parsing gpios parameter: %s\n", p_gpio); return -EINVAL; diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index e7315170b7a3..38716fd5cb58 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -7,13 +7,14 @@ # obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o -mc-bus-driver-objs := mc-bus.o \ +mc-bus-driver-objs := fsl-mc-bus.o \ mc-sys.o \ + mc-io.o \ dprc.o \ dpmng.o \ dprc-driver.o \ - mc-allocator.o \ - mc-msi.o \ + fsl-mc-allocator.o \ + fsl-mc-msi.o \ irq-gic-v3-its-fsl-mc-msi.o \ dpmcp.o \ dpbp.o diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index fe271fbd629b..5d4cd812a400 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -1,34 +1,34 @@ /* Copyright 2013-2016 Freescale Semiconductor Inc. -* -* 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 the above-listed copyright holders nor the -* names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* -* ALTERNATIVELY, this software may be distributed under the terms of the -* GNU General Public License ("GPL") as published by the Free Software -* Foundation, either version 2 of that License or (at your option) any -* later version. -* -* 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 HOLDERS 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. -*/ + * + * 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 the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS 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. + */ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dpbp.h" diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c index 06440176243a..55766f78a528 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.c +++ b/drivers/staging/fsl-mc/bus/dpmcp.c @@ -31,6 +31,7 @@ */ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" + #include "dpmcp.h" #include "dpmcp-cmd.h" @@ -368,7 +369,6 @@ int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, struct mc_command cmd = { 0 }; struct dpmcp_cmd_set_irq_mask *cmd_params; - /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK, cmd_flags, token); diff --git a/drivers/staging/fsl-mc/bus/dpmng-cmd.h b/drivers/staging/fsl-mc/bus/dpmng-cmd.h index 779bf9c25bc0..a7b77d58c8cd 100644 --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpmng-cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,12 +31,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/*************************************************************************//* - dpmng-cmd.h - - defines portal commands - - *//**************************************************************************/ +/* + * dpmng-cmd.h + * + * defines portal commands + * + */ #ifndef __FSL_DPMNG_CMD_H #define __FSL_DPMNG_CMD_H diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/staging/fsl-mc/bus/dpmng.c index 660bbe7ea899..96b1d67756fa 100644 --- a/drivers/staging/fsl-mc/bus/dpmng.c +++ b/drivers/staging/fsl-mc/bus/dpmng.c @@ -1,37 +1,38 @@ /* Copyright 2013-2016 Freescale Semiconductor Inc. -* -* 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 the above-listed copyright holders nor the -* names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* -* ALTERNATIVELY, this software may be distributed under the terms of the -* GNU General Public License ("GPL") as published by the Free Software -* Foundation, either version 2 of that License or (at your option) any -* later version. -* -* 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 HOLDERS 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. -*/ + * + * 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 the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS 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. + */ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dpmng.h" + #include "dpmng-cmd.h" /** diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h index bb127f4a3ae7..009d65673155 100644 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h +++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,12 +31,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/*************************************************************************//* - dprc-cmd.h - - defines dprc portal commands - - *//**************************************************************************/ +/* + * dprc-cmd.h + * + * defines dprc portal commands + * + */ #ifndef _FSL_DPRC_CMD_H #define _FSL_DPRC_CMD_H diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index d2a71f14bf72..c5ee4639682b 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -9,13 +9,21 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" -#include "../include/mc-sys.h" #include #include #include #include +#include "../include/mc-bus.h" +#include "../include/mc-sys.h" + #include "dprc-cmd.h" +#include "fsl-mc-private.h" + +#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" + +#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \ + (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ + (_mc_dev)->obj_desc.id == (_obj_desc)->id) struct dprc_child_objs { int child_count; @@ -190,55 +198,6 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, } } -static void dprc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) -{ - int pool_type; - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); - - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { - struct fsl_mc_resource_pool *res_pool = - &mc_bus->resource_pools[pool_type]; - - res_pool->type = pool_type; - res_pool->max_count = 0; - res_pool->free_count = 0; - res_pool->mc_bus = mc_bus; - INIT_LIST_HEAD(&res_pool->free_list); - mutex_init(&res_pool->mutex); - } -} - -static void dprc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, - enum fsl_mc_pool_type pool_type) -{ - struct fsl_mc_resource *resource; - struct fsl_mc_resource *next; - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); - struct fsl_mc_resource_pool *res_pool = - &mc_bus->resource_pools[pool_type]; - int free_count = 0; - - WARN_ON(res_pool->type != pool_type); - WARN_ON(res_pool->free_count != res_pool->max_count); - - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { - free_count++; - WARN_ON(resource->type != res_pool->type); - WARN_ON(resource->parent_pool != res_pool); - devm_kfree(&mc_bus_dev->dev, resource); - } - - WARN_ON(free_count != res_pool->free_count); -} - -static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) -{ - int pool_type; - - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) - dprc_cleanup_resource_pool(mc_bus_dev, pool_type); -} - /** * dprc_scan_objects - Discover objects in a DPRC * @@ -363,7 +322,7 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) unsigned int irq_count; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); - dprc_init_all_resource_pools(mc_bus_dev); + fsl_mc_init_all_resource_pools(mc_bus_dev); /* * Discover objects in the DPRC: @@ -390,7 +349,7 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) return 0; error: - dprc_cleanup_all_resource_pools(mc_bus_dev); + fsl_mc_cleanup_all_resource_pools(mc_bus_dev); return error; } EXPORT_SYMBOL_GPL(dprc_scan_container); @@ -649,7 +608,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) /* * This is a child DPRC: */ - if (WARN_ON(parent_dev->bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(parent_dev))) return -EINVAL; if (WARN_ON(mc_dev->obj_desc.region_count == 0)) @@ -681,7 +640,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) */ struct irq_domain *mc_msi_domain; - if (WARN_ON(parent_dev->bus == &fsl_mc_bus_type)) + if (WARN_ON(dev_is_fsl_mc(parent_dev))) return -EINVAL; error = fsl_mc_find_msi_domain(parent_dev, @@ -802,7 +761,7 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) dev_set_msi_domain(&mc_dev->dev, NULL); } - dprc_cleanup_all_resource_pools(mc_dev); + fsl_mc_cleanup_all_resource_pools(mc_dev); error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); if (error < 0) diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index c26054981333..9fea3def6041 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -1,37 +1,38 @@ /* Copyright 2013-2016 Freescale Semiconductor Inc. -* -* 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 the above-listed copyright holders nor the -* names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* -* ALTERNATIVELY, this software may be distributed under the terms of the -* GNU General Public License ("GPL") as published by the Free Software -* Foundation, either version 2 of that License or (at your option) any -* later version. -* -* 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 HOLDERS 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. -*/ + * + * 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 the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS 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. + */ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dprc.h" + #include "dprc-cmd.h" /** @@ -1334,20 +1335,20 @@ int dprc_disconnect(struct fsl_mc_io *mc_io, } /** -* dprc_get_connection() - Get connected endpoint and link status if connection -* exists. -* @mc_io: Pointer to MC portal's I/O object -* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -* @token: Token of DPRC object -* @endpoint1: Endpoint 1 configuration parameters -* @endpoint2: Returned endpoint 2 configuration parameters -* @state: Returned link state: -* 1 - link is up; -* 0 - link is down; -* -1 - no connection (endpoint2 information is irrelevant) -* -* Return: '0' on Success; -ENAVAIL if connection does not exist. -*/ + * dprc_get_connection() - Get connected endpoint and link status if connection + * exists. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPRC object + * @endpoint1: Endpoint 1 configuration parameters + * @endpoint2: Returned endpoint 2 configuration parameters + * @state: Returned link state: + * 1 - link is up; + * 0 - link is down; + * -1 - no connection (endpoint2 information is irrelevant) + * + * Return: '0' on Success; -ENAVAIL if connection does not exist. + */ int dprc_get_connection(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c similarity index 79% rename from drivers/staging/fsl-mc/bus/mc-allocator.c rename to drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index e59d85060c7b..e93ab53bae67 100644 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -8,14 +8,19 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" -#include "../include/mc-sys.h" #include +#include +#include "../include/mc-bus.h" +#include "../include/mc-sys.h" #include "../include/dpbp-cmd.h" #include "../include/dpcon-cmd.h" -#include "dpmcp-cmd.h" -#include "dpmcp.h" -#include + +#include "fsl-mc-private.h" + +#define FSL_MC_IS_ALLOCATABLE(_obj_type) \ + (strcmp(_obj_type, "dpbp") == 0 || \ + strcmp(_obj_type, "dpmcp") == 0 || \ + strcmp(_obj_type, "dpcon") == 0) /** * fsl_mc_resource_pool_add_device - add allocatable device to a resource @@ -137,8 +142,7 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device goto out_unlock; } - list_del(&resource->node); - INIT_LIST_HEAD(&resource->node); + list_del_init(&resource->node); res_pool->free_count--; res_pool->max_count--; @@ -215,8 +219,7 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, res_pool->free_count > res_pool->max_count)) goto out_unlock; - list_del(&resource->node); - INIT_LIST_HEAD(&resource->node); + list_del_init(&resource->node); res_pool->free_count--; error = 0; @@ -251,144 +254,6 @@ out_unlock: } EXPORT_SYMBOL_GPL(fsl_mc_resource_free); -/** - * fsl_mc_portal_allocate - Allocates an MC portal - * - * @mc_dev: MC device for which the MC portal is to be allocated - * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated - * MC portal. - * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object - * that wraps the allocated MC portal is to be returned - * - * This function allocates an MC portal from the device's parent DPRC, - * from the corresponding MC bus' pool of MC portals and wraps - * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the - * portal is allocated from its own MC bus. - */ -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, - u16 mc_io_flags, - struct fsl_mc_io **new_mc_io) -{ - struct fsl_mc_device *mc_bus_dev; - struct fsl_mc_bus *mc_bus; - phys_addr_t mc_portal_phys_addr; - size_t mc_portal_size; - struct fsl_mc_device *dpmcp_dev; - int error = -EINVAL; - struct fsl_mc_resource *resource = NULL; - struct fsl_mc_io *mc_io = NULL; - - if (mc_dev->flags & FSL_MC_IS_DPRC) { - mc_bus_dev = mc_dev; - } else { - if (WARN_ON(mc_dev->dev.parent->bus != &fsl_mc_bus_type)) - return error; - - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - } - - mc_bus = to_fsl_mc_bus(mc_bus_dev); - *new_mc_io = NULL; - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); - if (error < 0) - return error; - - error = -EINVAL; - dpmcp_dev = resource->data; - if (WARN_ON(!dpmcp_dev)) - goto error_cleanup_resource; - - if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || - (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && - dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { - dev_err(&dpmcp_dev->dev, - "ERROR: Version %d.%d of DPMCP not supported.\n", - dpmcp_dev->obj_desc.ver_major, - dpmcp_dev->obj_desc.ver_minor); - error = -ENOTSUPP; - goto error_cleanup_resource; - } - - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) - goto error_cleanup_resource; - - mc_portal_phys_addr = dpmcp_dev->regions[0].start; - mc_portal_size = dpmcp_dev->regions[0].end - - dpmcp_dev->regions[0].start + 1; - - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) - goto error_cleanup_resource; - - error = fsl_create_mc_io(&mc_bus_dev->dev, - mc_portal_phys_addr, - mc_portal_size, dpmcp_dev, - mc_io_flags, &mc_io); - if (error < 0) - goto error_cleanup_resource; - - *new_mc_io = mc_io; - return 0; - -error_cleanup_resource: - fsl_mc_resource_free(resource); - return error; -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); - -/** - * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals - * of a given MC bus - * - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free - */ -void fsl_mc_portal_free(struct fsl_mc_io *mc_io) -{ - struct fsl_mc_device *dpmcp_dev; - struct fsl_mc_resource *resource; - - /* - * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed - * to have a DPMCP object associated with. - */ - dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return; - - resource = dpmcp_dev->resource; - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) - return; - - if (WARN_ON(resource->data != dpmcp_dev)) - return; - - fsl_destroy_mc_io(mc_io); - fsl_mc_resource_free(resource); -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_free); - -/** - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object - * - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free - */ -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) -{ - int error; - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - - if (WARN_ON(!dpmcp_dev)) - return -EINVAL; - - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); - if (error < 0) { - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); - return error; - } - - return 0; -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); - /** * fsl_mc_object_allocate - Allocates a MC object device of the given * pool type from a given MC bus @@ -420,7 +285,7 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) goto error; - if (WARN_ON(mc_dev->dev.parent->bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) goto error; if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) @@ -663,6 +528,55 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) } EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) +{ + int pool_type; + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); + + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[pool_type]; + + res_pool->type = pool_type; + res_pool->max_count = 0; + res_pool->free_count = 0; + res_pool->mc_bus = mc_bus; + INIT_LIST_HEAD(&res_pool->free_list); + mutex_init(&res_pool->mutex); + } +} + +static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, + enum fsl_mc_pool_type pool_type) +{ + struct fsl_mc_resource *resource; + struct fsl_mc_resource *next; + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[pool_type]; + int free_count = 0; + + WARN_ON(res_pool->type != pool_type); + WARN_ON(res_pool->free_count != res_pool->max_count); + + list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { + free_count++; + WARN_ON(resource->type != res_pool->type); + WARN_ON(resource->parent_pool != res_pool); + devm_kfree(&mc_bus_dev->dev, resource); + } + + WARN_ON(free_count != res_pool->free_count); +} + +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) +{ + int pool_type; + + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) + fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); +} + /** * fsl_mc_allocator_probe - callback invoked when an allocatable device is * being added to the system @@ -678,7 +592,7 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) return -EINVAL; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - if (WARN_ON(mc_bus_dev->dev.bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) return -EINVAL; mc_bus = to_fsl_mc_bus(mc_bus_dev); @@ -736,7 +650,6 @@ static const struct fsl_mc_device_id match_id_table[] = { static struct fsl_mc_driver fsl_mc_allocator_driver = { .driver = { .name = "fsl_mc_allocator", - .owner = THIS_MODULE, .pm = NULL, }, .match_id_table = match_id_table, diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c similarity index 93% rename from drivers/staging/fsl-mc/bus/mc-bus.c rename to drivers/staging/fsl-mc/bus/fsl-mc-bus.c index db3afdbdf4ae..44f64b6f0fc9 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -9,7 +9,6 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" #include #include #include @@ -18,12 +17,49 @@ #include #include #include +#include +#include "../include/mc-bus.h" #include "../include/dpmng.h" #include "../include/mc-sys.h" + +#include "fsl-mc-private.h" #include "dprc-cmd.h" static struct kmem_cache *mc_dev_cache; +/** + * Default DMA mask for devices on a fsl-mc bus + */ +#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) + +/** + * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device + * @root_mc_bus_dev: MC object device representing the root DPRC + * @num_translation_ranges: number of entries in addr_translation_ranges + * @translation_ranges: array of bus to system address translation ranges + */ +struct fsl_mc { + struct fsl_mc_device *root_mc_bus_dev; + u8 num_translation_ranges; + struct fsl_mc_addr_translation_range *translation_ranges; +}; + +/** + * struct fsl_mc_addr_translation_range - bus to system address translation + * range + * @mc_region_type: Type of MC region for the range being translated + * @start_mc_offset: Start MC offset of the range being translated + * @end_mc_offset: MC offset of the first byte after the range (last MC + * offset of the range is end_mc_offset - 1) + * @start_phys_addr: system physical address corresponding to start_mc_addr + */ +struct fsl_mc_addr_translation_range { + enum dprc_region_type mc_region_type; + u64 start_mc_offset; + u64 end_mc_offset; + phys_addr_t start_phys_addr; +}; + /** * fsl_mc_bus_match - device to driver matching callback * @dev: the MC object device structure to match against @@ -101,14 +137,7 @@ static struct attribute *fsl_mc_dev_attrs[] = { NULL, }; -static const struct attribute_group fsl_mc_dev_group = { - .attrs = fsl_mc_dev_attrs, -}; - -static const struct attribute_group *fsl_mc_dev_groups[] = { - &fsl_mc_dev_group, - NULL, -}; +ATTRIBUTE_GROUPS(fsl_mc_dev); struct bus_type fsl_mc_bus_type = { .name = "fsl-mc", @@ -229,21 +258,22 @@ bool fsl_mc_bus_exists(void) EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); /** -* fsl_mc_get_root_dprc - function to traverse to the root dprc -*/ -static void fsl_mc_get_root_dprc(struct device *dev, - struct device **root_dprc_dev) + * fsl_mc_get_root_dprc - function to traverse to the root dprc + */ +void fsl_mc_get_root_dprc(struct device *dev, + struct device **root_dprc_dev) { if (WARN_ON(!dev)) { *root_dprc_dev = NULL; - } else if (WARN_ON(dev->bus != &fsl_mc_bus_type)) { + } else if (WARN_ON(!dev_is_fsl_mc(dev))) { *root_dprc_dev = NULL; } else { *root_dprc_dev = dev; - while ((*root_dprc_dev)->parent->bus == &fsl_mc_bus_type) + while (dev_is_fsl_mc((*root_dprc_dev)->parent)) *root_dprc_dev = (*root_dprc_dev)->parent; } } +EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc); static int get_dprc_attr(struct fsl_mc_io *mc_io, int container_id, struct dprc_attributes *attr) @@ -434,7 +464,7 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, struct fsl_mc_bus *mc_bus = NULL; struct fsl_mc_device *parent_mc_dev; - if (parent_dev->bus == &fsl_mc_bus_type) + if (dev_is_fsl_mc(parent_dev)) parent_mc_dev = to_fsl_mc_device(parent_dev); else parent_mc_dev = NULL; @@ -887,25 +917,4 @@ error_cleanup_cache: kmem_cache_destroy(mc_dev_cache); return error; } - postcore_initcall(fsl_mc_bus_driver_init); - -static void __exit fsl_mc_bus_driver_exit(void) -{ - if (WARN_ON(!mc_dev_cache)) - return; - - its_fsl_mc_msi_cleanup(); - fsl_mc_allocator_driver_exit(); - dprc_driver_exit(); - platform_driver_unregister(&fsl_mc_bus_driver); - bus_unregister(&fsl_mc_bus_type); - kmem_cache_destroy(mc_dev_cache); - pr_info("MC bus unregistered\n"); -} - -module_exit(fsl_mc_bus_driver_exit); - -MODULE_AUTHOR("Freescale Semiconductor Inc."); -MODULE_DESCRIPTION("Freescale Management Complex (MC) bus driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c similarity index 97% rename from drivers/staging/fsl-mc/bus/mc-msi.c rename to drivers/staging/fsl-mc/bus/fsl-mc-msi.c index 4fd8e41ef468..3d46b1b1fa18 100644 --- a/drivers/staging/fsl-mc/bus/mc-msi.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -9,7 +9,6 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" #include #include #include @@ -17,8 +16,7 @@ #include #include #include -#include "../include/mc-sys.h" -#include "dprc-cmd.h" +#include "../include/mc-bus.h" /* * Generate a unique ID identifying the interrupt (only used within the MSI @@ -52,7 +50,7 @@ static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) /* * set_desc should not be set by the caller */ - if (ops->set_desc == NULL) + if (!ops->set_desc) ops->set_desc = fsl_mc_msi_set_desc; } @@ -142,7 +140,7 @@ static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) /* * irq_write_msi_msg should not be set by the caller */ - if (chip->irq_write_msi_msg == NULL) + if (!chip->irq_write_msi_msg) chip->irq_write_msi_msg = fsl_mc_msi_write_msg; } diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-private.h b/drivers/staging/fsl-mc/bus/fsl-mc-private.h new file mode 100644 index 000000000000..d459c2673f39 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/fsl-mc-private.h @@ -0,0 +1,52 @@ +/* + * Freescale Management Complex (MC) bus private declarations + * + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#ifndef _FSL_MC_PRIVATE_H_ +#define _FSL_MC_PRIVATE_H_ + +int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, + struct fsl_mc_io *mc_io, + struct device *parent_dev, + struct fsl_mc_device **new_mc_dev); + +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); + +int __init dprc_driver_init(void); + +void dprc_driver_exit(void); + +int __init fsl_mc_allocator_driver_init(void); + +void fsl_mc_allocator_driver_exit(void); + +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, + enum fsl_mc_pool_type pool_type, + struct fsl_mc_resource + **new_resource); + +void fsl_mc_resource_free(struct fsl_mc_resource *resource); + +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, + unsigned int irq_count); + +void fsl_mc_msi_domain_free_irqs(struct device *dev); + +int __init its_fsl_mc_msi_init(void); + +void its_fsl_mc_msi_cleanup(void); + +int __must_check fsl_create_mc_io(struct device *dev, + phys_addr_t mc_portal_phys_addr, + u32 mc_portal_size, + struct fsl_mc_device *dpmcp_dev, + u32 flags, struct fsl_mc_io **new_mc_io); + +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); + +#endif /* _FSL_MC_PRIVATE_H_ */ diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index 720e2b018d00..7a6ac640752f 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -9,7 +9,6 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" #include #include #include @@ -17,8 +16,7 @@ #include #include #include -#include "../include/mc-sys.h" -#include "dprc-cmd.h" +#include "../include/mc-bus.h" static struct irq_chip its_msi_irq_chip = { .name = "fsl-mc-bus-msi", @@ -35,7 +33,7 @@ static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, struct fsl_mc_device *mc_bus_dev; struct msi_domain_info *msi_info; - if (WARN_ON(dev->bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(dev))) return -EINVAL; mc_bus_dev = to_fsl_mc_device(dev); diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c new file mode 100644 index 000000000000..798c965fe203 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -0,0 +1,320 @@ +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * + * 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 the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS 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. + */ + +#include +#include "../include/mc-bus.h" +#include "../include/mc-sys.h" + +#include "fsl-mc-private.h" +#include "dpmcp.h" +#include "dpmcp-cmd.h" + +static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, + struct fsl_mc_device *dpmcp_dev) +{ + int error; + + if (WARN_ON(!dpmcp_dev)) + return -EINVAL; + + if (WARN_ON(mc_io->dpmcp_dev)) + return -EINVAL; + + if (WARN_ON(dpmcp_dev->mc_io)) + return -EINVAL; + + error = dpmcp_open(mc_io, + 0, + dpmcp_dev->obj_desc.id, + &dpmcp_dev->mc_handle); + if (error < 0) + return error; + + mc_io->dpmcp_dev = dpmcp_dev; + dpmcp_dev->mc_io = mc_io; + return 0; +} + +static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) +{ + int error; + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (WARN_ON(!dpmcp_dev)) + return; + + if (WARN_ON(dpmcp_dev->mc_io != mc_io)) + return; + + error = dpmcp_close(mc_io, + 0, + dpmcp_dev->mc_handle); + if (error < 0) { + dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", + error); + } + + mc_io->dpmcp_dev = NULL; + dpmcp_dev->mc_io = NULL; +} + +/** + * Creates an MC I/O object + * + * @dev: device to be associated with the MC I/O object + * @mc_portal_phys_addr: physical address of the MC portal to use + * @mc_portal_size: size in bytes of the MC portal + * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O + * object or NULL if none. + * @flags: flags for the new MC I/O object + * @new_mc_io: Area to return pointer to newly created MC I/O object + * + * Returns '0' on Success; Error code otherwise. + */ +int __must_check fsl_create_mc_io(struct device *dev, + phys_addr_t mc_portal_phys_addr, + u32 mc_portal_size, + struct fsl_mc_device *dpmcp_dev, + u32 flags, struct fsl_mc_io **new_mc_io) +{ + int error; + struct fsl_mc_io *mc_io; + void __iomem *mc_portal_virt_addr; + struct resource *res; + + mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); + if (!mc_io) + return -ENOMEM; + + mc_io->dev = dev; + mc_io->flags = flags; + mc_io->portal_phys_addr = mc_portal_phys_addr; + mc_io->portal_size = mc_portal_size; + if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) + spin_lock_init(&mc_io->spinlock); + else + mutex_init(&mc_io->mutex); + + res = devm_request_mem_region(dev, + mc_portal_phys_addr, + mc_portal_size, + "mc_portal"); + if (!res) { + dev_err(dev, + "devm_request_mem_region failed for MC portal %#llx\n", + mc_portal_phys_addr); + return -EBUSY; + } + + mc_portal_virt_addr = devm_ioremap_nocache(dev, + mc_portal_phys_addr, + mc_portal_size); + if (!mc_portal_virt_addr) { + dev_err(dev, + "devm_ioremap_nocache failed for MC portal %#llx\n", + mc_portal_phys_addr); + return -ENXIO; + } + + mc_io->portal_virt_addr = mc_portal_virt_addr; + if (dpmcp_dev) { + error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); + if (error < 0) + goto error_destroy_mc_io; + } + + *new_mc_io = mc_io; + return 0; + +error_destroy_mc_io: + fsl_destroy_mc_io(mc_io); + return error; +} + +/** + * Destroys an MC I/O object + * + * @mc_io: MC I/O object to destroy + */ +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) +{ + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (dpmcp_dev) + fsl_mc_io_unset_dpmcp(mc_io); + + devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); + devm_release_mem_region(mc_io->dev, + mc_io->portal_phys_addr, + mc_io->portal_size); + + mc_io->portal_virt_addr = NULL; + devm_kfree(mc_io->dev, mc_io); +} + +/** + * fsl_mc_portal_allocate - Allocates an MC portal + * + * @mc_dev: MC device for which the MC portal is to be allocated + * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated + * MC portal. + * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object + * that wraps the allocated MC portal is to be returned + * + * This function allocates an MC portal from the device's parent DPRC, + * from the corresponding MC bus' pool of MC portals and wraps + * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the + * portal is allocated from its own MC bus. + */ +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, + u16 mc_io_flags, + struct fsl_mc_io **new_mc_io) +{ + struct fsl_mc_device *mc_bus_dev; + struct fsl_mc_bus *mc_bus; + phys_addr_t mc_portal_phys_addr; + size_t mc_portal_size; + struct fsl_mc_device *dpmcp_dev; + int error = -EINVAL; + struct fsl_mc_resource *resource = NULL; + struct fsl_mc_io *mc_io = NULL; + + if (mc_dev->flags & FSL_MC_IS_DPRC) { + mc_bus_dev = mc_dev; + } else { + if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) + return error; + + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); + } + + mc_bus = to_fsl_mc_bus(mc_bus_dev); + *new_mc_io = NULL; + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); + if (error < 0) + return error; + + error = -EINVAL; + dpmcp_dev = resource->data; + if (WARN_ON(!dpmcp_dev)) + goto error_cleanup_resource; + + if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || + (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && + dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { + dev_err(&dpmcp_dev->dev, + "ERROR: Version %d.%d of DPMCP not supported.\n", + dpmcp_dev->obj_desc.ver_major, + dpmcp_dev->obj_desc.ver_minor); + error = -ENOTSUPP; + goto error_cleanup_resource; + } + + if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) + goto error_cleanup_resource; + + mc_portal_phys_addr = dpmcp_dev->regions[0].start; + mc_portal_size = dpmcp_dev->regions[0].end - + dpmcp_dev->regions[0].start + 1; + + if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) + goto error_cleanup_resource; + + error = fsl_create_mc_io(&mc_bus_dev->dev, + mc_portal_phys_addr, + mc_portal_size, dpmcp_dev, + mc_io_flags, &mc_io); + if (error < 0) + goto error_cleanup_resource; + + *new_mc_io = mc_io; + return 0; + +error_cleanup_resource: + fsl_mc_resource_free(resource); + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); + +/** + * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals + * of a given MC bus + * + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free + */ +void fsl_mc_portal_free(struct fsl_mc_io *mc_io) +{ + struct fsl_mc_device *dpmcp_dev; + struct fsl_mc_resource *resource; + + /* + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed + * to have a DPMCP object associated with. + */ + dpmcp_dev = mc_io->dpmcp_dev; + if (WARN_ON(!dpmcp_dev)) + return; + + resource = dpmcp_dev->resource; + if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) + return; + + if (WARN_ON(resource->data != dpmcp_dev)) + return; + + fsl_destroy_mc_io(mc_io); + fsl_mc_resource_free(resource); +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_free); + +/** + * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object + * + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free + */ +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) +{ + int error; + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (WARN_ON(!dpmcp_dev)) + return -EINVAL; + + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); + if (error < 0) { + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); + return error; + } + + return 0; +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 0c185abe665e..285917c7c8e4 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -32,13 +32,15 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/mc-sys.h" -#include "../include/mc-cmd.h" -#include "../include/mc.h" #include #include #include #include +#include +#include "../include/mc-sys.h" +#include "../include/mc-cmd.h" +#include "../include/mc.h" + #include "dpmcp.h" /** @@ -68,153 +70,6 @@ static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd) return (cmd_id & MC_CMD_HDR_CMDID_MASK) >> MC_CMD_HDR_CMDID_SHIFT; } -/** - * Creates an MC I/O object - * - * @dev: device to be associated with the MC I/O object - * @mc_portal_phys_addr: physical address of the MC portal to use - * @mc_portal_size: size in bytes of the MC portal - * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O - * object or NULL if none. - * @flags: flags for the new MC I/O object - * @new_mc_io: Area to return pointer to newly created MC I/O object - * - * Returns '0' on Success; Error code otherwise. - */ -int __must_check fsl_create_mc_io(struct device *dev, - phys_addr_t mc_portal_phys_addr, - u32 mc_portal_size, - struct fsl_mc_device *dpmcp_dev, - u32 flags, struct fsl_mc_io **new_mc_io) -{ - int error; - struct fsl_mc_io *mc_io; - void __iomem *mc_portal_virt_addr; - struct resource *res; - - mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); - if (!mc_io) - return -ENOMEM; - - mc_io->dev = dev; - mc_io->flags = flags; - mc_io->portal_phys_addr = mc_portal_phys_addr; - mc_io->portal_size = mc_portal_size; - if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) - spin_lock_init(&mc_io->spinlock); - else - mutex_init(&mc_io->mutex); - - res = devm_request_mem_region(dev, - mc_portal_phys_addr, - mc_portal_size, - "mc_portal"); - if (!res) { - dev_err(dev, - "devm_request_mem_region failed for MC portal %#llx\n", - mc_portal_phys_addr); - return -EBUSY; - } - - mc_portal_virt_addr = devm_ioremap_nocache(dev, - mc_portal_phys_addr, - mc_portal_size); - if (!mc_portal_virt_addr) { - dev_err(dev, - "devm_ioremap_nocache failed for MC portal %#llx\n", - mc_portal_phys_addr); - return -ENXIO; - } - - mc_io->portal_virt_addr = mc_portal_virt_addr; - if (dpmcp_dev) { - error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); - if (error < 0) - goto error_destroy_mc_io; - } - - *new_mc_io = mc_io; - return 0; - -error_destroy_mc_io: - fsl_destroy_mc_io(mc_io); - return error; -} -EXPORT_SYMBOL_GPL(fsl_create_mc_io); - -/** - * Destroys an MC I/O object - * - * @mc_io: MC I/O object to destroy - */ -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) -{ - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - - if (dpmcp_dev) - fsl_mc_io_unset_dpmcp(mc_io); - - devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); - devm_release_mem_region(mc_io->dev, - mc_io->portal_phys_addr, - mc_io->portal_size); - - mc_io->portal_virt_addr = NULL; - devm_kfree(mc_io->dev, mc_io); -} -EXPORT_SYMBOL_GPL(fsl_destroy_mc_io); - -int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, - struct fsl_mc_device *dpmcp_dev) -{ - int error; - - if (WARN_ON(!dpmcp_dev)) - return -EINVAL; - - if (WARN_ON(mc_io->dpmcp_dev)) - return -EINVAL; - - if (WARN_ON(dpmcp_dev->mc_io)) - return -EINVAL; - - error = dpmcp_open(mc_io, - 0, - dpmcp_dev->obj_desc.id, - &dpmcp_dev->mc_handle); - if (error < 0) - return error; - - mc_io->dpmcp_dev = dpmcp_dev; - dpmcp_dev->mc_io = mc_io; - return 0; -} -EXPORT_SYMBOL_GPL(fsl_mc_io_set_dpmcp); - -void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) -{ - int error; - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - - if (WARN_ON(!dpmcp_dev)) - return; - - if (WARN_ON(dpmcp_dev->mc_io != mc_io)) - return; - - error = dpmcp_close(mc_io, - 0, - dpmcp_dev->mc_handle); - if (error < 0) { - dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", - error); - } - - mc_io->dpmcp_dev = NULL; - dpmcp_dev->mc_io = NULL; -} -EXPORT_SYMBOL_GPL(fsl_mc_io_unset_dpmcp); - static int mc_status_to_error(enum mc_cmd_status status) { static const int mc_status_to_error_map[] = { diff --git a/drivers/staging/fsl-mc/include/dpbp-cmd.h b/drivers/staging/fsl-mc/include/dpbp-cmd.h index 4828ccd0cffd..2860411ddb51 100644 --- a/drivers/staging/fsl-mc/include/dpbp-cmd.h +++ b/drivers/staging/fsl-mc/include/dpbp-cmd.h @@ -1,34 +1,34 @@ /* Copyright 2013-2016 Freescale Semiconductor Inc. -* -* 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 the above-listed copyright holders nor the -* names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* -* ALTERNATIVELY, this software may be distributed under the terms of the -* GNU General Public License ("GPL") as published by the Free Software -* Foundation, either version 2 of that License or (at your option) any -* later version. -* -* 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 HOLDERS 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. -*/ + * + * 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 the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _FSL_DPBP_CMD_H #define _FSL_DPBP_CMD_H diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-bus.h similarity index 53% rename from drivers/staging/fsl-mc/include/mc-private.h rename to drivers/staging/fsl-mc/include/mc-bus.h index cab1ae90f09e..170684a57ca2 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -1,5 +1,5 @@ /* - * Freescale Management Complex (MC) bus private declarations + * Freescale Management Complex (MC) bus declarations * * Copyright (C) 2014 Freescale Semiconductor, Inc. * Author: German Rivera @@ -8,23 +8,11 @@ * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ -#ifndef _FSL_MC_PRIVATE_H_ -#define _FSL_MC_PRIVATE_H_ +#ifndef _FSL_MC_MCBUS_H_ +#define _FSL_MC_MCBUS_H_ #include "../include/mc.h" #include -#include - -#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" - -#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \ - (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ - (_mc_dev)->obj_desc.id == (_obj_desc)->id) - -#define FSL_MC_IS_ALLOCATABLE(_obj_type) \ - (strcmp(_obj_type, "dpbp") == 0 || \ - strcmp(_obj_type, "dpmcp") == 0 || \ - strcmp(_obj_type, "dpcon") == 0) struct irq_domain; struct msi_domain_info; @@ -35,37 +23,12 @@ struct msi_domain_info; */ #define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 -struct device_node; -struct irq_domain; -struct msi_domain_info; - -/** - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device - * @root_mc_bus_dev: MC object device representing the root DPRC - * @num_translation_ranges: number of entries in addr_translation_ranges - * @translation_ranges: array of bus to system address translation ranges - */ -struct fsl_mc { - struct fsl_mc_device *root_mc_bus_dev; - u8 num_translation_ranges; - struct fsl_mc_addr_translation_range *translation_ranges; -}; - -/** - * struct fsl_mc_addr_translation_range - bus to system address translation - * range - * @mc_region_type: Type of MC region for the range being translated - * @start_mc_offset: Start MC offset of the range being translated - * @end_mc_offset: MC offset of the first byte after the range (last MC - * offset of the range is end_mc_offset - 1) - * @start_phys_addr: system physical address corresponding to start_mc_addr - */ -struct fsl_mc_addr_translation_range { - enum dprc_region_type mc_region_type; - u64 start_mc_offset; - u64 end_mc_offset; - phys_addr_t start_phys_addr; -}; +#ifdef CONFIG_FSL_MC_BUS +#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) +#else +/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ +#define dev_is_fsl_mc(_dev) (0) +#endif /** * struct fsl_mc_resource_pool - Pool of MC resources of a given @@ -107,13 +70,6 @@ struct fsl_mc_bus { #define to_fsl_mc_bus(_mc_dev) \ container_of(_mc_dev, struct fsl_mc_bus, mc_dev) -int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, - struct fsl_mc_io *mc_io, - struct device *parent_dev, - struct fsl_mc_device **new_mc_dev); - -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); - int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, @@ -127,13 +83,6 @@ int __init fsl_mc_allocator_driver_init(void); void fsl_mc_allocator_driver_exit(void); -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, - enum fsl_mc_pool_type pool_type, - struct fsl_mc_resource - **new_resource); - -void fsl_mc_resource_free(struct fsl_mc_resource *resource); - struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent); @@ -141,18 +90,22 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, int fsl_mc_find_msi_domain(struct device *mc_platform_dev, struct irq_domain **mc_msi_domain); -int fsl_mc_msi_domain_alloc_irqs(struct device *dev, - unsigned int irq_count); - -void fsl_mc_msi_domain_free_irqs(struct device *dev); - -int __init its_fsl_mc_msi_init(void); - -void its_fsl_mc_msi_cleanup(void); - int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, unsigned int irq_count); void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); -#endif /* _FSL_MC_PRIVATE_H_ */ +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); + +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); + +bool fsl_mc_bus_exists(void); + +void fsl_mc_get_root_dprc(struct device *dev, + struct device **root_dprc_dev); + +bool fsl_mc_is_root_dprc(struct device *dev); + +extern struct bus_type fsl_mc_bus_type; + +#endif /* _FSL_MC_MCBUS_H_ */ diff --git a/drivers/staging/fsl-mc/include/mc-sys.h b/drivers/staging/fsl-mc/include/mc-sys.h index c5038cc77240..89ad0cf54702 100644 --- a/drivers/staging/fsl-mc/include/mc-sys.h +++ b/drivers/staging/fsl-mc/include/mc-sys.h @@ -37,8 +37,6 @@ #include #include -#include -#include #include #include @@ -95,19 +93,6 @@ struct fsl_mc_io { }; }; -int __must_check fsl_create_mc_io(struct device *dev, - phys_addr_t mc_portal_phys_addr, - u32 mc_portal_size, - struct fsl_mc_device *dpmcp_dev, - u32 flags, struct fsl_mc_io **new_mc_io); - -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); - -int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, - struct fsl_mc_device *dpmcp_dev); - -void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io); - int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd); #endif /* _FSL_MC_SYS_H */ diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index 853cbf38a400..f6e720e84460 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -13,7 +13,6 @@ #include #include -#include #include #include "../include/dprc.h" @@ -21,7 +20,6 @@ struct fsl_mc_device; struct fsl_mc_io; -struct fsl_mc_bus; /** * struct fsl_mc_driver - MC object device driver object @@ -111,11 +109,6 @@ struct fsl_mc_device_irq { */ #define FSL_MC_IS_DPRC 0x0001 -/** - * Default DMA mask for devices on a fsl-mc bus - */ -#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) - /** * struct fsl_mc_device - MC object device object * @dev: Linux driver model device object @@ -187,8 +180,6 @@ int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver, void fsl_mc_driver_unregister(struct fsl_mc_driver *driver); -bool fsl_mc_bus_exists(void); - int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, u16 mc_io_flags, struct fsl_mc_io **new_mc_io); @@ -207,8 +198,4 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); -bool fsl_mc_is_root_dprc(struct device *dev); - -extern struct bus_type fsl_mc_bus_type; - #endif /* _FSL_MC_H_ */ diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index c241c0ae3f20..49c718b91e55 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -39,9 +39,9 @@ static int num_ttys = 4; /* # of std ttys to create per fw_card */ static bool auto_connect = true; /* try to VIRT_CABLE to every peer */ static bool create_loop_dev = true; /* create a loopback device for each card */ -module_param_named(ttys, num_ttys, int, S_IRUGO | S_IWUSR); -module_param_named(auto, auto_connect, bool, S_IRUGO | S_IWUSR); -module_param_named(loop, create_loop_dev, bool, S_IRUGO | S_IWUSR); +module_param_named(ttys, num_ttys, int, 0644); +module_param_named(auto, auto_connect, bool, 0644); +module_param_named(loop, create_loop_dev, bool, 0644); /* * Threshold below which the tty is woken for writing diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index bb552193e4ba..e72dfa9699f3 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -828,7 +828,7 @@ void start_rx_proc(struct phy_dev *phy_dev) rx_complete, phy_dev, USB_COMPLETE); } -static struct net_device_ops gdm_netdev_ops = { +static const struct net_device_ops gdm_netdev_ops = { .ndo_open = gdm_lte_open, .ndo_stop = gdm_lte_close, .ndo_set_config = gdm_lte_set_config, diff --git a/drivers/staging/gdm724x/gdm_mux.h b/drivers/staging/gdm724x/gdm_mux.h index 3d50383c6ced..0871b8feec55 100644 --- a/drivers/staging/gdm724x/gdm_mux.h +++ b/drivers/staging/gdm724x/gdm_mux.h @@ -27,8 +27,8 @@ #define START_FLAG 0xA512485A #define MUX_HEADER_SIZE 14 -#define MUX_TX_MAX_SIZE (1024*10) -#define MUX_RX_MAX_SIZE (1024*30) +#define MUX_TX_MAX_SIZE (1024 * 10) +#define MUX_RX_MAX_SIZE (1024 * 30) #define AT_PKT_TYPE 0xF011 #define DM_PKT_TYPE 0xF010 diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c index eb7e2523c354..ae396638f897 100644 --- a/drivers/staging/gdm724x/gdm_tty.c +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -225,7 +225,6 @@ int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device) int j; for (i = 0; i < TTY_MAX_COUNT; i++) { - gdm = kmalloc(sizeof(*gdm), GFP_KERNEL); if (!gdm) return -ENOMEM; diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index d650d772095b..15a7e81ec2d2 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -415,10 +415,10 @@ static void do_rx(struct work_struct *work) switch (cmd_evt) { case LTE_GET_INFORMATION_RESULT: if (set_mac_address(hci->data, r->cb_data) == 0) { - ret = r->callback(r->cb_data, - r->buf, - r->urb->actual_length, - KERNEL_THREAD); + r->callback(r->cb_data, + r->buf, + r->urb->actual_length, + KERNEL_THREAD); } break; diff --git a/drivers/staging/gdm724x/gdm_usb.h b/drivers/staging/gdm724x/gdm_usb.h index e6486e71a428..ffb3d995097d 100644 --- a/drivers/staging/gdm724x/gdm_usb.h +++ b/drivers/staging/gdm724x/gdm_usb.h @@ -26,10 +26,10 @@ #define PM_SUSPEND 1 #define AUTO_SUSPEND_TIMER 5000 /* ms */ -#define RX_BUF_SIZE (1024*32) -#define TX_BUF_SIZE (1024*32) +#define RX_BUF_SIZE (1024 * 32) +#define TX_BUF_SIZE (1024 * 32) #define SDU_BUF_SIZE 2048 -#define MAX_SDU_SIZE (1024*30) +#define MAX_SDU_SIZE (1024 * 30) #define MAX_PACKET_IN_MULTI_SDU 256 #define VID_GCT 0x1076 diff --git a/drivers/staging/gdm724x/hci_packet.h b/drivers/staging/gdm724x/hci_packet.h index dbc4446cf78d..4644f84038c9 100644 --- a/drivers/staging/gdm724x/hci_packet.h +++ b/drivers/staging/gdm724x/hci_packet.h @@ -89,5 +89,4 @@ struct hci_connect_ind { u32 connect; } __packed; - #endif /* _HCI_PACKET_H_ */ diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c index a0232e8aec10..abe242505882 100644 --- a/drivers/staging/gdm724x/netlink_k.c +++ b/drivers/staging/gdm724x/netlink_k.c @@ -14,6 +14,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -21,13 +22,7 @@ #include "netlink_k.h" -#if defined(DEFINE_MUTEX) static DEFINE_MUTEX(netlink_mutex); -#else -static struct semaphore netlink_mutex; -#define mutex_lock(x) down(x) -#define mutex_unlock(x) up(x) -#endif #define ND_MAX_GROUP 30 #define ND_IFINDEX_LEN sizeof(int) @@ -96,10 +91,6 @@ struct sock *netlink_init(int unit, .input = netlink_rcv, }; -#if !defined(DEFINE_MUTEX) - init_MUTEX(&netlink_mutex); -#endif - sock = netlink_kernel_create(&init_net, unit, &cfg); if (sock) diff --git a/drivers/staging/greybus/Documentation/firmware/authenticate.c b/drivers/staging/greybus/Documentation/firmware/authenticate.c new file mode 100644 index 000000000000..ab0688ad1e37 --- /dev/null +++ b/drivers/staging/greybus/Documentation/firmware/authenticate.c @@ -0,0 +1,139 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include "../../greybus_authentication.h" + +struct cap_ioc_get_endpoint_uid uid; +struct cap_ioc_get_ims_certificate cert = { + .certificate_class = 0, + .certificate_id = 0, +}; + +struct cap_ioc_authenticate authenticate = { + .auth_type = 0, + .challenge = {0}, +}; + +int main(int argc, char *argv[]) +{ + unsigned int timeout = 10000; + char *capdev; + int fd, ret; + + /* Make sure arguments are correct */ + if (argc != 2) { + printf("\nUsage: ./firmware \n"); + return 0; + } + + capdev = argv[1]; + + printf("Opening %s authentication device\n", capdev); + + fd = open(capdev, O_RDWR); + if (fd < 0) { + printf("Failed to open: %s\n", capdev); + return -1; + } + + /* Get UID */ + printf("Get UID\n"); + + ret = ioctl(fd, CAP_IOC_GET_ENDPOINT_UID, &uid); + if (ret < 0) { + printf("Failed to get UID: %s (%d)\n", capdev, ret); + ret = -1; + goto close_fd; + } + + printf("UID received: 0x%llx\n", *(long long unsigned int *)(uid.uid)); + + /* Get certificate */ + printf("Get IMS certificate\n"); + + ret = ioctl(fd, CAP_IOC_GET_IMS_CERTIFICATE, &cert); + if (ret < 0) { + printf("Failed to get IMS certificate: %s (%d)\n", capdev, ret); + ret = -1; + goto close_fd; + } + + printf("IMS Certificate size: %d\n", cert.cert_size); + + /* Authenticate */ + printf("Authenticate module\n"); + + memcpy(authenticate.uid, uid.uid, 8); + + ret = ioctl(fd, CAP_IOC_AUTHENTICATE, &authenticate); + if (ret < 0) { + printf("Failed to authenticate module: %s (%d)\n", capdev, ret); + ret = -1; + goto close_fd; + } + + printf("Authenticated, result (%02x), sig-size (%02x)\n", + authenticate.result_code, authenticate.signature_size); + +close_fd: + close(fd); + + return ret; +} diff --git a/drivers/staging/greybus/Documentation/firmware/firmware-management b/drivers/staging/greybus/Documentation/firmware/firmware-management new file mode 100644 index 000000000000..7918257e5b3b --- /dev/null +++ b/drivers/staging/greybus/Documentation/firmware/firmware-management @@ -0,0 +1,333 @@ + +Firmware Management +------------------- + Copyright 2016 Google Inc. + Copyright 2016 Linaro Ltd. + +Interface-Manifest +------------------ + +All firmware packages on the Modules or Interfaces are managed by a special +Firmware Management Protocol. To support Firmware Management by the AP, the +Interface Manifest shall at least contain the Firmware Management Bundle and a +Firmware Management Protocol CPort within it. + +The bundle may contain additional CPorts based on the extra functionality +required to manage firmware packages. + +For example, this is how the Firmware Management part of the Interface Manifest +may look like: + + ; Firmware Management Bundle (Bundle 1): + [bundle-descriptor 1] + class = 0x16 + + ; (Mandatory) Firmware Management Protocol on CPort 1 + [cport-descriptor 2] + bundle = 1 + protocol = 0x18 + + ; (Optional) Firmware Download Protocol on CPort 2 + [cport-descriptor 1] + bundle = 1 + protocol = 0x17 + + ; (Optional) SPI protocol on CPort 3 + [cport-descriptor 3] + bundle = 1 + protocol = 0x0b + + ; (Optional) Component Authentication Protocol (CAP) on CPort 4 + [cport-descriptor 4] + bundle = 1 + protocol = 0x19 + + +Sysfs Interfaces - Firmware Management +-------------------------------------- + +The Firmware Management Protocol interacts with Userspace using the character +device interface. The character device will be present in /dev/ directory +and will be named gb-fw-mgmt-. The number is assigned at runtime. + +Identifying the Character Device +================================ + +There can be multiple devices present in /dev/ directory with name gb-fw-mgmt-N +and user first needs to identify the character device used for +firmware-management for a particular interface. + +The Firmware Management core creates a device of class 'gb_fw_mgmt', which shall +be used by the user to identify the right character device for it. The class +device is created within the Bundle directory for a particular Interface. + +For example this is how the class-device can be present: + +/sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/gb_fw_mgmt/gb-fw-mgmt-0 + +The last name in this path: gb-fw-mgmt-0 is precisely the name of the char +device and so the device in this case will be: + +/dev/gb-fw-mgmt-0. + +Operations on the Char device +============================= + +The Character device (gb-fw-mgmt-0 in example) can be opened by the userspace +application and it can perform various 'ioctl' operations on the device. The +device doesn't support any read/write operations. + +Following are the IOCTLs and their data structures available to the user: + +/* IOCTL support */ +#define GB_FW_LOAD_METHOD_UNIPRO 0x01 +#define GB_FW_LOAD_METHOD_INTERNAL 0x02 + +#define GB_FW_LOAD_STATUS_FAILED 0x00 +#define GB_FW_LOAD_STATUS_UNVALIDATED 0x01 +#define GB_FW_LOAD_STATUS_VALIDATED 0x02 +#define GB_FW_LOAD_STATUS_VALIDATION_FAILED 0x03 + +#define GB_FW_BACKEND_FW_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FIND 0x02 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 +#define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 +#define GB_FW_BACKEND_FW_STATUS_INT 0x05 +#define GB_FW_BACKEND_FW_STATUS_RETRY 0x06 +#define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 + +#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 +#define GB_FW_BACKEND_VERSION_STATUS_RETRY 0x04 +#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT 0x05 + + +struct fw_mgmt_ioc_get_intf_version { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; + __u16 major; + __u16 minor; +} __attribute__ ((__packed__)); + +struct fw_mgmt_ioc_get_backend_version { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; + __u16 major; + __u16 minor; + __u8 status; +} __attribute__ ((__packed__)); + +struct fw_mgmt_ioc_intf_load_and_validate { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; + __u8 load_method; + __u8 status; + __u16 major; + __u16 minor; +} __packed; + +struct fw_mgmt_ioc_backend_fw_update { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; + __u8 status; +} __packed; + +#define FW_MGMT_IOCTL_BASE 'S' +#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_intf_version) +#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_backend_version) +#define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate) +#define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update) +#define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int) +#define FW_MGMT_IOC_MODE_SWITCH _IO(FW_MGMT_IOCTL_BASE, 5) + +1. FW_MGMT_IOC_GET_INTF_FW: + + This ioctl shall be used by the user to get the version and firmware-tag of + the currently running Interface Firmware. All the fields of the 'struct + fw_mgmt_ioc_get_fw' are filled by the kernel. + +2. FW_MGMT_IOC_GET_BACKEND_FW: + + This ioctl shall be used by the user to get the version of a currently + running Backend Interface Firmware identified by a firmware-tag. The user is + required to fill the 'firmware_tag' field of the 'struct fw_mgmt_ioc_get_fw' + in this case. The 'major' and 'minor' fields are set by the kernel in + response. + +3. FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE: + + This ioctl shall be used by the user to load an Interface Firmware package on + an Interface. The user needs to fill the 'firmware_tag' and 'load_method' + fields of the 'struct fw_mgmt_ioc_intf_load_and_validate'. The 'status', + 'major' and 'minor' fields are set by the kernel in response. + +4. FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE: + + This ioctl shall be used by the user to request an Interface to update a + Backend Interface Firmware. The user is required to fill the 'firmware_tag' + field of the 'struct fw_mgmt_ioc_get_fw' in this case. The 'status' field is + set by the kernel in response. + +5. FW_MGMT_IOC_SET_TIMEOUT_MS: + + This ioctl shall be used by the user to increase the timeout interval within + which the firmware must get loaded by the Module. The default timeout is 1 + second. The user needs to pass the timeout in milliseconds. + +6. FW_MGMT_IOC_MODE_SWITCH: + + This ioctl shall be used by the user to mode-switch the module to the + previously loaded interface firmware. If the interface firmware isn't loaded + previously, or if another unsuccessful FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE + operation is started after loading interface firmware, then the firmware core + wouldn't allow mode-switch. + + +Sysfs Interfaces - Authentication +--------------------------------- + +The Component Authentication Protocol interacts with Userspace using the +character device interface. The character device will be present in /dev/ +directory and will be named gb-authenticate-. The number is assigned at +runtime. + +Identifying the Character Device +================================ + +There can be multiple devices present in /dev/ directory with name +gb-authenticate-N and user first needs to identify the character device used for +authentication a of particular interface. + +The Authentication core creates a device of class 'gb_authenticate', which shall +be used by the user to identify the right character device for it. The class +device is created within the Bundle directory for a particular Interface. + +For example this is how the class-device can be present: + +/sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/gb_authenticate/gb-authenticate-0 + +The last name in this path: gb-authenticate-0 is precisely the name of the char +device and so the device in this case will be: + +/dev/gb-authenticate-0. + +Operations on the Char device +============================= + +The Character device (/dev/gb-authenticate-0 in above example) can be opened by +the userspace application and it can perform various 'ioctl' operations on the +device. The device doesn't support any read/write operations. + +Following are the IOCTLs and their data structures available to the user: + +#define CAP_CERTIFICATE_MAX_SIZE 1600 +#define CAP_SIGNATURE_MAX_SIZE 320 + +/* Certificate class types */ +#define CAP_CERT_IMS_EAPC 0x00000001 +#define CAP_CERT_IMS_EASC 0x00000002 +#define CAP_CERT_IMS_EARC 0x00000003 +#define CAP_CERT_IMS_IAPC 0x00000004 +#define CAP_CERT_IMS_IASC 0x00000005 +#define CAP_CERT_IMS_IARC 0x00000006 + +/* IMS Certificate response result codes */ +#define CAP_IMS_RESULT_CERT_FOUND 0x00 +#define CAP_IMS_RESULT_CERT_CLASS_INVAL 0x01 +#define CAP_IMS_RESULT_CERT_CORRUPT 0x02 +#define CAP_IMS_RESULT_CERT_NOT_FOUND 0x03 + +/* Authentication types */ +#define CAP_AUTH_IMS_PRI 0x00000001 +#define CAP_AUTH_IMS_SEC 0x00000002 +#define CAP_AUTH_IMS_RSA 0x00000003 + +/* Authenticate response result codes */ +#define CAP_AUTH_RESULT_CR_SUCCESS 0x00 +#define CAP_AUTH_RESULT_CR_BAD_TYPE 0x01 +#define CAP_AUTH_RESULT_CR_WRONG_EP 0x02 +#define CAP_AUTH_RESULT_CR_NO_KEY 0x03 +#define CAP_AUTH_RESULT_CR_SIG_FAIL 0x04 + + +/* IOCTL support */ +struct cap_ioc_get_endpoint_uid { + __u8 uid[8]; +} __attribute__ ((__packed__)); + +struct cap_ioc_get_ims_certificate { + __u32 certificate_class; + __u32 certificate_id; + + __u8 result_code; + __u32 cert_size; + __u8 certificate[CAP_CERTIFICATE_MAX_SIZE]; +} __attribute__ ((__packed__)); + +struct cap_ioc_authenticate { + __u32 auth_type; + __u8 uid[8]; + __u8 challenge[32]; + + __u8 result_code; + __u8 response[64]; + __u32 signature_size; + __u8 signature[CAP_SIGNATURE_MAX_SIZE]; +} __attribute__ ((__packed__)); + +#define CAP_IOCTL_BASE 'C' +#define CAP_IOC_GET_ENDPOINT_UID _IOR(CAP_IOCTL_BASE, 0, struct cap_ioc_get_endpoint_uid) +#define CAP_IOC_GET_IMS_CERTIFICATE _IOWR(CAP_IOCTL_BASE, 1, struct cap_ioc_get_ims_certificate) +#define CAP_IOC_AUTHENTICATE _IOWR(CAP_IOCTL_BASE, 2, struct cap_ioc_authenticate) + + +1. CAP_IOC_GET_ENDPOINT_UID: + + This ioctl shall be used by the user to get the endpoint UID associated with + the Interface. All the fields of the 'struct cap_ioc_get_endpoint_uid' are + filled by the kernel. + +2. CAP_IOC_GET_IMS_CERTIFICATE: + + This ioctl shall be used by the user to retrieve one of the available + cryptographic certificates held by the Interface for use in Component + Authentication. The user is required to fill the 'certificate_class' and + 'certificate_id' field of the 'struct cap_ioc_get_ims_certificate' in this + case. The other fields will be set by the kernel in response. The first + 'cert_size' bytes of the 'certificate' shall be read by the user and others + must be discarded. + +3. CAP_IOC_AUTHENTICATE: + + This ioctl shall be used by the user to authenticate the Module attached to + an Interface. The user needs to fill the 'auth_type', 'uid', and 'challenge' + fields of the 'struct cap_ioc_authenticate'. The other fields will be set by + the kernel in response. The first 'signature_size' bytes of the 'signature' + shall be read by the user and others must be discarded. + + +Sysfs Interfaces - Firmware Download +------------------------------------ + +The Firmware Download Protocol uses the existing Linux Kernel's Firmware class +and the interface provided to userspace are described in: +Documentation/firmware_class/. + + +Sysfs Interfaces - SPI Flash +---------------------------- + +The SPI flash is exposed in userspace as a MTD device and is created +within the Bundle directory. For example, this is how the path may look like: + +$ ls /sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/spi_master/spi32766/spi32766.0/mtd +mtd0 mtd0ro + + +Sample Applications +------------------- + +The current directory also provides a firmware.c test application, which can be +referenced while developing userspace application to talk to firmware-management +protocol. + +The current directory also provides a authenticate.c test application, which can +be referenced while developing userspace application to talk to +component authentication protocol. diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c new file mode 100644 index 000000000000..ff9382401030 --- /dev/null +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -0,0 +1,262 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include "../../greybus_firmware.h" + +#define FW_DEV_DEFAULT "/dev/gb-fw-mgmt-0" +#define FW_TAG_INT_DEFAULT "s3f" +#define FW_TAG_BCND_DEFAULT "bf_01" +#define FW_UPDATE_TYPE_DEFAULT 0 +#define FW_TIMEOUT_DEFAULT 10000; + +static const char *firmware_tag; +static const char *fwdev = FW_DEV_DEFAULT; +static int fw_update_type = FW_UPDATE_TYPE_DEFAULT; +static int fw_timeout = FW_TIMEOUT_DEFAULT; + +static struct fw_mgmt_ioc_get_intf_version intf_fw_info; +static struct fw_mgmt_ioc_get_backend_version backend_fw_info; +static struct fw_mgmt_ioc_intf_load_and_validate intf_load; +static struct fw_mgmt_ioc_backend_fw_update backend_update; + +static void usage(void) +{ + printf("\nUsage: ./firmware (default: \"s3f\"/\"bf_01\") \n"); +} + +static int update_intf_firmware(int fd) +{ + int ret; + + /* Get Interface Firmware Version */ + printf("Get Interface Firmware Version\n"); + + ret = ioctl(fd, FW_MGMT_IOC_GET_INTF_FW, &intf_fw_info); + if (ret < 0) { + printf("Failed to get interface firmware version: %s (%d)\n", + fwdev, ret); + return -1; + } + + printf("Interface Firmware tag (%s), major (%d), minor (%d)\n", + intf_fw_info.firmware_tag, intf_fw_info.major, + intf_fw_info.minor); + + /* Try Interface Firmware load over Unipro */ + printf("Loading Interface Firmware\n"); + + intf_load.load_method = GB_FW_U_LOAD_METHOD_UNIPRO; + intf_load.status = 0; + intf_load.major = 0; + intf_load.minor = 0; + + strncpy((char *)&intf_load.firmware_tag, firmware_tag, + GB_FIRMWARE_U_TAG_MAX_SIZE); + + ret = ioctl(fd, FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE, &intf_load); + if (ret < 0) { + printf("Failed to load interface firmware: %s (%d)\n", fwdev, + ret); + return -1; + } + + if (intf_load.status != GB_FW_U_LOAD_STATUS_VALIDATED && + intf_load.status != GB_FW_U_LOAD_STATUS_UNVALIDATED) { + printf("Load status says loading failed: %d\n", + intf_load.status); + return -1; + } + + printf("Interface Firmware (%s) Load done: major: %d, minor: %d, status: %d\n", + firmware_tag, intf_load.major, intf_load.minor, + intf_load.status); + + /* Initiate Mode-switch to the newly loaded firmware */ + printf("Initiate Mode switch\n"); + + ret = ioctl(fd, FW_MGMT_IOC_MODE_SWITCH); + if (ret < 0) + printf("Failed to initiate mode-switch (%d)\n", ret); + + return ret; +} + +static int update_backend_firmware(int fd) +{ + int ret; + + /* Get Backend Firmware Version */ + printf("Getting Backend Firmware Version\n"); + + strncpy((char *)&backend_fw_info.firmware_tag, firmware_tag, + GB_FIRMWARE_U_TAG_MAX_SIZE); + +retry_fw_version: + ret = ioctl(fd, FW_MGMT_IOC_GET_BACKEND_FW, &backend_fw_info); + if (ret < 0) { + printf("Failed to get backend firmware version: %s (%d)\n", + fwdev, ret); + return -1; + } + + printf("Backend Firmware tag (%s), major (%d), minor (%d), status (%d)\n", + backend_fw_info.firmware_tag, backend_fw_info.major, + backend_fw_info.minor, backend_fw_info.status); + + if (backend_fw_info.status == GB_FW_U_BACKEND_VERSION_STATUS_RETRY) + goto retry_fw_version; + + if ((backend_fw_info.status != GB_FW_U_BACKEND_VERSION_STATUS_SUCCESS) + && (backend_fw_info.status != GB_FW_U_BACKEND_VERSION_STATUS_NOT_AVAILABLE)) { + printf("Failed to get backend firmware version: %s (%d)\n", + fwdev, backend_fw_info.status); + return -1; + } + + /* Try Backend Firmware Update over Unipro */ + printf("Updating Backend Firmware\n"); + + strncpy((char *)&backend_update.firmware_tag, firmware_tag, + GB_FIRMWARE_U_TAG_MAX_SIZE); + +retry_fw_update: + backend_update.status = 0; + + ret = ioctl(fd, FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE, &backend_update); + if (ret < 0) { + printf("Failed to load backend firmware: %s (%d)\n", fwdev, ret); + return -1; + } + + if (backend_update.status == GB_FW_U_BACKEND_FW_STATUS_RETRY) { + printf("Retrying firmware update: %d\n", backend_update.status); + goto retry_fw_update; + } + + if (backend_update.status != GB_FW_U_BACKEND_FW_STATUS_SUCCESS) { + printf("Load status says loading failed: %d\n", + backend_update.status); + } else { + printf("Backend Firmware (%s) Load done: status: %d\n", + firmware_tag, backend_update.status); + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + int fd, ret; + + if (argc > 1 && + (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) { + usage(); + return -1; + } + + if (argc > 1) + fwdev = argv[1]; + + if (argc > 2) + sscanf(argv[2], "%u", &fw_update_type); + + if (argc > 3) { + firmware_tag = argv[3]; + } else if (!fw_update_type) { + firmware_tag = FW_TAG_INT_DEFAULT; + } else { + firmware_tag = FW_TAG_BCND_DEFAULT; + } + + if (argc > 4) + sscanf(argv[4], "%u", &fw_timeout); + + printf("Trying Firmware update: fwdev: %s, type: %s, tag: %s, timeout: %d\n", + fwdev, fw_update_type == 0 ? "interface" : "backend", + firmware_tag, fw_timeout); + + printf("Opening %s firmware management device\n", fwdev); + + fd = open(fwdev, O_RDWR); + if (fd < 0) { + printf("Failed to open: %s\n", fwdev); + return -1; + } + + /* Set Timeout */ + printf("Setting timeout to %u ms\n", fw_timeout); + + ret = ioctl(fd, FW_MGMT_IOC_SET_TIMEOUT_MS, &fw_timeout); + if (ret < 0) { + printf("Failed to set timeout: %s (%d)\n", fwdev, ret); + ret = -1; + goto close_fd; + } + + if (!fw_update_type) + ret = update_intf_firmware(fd); + else + ret = update_backend_firmware(fd); + +close_fd: + close(fd); + + return ret; +} diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus new file mode 100644 index 000000000000..2e998966cbe1 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -0,0 +1,275 @@ +What: /sys/bus/greybus/devices/greybusN +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The "root" greybus device for the Greybus device tree, or bus, + where N is a dynamically assigned 1-based id. + +What: /sys/bus/greybus/devices/greybusN/bus_id +Date: April 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The ID of the "root" greybus device, or bus. + +What: /sys/bus/greybus/devices/N-M +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + A Module M on the bus N, where M is the 1-byte interface + ID of the module's primary interface. + +What: /sys/bus/greybus/devices/N-M/eject +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Writing a non-zero argument to this attibute disables the + module's interfaces before physically ejecting it. + +What: /sys/bus/greybus/devices/N-M/module_id +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The ID of a Greybus module, corresponding to the ID of its + primary interface. + +What: /sys/bus/greybus/devices/N-M/num_interfaces +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The number of interfaces of a module. + +What: /sys/bus/greybus/devices/N-M.I +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + An Interface I on the bus N and module N-M, where I is the + 1-byte interface ID. + +What: /sys/bus/greybus/devices/N-M.I/current_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Current measurement of the interface in microamps (uA) + +What: /sys/bus/greybus/devices/N-M.I/ddbl1_manufacturer_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Unipro Device Descriptor Block Level 1 manufacturer ID for the + greybus Interface. + +What: /sys/bus/greybus/devices/N-M.I/ddbl1_product_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Unipro Device Descriptor Block Level 1 product ID for the + greybus Interface. + +What: /sys/bus/greybus/devices/N-M.I/interface_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The ID of a Greybus interface. + +What: /sys/bus/greybus/devices/N-M.I/interface_type +Date: June 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The type of a Greybus interface; "dummy", "unipro", "greybus", + or "unknown". + +What: /sys/bus/greybus/devices/N-M.I/power_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Power measurement of the interface in microwatts (uW) + +What: /sys/bus/greybus/devices/N-M.I/power_state +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + This file reflects the power state of a Greybus interface. If + the value read from it is "on", then power is currently + supplied to the interface. Otherwise it will read "off" and + power is currently not supplied to the interface. + + If the value read is "off", then writing "on" (or '1', 'y', + 'Y') to this file will enable power to the interface and an + attempt to boot and possibly enumerate it will be made. Note + that on errors, the interface will again be powered down. + + If the value read is "on", then writing "off" (or '0', 'n', + 'N') to this file will power down the interface. + +What: /sys/bus/greybus/devices/N-M.I/product_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Product ID of a Greybus interface. + +What: /sys/bus/greybus/devices/N-M.I/serial_number +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Serial Number of the Greybus interface, represented by a 64 bit + hexadecimal number. + +What: /sys/bus/greybus/devices/N-M.I/vendor_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Vendor ID of a Greybus interface. + +What: /sys/bus/greybus/devices/N-M.I/voltage_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Voltage measurement of the interface in microvolts (uV) + +What: /sys/bus/greybus/devices/N-M.I.ctrl +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Abstract control device for interface I that represents the + current mode of an enumerated Greybus interface. + +What: /sys/bus/greybus/devices/N-M.I.ctrl/product_string +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Product ID string of a Greybus interface. + +What: /sys/bus/greybus/devices/N-M.I.ctrl/vendor_string +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Vendor ID string of a Greybus interface. + +What: /sys/bus/greybus/devices/N-M.I.B +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + A bundle B on the Interface I, B is replaced by a 1-byte + number representing the bundle. + +What: /sys/bus/greybus/devices/N-M.I.B/bundle_class +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The greybus class of the bundle B. + +What: /sys/bus/greybus/devices/N-M.I.B/bundle_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The interface-unique id of the bundle B. + +What: /sys/bus/greybus/devices/N-M.I.B/gpbX +Date: April 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The General Purpose Bridged PHY device of the bundle B, + where X is a dynamically assigned 0-based id. + +What: /sys/bus/greybus/devices/N-M.I.B/state +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + A bundle has a state that is managed by the userspace + Endo process. This file allows that Endo to signal + other Android HALs that the state of the bundle has + changed to a specific value. When written to, any + process watching the file will be woken up, and the new + value can be read. It's a "poor-man's IPC", yes, but + simplifies the Android userspace code immensely. + +What: /sys/bus/greybus/devices/N-svc +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The singleton SVC device of bus N. + +What: /sys/bus/greybus/devices/N-svc/ap_intf_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The AP interface ID, a 1-byte non-zero integer which + defines the position of the AP module on the frame. + The interface positions are defined in the GMP + Module Developer Kit. + +What: /sys/bus/greybus/devices/N-svc/endo_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The Endo ID, which is a 2-byte hexadecimal value + defined by the Endo layout scheme, documented in + the GMP Module Developer Kit. + +What: /sys/bus/greybus/devices/N-svc/intf_eject +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Write the number of the interface that you wish to + forcibly eject from the system. + +What: /sys/bus/greybus/devices/N-svc/version +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The version number of the firmware in the SVC device. + +What: /sys/bus/greybus/devices/N-svc/watchdog +Date: October 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + If the SVC watchdog is enabled or not. Writing 0 to this + file will disable the watchdog, writing 1 will enable it. + +What: /sys/bus/greybus/devices/N-svc/watchdog_action +Date: July 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + This attribute indicates the action to be performed upon SVC + watchdog bite. + + The action can be one of the "reset" or "panic". Writing either + one of the "reset" or "panic" will change the behavior of SVC + watchdog bite. Default value is "reset". + + "reset" means the UniPro subsystem is to be reset. + + "panic" means SVC watchdog bite will cause kernel to panic. diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig new file mode 100644 index 000000000000..50de2d72dde0 --- /dev/null +++ b/drivers/staging/greybus/Kconfig @@ -0,0 +1,219 @@ +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 + ---help--- + Select this option if you have a device that follows the + Greybus Audio Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-audio.ko + +config GREYBUS_BOOTROM + tristate "Greybus Bootrom Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Bootrom Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-bootrom.ko + +config GREYBUS_CAMERA + tristate "Greybus Camera Class driver" + depends on MEDIA_SUPPORT && LEDS_CLASS_FLASH && BROKEN + ---help--- + Select this option if you have a device that follows the + Greybus Camera Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-camera.ko + +config GREYBUS_FIRMWARE + tristate "Greybus Firmware Download Class driver" + depends on SPI + ---help--- + Select this option if you have a device that follows the + Greybus Firmware Download Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-firmware.ko + +config GREYBUS_HID + tristate "Greybus HID Class driver" + depends on HID && INPUT + ---help--- + Select this option if you have a device that follows the + Greybus HID Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-hid.ko + +config GREYBUS_LIGHT + tristate "Greybus LED Class driver" + depends on LEDS_CLASS + ---help--- + Select this option if you have a device that follows the + Greybus LED Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-light.ko + +config GREYBUS_LOG + tristate "Greybus Debug Log Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Debug Log Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-log.ko + +config GREYBUS_LOOPBACK + tristate "Greybus Loopback Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Debug Log Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-log.ko + +config GREYBUS_POWER + tristate "Greybus Powersupply Class driver" + depends on POWER_SUPPLY + ---help--- + Select this option if you have a device that follows the + Greybus Powersupply Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-power-supply.ko + +config GREYBUS_RAW + tristate "Greybus Raw Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Raw Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-raw.ko + +config GREYBUS_VIBRATOR + tristate "Greybus Vibrator Motor Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Vibrator Motor Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-vibrator.ko + +menuconfig GREYBUS_BRIDGED_PHY + tristate "Greybus Bridged PHY Class drivers" + ---help--- + Select this option to pick from a variety of Greybus Bridged + PHY class drivers. These drivers emulate a number of + different "traditional" busses by tunneling them over Greybus. + Examples of this include serial, SPI, USB, and others. + + To compile this code as a module, chose M here: the module + will be called gb-phy.ko + +if GREYBUS_BRIDGED_PHY + +config GREYBUS_GPIO + tristate "Greybus GPIO Bridged PHY driver" + depends on GPIOLIB + ---help--- + Select this option if you have a device that follows the + Greybus GPIO Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-gpio.ko + +config GREYBUS_I2C + tristate "Greybus I2C Bridged PHY driver" + depends on I2C + ---help--- + Select this option if you have a device that follows the + Greybus I2C Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-i2c.ko + +config GREYBUS_PWM + tristate "Greybus PWM Bridged PHY driver" + depends on PWM + ---help--- + Select this option if you have a device that follows the + Greybus PWM Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-pwm.ko + +config GREYBUS_SDIO + tristate "Greybus SDIO Bridged PHY driver" + depends on MMC + ---help--- + Select this option if you have a device that follows the + Greybus SDIO Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-sdio.ko + +config GREYBUS_SPI + tristate "Greybus SPI Bridged PHY driver" + depends on SPI + ---help--- + Select this option if you have a device that follows the + Greybus SPI Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-spi.ko + +config GREYBUS_UART + tristate "Greybus UART Bridged PHY driver" + depends on TTY + ---help--- + Select this option if you have a device that follows the + Greybus UART Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-uart.ko + +config GREYBUS_USB + tristate "Greybus USB Host Bridged PHY driver" + depends on USB + ---help--- + Select this option if you have a device that follows the + Greybus USB Host Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-usb.ko + +endif # GREYBUS_BRIDGED_PHY +endif # GREYBUS diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile new file mode 100644 index 000000000000..f337b7b70782 --- /dev/null +++ b/drivers/staging/greybus/Makefile @@ -0,0 +1,96 @@ +# 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 \ + timesync.o \ + timesync_platform.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 +gb-firmware-y := fw-core.o fw-download.o fw-management.o authentication.o +gb-spilib-y := spilib.o +gb-hid-y := hid.o +gb-light-y := light.o +gb-log-y := log.o +gb-loopback-y := loopback.o +gb-power-supply-y := power_supply.o +gb-raw-y := raw.o +gb-vibrator-y := vibrator.o + +obj-$(CONFIG_GREYBUS_BOOTROM) += gb-bootrom.o +obj-$(CONFIG_GREYBUS_CAMERA) += gb-camera.o +obj-$(CONFIG_GREYBUS_FIRMWARE) += gb-firmware.o gb-spilib.o +obj-$(CONFIG_GREYBUS_HID) += gb-hid.o +obj-$(CONFIG_GREYBUS_LIGHT) += gb-light.o +obj-$(CONFIG_GREYBUS_LOG) += gb-log.o +obj-$(CONFIG_GREYBUS_LOOPBACK) += gb-loopback.o +obj-$(CONFIG_GREYBUS_POWER) += gb-power-supply.o +obj-$(CONFIG_GREYBUS_RAW) += gb-raw.o +obj-$(CONFIG_GREYBUS_VIBRATOR) += gb-vibrator.o + +# Greybus Audio is a bunch of modules +gb-audio-module-y := audio_module.o audio_topology.o +gb-audio-codec-y := audio_codec.o +gb-audio-gb-y := audio_gb.o +gb-audio-apbridgea-y := audio_apbridgea.o +gb-audio-manager-y := audio_manager.o audio_manager_module.o + +# Greybus Audio sysfs helpers can be useful when debugging +#GB_AUDIO_MANAGER_SYSFS ?= true +#ifeq ($(GB_AUDIO_MANAGER_SYSFS),true) +#gb-audio-manager-y += audio_manager_sysfs.o +#ccflags-y += -DGB_AUDIO_MANAGER_SYSFS +#endif + +obj-$(CONFIG_GREYBUS_AUDIO_MSM8994) += gb-audio-codec.o +obj-$(CONFIG_GREYBUS_AUDIO_MSM8994) += gb-audio-module.o +obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-gb.o +obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-apbridgea.o +obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-manager.o + + +# Greybus Bridged PHY drivers +gb-gbphy-y := gbphy.o +gb-gpio-y := gpio.o +gb-i2c-y := i2c.o +gb-pwm-y := pwm.o +gb-sdio-y := sdio.o +gb-spi-y := spi.o +gb-uart-y := uart.o +gb-usb-y := usb.o + +obj-$(CONFIG_GREYBUS_BRIDGED_PHY) += gb-gbphy.o +obj-$(CONFIG_GREYBUS_GPIO) += gb-gpio.o +obj-$(CONFIG_GREYBUS_I2C) += gb-i2c.o +obj-$(CONFIG_GREYBUS_PWM) += gb-pwm.o +obj-$(CONFIG_GREYBUS_SDIO) += gb-sdio.o +obj-$(CONFIG_GREYBUS_SPI) += gb-spi.o gb-spilib.o +obj-$(CONFIG_GREYBUS_UART) += gb-uart.o +obj-$(CONFIG_GREYBUS_USB) += gb-usb.o + + +# Greybus Platform driver +gb-arche-y := arche-platform.o arche-apb-ctrl.o + +obj-$(CONFIG_USB_HSIC_USB3613) += gb-arche.o diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c new file mode 100644 index 000000000000..70323aa11f24 --- /dev/null +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -0,0 +1,522 @@ +/* + * Arche Platform driver to control APB. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "arche_platform.h" + + +struct arche_apb_ctrl_drvdata { + /* Control GPIO signals to and from AP <=> AP Bridges */ + int resetn_gpio; + int boot_ret_gpio; + int pwroff_gpio; + int wake_in_gpio; + int wake_out_gpio; + int pwrdn_gpio; + + enum arche_platform_state state; + bool init_disabled; + + struct regulator *vcore; + struct regulator *vio; + + int clk_en_gpio; + struct clk *clk; + + struct pinctrl *pinctrl; + struct pinctrl_state *pin_default; + + /* V2: SPI Bus control */ + int spi_en_gpio; + bool spi_en_polarity_high; +}; + +/* + * Note that these low level api's are active high + */ +static inline void deassert_reset(unsigned int gpio) +{ + gpio_set_value(gpio, 1); +} + +static inline void assert_reset(unsigned int gpio) +{ + gpio_set_value(gpio, 0); +} + +/* + * Note: Please do not modify the below sequence, as it is as per the spec + */ +static int coldboot_seq(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + int ret; + + if (apb->init_disabled || + apb->state == ARCHE_PLATFORM_STATE_ACTIVE) + return 0; + + /* Hold APB in reset state */ + assert_reset(apb->resetn_gpio); + + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && + gpio_is_valid(apb->spi_en_gpio)) + devm_gpio_free(dev, apb->spi_en_gpio); + + /* Enable power to APB */ + if (!IS_ERR(apb->vcore)) { + ret = regulator_enable(apb->vcore); + if (ret) { + dev_err(dev, "failed to enable core regulator\n"); + return ret; + } + } + + if (!IS_ERR(apb->vio)) { + ret = regulator_enable(apb->vio); + if (ret) { + dev_err(dev, "failed to enable IO regulator\n"); + return ret; + } + } + + apb_bootret_deassert(dev); + + /* On DB3 clock was not mandatory */ + if (gpio_is_valid(apb->clk_en_gpio)) + gpio_set_value(apb->clk_en_gpio, 1); + + usleep_range(100, 200); + + /* deassert reset to APB : Active-low signal */ + deassert_reset(apb->resetn_gpio); + + apb->state = ARCHE_PLATFORM_STATE_ACTIVE; + + return 0; +} + +static int fw_flashing_seq(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + int ret; + + if (apb->init_disabled || + apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING) + return 0; + + ret = regulator_enable(apb->vcore); + if (ret) { + dev_err(dev, "failed to enable core regulator\n"); + return ret; + } + + ret = regulator_enable(apb->vio); + if (ret) { + dev_err(dev, "failed to enable IO regulator\n"); + return ret; + } + + if (gpio_is_valid(apb->spi_en_gpio)) { + unsigned long flags; + + if (apb->spi_en_polarity_high) + flags = GPIOF_OUT_INIT_HIGH; + else + flags = GPIOF_OUT_INIT_LOW; + + ret = devm_gpio_request_one(dev, apb->spi_en_gpio, + flags, "apb_spi_en"); + if (ret) { + dev_err(dev, "Failed requesting SPI bus en gpio %d\n", + apb->spi_en_gpio); + return ret; + } + } + + /* for flashing device should be in reset state */ + assert_reset(apb->resetn_gpio); + apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING; + + return 0; +} + +static int standby_boot_seq(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + + if (apb->init_disabled) + return 0; + + /* Even if it is in OFF state, then we do not want to change the state */ + if (apb->state == ARCHE_PLATFORM_STATE_STANDBY || + apb->state == ARCHE_PLATFORM_STATE_OFF) + return 0; + + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && + gpio_is_valid(apb->spi_en_gpio)) + devm_gpio_free(dev, apb->spi_en_gpio); + + /* + * As per WDM spec, do nothing + * + * Pasted from WDM spec, + * - A falling edge on POWEROFF_L is detected (a) + * - WDM enters standby mode, but no output signals are changed + * */ + + /* TODO: POWEROFF_L is input to WDM module */ + apb->state = ARCHE_PLATFORM_STATE_STANDBY; + return 0; +} + +static void poweroff_seq(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + + if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF) + return; + + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && + gpio_is_valid(apb->spi_en_gpio)) + devm_gpio_free(dev, apb->spi_en_gpio); + + /* disable the clock */ + if (gpio_is_valid(apb->clk_en_gpio)) + gpio_set_value(apb->clk_en_gpio, 0); + + if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0) + regulator_disable(apb->vcore); + + if (!IS_ERR(apb->vio) && regulator_is_enabled(apb->vio) > 0) + regulator_disable(apb->vio); + + /* As part of exit, put APB back in reset state */ + assert_reset(apb->resetn_gpio); + apb->state = ARCHE_PLATFORM_STATE_OFF; + + /* TODO: May have to send an event to SVC about this exit */ +} + +void apb_bootret_assert(struct device *dev) +{ + struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); + + gpio_set_value(apb->boot_ret_gpio, 1); +} + +void apb_bootret_deassert(struct device *dev) +{ + struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); + + gpio_set_value(apb->boot_ret_gpio, 0); +} + +int apb_ctrl_coldboot(struct device *dev) +{ + return coldboot_seq(to_platform_device(dev)); +} + +int apb_ctrl_fw_flashing(struct device *dev) +{ + return fw_flashing_seq(to_platform_device(dev)); +} + +int apb_ctrl_standby_boot(struct device *dev) +{ + return standby_boot_seq(to_platform_device(dev)); +} + +void apb_ctrl_poweroff(struct device *dev) +{ + poweroff_seq(to_platform_device(dev)); +} + +static ssize_t state_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + int ret = 0; + bool is_disabled; + + if (sysfs_streq(buf, "off")) { + if (apb->state == ARCHE_PLATFORM_STATE_OFF) + return count; + + poweroff_seq(pdev); + } else if (sysfs_streq(buf, "active")) { + if (apb->state == ARCHE_PLATFORM_STATE_ACTIVE) + return count; + + poweroff_seq(pdev); + is_disabled = apb->init_disabled; + apb->init_disabled = false; + ret = coldboot_seq(pdev); + if (ret) + apb->init_disabled = is_disabled; + } else if (sysfs_streq(buf, "standby")) { + if (apb->state == ARCHE_PLATFORM_STATE_STANDBY) + return count; + + ret = standby_boot_seq(pdev); + } else if (sysfs_streq(buf, "fw_flashing")) { + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING) + return count; + + /* First we want to make sure we power off everything + * and then enter FW flashing state */ + poweroff_seq(pdev); + ret = fw_flashing_seq(pdev); + } else { + dev_err(dev, "unknown state\n"); + ret = -EINVAL; + } + + return ret ? ret : count; +} + +static ssize_t state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); + + switch (apb->state) { + case ARCHE_PLATFORM_STATE_OFF: + return sprintf(buf, "off%s\n", + apb->init_disabled ? ",disabled" : ""); + case ARCHE_PLATFORM_STATE_ACTIVE: + return sprintf(buf, "active\n"); + case ARCHE_PLATFORM_STATE_STANDBY: + return sprintf(buf, "standby\n"); + case ARCHE_PLATFORM_STATE_FW_FLASHING: + return sprintf(buf, "fw_flashing\n"); + default: + return sprintf(buf, "unknown state\n"); + } +} + +static DEVICE_ATTR_RW(state); + +static int apb_ctrl_get_devtree_data(struct platform_device *pdev, + struct arche_apb_ctrl_drvdata *apb) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; + + apb->resetn_gpio = of_get_named_gpio(np, "reset-gpios", 0); + if (apb->resetn_gpio < 0) { + dev_err(dev, "failed to get reset gpio\n"); + return apb->resetn_gpio; + } + ret = devm_gpio_request_one(dev, apb->resetn_gpio, + GPIOF_OUT_INIT_LOW, "apb-reset"); + if (ret) { + dev_err(dev, "Failed requesting reset gpio %d\n", + apb->resetn_gpio); + return ret; + } + + apb->boot_ret_gpio = of_get_named_gpio(np, "boot-ret-gpios", 0); + if (apb->boot_ret_gpio < 0) { + dev_err(dev, "failed to get boot retention gpio\n"); + return apb->boot_ret_gpio; + } + ret = devm_gpio_request_one(dev, apb->boot_ret_gpio, + GPIOF_OUT_INIT_LOW, "boot retention"); + if (ret) { + dev_err(dev, "Failed requesting bootret gpio %d\n", + apb->boot_ret_gpio); + return ret; + } + + /* It's not mandatory to support power management interface */ + apb->pwroff_gpio = of_get_named_gpio(np, "pwr-off-gpios", 0); + if (apb->pwroff_gpio < 0) { + dev_err(dev, "failed to get power off gpio\n"); + return apb->pwroff_gpio; + } + ret = devm_gpio_request_one(dev, apb->pwroff_gpio, + GPIOF_IN, "pwroff_n"); + if (ret) { + dev_err(dev, "Failed requesting pwroff_n gpio %d\n", + apb->pwroff_gpio); + return ret; + } + + /* Do not make clock mandatory as of now (for DB3) */ + apb->clk_en_gpio = of_get_named_gpio(np, "clock-en-gpio", 0); + if (apb->clk_en_gpio < 0) { + dev_warn(dev, "failed to get clock en gpio\n"); + } else if (gpio_is_valid(apb->clk_en_gpio)) { + ret = devm_gpio_request_one(dev, apb->clk_en_gpio, + GPIOF_OUT_INIT_LOW, "apb_clk_en"); + if (ret) { + dev_warn(dev, "Failed requesting APB clock en gpio %d\n", + apb->clk_en_gpio); + return ret; + } + } + + apb->pwrdn_gpio = of_get_named_gpio(np, "pwr-down-gpios", 0); + if (apb->pwrdn_gpio < 0) + dev_warn(dev, "failed to get power down gpio\n"); + + /* Regulators are optional, as we may have fixed supply coming in */ + apb->vcore = devm_regulator_get(dev, "vcore"); + if (IS_ERR(apb->vcore)) + dev_warn(dev, "no core regulator found\n"); + + apb->vio = devm_regulator_get(dev, "vio"); + if (IS_ERR(apb->vio)) + dev_warn(dev, "no IO regulator found\n"); + + apb->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(apb->pinctrl)) { + dev_err(&pdev->dev, "could not get pinctrl handle\n"); + return PTR_ERR(apb->pinctrl); + } + apb->pin_default = pinctrl_lookup_state(apb->pinctrl, "default"); + if (IS_ERR(apb->pin_default)) { + dev_err(&pdev->dev, "could not get default pin state\n"); + return PTR_ERR(apb->pin_default); + } + + /* Only applicable for platform >= V2 */ + apb->spi_en_gpio = of_get_named_gpio(np, "spi-en-gpio", 0); + if (apb->spi_en_gpio >= 0) { + if (of_property_read_bool(pdev->dev.of_node, + "spi-en-active-high")) + apb->spi_en_polarity_high = true; + } + + return 0; +} + +static int arche_apb_ctrl_probe(struct platform_device *pdev) +{ + int ret; + struct arche_apb_ctrl_drvdata *apb; + struct device *dev = &pdev->dev; + + apb = devm_kzalloc(&pdev->dev, sizeof(*apb), GFP_KERNEL); + if (!apb) + return -ENOMEM; + + ret = apb_ctrl_get_devtree_data(pdev, apb); + if (ret) { + dev_err(dev, "failed to get apb devicetree data %d\n", ret); + return ret; + } + + /* Initially set APB to OFF state */ + apb->state = ARCHE_PLATFORM_STATE_OFF; + /* Check whether device needs to be enabled on boot */ + if (of_property_read_bool(pdev->dev.of_node, "arche,init-disable")) + apb->init_disabled = true; + + platform_set_drvdata(pdev, apb); + + /* Create sysfs interface to allow user to change state dynamically */ + ret = device_create_file(dev, &dev_attr_state); + if (ret) { + dev_err(dev, "failed to create state file in sysfs\n"); + return ret; + } + + dev_info(&pdev->dev, "Device registered successfully\n"); + return 0; +} + +static int arche_apb_ctrl_remove(struct platform_device *pdev) +{ + device_remove_file(&pdev->dev, &dev_attr_state); + poweroff_seq(pdev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static int arche_apb_ctrl_suspend(struct device *dev) +{ + /* + * If timing profile permits, we may shutdown bridge + * completely + * + * TODO: sequence ?? + * + * Also, need to make sure we meet precondition for unipro suspend + * Precondition: Definition ??? + */ + return 0; +} + +static int arche_apb_ctrl_resume(struct device *dev) +{ + /* + * Atleast for ES2 we have to meet the delay requirement between + * unipro switch and AP bridge init, depending on whether bridge is in + * OFF state or standby state. + * + * Based on whether bridge is in standby or OFF state we may have to + * assert multiple signals. Please refer to WDM spec, for more info. + * + */ + return 0; +} + +static void arche_apb_ctrl_shutdown(struct platform_device *pdev) +{ + apb_ctrl_poweroff(&pdev->dev); +} + +static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend, + arche_apb_ctrl_resume); + +static const struct of_device_id arche_apb_ctrl_of_match[] = { + { .compatible = "usbffff,2", }, + { }, +}; + +static struct platform_driver arche_apb_ctrl_device_driver = { + .probe = arche_apb_ctrl_probe, + .remove = arche_apb_ctrl_remove, + .shutdown = arche_apb_ctrl_shutdown, + .driver = { + .name = "arche-apb-ctrl", + .pm = &arche_apb_ctrl_pm_ops, + .of_match_table = arche_apb_ctrl_of_match, + } +}; + +int __init arche_apb_init(void) +{ + return platform_driver_register(&arche_apb_ctrl_device_driver); +} + +void __exit arche_apb_exit(void) +{ + platform_driver_unregister(&arche_apb_ctrl_device_driver); +} diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c new file mode 100644 index 000000000000..e36ee984485b --- /dev/null +++ b/drivers/staging/greybus/arche-platform.c @@ -0,0 +1,827 @@ +/* + * Arche Platform driver to enable Unipro link. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "arche_platform.h" +#include "greybus.h" + +#include + +#define WD_COLDBOOT_PULSE_WIDTH_MS 30 + +enum svc_wakedetect_state { + WD_STATE_IDLE, /* Default state = pulled high/low */ + WD_STATE_BOOT_INIT, /* WD = falling edge (low) */ + WD_STATE_COLDBOOT_TRIG, /* WD = rising edge (high), > 30msec */ + WD_STATE_STANDBYBOOT_TRIG, /* As of now not used ?? */ + WD_STATE_COLDBOOT_START, /* Cold boot process started */ + WD_STATE_STANDBYBOOT_START, /* Not used */ + WD_STATE_TIMESYNC, +}; + +struct arche_platform_drvdata { + /* Control GPIO signals to and from AP <=> SVC */ + int svc_reset_gpio; + bool is_reset_act_hi; + int svc_sysboot_gpio; + int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ + + enum arche_platform_state state; + + int svc_refclk_req; + struct clk *svc_ref_clk; + + struct pinctrl *pinctrl; + struct pinctrl_state *pin_default; + + int num_apbs; + + enum svc_wakedetect_state wake_detect_state; + int wake_detect_irq; + spinlock_t wake_lock; /* Protect wake_detect_state */ + struct mutex platform_state_mutex; /* Protect state */ + wait_queue_head_t wq; /* WQ for arche_pdata->state */ + unsigned long wake_detect_start; + struct notifier_block pm_notifier; + + struct device *dev; + struct gb_timesync_svc *timesync_svc_pdata; +}; + +static int arche_apb_bootret_assert(struct device *dev, void *data) +{ + apb_bootret_assert(dev); + return 0; +} + +static int arche_apb_bootret_deassert(struct device *dev, void *data) +{ + apb_bootret_deassert(dev); + return 0; +} + +/* Requires calling context to hold arche_pdata->platform_state_mutex */ +static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata, + enum arche_platform_state state) +{ + arche_pdata->state = state; +} + +/* + * arche_platform_change_state: Change the operational state + * + * This exported function allows external drivers to change the state + * of the arche-platform driver. + * Note that this function only supports transitions between two states + * with limited functionality. + * + * - ARCHE_PLATFORM_STATE_TIME_SYNC: + * Once set, allows timesync operations between SVC <=> AP and makes + * sure that arche-platform driver ignores any subsequent events/pulses + * from SVC over wake/detect. + * + * - ARCHE_PLATFORM_STATE_ACTIVE: + * Puts back driver to active state, where any pulse from SVC on wake/detect + * line would trigger either cold/standby boot. + * Note: Transition request from this function does not trigger cold/standby + * boot. It just puts back driver book keeping variable back to ACTIVE + * state and restores the interrupt. + * + * Returns -ENODEV if device not found, -EAGAIN if the driver cannot currently + * satisfy the requested state-transition or -EINVAL for all other + * state-transition requests. + */ +int arche_platform_change_state(enum arche_platform_state state, + struct gb_timesync_svc *timesync_svc_pdata) +{ + struct arche_platform_drvdata *arche_pdata; + struct platform_device *pdev; + struct device_node *np; + int ret = -EAGAIN; + unsigned long flags; + + np = of_find_compatible_node(NULL, NULL, "google,arche-platform"); + if (!np) { + pr_err("google,arche-platform device node not found\n"); + return -ENODEV; + } + + pdev = of_find_device_by_node(np); + if (!pdev) { + pr_err("arche-platform device not found\n"); + return -ENODEV; + } + + arche_pdata = platform_get_drvdata(pdev); + + mutex_lock(&arche_pdata->platform_state_mutex); + spin_lock_irqsave(&arche_pdata->wake_lock, flags); + + if (arche_pdata->state == state) { + ret = 0; + goto exit; + } + + switch (state) { + case ARCHE_PLATFORM_STATE_TIME_SYNC: + if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) { + ret = -EINVAL; + goto exit; + } + if (arche_pdata->wake_detect_state != WD_STATE_IDLE) { + dev_err(arche_pdata->dev, + "driver busy with wake/detect line ops\n"); + goto exit; + } + device_for_each_child(arche_pdata->dev, NULL, + arche_apb_bootret_assert); + arche_pdata->wake_detect_state = WD_STATE_TIMESYNC; + break; + case ARCHE_PLATFORM_STATE_ACTIVE: + if (arche_pdata->state != ARCHE_PLATFORM_STATE_TIME_SYNC) { + ret = -EINVAL; + goto exit; + } + device_for_each_child(arche_pdata->dev, NULL, + arche_apb_bootret_deassert); + arche_pdata->wake_detect_state = WD_STATE_IDLE; + break; + case ARCHE_PLATFORM_STATE_OFF: + case ARCHE_PLATFORM_STATE_STANDBY: + case ARCHE_PLATFORM_STATE_FW_FLASHING: + dev_err(arche_pdata->dev, "busy, request to retry later\n"); + goto exit; + default: + ret = -EINVAL; + dev_err(arche_pdata->dev, + "invalid state transition request\n"); + goto exit; + } + arche_pdata->timesync_svc_pdata = timesync_svc_pdata; + arche_platform_set_state(arche_pdata, state); + if (state == ARCHE_PLATFORM_STATE_ACTIVE) + wake_up(&arche_pdata->wq); + + ret = 0; +exit: + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); + mutex_unlock(&arche_pdata->platform_state_mutex); + of_node_put(np); + return ret; +} +EXPORT_SYMBOL_GPL(arche_platform_change_state); + +/* Requires arche_pdata->wake_lock is held by calling context */ +static void arche_platform_set_wake_detect_state( + struct arche_platform_drvdata *arche_pdata, + enum svc_wakedetect_state state) +{ + arche_pdata->wake_detect_state = state; +} + +static inline void svc_reset_onoff(unsigned int gpio, bool onoff) +{ + gpio_set_value(gpio, onoff); +} + +static int apb_cold_boot(struct device *dev, void *data) +{ + int ret; + + ret = apb_ctrl_coldboot(dev); + if (ret) + dev_warn(dev, "failed to coldboot\n"); + + /*Child nodes are independent, so do not exit coldboot operation */ + return 0; +} + +static int apb_poweroff(struct device *dev, void *data) +{ + apb_ctrl_poweroff(dev); + + /* Enable HUB3613 into HUB mode. */ + if (usb3613_hub_mode_ctrl(false)) + dev_warn(dev, "failed to control hub device\n"); + + return 0; +} + +static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata) +{ + /* Enable interrupt here, to read event back from SVC */ + gpio_direction_input(arche_pdata->wake_detect_gpio); + enable_irq(arche_pdata->wake_detect_irq); +} + +static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) +{ + struct arche_platform_drvdata *arche_pdata = devid; + unsigned long flags; + + spin_lock_irqsave(&arche_pdata->wake_lock, flags); + if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_TRIG) { + /* Something is wrong */ + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); + return IRQ_HANDLED; + } + + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_COLDBOOT_START); + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); + + /* It should complete power cycle, so first make sure it is poweroff */ + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + + /* Bring APB out of reset: cold boot sequence */ + device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot); + + /* Enable HUB3613 into HUB mode. */ + if (usb3613_hub_mode_ctrl(true)) + dev_warn(arche_pdata->dev, "failed to control hub device\n"); + + spin_lock_irqsave(&arche_pdata->wake_lock, flags); + arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); + + return IRQ_HANDLED; +} + +static irqreturn_t arche_platform_wd_irq(int irq, void *devid) +{ + struct arche_platform_drvdata *arche_pdata = devid; + unsigned long flags; + + spin_lock_irqsave(&arche_pdata->wake_lock, flags); + + if (arche_pdata->wake_detect_state == WD_STATE_TIMESYNC) { + gb_timesync_irq(arche_pdata->timesync_svc_pdata); + goto exit; + } + + if (gpio_get_value(arche_pdata->wake_detect_gpio)) { + /* wake/detect rising */ + + /* + * If wake/detect line goes high after low, within less than + * 30msec, then standby boot sequence is initiated, which is not + * supported/implemented as of now. So ignore it. + */ + if (arche_pdata->wake_detect_state == WD_STATE_BOOT_INIT) { + if (time_before(jiffies, + arche_pdata->wake_detect_start + + msecs_to_jiffies(WD_COLDBOOT_PULSE_WIDTH_MS))) { + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_IDLE); + } else { + /* Check we are not in middle of irq thread already */ + if (arche_pdata->wake_detect_state != + WD_STATE_COLDBOOT_START) { + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_COLDBOOT_TRIG); + spin_unlock_irqrestore( + &arche_pdata->wake_lock, + flags); + return IRQ_WAKE_THREAD; + } + } + } + } else { + /* wake/detect falling */ + if (arche_pdata->wake_detect_state == WD_STATE_IDLE) { + arche_pdata->wake_detect_start = jiffies; + /* + * In the begining, when wake/detect goes low (first time), we assume + * it is meant for coldboot and set the flag. If wake/detect line stays low + * beyond 30msec, then it is coldboot else fallback to standby boot. + */ + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_BOOT_INIT); + } + } + +exit: + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); + + return IRQ_HANDLED; +} + +/* + * Requires arche_pdata->platform_state_mutex to be held + */ +static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) +{ + int ret; + + if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) + return 0; + + dev_info(arche_pdata->dev, "Booting from cold boot state\n"); + + svc_reset_onoff(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); + + gpio_set_value(arche_pdata->svc_sysboot_gpio, 0); + usleep_range(100, 200); + + ret = clk_prepare_enable(arche_pdata->svc_ref_clk); + if (ret) { + dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n", + ret); + return ret; + } + + /* bring SVC out of reset */ + svc_reset_onoff(arche_pdata->svc_reset_gpio, + !arche_pdata->is_reset_act_hi); + + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE); + + return 0; +} + +/* + * Requires arche_pdata->platform_state_mutex to be held + */ +static int arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) +{ + int ret; + + if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) + return 0; + + dev_info(arche_pdata->dev, "Switching to FW flashing state\n"); + + svc_reset_onoff(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); + + gpio_set_value(arche_pdata->svc_sysboot_gpio, 1); + + usleep_range(100, 200); + + ret = clk_prepare_enable(arche_pdata->svc_ref_clk); + if (ret) { + dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n", + ret); + return ret; + } + + svc_reset_onoff(arche_pdata->svc_reset_gpio, + !arche_pdata->is_reset_act_hi); + + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING); + + return 0; +} + +/* + * Requires arche_pdata->platform_state_mutex to be held + */ +static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) +{ + unsigned long flags; + + if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) + return; + + /* If in fw_flashing mode, then no need to repeate things again */ + if (arche_pdata->state != ARCHE_PLATFORM_STATE_FW_FLASHING) { + disable_irq(arche_pdata->wake_detect_irq); + + spin_lock_irqsave(&arche_pdata->wake_lock, flags); + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_IDLE); + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); + } + + clk_disable_unprepare(arche_pdata->svc_ref_clk); + + /* As part of exit, put APB back in reset state */ + svc_reset_onoff(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); + + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); +} + +static ssize_t state_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + int ret = 0; + +retry: + mutex_lock(&arche_pdata->platform_state_mutex); + if (arche_pdata->state == ARCHE_PLATFORM_STATE_TIME_SYNC) { + mutex_unlock(&arche_pdata->platform_state_mutex); + ret = wait_event_interruptible( + arche_pdata->wq, + arche_pdata->state != ARCHE_PLATFORM_STATE_TIME_SYNC); + if (ret) + return ret; + goto retry; + } + + if (sysfs_streq(buf, "off")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) + goto exit; + + /* If SVC goes down, bring down APB's as well */ + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + + arche_platform_poweroff_seq(arche_pdata); + + } else if (sysfs_streq(buf, "active")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) + goto exit; + + /* First we want to make sure we power off everything + * and then activate back again */ + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + arche_platform_poweroff_seq(arche_pdata); + + arche_platform_wd_irq_en(arche_pdata); + ret = arche_platform_coldboot_seq(arche_pdata); + if (ret) + goto exit; + + } else if (sysfs_streq(buf, "standby")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) + goto exit; + + dev_warn(arche_pdata->dev, "standby state not supported\n"); + } else if (sysfs_streq(buf, "fw_flashing")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) + goto exit; + + /* + * Here we only control SVC. + * + * In case of FW_FLASHING mode we do not want to control + * APBs, as in case of V2, SPI bus is shared between both + * the APBs. So let user chose which APB he wants to flash. + */ + arche_platform_poweroff_seq(arche_pdata); + + ret = arche_platform_fw_flashing_seq(arche_pdata); + if (ret) + goto exit; + } else { + dev_err(arche_pdata->dev, "unknown state\n"); + ret = -EINVAL; + } + +exit: + mutex_unlock(&arche_pdata->platform_state_mutex); + return ret ? ret : count; +} + +static ssize_t state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev); + + switch (arche_pdata->state) { + case ARCHE_PLATFORM_STATE_OFF: + return sprintf(buf, "off\n"); + case ARCHE_PLATFORM_STATE_ACTIVE: + return sprintf(buf, "active\n"); + case ARCHE_PLATFORM_STATE_STANDBY: + return sprintf(buf, "standby\n"); + case ARCHE_PLATFORM_STATE_FW_FLASHING: + return sprintf(buf, "fw_flashing\n"); + case ARCHE_PLATFORM_STATE_TIME_SYNC: + return sprintf(buf, "time_sync\n"); + default: + return sprintf(buf, "unknown state\n"); + } +} + +static DEVICE_ATTR_RW(state); + +static int arche_platform_pm_notifier(struct notifier_block *notifier, + unsigned long pm_event, void *unused) +{ + struct arche_platform_drvdata *arche_pdata = + container_of(notifier, struct arche_platform_drvdata, + pm_notifier); + int ret = NOTIFY_DONE; + + mutex_lock(&arche_pdata->platform_state_mutex); + switch (pm_event) { + case PM_SUSPEND_PREPARE: + if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) { + ret = NOTIFY_STOP; + break; + } + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + arche_platform_poweroff_seq(arche_pdata); + break; + case PM_POST_SUSPEND: + if (arche_pdata->state != ARCHE_PLATFORM_STATE_OFF) + break; + + arche_platform_wd_irq_en(arche_pdata); + arche_platform_coldboot_seq(arche_pdata); + break; + default: + break; + } + mutex_unlock(&arche_pdata->platform_state_mutex); + + return ret; +} + +static int arche_platform_probe(struct platform_device *pdev) +{ + struct arche_platform_drvdata *arche_pdata; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; + + arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata), GFP_KERNEL); + if (!arche_pdata) + return -ENOMEM; + + /* setup svc reset gpio */ + arche_pdata->is_reset_act_hi = of_property_read_bool(np, + "svc,reset-active-high"); + arche_pdata->svc_reset_gpio = of_get_named_gpio(np, "svc,reset-gpio", 0); + if (arche_pdata->svc_reset_gpio < 0) { + dev_err(dev, "failed to get reset-gpio\n"); + return arche_pdata->svc_reset_gpio; + } + ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset"); + if (ret) { + dev_err(dev, "failed to request svc-reset gpio:%d\n", ret); + return ret; + } + ret = gpio_direction_output(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); + if (ret) { + dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); + return ret; + } + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); + + arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np, + "svc,sysboot-gpio", 0); + if (arche_pdata->svc_sysboot_gpio < 0) { + dev_err(dev, "failed to get sysboot gpio\n"); + return arche_pdata->svc_sysboot_gpio; + } + ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0"); + if (ret) { + dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret); + return ret; + } + ret = gpio_direction_output(arche_pdata->svc_sysboot_gpio, 0); + if (ret) { + dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); + return ret; + } + + /* setup the clock request gpio first */ + arche_pdata->svc_refclk_req = of_get_named_gpio(np, + "svc,refclk-req-gpio", 0); + if (arche_pdata->svc_refclk_req < 0) { + dev_err(dev, "failed to get svc clock-req gpio\n"); + return arche_pdata->svc_refclk_req; + } + ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req, "svc-clk-req"); + if (ret) { + dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret); + return ret; + } + ret = gpio_direction_input(arche_pdata->svc_refclk_req); + if (ret) { + dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret); + return ret; + } + + /* setup refclk2 to follow the pin */ + arche_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk"); + if (IS_ERR(arche_pdata->svc_ref_clk)) { + ret = PTR_ERR(arche_pdata->svc_ref_clk); + dev_err(dev, "failed to get svc_ref_clk: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, arche_pdata); + + arche_pdata->num_apbs = of_get_child_count(np); + dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); + + arche_pdata->wake_detect_gpio = of_get_named_gpio(np, "svc,wake-detect-gpio", 0); + if (arche_pdata->wake_detect_gpio < 0) { + dev_err(dev, "failed to get wake detect gpio\n"); + return arche_pdata->wake_detect_gpio; + } + + ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio, "wake detect"); + if (ret) { + dev_err(dev, "Failed requesting wake_detect gpio %d\n", + arche_pdata->wake_detect_gpio); + return ret; + } + + arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); + + arche_pdata->dev = &pdev->dev; + + spin_lock_init(&arche_pdata->wake_lock); + mutex_init(&arche_pdata->platform_state_mutex); + init_waitqueue_head(&arche_pdata->wq); + arche_pdata->wake_detect_irq = + gpio_to_irq(arche_pdata->wake_detect_gpio); + + ret = devm_request_threaded_irq(dev, arche_pdata->wake_detect_irq, + arche_platform_wd_irq, + arche_platform_wd_irq_thread, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, + dev_name(dev), arche_pdata); + if (ret) { + dev_err(dev, "failed to request wake detect IRQ %d\n", ret); + return ret; + } + disable_irq(arche_pdata->wake_detect_irq); + + ret = device_create_file(dev, &dev_attr_state); + if (ret) { + dev_err(dev, "failed to create state file in sysfs\n"); + return ret; + } + + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to populate child nodes %d\n", ret); + goto err_device_remove; + } + + arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier; + ret = register_pm_notifier(&arche_pdata->pm_notifier); + + if (ret) { + dev_err(dev, "failed to register pm notifier %d\n", ret); + goto err_device_remove; + } + + /* Register callback pointer */ + arche_platform_change_state_cb = arche_platform_change_state; + + /* Explicitly power off if requested */ + if (!of_property_read_bool(pdev->dev.of_node, "arche,init-off")) { + mutex_lock(&arche_pdata->platform_state_mutex); + ret = arche_platform_coldboot_seq(arche_pdata); + if (ret) { + dev_err(dev, "Failed to cold boot svc %d\n", ret); + goto err_coldboot; + } + arche_platform_wd_irq_en(arche_pdata); + mutex_unlock(&arche_pdata->platform_state_mutex); + } + + dev_info(dev, "Device registered successfully\n"); + return 0; + +err_coldboot: + mutex_unlock(&arche_pdata->platform_state_mutex); +err_device_remove: + device_remove_file(&pdev->dev, &dev_attr_state); + return ret; +} + +static int arche_remove_child(struct device *dev, void *unused) +{ + struct platform_device *pdev = to_platform_device(dev); + + platform_device_unregister(pdev); + + return 0; +} + +static int arche_platform_remove(struct platform_device *pdev) +{ + struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + + unregister_pm_notifier(&arche_pdata->pm_notifier); + device_remove_file(&pdev->dev, &dev_attr_state); + device_for_each_child(&pdev->dev, NULL, arche_remove_child); + arche_platform_poweroff_seq(arche_pdata); + platform_set_drvdata(pdev, NULL); + + if (usb3613_hub_mode_ctrl(false)) + dev_warn(arche_pdata->dev, "failed to control hub device\n"); + /* TODO: Should we do anything more here ?? */ + return 0; +} + +static int arche_platform_suspend(struct device *dev) +{ + /* + * If timing profile premits, we may shutdown bridge + * completely + * + * TODO: sequence ?? + * + * Also, need to make sure we meet precondition for unipro suspend + * Precondition: Definition ??? + */ + return 0; +} + +static int arche_platform_resume(struct device *dev) +{ + /* + * Atleast for ES2 we have to meet the delay requirement between + * unipro switch and AP bridge init, depending on whether bridge is in + * OFF state or standby state. + * + * Based on whether bridge is in standby or OFF state we may have to + * assert multiple signals. Please refer to WDM spec, for more info. + * + */ + return 0; +} + +static void arche_platform_shutdown(struct platform_device *pdev) +{ + struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + + arche_platform_poweroff_seq(arche_pdata); + + usb3613_hub_mode_ctrl(false); +} + +static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops, + arche_platform_suspend, + arche_platform_resume); + +static const struct of_device_id arche_platform_of_match[] = { + { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ + { }, +}; + +static const struct of_device_id arche_combined_id[] = { + { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ + { .compatible = "usbffff,2", }, + { }, +}; +MODULE_DEVICE_TABLE(of, arche_combined_id); + +static struct platform_driver arche_platform_device_driver = { + .probe = arche_platform_probe, + .remove = arche_platform_remove, + .shutdown = arche_platform_shutdown, + .driver = { + .name = "arche-platform-ctrl", + .pm = &arche_platform_pm_ops, + .of_match_table = arche_platform_of_match, + } +}; + +static int __init arche_init(void) +{ + int retval; + + retval = platform_driver_register(&arche_platform_device_driver); + if (retval) + return retval; + + retval = arche_apb_init(); + if (retval) + platform_driver_unregister(&arche_platform_device_driver); + + return retval; +} +module_init(arche_init); + +static void __exit arche_exit(void) +{ + arche_apb_exit(); + platform_driver_unregister(&arche_platform_device_driver); +} +module_exit(arche_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Vaibhav Hiremath "); +MODULE_DESCRIPTION("Arche Platform Driver"); diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h new file mode 100644 index 000000000000..bd12345b82a2 --- /dev/null +++ b/drivers/staging/greybus/arche_platform.h @@ -0,0 +1,39 @@ +/* + * Arche Platform driver to enable Unipro link. + * + * Copyright 2015-2016 Google Inc. + * Copyright 2015-2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __ARCHE_PLATFORM_H +#define __ARCHE_PLATFORM_H + +#include "timesync.h" + +enum arche_platform_state { + ARCHE_PLATFORM_STATE_OFF, + ARCHE_PLATFORM_STATE_ACTIVE, + ARCHE_PLATFORM_STATE_STANDBY, + ARCHE_PLATFORM_STATE_FW_FLASHING, + ARCHE_PLATFORM_STATE_TIME_SYNC, +}; + +int arche_platform_change_state(enum arche_platform_state state, + struct gb_timesync_svc *pdata); + +extern int (*arche_platform_change_state_cb)(enum arche_platform_state state, + struct gb_timesync_svc *pdata); +int __init arche_apb_init(void); +void __exit arche_apb_exit(void); + +/* Operational states for the APB device */ +int apb_ctrl_coldboot(struct device *dev); +int apb_ctrl_fw_flashing(struct device *dev); +int apb_ctrl_standby_boot(struct device *dev); +void apb_ctrl_poweroff(struct device *dev); +void apb_bootret_assert(struct device *dev); +void apb_bootret_deassert(struct device *dev); + +#endif /* __ARCHE_PLATFORM_H */ diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h new file mode 100644 index 000000000000..7fbddfc40d83 --- /dev/null +++ b/drivers/staging/greybus/arpc.h @@ -0,0 +1,109 @@ +/* + * 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 new file mode 100644 index 000000000000..1b4252d5d255 --- /dev/null +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -0,0 +1,207 @@ +/* + * Greybus Audio Device Class Protocol helpers + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" +#include "greybus_protocols.h" +#include "audio_apbridgea.h" +#include "audio_codec.h" + +int gb_audio_apbridgea_set_config(struct gb_connection *connection, + __u16 i2s_port, __u32 format, __u32 rate, + __u32 mclk_freq) +{ + struct audio_apbridgea_set_config_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_CONFIG; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.format = cpu_to_le32(format); + req.rate = cpu_to_le32(rate); + req.mclk_freq = cpu_to_le32(mclk_freq); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_config); + +int gb_audio_apbridgea_register_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid, + __u8 direction) +{ + struct audio_apbridgea_register_cport_request req; + int ret; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.cport = cpu_to_le16(cportid); + req.direction = direction; + + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + return ret; + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_register_cport); + +int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid, + __u8 direction) +{ + struct audio_apbridgea_unregister_cport_request req; + int ret; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.cport = cpu_to_le16(cportid); + req.direction = direction; + + ret = gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); + + gb_pm_runtime_put_autosuspend(connection->bundle); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_unregister_cport); + +int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size) +{ + struct audio_apbridgea_set_tx_data_size_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.size = cpu_to_le16(size); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_tx_data_size); + +int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_prepare_tx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_TX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_tx); + +int gb_audio_apbridgea_start_tx(struct gb_connection *connection, + __u16 i2s_port, __u64 timestamp) +{ + struct audio_apbridgea_start_tx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_TX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.timestamp = cpu_to_le64(timestamp); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_tx); + +int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, __u16 i2s_port) +{ + struct audio_apbridgea_stop_tx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_TX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_tx); + +int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_shutdown_tx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_tx); + +int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size) +{ + struct audio_apbridgea_set_rx_data_size_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.size = cpu_to_le16(size); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_rx_data_size); + +int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_prepare_rx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_RX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_rx); + +int gb_audio_apbridgea_start_rx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_start_rx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_RX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_rx); + +int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, __u16 i2s_port) +{ + struct audio_apbridgea_stop_rx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_RX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_rx); + +int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_shutdown_rx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_rx); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("greybus:audio-apbridgea"); +MODULE_DESCRIPTION("Greybus Special APBridgeA Audio Protocol library"); +MODULE_AUTHOR("Mark Greer "); diff --git a/drivers/staging/greybus/audio_apbridgea.h b/drivers/staging/greybus/audio_apbridgea.h new file mode 100644 index 000000000000..b94cb05c89e4 --- /dev/null +++ b/drivers/staging/greybus/audio_apbridgea.h @@ -0,0 +1,156 @@ +/** + * 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 + * I2S bus between the DSP on the MSM8994 and APBridgeA. Therefore, + * we can predefine several low-level attributes of the communication + * because we know that they are supported. In particular, the following + * assumptions are made: + * - there are two channels (i.e., stereo) + * - the low-level protocol is I2S as defined by Philips/NXP + * - the DSP on the MSM8994 is the clock master for MCLK, BCLK, and WCLK + * - WCLK changes on the falling edge of BCLK + * - WCLK low for left channel; high for right channel + * - TX data is sent on the falling edge of BCLK + * - RX data is received/latched on the rising edge of BCLK + */ + +#ifndef __AUDIO_APBRIDGEA_H +#define __AUDIO_APBRIDGEA_H + +#define AUDIO_APBRIDGEA_TYPE_SET_CONFIG 0x01 +#define AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT 0x02 +#define AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT 0x03 +#define AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE 0x04 + /* 0x05 unused */ +#define AUDIO_APBRIDGEA_TYPE_PREPARE_TX 0x06 +#define AUDIO_APBRIDGEA_TYPE_START_TX 0x07 +#define AUDIO_APBRIDGEA_TYPE_STOP_TX 0x08 +#define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX 0x09 +#define AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE 0x0a + /* 0x0b unused */ +#define AUDIO_APBRIDGEA_TYPE_PREPARE_RX 0x0c +#define AUDIO_APBRIDGEA_TYPE_START_RX 0x0d +#define AUDIO_APBRIDGEA_TYPE_STOP_RX 0x0e +#define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX 0x0f + +#define AUDIO_APBRIDGEA_PCM_FMT_8 BIT(0) +#define AUDIO_APBRIDGEA_PCM_FMT_16 BIT(1) +#define AUDIO_APBRIDGEA_PCM_FMT_24 BIT(2) +#define AUDIO_APBRIDGEA_PCM_FMT_32 BIT(3) +#define AUDIO_APBRIDGEA_PCM_FMT_64 BIT(4) + +#define AUDIO_APBRIDGEA_PCM_RATE_5512 BIT(0) +#define AUDIO_APBRIDGEA_PCM_RATE_8000 BIT(1) +#define AUDIO_APBRIDGEA_PCM_RATE_11025 BIT(2) +#define AUDIO_APBRIDGEA_PCM_RATE_16000 BIT(3) +#define AUDIO_APBRIDGEA_PCM_RATE_22050 BIT(4) +#define AUDIO_APBRIDGEA_PCM_RATE_32000 BIT(5) +#define AUDIO_APBRIDGEA_PCM_RATE_44100 BIT(6) +#define AUDIO_APBRIDGEA_PCM_RATE_48000 BIT(7) +#define AUDIO_APBRIDGEA_PCM_RATE_64000 BIT(8) +#define AUDIO_APBRIDGEA_PCM_RATE_88200 BIT(9) +#define AUDIO_APBRIDGEA_PCM_RATE_96000 BIT(10) +#define AUDIO_APBRIDGEA_PCM_RATE_176400 BIT(11) +#define AUDIO_APBRIDGEA_PCM_RATE_192000 BIT(12) + +#define AUDIO_APBRIDGEA_DIRECTION_TX BIT(0) +#define AUDIO_APBRIDGEA_DIRECTION_RX BIT(1) + +/* The I2S port is passed in the 'index' parameter of the USB request */ +/* The CPort is passed in the 'value' parameter of the USB request */ + +struct audio_apbridgea_hdr { + __u8 type; + __le16 i2s_port; + __u8 data[0]; +} __packed; + +struct audio_apbridgea_set_config_request { + struct audio_apbridgea_hdr hdr; + __le32 format; /* AUDIO_APBRIDGEA_PCM_FMT_* */ + __le32 rate; /* AUDIO_APBRIDGEA_PCM_RATE_* */ + __le32 mclk_freq; /* XXX Remove? */ +} __packed; + +struct audio_apbridgea_register_cport_request { + struct audio_apbridgea_hdr hdr; + __le16 cport; + __u8 direction; +} __packed; + +struct audio_apbridgea_unregister_cport_request { + struct audio_apbridgea_hdr hdr; + __le16 cport; + __u8 direction; +} __packed; + +struct audio_apbridgea_set_tx_data_size_request { + struct audio_apbridgea_hdr hdr; + __le16 size; +} __packed; + +struct audio_apbridgea_prepare_tx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_start_tx_request { + struct audio_apbridgea_hdr hdr; + __le64 timestamp; +} __packed; + +struct audio_apbridgea_stop_tx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_shutdown_tx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_set_rx_data_size_request { + struct audio_apbridgea_hdr hdr; + __le16 size; +} __packed; + +struct audio_apbridgea_prepare_rx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_start_rx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_stop_rx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_shutdown_rx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +#endif /*__AUDIO_APBRIDGEA_H */ diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c new file mode 100644 index 000000000000..8a0744b58a32 --- /dev/null +++ b/drivers/staging/greybus/audio_codec.c @@ -0,0 +1,1132 @@ +/* + * APBridge ALSA SoC dummy codec driver + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include + +#include "audio_codec.h" +#include "audio_apbridgea.h" +#include "audio_manager.h" + +static struct gbaudio_codec_info *gbcodec; + +static struct gbaudio_data_connection * +find_data(struct gbaudio_module_info *module, int id) +{ + struct gbaudio_data_connection *data; + + list_for_each_entry(data, &module->data_list, list) { + if (id == data->id) + return data; + } + return NULL; +} + +static struct gbaudio_stream_params * +find_dai_stream_params(struct gbaudio_codec_info *codec, int id, int stream) +{ + struct gbaudio_codec_dai *dai; + + list_for_each_entry(dai, &codec->dai_list, list) { + if (dai->id == id) + return &dai->params[stream]; + } + return NULL; +} + +static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, + struct gbaudio_module_info *module, int id) +{ + int module_state, ret = 0; + u16 data_cport, i2s_port, cportid; + u8 sig_bits, channels; + uint32_t format, rate; + struct gbaudio_data_connection *data; + struct gbaudio_stream_params *params; + + /* find the dai */ + data = find_data(module, id); + if (!data) { + dev_err(module->dev, "%d:DATA connection missing\n", id); + return -ENODEV; + } + module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK]; + + params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_PLAYBACK); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + return -EINVAL; + } + + /* register cport */ + if (module_state < GBAUDIO_CODEC_STARTUP) { + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_register_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + if (ret) { + dev_err_ratelimited(module->dev, + "reg_cport failed:%d\n", ret); + return ret; + } + data->state[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_STARTUP; + dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid); + } + + /* hw_params */ + if (module_state < GBAUDIO_CODEC_HWPARAMS) { + format = params->format; + channels = params->channels; + rate = params->rate; + sig_bits = params->sig_bits; + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, + format, rate, channels, sig_bits); + if (ret) { + dev_err_ratelimited(module->dev, "set_pcm failed:%d\n", + ret); + return ret; + } + data->state[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_HWPARAMS; + dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport); + } + + /* prepare */ + if (module_state < GBAUDIO_CODEC_PREPARE) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err_ratelimited(module->dev, + "set_tx_data_size failed:%d\n", + ret); + return ret; + } + ret = gb_audio_gb_activate_tx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err_ratelimited(module->dev, + "activate_tx failed:%d\n", ret); + return ret; + } + data->state[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_PREPARE; + dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport); + } + + return 0; +} + +static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) +{ + int ret; + u16 data_cport, cportid, i2s_port; + int module_state; + struct gbaudio_data_connection *data; + + /* find the dai */ + data = find_data(module, id); + if (!data) { + dev_err(module->dev, "%d:DATA connection missing\n", id); + return -ENODEV; + } + module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK]; + + if (module_state > GBAUDIO_CODEC_HWPARAMS) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err_ratelimited(module->dev, + "deactivate_tx failed:%d\n", ret); + return ret; + } + dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport); + data->state[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_HWPARAMS; + } + + if (module_state > GBAUDIO_CODEC_SHUTDOWN) { + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + if (ret) { + dev_err_ratelimited(module->dev, + "unregister_cport failed:%d\n", + ret); + return ret; + } + dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid); + data->state[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_SHUTDOWN; + } + + return 0; +} + +static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, + struct gbaudio_module_info *module, int id) +{ + int module_state, ret = 0; + u16 data_cport, i2s_port, cportid; + u8 sig_bits, channels; + uint32_t format, rate; + struct gbaudio_data_connection *data; + struct gbaudio_stream_params *params; + + /* find the dai */ + data = find_data(module, id); + if (!data) { + dev_err(module->dev, "%d:DATA connection missing\n", id); + return -ENODEV; + } + module_state = data->state[SNDRV_PCM_STREAM_CAPTURE]; + + params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_CAPTURE); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + return -EINVAL; + } + + /* register cport */ + if (module_state < GBAUDIO_CODEC_STARTUP) { + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_register_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + if (ret) { + dev_err_ratelimited(module->dev, + "reg_cport failed:%d\n", ret); + return ret; + } + data->state[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_STARTUP; + dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid); + } + + /* hw_params */ + if (module_state < GBAUDIO_CODEC_HWPARAMS) { + format = params->format; + channels = params->channels; + rate = params->rate; + sig_bits = params->sig_bits; + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, + format, rate, channels, sig_bits); + if (ret) { + dev_err_ratelimited(module->dev, "set_pcm failed:%d\n", + ret); + return ret; + } + data->state[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_HWPARAMS; + dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport); + } + + /* prepare */ + if (module_state < GBAUDIO_CODEC_PREPARE) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_rx_data_size(module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err_ratelimited(module->dev, + "set_rx_data_size failed:%d\n", + ret); + return ret; + } + ret = gb_audio_gb_activate_rx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err_ratelimited(module->dev, + "activate_rx failed:%d\n", ret); + return ret; + } + data->state[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_PREPARE; + dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport); + } + + return 0; +} + +static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) +{ + int ret; + u16 data_cport, cportid, i2s_port; + int module_state; + struct gbaudio_data_connection *data; + + /* find the dai */ + data = find_data(module, id); + if (!data) { + dev_err(module->dev, "%d:DATA connection missing\n", id); + return -ENODEV; + } + module_state = data->state[SNDRV_PCM_STREAM_CAPTURE]; + + if (module_state > GBAUDIO_CODEC_HWPARAMS) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_deactivate_rx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err_ratelimited(module->dev, + "deactivate_rx failed:%d\n", ret); + return ret; + } + dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport); + data->state[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_HWPARAMS; + } + + if (module_state > GBAUDIO_CODEC_SHUTDOWN) { + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + if (ret) { + dev_err_ratelimited(module->dev, + "unregister_cport failed:%d\n", + ret); + return ret; + } + dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid); + data->state[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_SHUTDOWN; + } + + return 0; +} + +int gbaudio_module_update(struct gbaudio_codec_info *codec, + struct snd_soc_dapm_widget *w, + struct gbaudio_module_info *module, int enable) +{ + int dai_id, ret; + char intf_name[NAME_SIZE], dir[NAME_SIZE]; + + dev_dbg(module->dev, "%s:Module update %s sequence\n", w->name, + enable ? "Enable":"Disable"); + + if ((w->id != snd_soc_dapm_aif_in) && (w->id != snd_soc_dapm_aif_out)) { + dev_dbg(codec->dev, "No action required for %s\n", w->name); + return 0; + } + + /* parse dai_id from AIF widget's stream_name */ + ret = sscanf(w->sname, "%s %d %s", intf_name, &dai_id, dir); + if (ret < 3) { + dev_err(codec->dev, "Error while parsing dai_id for %s\n", + w->name); + return -EINVAL; + } + + mutex_lock(&codec->lock); + if (w->id == snd_soc_dapm_aif_in) { + if (enable) + ret = gbaudio_module_enable_tx(codec, module, dai_id); + else + ret = gbaudio_module_disable_tx(module, dai_id); + } else if (w->id == snd_soc_dapm_aif_out) { + if (enable) + ret = gbaudio_module_enable_rx(codec, module, dai_id); + else + ret = gbaudio_module_disable_rx(module, dai_id); + } + + mutex_unlock(&codec->lock); + + return ret; +} +EXPORT_SYMBOL(gbaudio_module_update); + +/* + * codec DAI ops + */ +static int gbcodec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; + + mutex_lock(&codec->lock); + + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + mutex_unlock(&codec->lock); + return -ENODEV; + } + + params = find_dai_stream_params(codec, dai->id, substream->stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + params->state = GBAUDIO_CODEC_STARTUP; + mutex_unlock(&codec->lock); + /* to prevent suspend in case of active audio */ + pm_stay_awake(dai->dev); + + return 0; +} + +static void gbcodec_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; + + mutex_lock(&codec->lock); + + if (list_empty(&codec->module_list)) + dev_info(codec->dev, "No codec module available during shutdown\n"); + + params = find_dai_stream_params(codec, dai->id, substream->stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return; + } + params->state = GBAUDIO_CODEC_SHUTDOWN; + mutex_unlock(&codec->lock); + pm_relax(dai->dev); + return; +} + +static int gbcodec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hwparams, + struct snd_soc_dai *dai) +{ + int ret; + u8 sig_bits, channels; + uint32_t format, rate; + struct gbaudio_module_info *module; + struct gbaudio_data_connection *data; + struct gb_bundle *bundle; + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; + + mutex_lock(&codec->lock); + + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + mutex_unlock(&codec->lock); + return -ENODEV; + } + + /* + * assuming, currently only 48000 Hz, 16BIT_LE, stereo + * is supported, validate params before configuring codec + */ + if (params_channels(hwparams) != 2) { + dev_err(dai->dev, "Invalid channel count:%d\n", + params_channels(hwparams)); + mutex_unlock(&codec->lock); + return -EINVAL; + } + channels = params_channels(hwparams); + + if (params_rate(hwparams) != 48000) { + dev_err(dai->dev, "Invalid sampling rate:%d\n", + params_rate(hwparams)); + mutex_unlock(&codec->lock); + return -EINVAL; + } + rate = GB_AUDIO_PCM_RATE_48000; + + if (params_format(hwparams) != SNDRV_PCM_FORMAT_S16_LE) { + dev_err(dai->dev, "Invalid format:%d\n", + params_format(hwparams)); + mutex_unlock(&codec->lock); + return -EINVAL; + } + format = GB_AUDIO_PCM_FMT_S16_LE; + + /* find the data connection */ + list_for_each_entry(module, &codec->module_list, list) { + data = find_data(module, dai->id); + if (data) + break; + } + + if (!data) { + dev_err(dai->dev, "DATA connection missing\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + + params = find_dai_stream_params(codec, dai->id, substream->stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + + bundle = to_gb_bundle(module->dev); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) { + mutex_unlock(&codec->lock); + return ret; + } + + ret = gb_audio_apbridgea_set_config(data->connection, 0, + AUDIO_APBRIDGEA_PCM_FMT_16, + AUDIO_APBRIDGEA_PCM_RATE_48000, + 6144000); + if (ret) { + dev_err_ratelimited(dai->dev, "%d: Error during set_config\n", + ret); + mutex_unlock(&codec->lock); + return ret; + } + + gb_pm_runtime_put_noidle(bundle); + + params->state = GBAUDIO_CODEC_HWPARAMS; + params->format = format; + params->rate = rate; + params->channels = channels; + params->sig_bits = sig_bits; + + mutex_unlock(&codec->lock); + return 0; +} + +static int gbcodec_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int ret; + struct gbaudio_module_info *module; + struct gbaudio_data_connection *data; + struct gb_bundle *bundle; + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; + + mutex_lock(&codec->lock); + + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + mutex_unlock(&codec->lock); + return -ENODEV; + } + + list_for_each_entry(module, &codec->module_list, list) { + /* find the dai */ + data = find_data(module, dai->id); + if (data) + break; + } + if (!data) { + dev_err(dai->dev, "DATA connection missing\n"); + mutex_unlock(&codec->lock); + return -ENODEV; + } + + params = find_dai_stream_params(codec, dai->id, substream->stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + + bundle = to_gb_bundle(module->dev); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) { + mutex_unlock(&codec->lock); + return ret; + } + + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_apbridgea_set_tx_data_size(data->connection, 0, + 192); + break; + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_apbridgea_set_rx_data_size(data->connection, 0, + 192); + break; + } + if (ret) { + mutex_unlock(&codec->lock); + dev_err_ratelimited(dai->dev, "set_data_size failed:%d\n", + ret); + return ret; + } + + gb_pm_runtime_put_noidle(bundle); + + params->state = GBAUDIO_CODEC_PREPARE; + mutex_unlock(&codec->lock); + return 0; +} + +static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + int ret; + struct gbaudio_data_connection *data; + struct gbaudio_module_info *module; + struct gb_bundle *bundle; + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; + + + dev_dbg(dai->dev, "Mute:%d, Direction:%s\n", mute, + stream ? "CAPTURE":"PLAYBACK"); + + mutex_lock(&codec->lock); + + params = find_dai_stream_params(codec, dai->id, stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + if (mute) { + params->state = GBAUDIO_CODEC_STOP; + ret = 0; + } else { + ret = -ENODEV; + } + mutex_unlock(&codec->lock); + return ret; + } + + list_for_each_entry(module, &codec->module_list, list) { + /* find the dai */ + data = find_data(module, dai->id); + if (data) + break; + } + if (!data) { + dev_err(dai->dev, "%s:%s DATA connection missing\n", + dai->name, module->name); + mutex_unlock(&codec->lock); + return -ENODEV; + } + + bundle = to_gb_bundle(module->dev); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) { + mutex_unlock(&codec->lock); + return ret; + } + + if (!mute && !stream) {/* start playback */ + ret = gb_audio_apbridgea_prepare_tx(data->connection, + 0); + if (!ret) + ret = gb_audio_apbridgea_start_tx(data->connection, + 0, 0); + params->state = GBAUDIO_CODEC_START; + } else if (!mute && stream) {/* start capture */ + ret = gb_audio_apbridgea_prepare_rx(data->connection, + 0); + if (!ret) + ret = gb_audio_apbridgea_start_rx(data->connection, + 0); + params->state = GBAUDIO_CODEC_START; + } else if (mute && !stream) {/* stop playback */ + ret = gb_audio_apbridgea_stop_tx(data->connection, 0); + if (!ret) + ret = gb_audio_apbridgea_shutdown_tx(data->connection, + 0); + params->state = GBAUDIO_CODEC_STOP; + } else if (mute && stream) {/* stop capture */ + ret = gb_audio_apbridgea_stop_rx(data->connection, 0); + if (!ret) + ret = gb_audio_apbridgea_shutdown_rx(data->connection, + 0); + params->state = GBAUDIO_CODEC_STOP; + } else + ret = -EINVAL; + if (ret) + dev_err_ratelimited(dai->dev, + "%s:Error during %s %s stream:%d\n", + module->name, mute ? "Mute" : "Unmute", + stream ? "Capture" : "Playback", ret); + + gb_pm_runtime_put_noidle(bundle); + mutex_unlock(&codec->lock); + return ret; +} + +static struct snd_soc_dai_ops gbcodec_dai_ops = { + .startup = gbcodec_startup, + .shutdown = gbcodec_shutdown, + .hw_params = gbcodec_hw_params, + .prepare = gbcodec_prepare, + .mute_stream = gbcodec_mute_stream, +}; + +static struct snd_soc_dai_driver gbaudio_dai[] = { + { + .name = "apb-i2s0", + .id = 0, + .playback = { + .stream_name = "I2S 0 Playback", + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FORMAT_S16_LE, + .rate_max = 48000, + .rate_min = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .capture = { + .stream_name = "I2S 0 Capture", + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FORMAT_S16_LE, + .rate_max = 48000, + .rate_min = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &gbcodec_dai_ops, + }, +}; + +static int gbaudio_init_jack(struct gbaudio_module_info *module, + struct snd_soc_codec *codec) +{ + int ret; + + if (!module->jack_mask) + return 0; + + snprintf(module->jack_name, NAME_SIZE, "GB %d Headset Jack", + module->dev_id); + ret = snd_soc_jack_new(codec, module->jack_name, module->jack_mask, + &module->headset_jack); + if (ret) { + dev_err(module->dev, "Failed to create new jack\n"); + return ret; + } + + if (!module->button_mask) + return 0; + + snprintf(module->button_name, NAME_SIZE, "GB %d Button Jack", + module->dev_id); + ret = snd_soc_jack_new(codec, module->button_name, module->button_mask, + &module->button_jack); + if (ret) { + dev_err(module->dev, "Failed to create button jack\n"); + return ret; + } + + /* + * Currently, max 4 buttons are supported with following key mapping + * BTN_0 = KEY_MEDIA + * BTN_1 = KEY_VOICECOMMAND + * BTN_2 = KEY_VOLUMEUP + * BTN_3 = KEY_VOLUMEDOWN + */ + + if (module->button_mask & SND_JACK_BTN_0) { + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_0, + KEY_MEDIA); + if (ret) { + dev_err(module->dev, "Failed to set BTN_0\n"); + return ret; + } + } + + if (module->button_mask & SND_JACK_BTN_1) { + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_1, + KEY_VOICECOMMAND); + if (ret) { + dev_err(module->dev, "Failed to set BTN_1\n"); + return ret; + } + } + + if (module->button_mask & SND_JACK_BTN_2) { + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_2, + KEY_VOLUMEUP); + if (ret) { + dev_err(module->dev, "Failed to set BTN_2\n"); + return ret; + } + } + + if (module->button_mask & SND_JACK_BTN_3) { + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_3, + KEY_VOLUMEDOWN); + if (ret) { + dev_err(module->dev, "Failed to set BTN_0\n"); + return ret; + } + } + + /* FIXME + * verify if this is really required + set_bit(INPUT_PROP_NO_DUMMY_RELEASE, + module->button_jack.jack->input_dev->propbit); + */ + + return 0; +} + +int gbaudio_register_module(struct gbaudio_module_info *module) +{ + int ret; + struct snd_soc_codec *codec; + struct snd_card *card; + struct snd_soc_jack *jack = NULL; + + if (!gbcodec) { + dev_err(module->dev, "GB Codec not yet probed\n"); + return -EAGAIN; + } + + codec = gbcodec->codec; + card = codec->card->snd_card; + + down_write(&card->controls_rwsem); + + if (module->num_dais) { + dev_err(gbcodec->dev, + "%d:DAIs not supported via gbcodec driver\n", + module->num_dais); + up_write(&card->controls_rwsem); + return -EINVAL; + } + + ret = gbaudio_init_jack(module, codec); + if (ret) { + up_write(&card->controls_rwsem); + return ret; + } + + if (module->dapm_widgets) + snd_soc_dapm_new_controls(&codec->dapm, module->dapm_widgets, + module->num_dapm_widgets); + if (module->controls) + snd_soc_add_codec_controls(codec, module->controls, + module->num_controls); + if (module->dapm_routes) + snd_soc_dapm_add_routes(&codec->dapm, module->dapm_routes, + module->num_dapm_routes); + + /* card already instantiated, create widgets here only */ + if (codec->card->instantiated) { + snd_soc_dapm_link_component_dai_widgets(codec->card, + &codec->dapm); +#ifdef CONFIG_SND_JACK + /* register jack devices for this module from codec->jack_list */ + list_for_each_entry(jack, &codec->jack_list, list) { + if ((jack == &module->headset_jack) + || (jack == &module->button_jack)) + snd_device_register(codec->card->snd_card, + jack->jack); + } +#endif + } + + mutex_lock(&gbcodec->lock); + list_add(&module->list, &gbcodec->module_list); + mutex_unlock(&gbcodec->lock); + + if (codec->card->instantiated) + ret = snd_soc_dapm_new_widgets(&codec->dapm); + dev_dbg(codec->dev, "Registered %s module\n", module->name); + + up_write(&card->controls_rwsem); + return ret; +} +EXPORT_SYMBOL(gbaudio_register_module); + +static void gbaudio_codec_clean_data_tx(struct gbaudio_data_connection *data) +{ + u16 i2s_port, cportid; + int ret; + + if (list_is_singular(&gbcodec->module_list)) { + ret = gb_audio_apbridgea_stop_tx(data->connection, 0); + if (ret) + return; + ret = gb_audio_apbridgea_shutdown_tx(data->connection, + 0); + if (ret) + return; + } + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + data->state[0] = GBAUDIO_CODEC_SHUTDOWN; +} + +static void gbaudio_codec_clean_data_rx(struct gbaudio_data_connection *data) +{ + u16 i2s_port, cportid; + int ret; + + if (list_is_singular(&gbcodec->module_list)) { + ret = gb_audio_apbridgea_stop_rx(data->connection, 0); + if (ret) + return; + ret = gb_audio_apbridgea_shutdown_rx(data->connection, + 0); + if (ret) + return; + } + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + data->state[1] = GBAUDIO_CODEC_SHUTDOWN; +} + + +static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) +{ + struct gbaudio_data_connection *data; + int pb_state, cap_state; + + dev_dbg(gbcodec->dev, "%s: removed, cleanup APBridge\n", module->name); + list_for_each_entry(data, &module->data_list, list) { + pb_state = data->state[0]; + cap_state = data->state[1]; + + if (pb_state > GBAUDIO_CODEC_SHUTDOWN) + gbaudio_codec_clean_data_tx(data); + + if (cap_state > GBAUDIO_CODEC_SHUTDOWN) + gbaudio_codec_clean_data_rx(data); + + } +} + +void gbaudio_unregister_module(struct gbaudio_module_info *module) +{ + struct snd_soc_codec *codec = gbcodec->codec; + struct snd_card *card = codec->card->snd_card; + struct snd_soc_jack *jack, *next_j; + int mask; + + dev_dbg(codec->dev, "Unregister %s module\n", module->name); + + down_write(&card->controls_rwsem); + mutex_lock(&gbcodec->lock); + gbaudio_codec_cleanup(module); + list_del(&module->list); + dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); + mutex_unlock(&gbcodec->lock); + +#ifdef CONFIG_SND_JACK + /* free jack devices for this module from codec->jack_list */ + list_for_each_entry_safe(jack, next_j, &codec->jack_list, list) { + if (jack == &module->headset_jack) + mask = GBCODEC_JACK_MASK; + else if (jack == &module->button_jack) + mask = GBCODEC_JACK_BUTTON_MASK; + else + mask = 0; + if (mask) { + dev_dbg(module->dev, "Report %s removal\n", + jack->jack->id); + snd_soc_jack_report(jack, 0, mask); + snd_device_free(codec->card->snd_card, jack->jack); + list_del(&jack->list); + } + } +#endif + + if (module->dapm_routes) { + dev_dbg(codec->dev, "Removing %d routes\n", + module->num_dapm_routes); + snd_soc_dapm_del_routes(&codec->dapm, module->dapm_routes, + module->num_dapm_routes); + } + if (module->controls) { + dev_dbg(codec->dev, "Removing %d controls\n", + module->num_controls); + snd_soc_remove_codec_controls(codec, module->controls, + module->num_controls); + } + if (module->dapm_widgets) { + dev_dbg(codec->dev, "Removing %d widgets\n", + module->num_dapm_widgets); + snd_soc_dapm_free_controls(&codec->dapm, module->dapm_widgets, + module->num_dapm_widgets); + } + + dev_dbg(codec->dev, "Unregistered %s module\n", module->name); + + up_write(&card->controls_rwsem); +} +EXPORT_SYMBOL(gbaudio_unregister_module); + +/* + * codec driver ops + */ +static int gbcodec_probe(struct snd_soc_codec *codec) +{ + int i; + struct gbaudio_codec_info *info; + struct gbaudio_codec_dai *dai; + + info = devm_kzalloc(codec->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->dev = codec->dev; + INIT_LIST_HEAD(&info->module_list); + mutex_init(&info->lock); + INIT_LIST_HEAD(&info->dai_list); + + /* init dai_list used to maintain runtime stream info */ + for (i = 0; i < ARRAY_SIZE(gbaudio_dai); i++) { + dai = devm_kzalloc(codec->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + dai->id = gbaudio_dai[i].id; + list_add(&dai->list, &info->dai_list); + } + + info->codec = codec; + snd_soc_codec_set_drvdata(codec, info); + gbcodec = info; + + device_init_wakeup(codec->dev, 1); + return 0; +} + +static int gbcodec_remove(struct snd_soc_codec *codec) +{ + /* Empty function for now */ + return 0; +} + +static u8 gbcodec_reg[GBCODEC_REG_COUNT] = { + [GBCODEC_CTL_REG] = GBCODEC_CTL_REG_DEFAULT, + [GBCODEC_MUTE_REG] = GBCODEC_MUTE_REG_DEFAULT, + [GBCODEC_PB_LVOL_REG] = GBCODEC_PB_VOL_REG_DEFAULT, + [GBCODEC_PB_RVOL_REG] = GBCODEC_PB_VOL_REG_DEFAULT, + [GBCODEC_CAP_LVOL_REG] = GBCODEC_CAP_VOL_REG_DEFAULT, + [GBCODEC_CAP_RVOL_REG] = GBCODEC_CAP_VOL_REG_DEFAULT, + [GBCODEC_APB1_MUX_REG] = GBCODEC_APB1_MUX_REG_DEFAULT, + [GBCODEC_APB2_MUX_REG] = GBCODEC_APB2_MUX_REG_DEFAULT, +}; + +static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + int ret = 0; + + if (reg == SND_SOC_NOPM) + return 0; + + BUG_ON(reg >= GBCODEC_REG_COUNT); + + gbcodec_reg[reg] = value; + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, value); + + return ret; +} + +static unsigned int gbcodec_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int val = 0; + + if (reg == SND_SOC_NOPM) + return 0; + + BUG_ON(reg >= GBCODEC_REG_COUNT); + + val = gbcodec_reg[reg]; + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, val); + + return val; +} + +static struct snd_soc_codec_driver soc_codec_dev_gbaudio = { + .probe = gbcodec_probe, + .remove = gbcodec_remove, + + .read = gbcodec_read, + .write = gbcodec_write, + + .reg_cache_size = GBCODEC_REG_COUNT, + .reg_cache_default = gbcodec_reg_defaults, + .reg_word_size = 1, + + .idle_bias_off = true, + .ignore_pmdown_time = 1, +}; + +#ifdef CONFIG_PM +static int gbaudio_codec_suspend(struct device *dev) +{ + dev_dbg(dev, "%s: suspend\n", __func__); + return 0; +} + +static int gbaudio_codec_resume(struct device *dev) +{ + dev_dbg(dev, "%s: resume\n", __func__); + return 0; +} + +static const struct dev_pm_ops gbaudio_codec_pm_ops = { + .suspend = gbaudio_codec_suspend, + .resume = gbaudio_codec_resume, +}; +#endif + +static int gbaudio_codec_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_gbaudio, + gbaudio_dai, ARRAY_SIZE(gbaudio_dai)); +} + +static int gbaudio_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static const struct of_device_id greybus_asoc_machine_of_match[] = { + { .compatible = "toshiba,apb-dummy-codec", }, + {}, +}; + +static struct platform_driver gbaudio_codec_driver = { + .driver = { + .name = "apb-dummy-codec", + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &gbaudio_codec_pm_ops, +#endif + .of_match_table = greybus_asoc_machine_of_match, + }, + .probe = gbaudio_codec_probe, + .remove = gbaudio_codec_remove, +}; +module_platform_driver(gbaudio_codec_driver); + +MODULE_DESCRIPTION("APBridge ALSA SoC dummy codec driver"); +MODULE_AUTHOR("Vaibhav Agarwal "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:apb-dummy-codec"); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h new file mode 100644 index 000000000000..ca027bd99ad7 --- /dev/null +++ b/drivers/staging/greybus/audio_codec.h @@ -0,0 +1,283 @@ +/* + * Greybus audio driver + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __LINUX_GBAUDIO_CODEC_H +#define __LINUX_GBAUDIO_CODEC_H + +#include +#include + +#include "greybus.h" +#include "greybus_protocols.h" + +#define NAME_SIZE 32 +#define MAX_DAIS 2 /* APB1, APB2 */ + +enum { + APB1_PCM = 0, + APB2_PCM, + NUM_CODEC_DAIS, +}; + +enum gbcodec_reg_index { + GBCODEC_CTL_REG, + GBCODEC_MUTE_REG, + GBCODEC_PB_LVOL_REG, + GBCODEC_PB_RVOL_REG, + GBCODEC_CAP_LVOL_REG, + GBCODEC_CAP_RVOL_REG, + GBCODEC_APB1_MUX_REG, + GBCODEC_APB2_MUX_REG, + GBCODEC_REG_COUNT +}; + +/* device_type should be same as defined in audio.h (Android media layer) */ +enum { + GBAUDIO_DEVICE_NONE = 0x0, + /* reserved bits */ + GBAUDIO_DEVICE_BIT_IN = 0x80000000, + GBAUDIO_DEVICE_BIT_DEFAULT = 0x40000000, + /* output devices */ + GBAUDIO_DEVICE_OUT_SPEAKER = 0x2, + GBAUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4, + GBAUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8, + /* input devices */ + GBAUDIO_DEVICE_IN_BUILTIN_MIC = GBAUDIO_DEVICE_BIT_IN | 0x4, + GBAUDIO_DEVICE_IN_WIRED_HEADSET = GBAUDIO_DEVICE_BIT_IN | 0x10, +}; + +/* bit 0-SPK, 1-HP, 2-DAC, + * 4-MIC, 5-HSMIC, 6-MIC2 + */ +#define GBCODEC_CTL_REG_DEFAULT 0x00 + +/* bit 0,1 - APB1-PB-L/R + * bit 2,3 - APB2-PB-L/R + * bit 4,5 - APB1-Cap-L/R + * bit 6,7 - APB2-Cap-L/R + */ +#define GBCODEC_MUTE_REG_DEFAULT 0x00 + +/* 0-127 steps */ +#define GBCODEC_PB_VOL_REG_DEFAULT 0x00 +#define GBCODEC_CAP_VOL_REG_DEFAULT 0x00 + +/* bit 0,1,2 - PB stereo, left, right + * bit 8,9,10 - Cap stereo, left, right + */ +#define GBCODEC_APB1_MUX_REG_DEFAULT 0x00 +#define GBCODEC_APB2_MUX_REG_DEFAULT 0x00 + +#define GBCODEC_JACK_MASK 0x0000FFFF +#define GBCODEC_JACK_BUTTON_MASK 0xFFFF0000 + +static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { + GBCODEC_CTL_REG_DEFAULT, + GBCODEC_MUTE_REG_DEFAULT, + GBCODEC_PB_VOL_REG_DEFAULT, + GBCODEC_PB_VOL_REG_DEFAULT, + GBCODEC_CAP_VOL_REG_DEFAULT, + GBCODEC_CAP_VOL_REG_DEFAULT, + GBCODEC_APB1_MUX_REG_DEFAULT, + GBCODEC_APB2_MUX_REG_DEFAULT, +}; + +enum gbaudio_codec_state { + GBAUDIO_CODEC_SHUTDOWN = 0, + GBAUDIO_CODEC_STARTUP, + GBAUDIO_CODEC_HWPARAMS, + GBAUDIO_CODEC_PREPARE, + GBAUDIO_CODEC_START, + GBAUDIO_CODEC_STOP, +}; + +struct gbaudio_stream_params { + int state; + u8 sig_bits, channels; + uint32_t format, rate; +}; + +struct gbaudio_codec_dai { + int id; + /* runtime params for playback/capture streams */ + struct gbaudio_stream_params params[2]; + struct list_head list; +}; + +struct gbaudio_codec_info { + struct device *dev; + struct snd_soc_codec *codec; + struct list_head module_list; + /* to maintain runtime stream params for each DAI */ + struct list_head dai_list; + struct mutex lock; + u8 reg[GBCODEC_REG_COUNT]; +}; + +struct gbaudio_widget { + __u8 id; + const char *name; + struct list_head list; +}; + +struct gbaudio_control { + __u8 id; + char *name; + char *wname; + const char * const *texts; + int items; + struct list_head list; +}; + +struct gbaudio_data_connection { + int id; + __le16 data_cport; + struct gb_connection *connection; + struct list_head list; + /* maintain runtime state for playback/capture stream */ + int state[2]; +}; + +/* stream direction */ +#define GB_PLAYBACK BIT(0) +#define GB_CAPTURE BIT(1) + +enum gbaudio_module_state { + GBAUDIO_MODULE_OFF = 0, + GBAUDIO_MODULE_ON, +}; + +struct gbaudio_module_info { + /* module info */ + struct device *dev; + int dev_id; /* check if it should be bundle_id/hd_cport_id */ + int vid; + int pid; + int slot; + int type; + int set_uevent; + char vstr[NAME_SIZE]; + char pstr[NAME_SIZE]; + struct list_head list; + /* need to share this info to above user space */ + int manager_id; + char name[NAME_SIZE]; + unsigned int ip_devices; + unsigned int op_devices; + + /* jack related */ + char jack_name[NAME_SIZE]; + char button_name[NAME_SIZE]; + int jack_type; + int jack_mask; + int button_mask; + int button_status; + struct snd_soc_jack headset_jack; + struct snd_soc_jack button_jack; + + /* connection info */ + struct gb_connection *mgmt_connection; + size_t num_data_connections; + struct list_head data_list; + + /* topology related */ + int num_dais; + int num_controls; + int num_dapm_widgets; + int num_dapm_routes; + unsigned long dai_offset; + unsigned long widget_offset; + unsigned long control_offset; + unsigned long route_offset; + struct snd_kcontrol_new *controls; + struct snd_soc_dapm_widget *dapm_widgets; + struct snd_soc_dapm_route *dapm_routes; + struct snd_soc_dai_driver *dais; + + struct list_head widget_list; + struct list_head ctl_list; + struct list_head widget_ctl_list; + + struct gb_audio_topology *topology; +}; + +int gbaudio_tplg_parse_data(struct gbaudio_module_info *module, + struct gb_audio_topology *tplg_data); +void gbaudio_tplg_release(struct gbaudio_module_info *module); + +int gbaudio_module_update(struct gbaudio_codec_info *codec, + struct snd_soc_dapm_widget *w, + struct gbaudio_module_info *module, + int enable); +int gbaudio_register_module(struct gbaudio_module_info *module); +void gbaudio_unregister_module(struct gbaudio_module_info *module); + +/* protocol related */ +extern int gb_audio_gb_get_topology(struct gb_connection *connection, + struct gb_audio_topology **topology); +extern int gb_audio_gb_get_control(struct gb_connection *connection, + u8 control_id, u8 index, + struct gb_audio_ctl_elem_value *value); +extern int gb_audio_gb_set_control(struct gb_connection *connection, + u8 control_id, u8 index, + struct gb_audio_ctl_elem_value *value); +extern int gb_audio_gb_enable_widget(struct gb_connection *connection, + u8 widget_id); +extern int gb_audio_gb_disable_widget(struct gb_connection *connection, + u8 widget_id); +extern int gb_audio_gb_get_pcm(struct gb_connection *connection, + u16 data_cport, uint32_t *format, + uint32_t *rate, u8 *channels, + u8 *sig_bits); +extern int gb_audio_gb_set_pcm(struct gb_connection *connection, + u16 data_cport, uint32_t format, + uint32_t rate, u8 channels, + u8 sig_bits); +extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, + u16 data_cport, u16 size); +extern int gb_audio_gb_activate_tx(struct gb_connection *connection, + u16 data_cport); +extern int gb_audio_gb_deactivate_tx(struct gb_connection *connection, + u16 data_cport); +extern int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, + u16 data_cport, u16 size); +extern int gb_audio_gb_activate_rx(struct gb_connection *connection, + u16 data_cport); +extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection, + u16 data_cport); +extern int gb_audio_apbridgea_set_config(struct gb_connection *connection, + __u16 i2s_port, __u32 format, + __u32 rate, __u32 mclk_freq); +extern int gb_audio_apbridgea_register_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid, + __u8 direction); +extern int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid, + __u8 direction); +extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size); +extern int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_start_tx(struct gb_connection *connection, + __u16 i2s_port, __u64 timestamp); +extern int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size); +extern int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_start_rx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection, + __u16 i2s_port); + +#endif /* __LINUX_GBAUDIO_CODEC_H */ diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c new file mode 100644 index 000000000000..42f287dd7b84 --- /dev/null +++ b/drivers/staging/greybus/audio_gb.c @@ -0,0 +1,228 @@ +/* + * Greybus Audio Device Class Protocol helpers + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" +#include "greybus_protocols.h" +#include "operation.h" +#include "audio_codec.h" + +/* TODO: Split into separate calls */ +int gb_audio_gb_get_topology(struct gb_connection *connection, + struct gb_audio_topology **topology) +{ + struct gb_audio_get_topology_size_response size_resp; + struct gb_audio_topology *topo; + u16 size; + int ret; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE, + NULL, 0, &size_resp, sizeof(size_resp)); + if (ret) + return ret; + + size = le16_to_cpu(size_resp.size); + if (size < sizeof(*topo)) + return -ENODATA; + + topo = kzalloc(size, GFP_KERNEL); + if (!topo) + return -ENOMEM; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY, NULL, 0, + topo, size); + if (ret) { + kfree(topo); + return ret; + } + + *topology = topo; + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology); + +int gb_audio_gb_get_control(struct gb_connection *connection, + u8 control_id, u8 index, + struct gb_audio_ctl_elem_value *value) +{ + struct gb_audio_get_control_request req; + struct gb_audio_get_control_response resp; + int ret; + + req.control_id = control_id; + req.index = index; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_CONTROL, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + return ret; + + memcpy(value, &resp.value, sizeof(*value)); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_control); + +int gb_audio_gb_set_control(struct gb_connection *connection, + u8 control_id, u8 index, + struct gb_audio_ctl_elem_value *value) +{ + struct gb_audio_set_control_request req; + + req.control_id = control_id; + req.index = index; + memcpy(&req.value, value, sizeof(req.value)); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_CONTROL, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_control); + +int gb_audio_gb_enable_widget(struct gb_connection *connection, + u8 widget_id) +{ + struct gb_audio_enable_widget_request req; + + req.widget_id = widget_id; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ENABLE_WIDGET, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget); + +int gb_audio_gb_disable_widget(struct gb_connection *connection, + u8 widget_id) +{ + struct gb_audio_disable_widget_request req; + + req.widget_id = widget_id; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DISABLE_WIDGET, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget); + +int gb_audio_gb_get_pcm(struct gb_connection *connection, u16 data_cport, + uint32_t *format, uint32_t *rate, u8 *channels, + u8 *sig_bits) +{ + struct gb_audio_get_pcm_request req; + struct gb_audio_get_pcm_response resp; + int ret; + + req.data_cport = cpu_to_le16(data_cport); + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_PCM, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + return ret; + + *format = le32_to_cpu(resp.format); + *rate = le32_to_cpu(resp.rate); + *channels = resp.channels; + *sig_bits = resp.sig_bits; + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm); + +int gb_audio_gb_set_pcm(struct gb_connection *connection, u16 data_cport, + uint32_t format, uint32_t rate, u8 channels, + u8 sig_bits) +{ + struct gb_audio_set_pcm_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.format = cpu_to_le32(format); + req.rate = cpu_to_le32(rate); + req.channels = channels; + req.sig_bits = sig_bits; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_PCM, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm); + +int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, + u16 data_cport, u16 size) +{ + struct gb_audio_set_tx_data_size_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.size = cpu_to_le16(size); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_TX_DATA_SIZE, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size); + +int gb_audio_gb_activate_tx(struct gb_connection *connection, + u16 data_cport) +{ + struct gb_audio_activate_tx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_TX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx); + +int gb_audio_gb_deactivate_tx(struct gb_connection *connection, + u16 data_cport) +{ + struct gb_audio_deactivate_tx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_TX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx); + +int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, + u16 data_cport, u16 size) +{ + struct gb_audio_set_rx_data_size_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.size = cpu_to_le16(size); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_RX_DATA_SIZE, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size); + +int gb_audio_gb_activate_rx(struct gb_connection *connection, + u16 data_cport) +{ + struct gb_audio_activate_rx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_RX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx); + +int gb_audio_gb_deactivate_rx(struct gb_connection *connection, + u16 data_cport) +{ + struct gb_audio_deactivate_rx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_RX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("greybus:audio-gb"); +MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library"); +MODULE_AUTHOR("Mark Greer "); diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c new file mode 100644 index 000000000000..aa6508b44fab --- /dev/null +++ b/drivers/staging/greybus/audio_manager.c @@ -0,0 +1,184 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include + +#include "audio_manager.h" +#include "audio_manager_private.h" + +static struct kset *manager_kset; + +static LIST_HEAD(modules_list); +static DECLARE_RWSEM(modules_rwsem); +static DEFINE_IDA(module_id); + +/* helpers */ +static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id) +{ + struct gb_audio_manager_module *module; + + if (id < 0) + return NULL; + + list_for_each_entry(module, &modules_list, list) { + if (module->id == id) + return module; + } + + return NULL; +} + +/* public API */ +int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc) +{ + struct gb_audio_manager_module *module; + int id; + int err; + + id = ida_simple_get(&module_id, 0, 0, GFP_KERNEL); + err = gb_audio_manager_module_create(&module, manager_kset, + id, desc); + if (err) { + ida_simple_remove(&module_id, id); + return err; + } + + /* Add it to the list */ + down_write(&modules_rwsem); + list_add_tail(&module->list, &modules_list); + up_write(&modules_rwsem); + + return module->id; +} +EXPORT_SYMBOL_GPL(gb_audio_manager_add); + +int gb_audio_manager_remove(int id) +{ + struct gb_audio_manager_module *module; + + down_write(&modules_rwsem); + + module = gb_audio_manager_get_locked(id); + if (!module) { + up_write(&modules_rwsem); + return -EINVAL; + } + list_del(&module->list); + kobject_put(&module->kobj); + up_write(&modules_rwsem); + ida_simple_remove(&module_id, id); + return 0; +} +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; + + down_write(&modules_rwsem); + + list_for_each_entry_safe(module, next, &modules_list, list) { + list_del(&module->list); + kobject_put(&module->kobj); + ida_simple_remove(&module_id, module->id); + } + + is_empty = list_empty(&modules_list); + + up_write(&modules_rwsem); + + if (!is_empty) + pr_warn("Not all nodes were deleted\n"); +} +EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all); + +struct gb_audio_manager_module *gb_audio_manager_get_module(int id) +{ + struct gb_audio_manager_module *module; + + down_read(&modules_rwsem); + module = gb_audio_manager_get_locked(id); + kobject_get(&module->kobj); + up_read(&modules_rwsem); + return module; +} +EXPORT_SYMBOL_GPL(gb_audio_manager_get_module); + +void gb_audio_manager_put_module(struct gb_audio_manager_module *module) +{ + kobject_put(&module->kobj); +} +EXPORT_SYMBOL_GPL(gb_audio_manager_put_module); + +int gb_audio_manager_dump_module(int id) +{ + struct gb_audio_manager_module *module; + + down_read(&modules_rwsem); + module = gb_audio_manager_get_locked(id); + up_read(&modules_rwsem); + + if (!module) + return -EINVAL; + + gb_audio_manager_module_dump(module); + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_manager_dump_module); + +void gb_audio_manager_dump_all(void) +{ + struct gb_audio_manager_module *module; + int count = 0; + + down_read(&modules_rwsem); + list_for_each_entry(module, &modules_list, list) { + gb_audio_manager_module_dump(module); + count++; + } + up_read(&modules_rwsem); + + pr_info("Number of connected modules: %d\n", count); +} +EXPORT_SYMBOL_GPL(gb_audio_manager_dump_all); + +/* + * module init/deinit + */ +static int __init manager_init(void) +{ + manager_kset = kset_create_and_add(GB_AUDIO_MANAGER_NAME, NULL, + kernel_kobj); + if (!manager_kset) + return -ENOMEM; + +#ifdef GB_AUDIO_MANAGER_SYSFS + gb_audio_manager_sysfs_init(&manager_kset->kobj); +#endif + + return 0; +} + +static void __exit manager_exit(void) +{ + gb_audio_manager_remove_all(); + kset_unregister(manager_kset); + ida_destroy(&module_id); +} + +module_init(manager_init); +module_exit(manager_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Svetlin Ankov "); diff --git a/drivers/staging/greybus/audio_manager.h b/drivers/staging/greybus/audio_manager.h new file mode 100644 index 000000000000..c4ca09754a6a --- /dev/null +++ b/drivers/staging/greybus/audio_manager.h @@ -0,0 +1,83 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef _GB_AUDIO_MANAGER_H_ +#define _GB_AUDIO_MANAGER_H_ + +#include +#include + +#define GB_AUDIO_MANAGER_NAME "gb_audio_manager" +#define GB_AUDIO_MANAGER_MODULE_NAME_LEN 64 +#define GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "63" + +struct gb_audio_manager_module_descriptor { + char name[GB_AUDIO_MANAGER_MODULE_NAME_LEN]; + int slot; + int vid; + int pid; + int cport; + unsigned int ip_devices; + unsigned int op_devices; +}; + +struct gb_audio_manager_module { + struct kobject kobj; + struct list_head list; + int id; + struct gb_audio_manager_module_descriptor desc; +}; + +/* + * Creates a new gb_audio_manager_module_descriptor, using the specified + * descriptor. + * + * Returns a negative result on error, or the id of the newly created module. + * + */ +int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc); + +/* + * Removes a connected gb_audio_manager_module_descriptor for the specified ID. + * + * Returns zero on success, or a negative value on error. + */ +int gb_audio_manager_remove(int id); + +/* + * Removes all connected gb_audio_modules + * + * Returns zero on success, or a negative value on error. + */ +void gb_audio_manager_remove_all(void); + +/* + * Retrieves a gb_audio_manager_module_descriptor for the specified id. + * Returns the gb_audio_manager_module_descriptor structure, + * or NULL if there is no module with the specified ID. + */ +struct gb_audio_manager_module *gb_audio_manager_get_module(int id); + +/* + * Decreases the refcount of the module, obtained by the get function. + * Modules are removed via gb_audio_manager_remove + */ +void gb_audio_manager_put_module(struct gb_audio_manager_module *module); + +/* + * Dumps the module for the specified id + * Return 0 on success + */ +int gb_audio_manager_dump_module(int id); + +/* + * Dumps all connected modules + */ +void gb_audio_manager_dump_all(void); + +#endif /* _GB_AUDIO_MANAGER_H_ */ diff --git a/drivers/staging/greybus/audio_manager_module.c b/drivers/staging/greybus/audio_manager_module.c new file mode 100644 index 000000000000..a10e96ad79c1 --- /dev/null +++ b/drivers/staging/greybus/audio_manager_module.c @@ -0,0 +1,258 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include + +#include "audio_manager.h" +#include "audio_manager_private.h" + +#define to_gb_audio_module_attr(x) \ + container_of(x, struct gb_audio_manager_module_attribute, attr) +#define to_gb_audio_module(x) \ + container_of(x, struct gb_audio_manager_module, kobj) + +struct gb_audio_manager_module_attribute { + struct attribute attr; + ssize_t (*show)(struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, + char *buf); + ssize_t (*store)(struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, + const char *buf, size_t count); +}; + +static ssize_t gb_audio_module_attr_show( + struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct gb_audio_manager_module_attribute *attribute; + struct gb_audio_manager_module *module; + + attribute = to_gb_audio_module_attr(attr); + module = to_gb_audio_module(kobj); + + if (!attribute->show) + return -EIO; + + return attribute->show(module, attribute, buf); +} + +static ssize_t gb_audio_module_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t len) +{ + struct gb_audio_manager_module_attribute *attribute; + struct gb_audio_manager_module *module; + + attribute = to_gb_audio_module_attr(attr); + module = to_gb_audio_module(kobj); + + if (!attribute->store) + return -EIO; + + return attribute->store(module, attribute, buf, len); +} + +static const struct sysfs_ops gb_audio_module_sysfs_ops = { + .show = gb_audio_module_attr_show, + .store = gb_audio_module_attr_store, +}; + +static void gb_audio_module_release(struct kobject *kobj) +{ + struct gb_audio_manager_module *module = to_gb_audio_module(kobj); + + pr_info("Destroying audio module #%d\n", module->id); + /* TODO -> delete from list */ + kfree(module); +} + +static ssize_t gb_audio_module_name_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%s", module->desc.name); +} + +static struct gb_audio_manager_module_attribute gb_audio_module_name_attribute = + __ATTR(name, 0664, gb_audio_module_name_show, NULL); + +static ssize_t gb_audio_module_slot_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%d", module->desc.slot); +} + +static struct gb_audio_manager_module_attribute gb_audio_module_slot_attribute = + __ATTR(slot, 0664, gb_audio_module_slot_show, NULL); + +static ssize_t gb_audio_module_vid_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%d", module->desc.vid); +} + +static struct gb_audio_manager_module_attribute gb_audio_module_vid_attribute = + __ATTR(vid, 0664, gb_audio_module_vid_show, NULL); + +static ssize_t gb_audio_module_pid_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%d", module->desc.pid); +} + +static struct gb_audio_manager_module_attribute gb_audio_module_pid_attribute = + __ATTR(pid, 0664, gb_audio_module_pid_show, NULL); + +static ssize_t gb_audio_module_cport_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%d", module->desc.cport); +} + +static struct gb_audio_manager_module_attribute + gb_audio_module_cport_attribute = + __ATTR(cport, 0664, gb_audio_module_cport_show, NULL); + +static ssize_t gb_audio_module_ip_devices_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "0x%X", module->desc.ip_devices); +} + +static struct gb_audio_manager_module_attribute + gb_audio_module_ip_devices_attribute = + __ATTR(ip_devices, 0664, gb_audio_module_ip_devices_show, NULL); + +static ssize_t gb_audio_module_op_devices_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "0x%X", module->desc.op_devices); +} + +static struct gb_audio_manager_module_attribute + gb_audio_module_op_devices_attribute = + __ATTR(op_devices, 0664, gb_audio_module_op_devices_show, NULL); + +static struct attribute *gb_audio_module_default_attrs[] = { + &gb_audio_module_name_attribute.attr, + &gb_audio_module_slot_attribute.attr, + &gb_audio_module_vid_attribute.attr, + &gb_audio_module_pid_attribute.attr, + &gb_audio_module_cport_attribute.attr, + &gb_audio_module_ip_devices_attribute.attr, + &gb_audio_module_op_devices_attribute.attr, + NULL, /* need to NULL terminate the list of attributes */ +}; + +static struct kobj_type gb_audio_module_type = { + .sysfs_ops = &gb_audio_module_sysfs_ops, + .release = gb_audio_module_release, + .default_attrs = gb_audio_module_default_attrs, +}; + +static void send_add_uevent(struct gb_audio_manager_module *module) +{ + char name_string[128]; + char slot_string[64]; + char vid_string[64]; + char pid_string[64]; + char cport_string[64]; + char ip_devices_string[64]; + char op_devices_string[64]; + + char *envp[] = { + name_string, + slot_string, + vid_string, + pid_string, + cport_string, + ip_devices_string, + op_devices_string, + NULL + }; + + snprintf(name_string, 128, "NAME=%s", module->desc.name); + snprintf(slot_string, 64, "SLOT=%d", module->desc.slot); + snprintf(vid_string, 64, "VID=%d", module->desc.vid); + snprintf(pid_string, 64, "PID=%d", module->desc.pid); + snprintf(cport_string, 64, "CPORT=%d", module->desc.cport); + snprintf(ip_devices_string, 64, "I/P DEVICES=0x%X", + module->desc.ip_devices); + snprintf(op_devices_string, 64, "O/P DEVICES=0x%X", + module->desc.op_devices); + + kobject_uevent_env(&module->kobj, KOBJ_ADD, envp); +} + +int gb_audio_manager_module_create( + struct gb_audio_manager_module **module, + struct kset *manager_kset, + int id, struct gb_audio_manager_module_descriptor *desc) +{ + int err; + struct gb_audio_manager_module *m; + + m = kzalloc(sizeof(*m), GFP_ATOMIC); + if (!m) + return -ENOMEM; + + /* Initialize the node */ + INIT_LIST_HEAD(&m->list); + + /* Set the module id */ + m->id = id; + + /* Copy the provided descriptor */ + memcpy(&m->desc, desc, sizeof(*desc)); + + /* set the kset */ + m->kobj.kset = manager_kset; + + /* + * Initialize and add the kobject to the kernel. All the default files + * will be created here. As we have already specified a kset for this + * kobject, we don't have to set a parent for the kobject, the kobject + * will be placed beneath that kset automatically. + */ + err = kobject_init_and_add(&m->kobj, &gb_audio_module_type, NULL, "%d", + id); + if (err) { + pr_err("failed initializing kobject for audio module #%d\n", + id); + kobject_put(&m->kobj); + return err; + } + + /* + * Notify the object was created + */ + send_add_uevent(m); + + *module = m; + pr_info("Created audio module #%d\n", id); + return 0; +} + +void gb_audio_manager_module_dump(struct gb_audio_manager_module *module) +{ + pr_info("audio module #%d name=%s slot=%d vid=%d pid=%d cport=%d i/p devices=0x%X o/p devices=0x%X\n", + module->id, + module->desc.name, + module->desc.slot, + module->desc.vid, + module->desc.pid, + module->desc.cport, + module->desc.ip_devices, + module->desc.op_devices); +} diff --git a/drivers/staging/greybus/audio_manager_private.h b/drivers/staging/greybus/audio_manager_private.h new file mode 100644 index 000000000000..079ce953c256 --- /dev/null +++ b/drivers/staging/greybus/audio_manager_private.h @@ -0,0 +1,28 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef _GB_AUDIO_MANAGER_PRIVATE_H_ +#define _GB_AUDIO_MANAGER_PRIVATE_H_ + +#include + +#include "audio_manager.h" + +int gb_audio_manager_module_create( + struct gb_audio_manager_module **module, + struct kset *manager_kset, + int id, struct gb_audio_manager_module_descriptor *desc); + +/* module destroyed via kobject_put */ + +void gb_audio_manager_module_dump(struct gb_audio_manager_module *module); + +/* sysfs control */ +void gb_audio_manager_sysfs_init(struct kobject *kobj); + +#endif /* _GB_AUDIO_MANAGER_PRIVATE_H_ */ diff --git a/drivers/staging/greybus/audio_manager_sysfs.c b/drivers/staging/greybus/audio_manager_sysfs.c new file mode 100644 index 000000000000..d8bf8591ff9e --- /dev/null +++ b/drivers/staging/greybus/audio_manager_sysfs.c @@ -0,0 +1,102 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include + +#include "audio_manager.h" +#include "audio_manager_private.h" + +static ssize_t manager_sysfs_add_store( + struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct gb_audio_manager_module_descriptor desc = { {0} }; + + int num = sscanf(buf, + "name=%" GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "s " + "slot=%d vid=%d pid=%d cport=%d i/p devices=0x%X" + "o/p devices=0x%X", + desc.name, &desc.slot, &desc.vid, &desc.pid, + &desc.cport, &desc.ip_devices, &desc.op_devices); + + if (num != 7) + return -EINVAL; + + num = gb_audio_manager_add(&desc); + if (num < 0) + return -EINVAL; + + return count; +} + +static struct kobj_attribute manager_add_attribute = + __ATTR(add, 0664, NULL, manager_sysfs_add_store); + +static ssize_t manager_sysfs_remove_store( + struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int id; + + int num = sscanf(buf, "%d", &id); + + if (num != 1) + return -EINVAL; + + num = gb_audio_manager_remove(id); + if (num) + return num; + + return count; +} + +static struct kobj_attribute manager_remove_attribute = + __ATTR(remove, 0664, NULL, manager_sysfs_remove_store); + +static ssize_t manager_sysfs_dump_store( + struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int id; + + int num = sscanf(buf, "%d", &id); + + if (num == 1) { + num = gb_audio_manager_dump_module(id); + if (num) + return num; + } else if (!strncmp("all", buf, 3)) + gb_audio_manager_dump_all(); + else + return -EINVAL; + + return count; +} + +static struct kobj_attribute manager_dump_attribute = + __ATTR(dump, 0664, NULL, manager_sysfs_dump_store); + +static void manager_sysfs_init_attribute( + struct kobject *kobj, struct kobj_attribute *kattr) +{ + int err; + + err = sysfs_create_file(kobj, &kattr->attr); + if (err) { + pr_warn("creating the sysfs entry for %s failed: %d\n", + kattr->attr.name, err); + } +} + +void gb_audio_manager_sysfs_init(struct kobject *kobj) +{ + manager_sysfs_init_attribute(kobj, &manager_add_attribute); + manager_sysfs_init_attribute(kobj, &manager_remove_attribute); + manager_sysfs_init_attribute(kobj, &manager_dump_attribute); +} diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c new file mode 100644 index 000000000000..ae1c0fa85752 --- /dev/null +++ b/drivers/staging/greybus/audio_module.c @@ -0,0 +1,482 @@ +/* + * Greybus audio driver + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include + +#include "audio_codec.h" +#include "audio_apbridgea.h" +#include "audio_manager.h" + +/* + * gb_snd management functions + */ + +static int gbaudio_request_jack(struct gbaudio_module_info *module, + struct gb_audio_jack_event_request *req) +{ + int report; + struct snd_jack *jack = module->headset_jack.jack; + struct snd_jack *btn_jack = module->button_jack.jack; + + if (!jack) { + dev_err_ratelimited(module->dev, + "Invalid jack event received:type: %u, event: %u\n", + req->jack_attribute, req->event); + return -EINVAL; + } + + dev_warn_ratelimited(module->dev, + "Jack Event received: type: %u, event: %u\n", + req->jack_attribute, req->event); + + if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) { + module->jack_type = 0; + if (btn_jack && module->button_status) { + snd_soc_jack_report(&module->button_jack, 0, + module->button_mask); + module->button_status = 0; + } + snd_soc_jack_report(&module->headset_jack, 0, + module->jack_mask); + return 0; + } + + report = req->jack_attribute & module->jack_mask; + if (!report) { + dev_err_ratelimited(module->dev, + "Invalid jack event received:type: %u, event: %u\n", + req->jack_attribute, req->event); + return -EINVAL; + } + + if (module->jack_type) + dev_warn_ratelimited(module->dev, + "Modifying jack from %d to %d\n", + module->jack_type, report); + + module->jack_type = report; + snd_soc_jack_report(&module->headset_jack, report, module->jack_mask); + + return 0; +} + +static int gbaudio_request_button(struct gbaudio_module_info *module, + struct gb_audio_button_event_request *req) +{ + int soc_button_id, report; + struct snd_jack *btn_jack = module->button_jack.jack; + + if (!btn_jack) { + dev_err_ratelimited(module->dev, + "Invalid button event received:type: %u, event: %u\n", + req->button_id, req->event); + return -EINVAL; + } + + dev_warn_ratelimited(module->dev, + "Button Event received: id: %u, event: %u\n", + req->button_id, req->event); + + /* currently supports 4 buttons only */ + if (!module->jack_type) { + dev_err_ratelimited(module->dev, + "Jack not present. Bogus event!!\n"); + return -EINVAL; + } + + report = module->button_status & module->button_mask; + soc_button_id = 0; + + switch (req->button_id) { + case 1: + soc_button_id = SND_JACK_BTN_0 & module->button_mask; + break; + + case 2: + soc_button_id = SND_JACK_BTN_1 & module->button_mask; + break; + + case 3: + soc_button_id = SND_JACK_BTN_2 & module->button_mask; + break; + + case 4: + soc_button_id = SND_JACK_BTN_3 & module->button_mask; + break; + } + + if (!soc_button_id) { + dev_err_ratelimited(module->dev, + "Invalid button request received\n"); + return -EINVAL; + } + + if (req->event == GB_AUDIO_BUTTON_EVENT_PRESS) + report = report | soc_button_id; + else + report = report & ~soc_button_id; + + module->button_status = report; + + snd_soc_jack_report(&module->button_jack, report, module->button_mask); + + return 0; +} + +static int gbaudio_request_stream(struct gbaudio_module_info *module, + struct gb_audio_streaming_event_request *req) +{ + dev_warn(module->dev, "Audio Event received: cport: %u, event: %u\n", + req->data_cport, req->event); + + return 0; +} + +static int gbaudio_codec_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gbaudio_module_info *module = + greybus_get_drvdata(connection->bundle); + struct gb_operation_msg_hdr *header = op->request->header; + struct gb_audio_streaming_event_request *stream_req; + struct gb_audio_jack_event_request *jack_req; + struct gb_audio_button_event_request *button_req; + int ret; + + switch (header->type) { + case GB_AUDIO_TYPE_STREAMING_EVENT: + stream_req = op->request->payload; + ret = gbaudio_request_stream(module, stream_req); + break; + + case GB_AUDIO_TYPE_JACK_EVENT: + jack_req = op->request->payload; + ret = gbaudio_request_jack(module, jack_req); + break; + + case GB_AUDIO_TYPE_BUTTON_EVENT: + button_req = op->request->payload; + ret = gbaudio_request_button(module, button_req); + break; + + default: + dev_err_ratelimited(&connection->bundle->dev, + "Invalid Audio Event received\n"); + return -EINVAL; + } + + return ret; +} + +static int gb_audio_add_mgmt_connection(struct gbaudio_module_info *gbmodule, + struct greybus_descriptor_cport *cport_desc, + struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + /* Management Cport */ + if (gbmodule->mgmt_connection) { + dev_err(&bundle->dev, + "Can't have multiple Management connections\n"); + return -ENODEV; + } + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gbaudio_codec_request_handler); + if (IS_ERR(connection)) + return PTR_ERR(connection); + + greybus_set_drvdata(bundle, gbmodule); + gbmodule->mgmt_connection = connection; + + return 0; +} + +static int gb_audio_add_data_connection(struct gbaudio_module_info *gbmodule, + struct greybus_descriptor_cport *cport_desc, + struct gb_bundle *bundle) +{ + struct gb_connection *connection; + struct gbaudio_data_connection *dai; + + dai = devm_kzalloc(gbmodule->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) { + dev_err(gbmodule->dev, "DAI Malloc failure\n"); + return -ENOMEM; + } + + connection = gb_connection_create_offloaded(bundle, + le16_to_cpu(cport_desc->id), + GB_CONNECTION_FLAG_CSD); + if (IS_ERR(connection)) { + devm_kfree(gbmodule->dev, dai); + return PTR_ERR(connection); + } + + greybus_set_drvdata(bundle, gbmodule); + dai->id = 0; + dai->data_cport = connection->intf_cport_id; + dai->connection = connection; + list_add(&dai->list, &gbmodule->data_list); + + return 0; +} + +/* + * This is the basic hook get things initialized and registered w/ gb + */ + +static int gb_audio_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct device *dev = &bundle->dev; + struct gbaudio_module_info *gbmodule; + struct greybus_descriptor_cport *cport_desc; + struct gb_audio_manager_module_descriptor desc; + struct gbaudio_data_connection *dai, *_dai; + int ret, i; + struct gb_audio_topology *topology; + + /* There should be at least one Management and one Data cport */ + if (bundle->num_cports < 2) + return -ENODEV; + + /* + * There can be only one Management connection and any number of data + * connections. + */ + gbmodule = devm_kzalloc(dev, sizeof(*gbmodule), GFP_KERNEL); + if (!gbmodule) + return -ENOMEM; + + gbmodule->num_data_connections = bundle->num_cports - 1; + INIT_LIST_HEAD(&gbmodule->data_list); + INIT_LIST_HEAD(&gbmodule->widget_list); + INIT_LIST_HEAD(&gbmodule->ctl_list); + INIT_LIST_HEAD(&gbmodule->widget_ctl_list); + gbmodule->dev = dev; + snprintf(gbmodule->name, NAME_SIZE, "%s.%s", dev->driver->name, + dev_name(dev)); + greybus_set_drvdata(bundle, gbmodule); + + /* Create all connections */ + for (i = 0; i < bundle->num_cports; i++) { + cport_desc = &bundle->cport_desc[i]; + + switch (cport_desc->protocol_id) { + case GREYBUS_PROTOCOL_AUDIO_MGMT: + ret = gb_audio_add_mgmt_connection(gbmodule, cport_desc, + bundle); + if (ret) + goto destroy_connections; + break; + case GREYBUS_PROTOCOL_AUDIO_DATA: + ret = gb_audio_add_data_connection(gbmodule, cport_desc, + bundle); + if (ret) + goto destroy_connections; + break; + default: + dev_err(dev, "Unsupported protocol: 0x%02x\n", + cport_desc->protocol_id); + ret = -ENODEV; + goto destroy_connections; + } + } + + /* There must be a management cport */ + if (!gbmodule->mgmt_connection) { + ret = -EINVAL; + dev_err(dev, "Missing management connection\n"); + goto destroy_connections; + } + + /* Initialize management connection */ + ret = gb_connection_enable(gbmodule->mgmt_connection); + if (ret) { + dev_err(dev, "%d: Error while enabling mgmt connection\n", ret); + goto destroy_connections; + } + gbmodule->dev_id = gbmodule->mgmt_connection->intf->interface_id; + + /* + * FIXME: malloc for topology happens via audio_gb driver + * should be done within codec driver itself + */ + ret = gb_audio_gb_get_topology(gbmodule->mgmt_connection, &topology); + if (ret) { + dev_err(dev, "%d:Error while fetching topology\n", ret); + goto disable_connection; + } + + /* process topology data */ + ret = gbaudio_tplg_parse_data(gbmodule, topology); + if (ret) { + dev_err(dev, "%d:Error while parsing topology data\n", + ret); + goto free_topology; + } + gbmodule->topology = topology; + + /* Initialize data connections */ + list_for_each_entry(dai, &gbmodule->data_list, list) { + ret = gb_connection_enable(dai->connection); + if (ret) { + dev_err(dev, + "%d:Error while enabling %d:data connection\n", + ret, dai->data_cport); + goto disable_data_connection; + } + } + + /* register module with gbcodec */ + ret = gbaudio_register_module(gbmodule); + if (ret) + goto disable_data_connection; + + /* inform above layer for uevent */ + dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); + /* prepare for the audio manager */ + strlcpy(desc.name, gbmodule->name, GB_AUDIO_MANAGER_MODULE_NAME_LEN); + desc.slot = 1; /* todo */ + desc.vid = 2; /* todo */ + desc.pid = 3; /* todo */ + desc.cport = gbmodule->dev_id; + desc.op_devices = gbmodule->op_devices; + desc.ip_devices = gbmodule->ip_devices; + gbmodule->manager_id = gb_audio_manager_add(&desc); + + dev_dbg(dev, "Add GB Audio device:%s\n", gbmodule->name); + + gb_pm_runtime_put_autosuspend(bundle); + + return 0; + +disable_data_connection: + list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) + gb_connection_disable(dai->connection); + gbaudio_tplg_release(gbmodule); + gbmodule->topology = NULL; + +free_topology: + kfree(topology); + +disable_connection: + gb_connection_disable(gbmodule->mgmt_connection); + +destroy_connections: + list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) { + gb_connection_destroy(dai->connection); + list_del(&dai->list); + devm_kfree(dev, dai); + } + + if (gbmodule->mgmt_connection) + gb_connection_destroy(gbmodule->mgmt_connection); + + devm_kfree(dev, gbmodule); + + return ret; +} + +static void gb_audio_disconnect(struct gb_bundle *bundle) +{ + struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); + struct gbaudio_data_connection *dai, *_dai; + + gb_pm_runtime_get_sync(bundle); + + /* cleanup module related resources first */ + gbaudio_unregister_module(gbmodule); + + /* inform uevent to above layers */ + gb_audio_manager_remove(gbmodule->manager_id); + + gbaudio_tplg_release(gbmodule); + kfree(gbmodule->topology); + gbmodule->topology = NULL; + gb_connection_disable(gbmodule->mgmt_connection); + list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) { + gb_connection_disable(dai->connection); + gb_connection_destroy(dai->connection); + list_del(&dai->list); + devm_kfree(gbmodule->dev, dai); + } + gb_connection_destroy(gbmodule->mgmt_connection); + gbmodule->mgmt_connection = NULL; + + devm_kfree(&bundle->dev, gbmodule); +} + +static const struct greybus_bundle_id gb_audio_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_audio_id_table); + +#ifdef CONFIG_PM +static int gb_audio_suspend(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); + struct gbaudio_data_connection *dai; + + list_for_each_entry(dai, &gbmodule->data_list, list) + gb_connection_disable(dai->connection); + + gb_connection_disable(gbmodule->mgmt_connection); + + return 0; +} + +static int gb_audio_resume(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); + struct gbaudio_data_connection *dai; + int ret; + + ret = gb_connection_enable(gbmodule->mgmt_connection); + if (ret) { + dev_err(dev, "%d:Error while enabling mgmt connection\n", ret); + return ret; + } + + list_for_each_entry(dai, &gbmodule->data_list, list) { + ret = gb_connection_enable(dai->connection); + if (ret) { + dev_err(dev, + "%d:Error while enabling %d:data connection\n", + ret, dai->data_cport); + return ret; + } + } + + return 0; +} +#endif + +static const struct dev_pm_ops gb_audio_pm_ops = { + SET_RUNTIME_PM_OPS(gb_audio_suspend, gb_audio_resume, NULL) +}; + +static struct greybus_driver gb_audio_driver = { + .name = "gb-audio", + .probe = gb_audio_probe, + .disconnect = gb_audio_disconnect, + .id_table = gb_audio_id_table, + .driver.pm = &gb_audio_pm_ops, +}; +module_greybus_driver(gb_audio_driver); + +MODULE_DESCRIPTION("Greybus Audio module driver"); +MODULE_AUTHOR("Vaibhav Agarwal "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gbaudio-module"); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c new file mode 100644 index 000000000000..b6251691a33d --- /dev/null +++ b/drivers/staging/greybus/audio_topology.c @@ -0,0 +1,1443 @@ +/* + * Greybus audio driver + * Copyright 2015-2016 Google Inc. + * Copyright 2015-2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "audio_codec.h" +#include "greybus_protocols.h" + +#define GBAUDIO_INVALID_ID 0xFF + +/* mixer control */ +struct gb_mixer_control { + int min, max; + unsigned int reg, rreg, shift, rshift, invert; +}; + +struct gbaudio_ctl_pvt { + unsigned int ctl_id; + unsigned int data_cport; + unsigned int access; + unsigned int vcount; + struct gb_audio_ctl_elem_info *info; +}; + +static struct gbaudio_module_info *find_gb_module( + struct gbaudio_codec_info *codec, + char const *name) +{ + int dev_id, ret; + char begin[NAME_SIZE]; + struct gbaudio_module_info *module; + + if (!name) + return NULL; + + ret = sscanf(name, "%s %d", begin, &dev_id); + dev_dbg(codec->dev, "%s:Find module#%d\n", __func__, dev_id); + + mutex_lock(&codec->lock); + list_for_each_entry(module, &codec->module_list, list) { + if (module->dev_id == dev_id) { + mutex_unlock(&codec->lock); + return module; + } + } + mutex_unlock(&codec->lock); + dev_warn(codec->dev, "%s: module#%d missing in codec list\n", name, + dev_id); + return NULL; +} + +static const char *gbaudio_map_controlid(struct gbaudio_module_info *module, + __u8 control_id, __u8 index) +{ + struct gbaudio_control *control; + + if (control_id == GBAUDIO_INVALID_ID) + return NULL; + + list_for_each_entry(control, &module->ctl_list, list) { + if (control->id == control_id) { + if (index == GBAUDIO_INVALID_ID) + return control->name; + if (index >= control->items) + return NULL; + return control->texts[index]; + } + } + list_for_each_entry(control, &module->widget_ctl_list, list) { + if (control->id == control_id) { + if (index == GBAUDIO_INVALID_ID) + return control->name; + if (index >= control->items) + return NULL; + return control->texts[index]; + } + } + return NULL; +} + +static int gbaudio_map_controlname(struct gbaudio_module_info *module, + const char *name) +{ + struct gbaudio_control *control; + + list_for_each_entry(control, &module->ctl_list, list) { + if (!strncmp(control->name, name, NAME_SIZE)) + return control->id; + } + + dev_warn(module->dev, "%s: missing in modules controls list\n", name); + + return -EINVAL; +} + +static int gbaudio_map_wcontrolname(struct gbaudio_module_info *module, + const char *name) +{ + struct gbaudio_control *control; + + list_for_each_entry(control, &module->widget_ctl_list, list) { + if (!strncmp(control->wname, name, NAME_SIZE)) + return control->id; + } + dev_warn(module->dev, "%s: missing in modules controls list\n", name); + + return -EINVAL; +} + +static int gbaudio_map_widgetname(struct gbaudio_module_info *module, + const char *name) +{ + struct gbaudio_widget *widget; + list_for_each_entry(widget, &module->widget_list, list) { + if (!strncmp(widget->name, name, NAME_SIZE)) + return widget->id; + } + dev_warn(module->dev, "%s: missing in modules widgets list\n", name); + + return -EINVAL; +} + +static const char *gbaudio_map_widgetid(struct gbaudio_module_info *module, + __u8 widget_id) +{ + struct gbaudio_widget *widget; + + list_for_each_entry(widget, &module->widget_list, list) { + if (widget->id == widget_id) + return widget->name; + } + return NULL; +} + +static const char **gb_generate_enum_strings(struct gbaudio_module_info *gb, + struct gb_audio_enumerated *gbenum) +{ + const char **strings; + int i; + __u8 *data; + + strings = devm_kzalloc(gb->dev, sizeof(char *) * gbenum->items, + GFP_KERNEL); + data = gbenum->names; + + for (i = 0; i < gbenum->items; i++) { + strings[i] = (const char *)data; + while (*data != '\0') + data++; + data++; + } + + return strings; +} + +static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + unsigned int max; + const char *name; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_module_info *module; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + + if (!info) { + dev_err(codec->dev, "NULL info for %s\n", uinfo->id.name); + return -EINVAL; + } + + /* update uinfo */ + uinfo->access = data->access; + uinfo->count = data->vcount; + uinfo->type = (snd_ctl_elem_type_t)info->type; + + switch (info->type) { + case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN: + case GB_AUDIO_CTL_ELEM_TYPE_INTEGER: + uinfo->value.integer.min = info->value.integer.min; + uinfo->value.integer.max = info->value.integer.max; + break; + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + max = info->value.enumerated.items; + uinfo->value.enumerated.items = max; + if (uinfo->value.enumerated.item > max - 1) + uinfo->value.enumerated.item = max - 1; + module = find_gb_module(gbcodec, kcontrol->id.name); + if (!module) + return -EINVAL; + name = gbaudio_map_controlid(module, data->ctl_id, + uinfo->value.enumerated.item); + strlcpy(uinfo->value.enumerated.name, name, NAME_SIZE); + break; + default: + dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + info->type, kcontrol->id.name); + break; + } + return 0; +} + +static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; + + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } + + /* update ucontrol */ + switch (info->type) { + case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN: + case GB_AUDIO_CTL_ELEM_TYPE_INTEGER: + ucontrol->value.integer.value[0] = + gbvalue.value.integer_value[0]; + if (data->vcount == 2) + ucontrol->value.integer.value[1] = + gbvalue.value.integer_value[1]; + break; + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + ucontrol->value.enumerated.item[0] = + gbvalue.value.enumerated_item[0]; + if (data->vcount == 2) + ucontrol->value.enumerated.item[1] = + gbvalue.value.enumerated_item[1]; + break; + default: + dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + info->type, kcontrol->id.name); + ret = -EINVAL; + break; + } + return ret; +} + +static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; + + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + bundle = to_gb_bundle(module->dev); + + /* update ucontrol */ + switch (info->type) { + case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN: + case GB_AUDIO_CTL_ELEM_TYPE_INTEGER: + gbvalue.value.integer_value[0] = + ucontrol->value.integer.value[0]; + if (data->vcount == 2) + gbvalue.value.integer_value[1] = + ucontrol->value.integer.value[1]; + break; + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + gbvalue.value.enumerated_item[0] = + ucontrol->value.enumerated.item[0]; + if (data->vcount == 2) + gbvalue.value.enumerated_item[1] = + ucontrol->value.enumerated.item[1]; + break; + default: + dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + info->type, kcontrol->id.name); + ret = -EINVAL; + break; + } + + if (ret) + return ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_set_control(module->mgmt_connection, data->ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + } + + return ret; +} + +#define SOC_MIXER_GB(xname, kcount, data) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .count = kcount, .info = gbcodec_mixer_ctl_info, \ + .get = gbcodec_mixer_ctl_get, .put = gbcodec_mixer_ctl_put, \ + .private_value = (unsigned long)data } + +/* + * although below callback functions seems redundant to above functions. + * same are kept to allow provision for different handling in case + * of DAPM related sequencing, etc. + */ +static int gbcodec_mixer_dapm_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + int platform_max, platform_min; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_info *info; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = widget->codec; + + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + + /* update uinfo */ + platform_max = info->value.integer.max; + platform_min = info->value.integer.min; + + if (platform_max == 1 && + !strnstr(kcontrol->id.name, " Volume", NAME_SIZE)) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + + uinfo->count = data->vcount; + uinfo->value.integer.min = 0; + if (info->value.integer.min < 0 && + (uinfo->type == SNDRV_CTL_ELEM_TYPE_INTEGER)) + uinfo->value.integer.max = platform_max - platform_min; + else + uinfo->value.integer.max = platform_max; + + return 0; +} + +static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = widget->codec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; + + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + bundle = to_gb_bundle(module->dev); + + if (data->vcount == 2) + dev_warn(widget->dapm->dev, + "GB: Control '%s' is stereo, which is not supported\n", + kcontrol->id.name); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } + /* update ucontrol */ + ucontrol->value.integer.value[0] = gbvalue.value.integer_value[0]; + + return ret; +} + +static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, wi, max, connect; + unsigned int mask, val; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = widget->codec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; + + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + bundle = to_gb_bundle(module->dev); + + if (data->vcount == 2) + dev_warn(widget->dapm->dev, + "GB: Control '%s' is stereo, which is not supported\n", + kcontrol->id.name); + + max = info->value.integer.max; + mask = (1 << fls(max)) - 1; + val = ucontrol->value.integer.value[0] & mask; + connect = !!val; + + /* update ucontrol */ + if (gbvalue.value.integer_value[0] != val) { + for (wi = 0; wi < wlist->num_widgets; wi++) { + widget = wlist->widgets[wi]; + + widget->value = val; + widget->dapm->update = NULL; + snd_soc_dapm_mixer_update_power(widget, kcontrol, + connect); + } + gbvalue.value.integer_value[0] = + ucontrol->value.integer.value[0]; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_set_control(module->mgmt_connection, + data->ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, + "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } + } + + return 0; +} + +#define SOC_DAPM_MIXER_GB(xname, kcount, data) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .count = kcount, .info = gbcodec_mixer_dapm_ctl_info, \ + .get = gbcodec_mixer_dapm_ctl_get, .put = gbcodec_mixer_dapm_ctl_put, \ + .private_value = (unsigned long)data} + +static int gbcodec_event_spk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB speaker is connected */ + + return 0; +} + +static int gbcodec_event_hp(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB module supports jack slot */ + + return 0; +} + +static int gbcodec_event_int_mic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB module supports jack slot */ + + return 0; +} + +static int gbaudio_validate_kcontrol_count(struct gb_audio_widget *w) +{ + int ret = 0; + + switch (w->type) { + case snd_soc_dapm_spk: + case snd_soc_dapm_hp: + case snd_soc_dapm_mic: + case snd_soc_dapm_output: + case snd_soc_dapm_input: + if (w->ncontrols) + ret = -EINVAL; + break; + case snd_soc_dapm_switch: + case snd_soc_dapm_mux: + if (w->ncontrols != 1) + ret = -EINVAL; + break; + default: + break; + } + + return ret; +} + +static int gbcodec_enum_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, ctl_id; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; + + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + ctl_id = gbaudio_map_controlname(module, kcontrol->id.name); + if (ctl_id < 0) + return -EINVAL; + + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } + + ucontrol->value.enumerated.item[0] = gbvalue.value.enumerated_item[0]; + if (e->shift_l != e->shift_r) + ucontrol->value.enumerated.item[1] = + gbvalue.value.enumerated_item[1]; + + return 0; +} + +static int gbcodec_enum_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, ctl_id; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; + + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + ctl_id = gbaudio_map_controlname(module, kcontrol->id.name); + if (ctl_id < 0) + return -EINVAL; + + if (ucontrol->value.enumerated.item[0] > e->max - 1) + return -EINVAL; + gbvalue.value.enumerated_item[0] = ucontrol->value.enumerated.item[0]; + + if (e->shift_l != e->shift_r) { + if (ucontrol->value.enumerated.item[1] > e->max - 1) + return -EINVAL; + gbvalue.value.enumerated_item[1] = + ucontrol->value.enumerated.item[1]; + } + + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_set_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + } + + return ret; +} + +static int gbaudio_tplg_create_enum_kctl(struct gbaudio_module_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + struct soc_enum *gbe; + struct gb_audio_enumerated *gb_enum; + int i; + + gbe = devm_kzalloc(gb->dev, sizeof(*gbe), GFP_KERNEL); + if (!gbe) + return -ENOMEM; + + gb_enum = &ctl->info.value.enumerated; + + /* since count=1, and reg is dummy */ + gbe->max = gb_enum->items; + gbe->texts = gb_generate_enum_strings(gb, gb_enum); + + /* debug enum info */ + dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gb_enum->items, + gb_enum->names_length); + for (i = 0; i < gb_enum->items; i++) + dev_dbg(gb->dev, "src[%d]: %s\n", i, gbe->texts[i]); + + *kctl = (struct snd_kcontrol_new) + SOC_ENUM_EXT(ctl->name, *gbe, gbcodec_enum_ctl_get, + gbcodec_enum_ctl_put); + return 0; +} + +static int gbaudio_tplg_create_kcontrol(struct gbaudio_module_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + int ret = 0; + struct gbaudio_ctl_pvt *ctldata; + + switch (ctl->iface) { + case SNDRV_CTL_ELEM_IFACE_MIXER: + switch (ctl->info.type) { + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + ret = gbaudio_tplg_create_enum_kctl(gb, kctl, ctl); + break; + default: + ctldata = devm_kzalloc(gb->dev, + sizeof(struct gbaudio_ctl_pvt), + GFP_KERNEL); + if (!ctldata) + return -ENOMEM; + ctldata->ctl_id = ctl->id; + ctldata->data_cport = ctl->data_cport; + ctldata->access = ctl->access; + ctldata->vcount = ctl->count_values; + ctldata->info = &ctl->info; + *kctl = (struct snd_kcontrol_new) + SOC_MIXER_GB(ctl->name, ctl->count, ctldata); + ctldata = NULL; + break; + } + break; + default: + return -EINVAL; + } + + dev_dbg(gb->dev, "%s:%d control created\n", ctl->name, ctl->id); + return ret; +} + +static int gbcodec_enum_dapm_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, ctl_id; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct gbaudio_module_info *module; + struct gb_audio_ctl_elem_value gbvalue; + struct snd_soc_codec *codec = widget->codec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct gb_bundle *bundle; + + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + ctl_id = gbaudio_map_wcontrolname(module, kcontrol->id.name); + if (ctl_id < 0) + return -EINVAL; + + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } + + ucontrol->value.enumerated.item[0] = gbvalue.value.enumerated_item[0]; + if (e->shift_l != e->shift_r) + ucontrol->value.enumerated.item[1] = + gbvalue.value.enumerated_item[1]; + + return 0; +} + +static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, wi, ctl_id; + unsigned int val, mux, change; + unsigned int mask; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct snd_soc_codec *codec = widget->codec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct gb_bundle *bundle; + + if (ucontrol->value.enumerated.item[0] > e->max - 1) + return -EINVAL; + + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + ctl_id = gbaudio_map_wcontrolname(module, kcontrol->id.name); + if (ctl_id < 0) + return -EINVAL; + + change = 0; + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } + + mux = ucontrol->value.enumerated.item[0]; + val = mux << e->shift_l; + mask = e->mask << e->shift_l; + + if (gbvalue.value.enumerated_item[0] != + ucontrol->value.enumerated.item[0]) { + change = 1; + gbvalue.value.enumerated_item[0] = + ucontrol->value.enumerated.item[0]; + } + + if (e->shift_l != e->shift_r) { + if (ucontrol->value.enumerated.item[1] > e->max - 1) + return -EINVAL; + val |= ucontrol->value.enumerated.item[1] << e->shift_r; + mask |= e->mask << e->shift_r; + if (gbvalue.value.enumerated_item[1] != + ucontrol->value.enumerated.item[1]) { + change = 1; + gbvalue.value.enumerated_item[1] = + ucontrol->value.enumerated.item[1]; + } + } + + if (change) { + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_audio_gb_set_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + + if (ret) { + dev_err_ratelimited(codec->dev, + "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + } + for (wi = 0; wi < wlist->num_widgets; wi++) { + widget = wlist->widgets[wi]; + + widget->value = val; + widget->dapm->update = NULL; + snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e); + } + } + + return change; +} + +static int gbaudio_tplg_create_enum_ctl(struct gbaudio_module_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + struct soc_enum *gbe; + struct gb_audio_enumerated *gb_enum; + int i; + + gbe = devm_kzalloc(gb->dev, sizeof(*gbe), GFP_KERNEL); + if (!gbe) + return -ENOMEM; + + gb_enum = &ctl->info.value.enumerated; + + /* since count=1, and reg is dummy */ + gbe->max = gb_enum->items; + gbe->texts = gb_generate_enum_strings(gb, gb_enum); + + /* debug enum info */ + dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gb_enum->items, + gb_enum->names_length); + for (i = 0; i < gb_enum->items; i++) + dev_dbg(gb->dev, "src[%d]: %s\n", i, gbe->texts[i]); + + *kctl = (struct snd_kcontrol_new) + SOC_DAPM_ENUM_EXT(ctl->name, *gbe, gbcodec_enum_dapm_ctl_get, + gbcodec_enum_dapm_ctl_put); + return 0; +} + +static int gbaudio_tplg_create_mixer_ctl(struct gbaudio_module_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + struct gbaudio_ctl_pvt *ctldata; + + ctldata = devm_kzalloc(gb->dev, sizeof(struct gbaudio_ctl_pvt), + GFP_KERNEL); + if (!ctldata) + return -ENOMEM; + ctldata->ctl_id = ctl->id; + ctldata->data_cport = ctl->data_cport; + ctldata->access = ctl->access; + ctldata->vcount = ctl->count_values; + ctldata->info = &ctl->info; + *kctl = (struct snd_kcontrol_new) + SOC_DAPM_MIXER_GB(ctl->name, ctl->count, ctldata); + + return 0; +} + +static int gbaudio_tplg_create_wcontrol(struct gbaudio_module_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + int ret; + + switch (ctl->iface) { + case SNDRV_CTL_ELEM_IFACE_MIXER: + switch (ctl->info.type) { + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + ret = gbaudio_tplg_create_enum_ctl(gb, kctl, ctl); + break; + default: + ret = gbaudio_tplg_create_mixer_ctl(gb, kctl, ctl); + break; + } + break; + default: + return -EINVAL; + + } + + dev_dbg(gb->dev, "%s:%d DAPM control created, ret:%d\n", ctl->name, + ctl->id, ret); + return ret; +} + +static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + int wid; + int ret; + struct snd_soc_codec *codec = w->codec; + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + struct gbaudio_module_info *module; + struct gb_bundle *bundle; + + dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); + + /* Find relevant module */ + module = find_gb_module(gbcodec, w->name); + if (!module) + return -EINVAL; + + /* map name to widget id */ + wid = gbaudio_map_widgetname(module, w->name); + if (wid < 0) { + dev_err(codec->dev, "Invalid widget name:%s\n", w->name); + return -EINVAL; + } + + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = gb_audio_gb_enable_widget(module->mgmt_connection, wid); + if (!ret) + ret = gbaudio_module_update(gbcodec, w, module, 1); + break; + case SND_SOC_DAPM_POST_PMD: + ret = gb_audio_gb_disable_widget(module->mgmt_connection, wid); + if (!ret) + ret = gbaudio_module_update(gbcodec, w, module, 0); + break; + } + if (ret) + dev_err_ratelimited(codec->dev, + "%d: widget, event:%d failed:%d\n", wid, + event, ret); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; +} + +static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, + struct snd_soc_dapm_widget *dw, + struct gb_audio_widget *w, int *w_size) +{ + int i, ret, csize; + struct snd_kcontrol_new *widget_kctls; + struct gb_audio_control *curr; + struct gbaudio_control *control, *_control; + size_t size; + char temp_name[NAME_SIZE]; + + ret = gbaudio_validate_kcontrol_count(w); + if (ret) { + dev_err(module->dev, "Inavlid kcontrol count=%d for %s\n", + w->ncontrols, w->name); + return ret; + } + + /* allocate memory for kcontrol */ + if (w->ncontrols) { + size = sizeof(struct snd_kcontrol_new) * w->ncontrols; + widget_kctls = devm_kzalloc(module->dev, size, GFP_KERNEL); + if (!widget_kctls) + return -ENOMEM; + } + + *w_size = sizeof(struct gb_audio_widget); + + /* create relevant kcontrols */ + curr = w->ctl; + for (i = 0; i < w->ncontrols; i++) { + ret = gbaudio_tplg_create_wcontrol(module, &widget_kctls[i], + curr); + if (ret) { + dev_err(module->dev, + "%s:%d type widget_ctl not supported\n", + curr->name, curr->iface); + goto error; + } + control = devm_kzalloc(module->dev, + sizeof(struct gbaudio_control), + GFP_KERNEL); + if (!control) { + ret = -ENOMEM; + goto error; + } + control->id = curr->id; + control->name = curr->name; + control->wname = w->name; + + if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) { + struct gb_audio_enumerated *gbenum = + &curr->info.value.enumerated; + + csize = offsetof(struct gb_audio_control, info); + csize += offsetof(struct gb_audio_ctl_elem_info, value); + csize += offsetof(struct gb_audio_enumerated, names); + csize += gbenum->names_length; + control->texts = (const char * const *) + gb_generate_enum_strings(module, gbenum); + control->items = gbenum->items; + } else + csize = sizeof(struct gb_audio_control); + *w_size += csize; + curr = (void *)curr + csize; + list_add(&control->list, &module->widget_ctl_list); + dev_dbg(module->dev, "%s: control of type %d created\n", + widget_kctls[i].name, widget_kctls[i].iface); + } + + /* Prefix dev_id to widget control_name */ + strlcpy(temp_name, w->name, NAME_SIZE); + snprintf(w->name, NAME_SIZE, "GB %d %s", module->dev_id, temp_name); + + switch (w->type) { + case snd_soc_dapm_spk: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_SPK(w->name, gbcodec_event_spk); + module->op_devices |= GBAUDIO_DEVICE_OUT_SPEAKER; + break; + case snd_soc_dapm_hp: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_HP(w->name, gbcodec_event_hp); + module->op_devices |= (GBAUDIO_DEVICE_OUT_WIRED_HEADSET + | GBAUDIO_DEVICE_OUT_WIRED_HEADPHONE); + module->ip_devices |= GBAUDIO_DEVICE_IN_WIRED_HEADSET; + break; + case snd_soc_dapm_mic: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_MIC(w->name, gbcodec_event_int_mic); + module->ip_devices |= GBAUDIO_DEVICE_IN_BUILTIN_MIC; + break; + case snd_soc_dapm_output: + *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_OUTPUT(w->name); + break; + case snd_soc_dapm_input: + *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_INPUT(w->name); + break; + case snd_soc_dapm_switch: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_SWITCH_E(w->name, SND_SOC_NOPM, 0, 0, + widget_kctls, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_pga: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_PGA_E(w->name, SND_SOC_NOPM, 0, 0, NULL, 0, + gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_mixer: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_MIXER_E(w->name, SND_SOC_NOPM, 0, 0, NULL, + 0, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_mux: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_MUX_E(w->name, SND_SOC_NOPM, 0, 0, + widget_kctls, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_aif_in: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_AIF_IN_E(w->name, w->sname, 0, + SND_SOC_NOPM, + 0, 0, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_aif_out: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_AIF_OUT_E(w->name, w->sname, 0, + SND_SOC_NOPM, + 0, 0, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + default: + ret = -EINVAL; + goto error; + } + + dev_dbg(module->dev, "%s: widget of type %d created\n", dw->name, + dw->id); + return 0; +error: + list_for_each_entry_safe(control, _control, &module->widget_ctl_list, + list) { + list_del(&control->list); + devm_kfree(module->dev, control); + } + return ret; +} + +static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module, + struct gb_audio_control *controls) +{ + int i, csize, ret; + struct snd_kcontrol_new *dapm_kctls; + struct gb_audio_control *curr; + struct gbaudio_control *control, *_control; + size_t size; + char temp_name[NAME_SIZE]; + + size = sizeof(struct snd_kcontrol_new) * module->num_controls; + dapm_kctls = devm_kzalloc(module->dev, size, GFP_KERNEL); + if (!dapm_kctls) + return -ENOMEM; + + curr = controls; + for (i = 0; i < module->num_controls; i++) { + ret = gbaudio_tplg_create_kcontrol(module, &dapm_kctls[i], + curr); + if (ret) { + dev_err(module->dev, "%s:%d type not supported\n", + curr->name, curr->iface); + goto error; + } + control = devm_kzalloc(module->dev, sizeof(struct + gbaudio_control), + GFP_KERNEL); + if (!control) { + ret = -ENOMEM; + goto error; + } + control->id = curr->id; + /* Prefix dev_id to widget_name */ + strlcpy(temp_name, curr->name, NAME_SIZE); + snprintf(curr->name, NAME_SIZE, "GB %d %s", module->dev_id, + temp_name); + control->name = curr->name; + if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) { + struct gb_audio_enumerated *gbenum = + &curr->info.value.enumerated; + + csize = offsetof(struct gb_audio_control, info); + csize += offsetof(struct gb_audio_ctl_elem_info, value); + csize += offsetof(struct gb_audio_enumerated, names); + csize += gbenum->names_length; + control->texts = (const char * const *) + gb_generate_enum_strings(module, gbenum); + control->items = gbenum->items; + } else + csize = sizeof(struct gb_audio_control); + + list_add(&control->list, &module->ctl_list); + dev_dbg(module->dev, "%d:%s created of type %d\n", curr->id, + curr->name, curr->info.type); + curr = (void *)curr + csize; + } + module->controls = dapm_kctls; + + return 0; +error: + list_for_each_entry_safe(control, _control, &module->ctl_list, + list) { + list_del(&control->list); + devm_kfree(module->dev, control); + } + devm_kfree(module->dev, dapm_kctls); + return ret; +} + +static int gbaudio_tplg_process_widgets(struct gbaudio_module_info *module, + struct gb_audio_widget *widgets) +{ + int i, ret, w_size; + struct snd_soc_dapm_widget *dapm_widgets; + struct gb_audio_widget *curr; + struct gbaudio_widget *widget, *_widget; + size_t size; + + size = sizeof(struct snd_soc_dapm_widget) * module->num_dapm_widgets; + dapm_widgets = devm_kzalloc(module->dev, size, GFP_KERNEL); + if (!dapm_widgets) + return -ENOMEM; + + curr = widgets; + for (i = 0; i < module->num_dapm_widgets; i++) { + ret = gbaudio_tplg_create_widget(module, &dapm_widgets[i], + curr, &w_size); + if (ret) { + dev_err(module->dev, "%s:%d type not supported\n", + curr->name, curr->type); + goto error; + } + widget = devm_kzalloc(module->dev, sizeof(struct + gbaudio_widget), + GFP_KERNEL); + if (!widget) { + ret = -ENOMEM; + goto error; + } + widget->id = curr->id; + widget->name = curr->name; + list_add(&widget->list, &module->widget_list); + curr = (void *)curr + w_size; + } + module->dapm_widgets = dapm_widgets; + + return 0; + +error: + list_for_each_entry_safe(widget, _widget, &module->widget_list, + list) { + list_del(&widget->list); + devm_kfree(module->dev, widget); + } + devm_kfree(module->dev, dapm_widgets); + return ret; +} + +static int gbaudio_tplg_process_routes(struct gbaudio_module_info *module, + struct gb_audio_route *routes) +{ + int i, ret; + struct snd_soc_dapm_route *dapm_routes; + struct gb_audio_route *curr; + size_t size; + + size = sizeof(struct snd_soc_dapm_route) * module->num_dapm_routes; + dapm_routes = devm_kzalloc(module->dev, size, GFP_KERNEL); + if (!dapm_routes) + return -ENOMEM; + + module->dapm_routes = dapm_routes; + curr = routes; + + for (i = 0; i < module->num_dapm_routes; i++) { + dapm_routes->sink = + gbaudio_map_widgetid(module, curr->destination_id); + if (!dapm_routes->sink) { + dev_err(module->dev, "%d:%d:%d:%d - Invalid sink\n", + curr->source_id, curr->destination_id, + curr->control_id, curr->index); + ret = -EINVAL; + goto error; + } + dapm_routes->source = + gbaudio_map_widgetid(module, curr->source_id); + if (!dapm_routes->source) { + dev_err(module->dev, "%d:%d:%d:%d - Invalid source\n", + curr->source_id, curr->destination_id, + curr->control_id, curr->index); + ret = -EINVAL; + goto error; + } + dapm_routes->control = + gbaudio_map_controlid(module, + curr->control_id, + curr->index); + if ((curr->control_id != GBAUDIO_INVALID_ID) && + !dapm_routes->control) { + dev_err(module->dev, "%d:%d:%d:%d - Invalid control\n", + curr->source_id, curr->destination_id, + curr->control_id, curr->index); + ret = -EINVAL; + goto error; + } + dev_dbg(module->dev, "Route {%s, %s, %s}\n", dapm_routes->sink, + (dapm_routes->control) ? dapm_routes->control:"NULL", + dapm_routes->source); + dapm_routes++; + curr++; + } + + return 0; + +error: + devm_kfree(module->dev, module->dapm_routes); + return ret; +} + +static int gbaudio_tplg_process_header(struct gbaudio_module_info *module, + struct gb_audio_topology *tplg_data) +{ + /* fetch no. of kcontrols, widgets & routes */ + module->num_controls = tplg_data->num_controls; + module->num_dapm_widgets = tplg_data->num_widgets; + module->num_dapm_routes = tplg_data->num_routes; + + /* update block offset */ + module->dai_offset = (unsigned long)&tplg_data->data; + module->control_offset = module->dai_offset + tplg_data->size_dais; + module->widget_offset = module->control_offset + + tplg_data->size_controls; + module->route_offset = module->widget_offset + + tplg_data->size_widgets; + + dev_dbg(module->dev, "DAI offset is 0x%lx\n", module->dai_offset); + dev_dbg(module->dev, "control offset is %lx\n", + module->control_offset); + dev_dbg(module->dev, "widget offset is %lx\n", module->widget_offset); + dev_dbg(module->dev, "route offset is %lx\n", module->route_offset); + + return 0; +} + +int gbaudio_tplg_parse_data(struct gbaudio_module_info *module, + struct gb_audio_topology *tplg_data) +{ + int ret; + struct gb_audio_control *controls; + struct gb_audio_widget *widgets; + struct gb_audio_route *routes; + + if (!tplg_data) + return -EINVAL; + + ret = gbaudio_tplg_process_header(module, tplg_data); + if (ret) { + dev_err(module->dev, "%d: Error in parsing topology header\n", + ret); + return ret; + } + + /* process control */ + controls = (struct gb_audio_control *)module->control_offset; + ret = gbaudio_tplg_process_kcontrols(module, controls); + if (ret) { + dev_err(module->dev, + "%d: Error in parsing controls data\n", ret); + return ret; + } + dev_dbg(module->dev, "Control parsing finished\n"); + + /* process widgets */ + widgets = (struct gb_audio_widget *)module->widget_offset; + ret = gbaudio_tplg_process_widgets(module, widgets); + if (ret) { + dev_err(module->dev, + "%d: Error in parsing widgets data\n", ret); + return ret; + } + dev_dbg(module->dev, "Widget parsing finished\n"); + + /* process route */ + routes = (struct gb_audio_route *)module->route_offset; + ret = gbaudio_tplg_process_routes(module, routes); + if (ret) { + dev_err(module->dev, + "%d: Error in parsing routes data\n", ret); + return ret; + } + dev_dbg(module->dev, "Route parsing finished\n"); + + /* parse jack capabilities */ + if (tplg_data->jack_type) { + module->jack_mask = tplg_data->jack_type & GBCODEC_JACK_MASK; + module->button_mask = tplg_data->jack_type & + GBCODEC_JACK_BUTTON_MASK; + } + + return ret; +} + +void gbaudio_tplg_release(struct gbaudio_module_info *module) +{ + struct gbaudio_control *control, *_control; + struct gbaudio_widget *widget, *_widget; + + if (!module->topology) + return; + + /* release kcontrols */ + list_for_each_entry_safe(control, _control, &module->ctl_list, + list) { + list_del(&control->list); + devm_kfree(module->dev, control); + } + if (module->controls) + devm_kfree(module->dev, module->controls); + + /* release widget controls */ + list_for_each_entry_safe(control, _control, &module->widget_ctl_list, + list) { + list_del(&control->list); + devm_kfree(module->dev, control); + } + + /* release widgets */ + list_for_each_entry_safe(widget, _widget, &module->widget_list, + list) { + list_del(&widget->list); + devm_kfree(module->dev, widget); + } + if (module->dapm_widgets) + devm_kfree(module->dev, module->dapm_widgets); + + /* release routes */ + if (module->dapm_routes) + devm_kfree(module->dev, module->dapm_routes); +} diff --git a/drivers/staging/greybus/authentication.c b/drivers/staging/greybus/authentication.c new file mode 100644 index 000000000000..168626ba0c03 --- /dev/null +++ b/drivers/staging/greybus/authentication.c @@ -0,0 +1,429 @@ +/* + * Greybus Component Authentication Protocol (CAP) Driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +#include +#include +#include +#include + +#include "greybus_authentication.h" +#include "firmware.h" +#include "greybus.h" + +#define CAP_TIMEOUT_MS 1000 + +/* + * Number of minor devices this driver supports. + * There will be exactly one required per Interface. + */ +#define NUM_MINORS U8_MAX + +struct gb_cap { + struct device *parent; + struct gb_connection *connection; + struct kref kref; + struct list_head node; + bool disabled; /* connection getting disabled */ + + struct mutex mutex; + struct cdev cdev; + struct device *class_device; + dev_t dev_num; +}; + +static struct class *cap_class; +static dev_t cap_dev_num; +static DEFINE_IDA(cap_minors_map); +static LIST_HEAD(cap_list); +static DEFINE_MUTEX(list_mutex); + +static void cap_kref_release(struct kref *kref) +{ + struct gb_cap *cap = container_of(kref, struct gb_cap, kref); + + kfree(cap); +} + +/* + * All users of cap take a reference (from within list_mutex lock), before + * they get a pointer to play with. And the structure will be freed only after + * the last user has put the reference to it. + */ +static void put_cap(struct gb_cap *cap) +{ + kref_put(&cap->kref, cap_kref_release); +} + +/* Caller must call put_cap() after using struct gb_cap */ +static struct gb_cap *get_cap(struct cdev *cdev) +{ + struct gb_cap *cap; + + mutex_lock(&list_mutex); + + list_for_each_entry(cap, &cap_list, node) { + if (&cap->cdev == cdev) { + kref_get(&cap->kref); + goto unlock; + } + } + + cap = NULL; + +unlock: + mutex_unlock(&list_mutex); + + return cap; +} + +static int cap_get_endpoint_uid(struct gb_cap *cap, u8 *euid) +{ + struct gb_connection *connection = cap->connection; + struct gb_cap_get_endpoint_uid_response response; + int ret; + + ret = gb_operation_sync(connection, GB_CAP_TYPE_GET_ENDPOINT_UID, NULL, + 0, &response, sizeof(response)); + if (ret) { + dev_err(cap->parent, "failed to get endpoint uid (%d)\n", ret); + return ret; + } + + memcpy(euid, response.uid, sizeof(response.uid)); + + return 0; +} + +static int cap_get_ims_certificate(struct gb_cap *cap, u32 class, u32 id, + u8 *certificate, u32 *size, u8 *result) +{ + struct gb_connection *connection = cap->connection; + struct gb_cap_get_ims_certificate_request *request; + struct gb_cap_get_ims_certificate_response *response; + size_t max_size = gb_operation_get_payload_size_max(connection); + struct gb_operation *op; + int ret; + + op = gb_operation_create_flags(connection, + GB_CAP_TYPE_GET_IMS_CERTIFICATE, + sizeof(*request), max_size, + GB_OPERATION_FLAG_SHORT_RESPONSE, + GFP_KERNEL); + if (!op) + return -ENOMEM; + + request = op->request->payload; + request->certificate_class = cpu_to_le32(class); + request->certificate_id = cpu_to_le32(id); + + ret = gb_operation_request_send_sync(op); + if (ret) { + dev_err(cap->parent, "failed to get certificate (%d)\n", ret); + goto done; + } + + response = op->response->payload; + *result = response->result_code; + *size = op->response->payload_size - sizeof(*response); + memcpy(certificate, response->certificate, *size); + +done: + gb_operation_put(op); + return ret; +} + +static int cap_authenticate(struct gb_cap *cap, u32 auth_type, u8 *uid, + u8 *challenge, u8 *result, u8 *auth_response, + u32 *signature_size, u8 *signature) +{ + struct gb_connection *connection = cap->connection; + struct gb_cap_authenticate_request *request; + struct gb_cap_authenticate_response *response; + size_t max_size = gb_operation_get_payload_size_max(connection); + struct gb_operation *op; + int ret; + + op = gb_operation_create_flags(connection, GB_CAP_TYPE_AUTHENTICATE, + sizeof(*request), max_size, + GB_OPERATION_FLAG_SHORT_RESPONSE, + GFP_KERNEL); + if (!op) + return -ENOMEM; + + request = op->request->payload; + request->auth_type = cpu_to_le32(auth_type); + memcpy(request->uid, uid, sizeof(request->uid)); + memcpy(request->challenge, challenge, sizeof(request->challenge)); + + ret = gb_operation_request_send_sync(op); + if (ret) { + dev_err(cap->parent, "failed to authenticate (%d)\n", ret); + goto done; + } + + response = op->response->payload; + *result = response->result_code; + *signature_size = op->response->payload_size - sizeof(*response); + memcpy(auth_response, response->response, sizeof(response->response)); + memcpy(signature, response->signature, *signature_size); + +done: + gb_operation_put(op); + return ret; +} + +/* Char device fops */ + +static int cap_open(struct inode *inode, struct file *file) +{ + struct gb_cap *cap = get_cap(inode->i_cdev); + + /* cap structure can't get freed until file descriptor is closed */ + if (cap) { + file->private_data = cap; + return 0; + } + + return -ENODEV; +} + +static int cap_release(struct inode *inode, struct file *file) +{ + struct gb_cap *cap = file->private_data; + + put_cap(cap); + return 0; +} + +static int cap_ioctl(struct gb_cap *cap, unsigned int cmd, + void __user *buf) +{ + struct cap_ioc_get_endpoint_uid endpoint_uid; + struct cap_ioc_get_ims_certificate *ims_cert; + struct cap_ioc_authenticate *authenticate; + size_t size; + int ret; + + switch (cmd) { + case CAP_IOC_GET_ENDPOINT_UID: + ret = cap_get_endpoint_uid(cap, endpoint_uid.uid); + if (ret) + return ret; + + if (copy_to_user(buf, &endpoint_uid, sizeof(endpoint_uid))) + return -EFAULT; + + return 0; + case CAP_IOC_GET_IMS_CERTIFICATE: + size = sizeof(*ims_cert); + ims_cert = memdup_user(buf, size); + if (IS_ERR(ims_cert)) + return PTR_ERR(ims_cert); + + ret = cap_get_ims_certificate(cap, ims_cert->certificate_class, + ims_cert->certificate_id, + ims_cert->certificate, + &ims_cert->cert_size, + &ims_cert->result_code); + if (!ret && copy_to_user(buf, ims_cert, size)) + ret = -EFAULT; + kfree(ims_cert); + + return ret; + case CAP_IOC_AUTHENTICATE: + size = sizeof(*authenticate); + authenticate = memdup_user(buf, size); + if (IS_ERR(authenticate)) + return PTR_ERR(authenticate); + + ret = cap_authenticate(cap, authenticate->auth_type, + authenticate->uid, + authenticate->challenge, + &authenticate->result_code, + authenticate->response, + &authenticate->signature_size, + authenticate->signature); + if (!ret && copy_to_user(buf, authenticate, size)) + ret = -EFAULT; + kfree(authenticate); + + return ret; + default: + return -ENOTTY; + } +} + +static long cap_ioctl_unlocked(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct gb_cap *cap = file->private_data; + struct gb_bundle *bundle = cap->connection->bundle; + int ret = -ENODEV; + + /* + * Serialize ioctls. + * + * We don't want the user to do multiple authentication operations in + * parallel. + * + * This is also used to protect ->disabled, which is used to check if + * the connection is getting disconnected, so that we don't start any + * new operations. + */ + mutex_lock(&cap->mutex); + if (!cap->disabled) { + ret = gb_pm_runtime_get_sync(bundle); + if (!ret) { + ret = cap_ioctl(cap, cmd, (void __user *)arg); + gb_pm_runtime_put_autosuspend(bundle); + } + } + mutex_unlock(&cap->mutex); + + return ret; +} + +static const struct file_operations cap_fops = { + .owner = THIS_MODULE, + .open = cap_open, + .release = cap_release, + .unlocked_ioctl = cap_ioctl_unlocked, +}; + +int gb_cap_connection_init(struct gb_connection *connection) +{ + struct gb_cap *cap; + int ret, minor; + + if (!connection) + return 0; + + cap = kzalloc(sizeof(*cap), GFP_KERNEL); + if (!cap) + return -ENOMEM; + + cap->parent = &connection->bundle->dev; + cap->connection = connection; + mutex_init(&cap->mutex); + gb_connection_set_data(connection, cap); + kref_init(&cap->kref); + + mutex_lock(&list_mutex); + list_add(&cap->node, &cap_list); + mutex_unlock(&list_mutex); + + ret = gb_connection_enable(connection); + if (ret) + goto err_list_del; + + minor = ida_simple_get(&cap_minors_map, 0, NUM_MINORS, GFP_KERNEL); + if (minor < 0) { + ret = minor; + goto err_connection_disable; + } + + /* Add a char device to allow userspace to interact with cap */ + cap->dev_num = MKDEV(MAJOR(cap_dev_num), minor); + cdev_init(&cap->cdev, &cap_fops); + + ret = cdev_add(&cap->cdev, cap->dev_num, 1); + if (ret) + goto err_remove_ida; + + /* Add a soft link to the previously added char-dev within the bundle */ + cap->class_device = device_create(cap_class, cap->parent, cap->dev_num, + NULL, "gb-authenticate-%d", minor); + if (IS_ERR(cap->class_device)) { + ret = PTR_ERR(cap->class_device); + goto err_del_cdev; + } + + return 0; + +err_del_cdev: + cdev_del(&cap->cdev); +err_remove_ida: + ida_simple_remove(&cap_minors_map, minor); +err_connection_disable: + gb_connection_disable(connection); +err_list_del: + mutex_lock(&list_mutex); + list_del(&cap->node); + mutex_unlock(&list_mutex); + + put_cap(cap); + + return ret; +} + +void gb_cap_connection_exit(struct gb_connection *connection) +{ + struct gb_cap *cap; + + if (!connection) + return; + + cap = gb_connection_get_data(connection); + + device_destroy(cap_class, cap->dev_num); + cdev_del(&cap->cdev); + ida_simple_remove(&cap_minors_map, MINOR(cap->dev_num)); + + /* + * Disallow any new ioctl operations on the char device and wait for + * existing ones to finish. + */ + mutex_lock(&cap->mutex); + cap->disabled = true; + mutex_unlock(&cap->mutex); + + /* All pending greybus operations should have finished by now */ + gb_connection_disable(cap->connection); + + /* Disallow new users to get access to the cap structure */ + mutex_lock(&list_mutex); + list_del(&cap->node); + mutex_unlock(&list_mutex); + + /* + * All current users of cap would have taken a reference to it by + * now, we can drop our reference and wait the last user will get + * cap freed. + */ + put_cap(cap); +} + +int cap_init(void) +{ + int ret; + + cap_class = class_create(THIS_MODULE, "gb_authenticate"); + if (IS_ERR(cap_class)) + return PTR_ERR(cap_class); + + ret = alloc_chrdev_region(&cap_dev_num, 0, NUM_MINORS, + "gb_authenticate"); + if (ret) + goto err_remove_class; + + return 0; + +err_remove_class: + class_destroy(cap_class); + return ret; +} + +void cap_exit(void) +{ + unregister_chrdev_region(cap_dev_num, NUM_MINORS); + class_destroy(cap_class); + ida_destroy(&cap_minors_map); +} diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c new file mode 100644 index 000000000000..5f90721bcc51 --- /dev/null +++ b/drivers/staging/greybus/bootrom.c @@ -0,0 +1,524 @@ +/* + * BOOTROM Greybus driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include + +#include "greybus.h" +#include "firmware.h" + +/* Timeout, in jiffies, within which the next request must be received */ +#define NEXT_REQ_TIMEOUT_MS 1000 + +/* + * FIXME: Reduce this timeout once svc core handles parallel processing of + * events from the SVC, which are handled sequentially today. + */ +#define MODE_SWITCH_TIMEOUT_MS 10000 + +enum next_request_type { + NEXT_REQ_FIRMWARE_SIZE, + NEXT_REQ_GET_FIRMWARE, + NEXT_REQ_READY_TO_BOOT, + NEXT_REQ_MODE_SWITCH, +}; + +struct gb_bootrom { + struct gb_connection *connection; + const struct firmware *fw; + u8 protocol_major; + u8 protocol_minor; + enum next_request_type next_request; + struct delayed_work dwork; + struct mutex mutex; /* Protects bootrom->fw */ +}; + +static void free_firmware(struct gb_bootrom *bootrom) +{ + if (!bootrom->fw) + return; + + release_firmware(bootrom->fw); + bootrom->fw = NULL; +} + +static void gb_bootrom_timedout(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct gb_bootrom *bootrom = container_of(dwork, struct gb_bootrom, dwork); + struct device *dev = &bootrom->connection->bundle->dev; + const char *reason; + + switch (bootrom->next_request) { + case NEXT_REQ_FIRMWARE_SIZE: + reason = "Firmware Size Request"; + break; + case NEXT_REQ_GET_FIRMWARE: + reason = "Get Firmware Request"; + break; + case NEXT_REQ_READY_TO_BOOT: + reason = "Ready to Boot Request"; + break; + case NEXT_REQ_MODE_SWITCH: + reason = "Interface Mode Switch"; + break; + default: + reason = NULL; + dev_err(dev, "Invalid next-request: %u", bootrom->next_request); + break; + } + + dev_err(dev, "Timed out waiting for %s from the Module\n", reason); + + mutex_lock(&bootrom->mutex); + free_firmware(bootrom); + mutex_unlock(&bootrom->mutex); + + /* TODO: Power-off Module ? */ +} + +static void gb_bootrom_set_timeout(struct gb_bootrom *bootrom, + enum next_request_type next, unsigned long timeout) +{ + bootrom->next_request = next; + schedule_delayed_work(&bootrom->dwork, msecs_to_jiffies(timeout)); +} + +static void gb_bootrom_cancel_timeout(struct gb_bootrom *bootrom) +{ + cancel_delayed_work_sync(&bootrom->dwork); +} + +/* + * The es2 chip doesn't have VID/PID programmed into the hardware and we need to + * hack that up to distinguish different modules and their firmware blobs. + * + * This fetches VID/PID (over bootrom protocol) for es2 chip only, when VID/PID + * already sent during hotplug are 0. + * + * Otherwise, we keep intf->vendor_id/product_id same as what's passed + * during hotplug. + */ +static void bootrom_es2_fixup_vid_pid(struct gb_bootrom *bootrom) +{ + struct gb_bootrom_get_vid_pid_response response; + struct gb_connection *connection = bootrom->connection; + struct gb_interface *intf = connection->bundle->intf; + int ret; + + if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_GMP_IDS)) + return; + + ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_GET_VID_PID, + NULL, 0, &response, sizeof(response)); + if (ret) { + dev_err(&connection->bundle->dev, + "Bootrom get vid/pid operation failed (%d)\n", ret); + return; + } + + /* + * NOTE: This is hacked, so that the same values of VID/PID can be used + * by next firmware level as well. The uevent for bootrom will still + * have VID/PID as 0, though after this point the sysfs files will start + * showing the updated values. But yeah, that's a bit racy as the same + * sysfs files would be showing 0 before this point. + */ + intf->vendor_id = le32_to_cpu(response.vendor_id); + intf->product_id = le32_to_cpu(response.product_id); + + dev_dbg(&connection->bundle->dev, "Bootrom got vid (0x%x)/pid (0x%x)\n", + intf->vendor_id, intf->product_id); +} + +/* This returns path of the firmware blob on the disk */ +static int find_firmware(struct gb_bootrom *bootrom, u8 stage) +{ + struct gb_connection *connection = bootrom->connection; + struct gb_interface *intf = connection->bundle->intf; + char firmware_name[49]; + int rc; + + /* Already have a firmware, free it */ + free_firmware(bootrom); + + /* Bootrom protocol is only supported for loading Stage 2 firmware */ + if (stage != 2) { + dev_err(&connection->bundle->dev, "Invalid boot stage: %u\n", + stage); + return -EINVAL; + } + + /* + * Create firmware name + * + * XXX Name it properly.. + */ + snprintf(firmware_name, sizeof(firmware_name), + FW_NAME_PREFIX "%08x_%08x_%08x_%08x_s2l.tftf", + intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, + intf->vendor_id, intf->product_id); + + // FIXME: + // Turn to dev_dbg later after everyone has valid bootloaders with good + // ids, but leave this as dev_info for now to make it easier to track + // down "empty" vid/pid modules. + dev_info(&connection->bundle->dev, "Firmware file '%s' requested\n", + firmware_name); + + rc = request_firmware(&bootrom->fw, firmware_name, + &connection->bundle->dev); + if (rc) { + dev_err(&connection->bundle->dev, + "failed to find %s firmware (%d)\n", firmware_name, rc); + } + + return rc; +} + +static int gb_bootrom_firmware_size_request(struct gb_operation *op) +{ + struct gb_bootrom *bootrom = gb_connection_get_data(op->connection); + struct gb_bootrom_firmware_size_request *size_request = op->request->payload; + struct gb_bootrom_firmware_size_response *size_response; + struct device *dev = &op->connection->bundle->dev; + int ret; + + /* Disable timeouts */ + gb_bootrom_cancel_timeout(bootrom); + + if (op->request->payload_size != sizeof(*size_request)) { + dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n", + __func__, op->request->payload_size, + sizeof(*size_request)); + ret = -EINVAL; + goto queue_work; + } + + mutex_lock(&bootrom->mutex); + + ret = find_firmware(bootrom, size_request->stage); + if (ret) + goto unlock; + + if (!gb_operation_response_alloc(op, sizeof(*size_response), + GFP_KERNEL)) { + dev_err(dev, "%s: error allocating response\n", __func__); + free_firmware(bootrom); + ret = -ENOMEM; + goto unlock; + } + + size_response = op->response->payload; + size_response->size = cpu_to_le32(bootrom->fw->size); + + dev_dbg(dev, "%s: firmware size %d bytes\n", __func__, size_response->size); + +unlock: + mutex_unlock(&bootrom->mutex); + +queue_work: + if (!ret) { + /* Refresh timeout */ + gb_bootrom_set_timeout(bootrom, NEXT_REQ_GET_FIRMWARE, + NEXT_REQ_TIMEOUT_MS); + } + + return ret; +} + +static int gb_bootrom_get_firmware(struct gb_operation *op) +{ + struct gb_bootrom *bootrom = gb_connection_get_data(op->connection); + const struct firmware *fw; + struct gb_bootrom_get_firmware_request *firmware_request; + struct gb_bootrom_get_firmware_response *firmware_response; + struct device *dev = &op->connection->bundle->dev; + unsigned int offset, size; + enum next_request_type next_request; + int ret = 0; + + /* Disable timeouts */ + gb_bootrom_cancel_timeout(bootrom); + + if (op->request->payload_size != sizeof(*firmware_request)) { + dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n", + __func__, op->request->payload_size, + sizeof(*firmware_request)); + ret = -EINVAL; + goto queue_work; + } + + mutex_lock(&bootrom->mutex); + + fw = bootrom->fw; + if (!fw) { + dev_err(dev, "%s: firmware not available\n", __func__); + ret = -EINVAL; + goto unlock; + } + + firmware_request = op->request->payload; + offset = le32_to_cpu(firmware_request->offset); + size = le32_to_cpu(firmware_request->size); + + if (offset >= fw->size || size > fw->size - offset) { + dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n", + offset, size); + ret = -EINVAL; + goto unlock; + } + + if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size, + GFP_KERNEL)) { + dev_err(dev, "%s: error allocating response\n", __func__); + ret = -ENOMEM; + goto unlock; + } + + firmware_response = op->response->payload; + memcpy(firmware_response->data, fw->data + offset, size); + + dev_dbg(dev, "responding with firmware (offs = %u, size = %u)\n", offset, + size); + +unlock: + mutex_unlock(&bootrom->mutex); + +queue_work: + /* Refresh timeout */ + if (!ret && (offset + size == fw->size)) + next_request = NEXT_REQ_READY_TO_BOOT; + else + next_request = NEXT_REQ_GET_FIRMWARE; + + gb_bootrom_set_timeout(bootrom, next_request, NEXT_REQ_TIMEOUT_MS); + + return ret; +} + +static int gb_bootrom_ready_to_boot(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_bootrom *bootrom = gb_connection_get_data(connection); + struct gb_bootrom_ready_to_boot_request *rtb_request; + struct device *dev = &connection->bundle->dev; + u8 status; + int ret = 0; + + /* Disable timeouts */ + gb_bootrom_cancel_timeout(bootrom); + + if (op->request->payload_size != sizeof(*rtb_request)) { + dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", + __func__, op->request->payload_size, + sizeof(*rtb_request)); + ret = -EINVAL; + goto queue_work; + } + + rtb_request = op->request->payload; + status = rtb_request->status; + + /* Return error if the blob was invalid */ + if (status == GB_BOOTROM_BOOT_STATUS_INVALID) { + ret = -EINVAL; + goto queue_work; + } + + /* + * XXX Should we return error for insecure firmware? + */ + dev_dbg(dev, "ready to boot: 0x%x, 0\n", status); + +queue_work: + /* + * Refresh timeout, the Interface shall load the new personality and + * send a new hotplug request, which shall get rid of the bootrom + * connection. As that can take some time, increase the timeout a bit. + */ + gb_bootrom_set_timeout(bootrom, NEXT_REQ_MODE_SWITCH, + MODE_SWITCH_TIMEOUT_MS); + + return ret; +} + +static int gb_bootrom_request_handler(struct gb_operation *op) +{ + u8 type = op->type; + + switch (type) { + case GB_BOOTROM_TYPE_FIRMWARE_SIZE: + return gb_bootrom_firmware_size_request(op); + case GB_BOOTROM_TYPE_GET_FIRMWARE: + return gb_bootrom_get_firmware(op); + case GB_BOOTROM_TYPE_READY_TO_BOOT: + return gb_bootrom_ready_to_boot(op); + default: + dev_err(&op->connection->bundle->dev, + "unsupported request: %u\n", type); + return -EINVAL; + } +} + +static int gb_bootrom_get_version(struct gb_bootrom *bootrom) +{ + struct gb_bundle *bundle = bootrom->connection->bundle; + struct gb_bootrom_version_request request; + struct gb_bootrom_version_response response; + int ret; + + request.major = GB_BOOTROM_VERSION_MAJOR; + request.minor = GB_BOOTROM_VERSION_MINOR; + + ret = gb_operation_sync(bootrom->connection, + GB_BOOTROM_TYPE_VERSION, + &request, sizeof(request), &response, + sizeof(response)); + if (ret) { + dev_err(&bundle->dev, + "failed to get protocol version: %d\n", + ret); + return ret; + } + + if (response.major > request.major) { + dev_err(&bundle->dev, + "unsupported major protocol version (%u > %u)\n", + response.major, request.major); + return -ENOTSUPP; + } + + bootrom->protocol_major = response.major; + bootrom->protocol_minor = response.minor; + + dev_dbg(&bundle->dev, "%s - %u.%u\n", __func__, response.major, + response.minor); + + return 0; +} + +static int gb_bootrom_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_bootrom *bootrom; + int ret; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_BOOTROM) + return -ENODEV; + + bootrom = kzalloc(sizeof(*bootrom), GFP_KERNEL); + if (!bootrom) + return -ENOMEM; + + connection = gb_connection_create(bundle, + le16_to_cpu(cport_desc->id), + gb_bootrom_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto err_free_bootrom; + } + + gb_connection_set_data(connection, bootrom); + + bootrom->connection = connection; + + mutex_init(&bootrom->mutex); + INIT_DELAYED_WORK(&bootrom->dwork, gb_bootrom_timedout); + greybus_set_drvdata(bundle, bootrom); + + ret = gb_connection_enable_tx(connection); + if (ret) + goto err_connection_destroy; + + ret = gb_bootrom_get_version(bootrom); + if (ret) + goto err_connection_disable; + + bootrom_es2_fixup_vid_pid(bootrom); + + ret = gb_connection_enable(connection); + if (ret) + goto err_connection_disable; + + /* Refresh timeout */ + gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE, + NEXT_REQ_TIMEOUT_MS); + + /* Tell bootrom we're ready. */ + ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_AP_READY, NULL, 0, + NULL, 0); + if (ret) { + dev_err(&connection->bundle->dev, + "failed to send AP READY: %d\n", ret); + goto err_cancel_timeout; + } + + dev_dbg(&bundle->dev, "AP_READY sent\n"); + + return 0; + +err_cancel_timeout: + gb_bootrom_cancel_timeout(bootrom); +err_connection_disable: + gb_connection_disable(connection); +err_connection_destroy: + gb_connection_destroy(connection); +err_free_bootrom: + kfree(bootrom); + + return ret; +} + +static void gb_bootrom_disconnect(struct gb_bundle *bundle) +{ + struct gb_bootrom *bootrom = greybus_get_drvdata(bundle); + + dev_dbg(&bundle->dev, "%s\n", __func__); + + gb_connection_disable(bootrom->connection); + + /* Disable timeouts */ + gb_bootrom_cancel_timeout(bootrom); + + /* + * Release firmware: + * + * As the connection and the delayed work are already disabled, we don't + * need to lock access to bootrom->fw here. + */ + free_firmware(bootrom); + + gb_connection_destroy(bootrom->connection); + kfree(bootrom); +} + +static const struct greybus_bundle_id gb_bootrom_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BOOTROM) }, + { } +}; + +static struct greybus_driver gb_bootrom_driver = { + .name = "bootrom", + .probe = gb_bootrom_probe, + .disconnect = gb_bootrom_disconnect, + .id_table = gb_bootrom_id_table, +}; + +module_greybus_driver(gb_bootrom_driver); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c new file mode 100644 index 000000000000..d2ef57d090be --- /dev/null +++ b/drivers/staging/greybus/bundle.c @@ -0,0 +1,253 @@ +/* + * Greybus bundles + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" +#include "greybus_trace.h" + +static ssize_t bundle_class_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + return sprintf(buf, "0x%02x\n", bundle->class); +} +static DEVICE_ATTR_RO(bundle_class); + +static ssize_t bundle_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + return sprintf(buf, "%u\n", bundle->id); +} +static DEVICE_ATTR_RO(bundle_id); + +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + if (bundle->state == NULL) + return sprintf(buf, "\n"); + + return sprintf(buf, "%s\n", bundle->state); +} + +static ssize_t state_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + kfree(bundle->state); + bundle->state = kstrdup(buf, GFP_KERNEL); + if (!bundle->state) + return -ENOMEM; + + /* Tell userspace that the file contents changed */ + sysfs_notify(&bundle->dev.kobj, NULL, "state"); + + return size; +} +static DEVICE_ATTR_RW(state); + +static struct attribute *bundle_attrs[] = { + &dev_attr_bundle_class.attr, + &dev_attr_bundle_id.attr, + &dev_attr_state.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(bundle); + +static struct gb_bundle *gb_bundle_find(struct gb_interface *intf, + u8 bundle_id) +{ + struct gb_bundle *bundle; + + list_for_each_entry(bundle, &intf->bundles, links) { + if (bundle->id == bundle_id) + return bundle; + } + + return NULL; +} + +static void gb_bundle_release(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + trace_gb_bundle_release(bundle); + + kfree(bundle->state); + kfree(bundle->cport_desc); + kfree(bundle); +} + +#ifdef CONFIG_PM +static void gb_bundle_disable_all_connections(struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + list_for_each_entry(connection, &bundle->connections, bundle_links) + gb_connection_disable(connection); +} + +static void gb_bundle_enable_all_connections(struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + list_for_each_entry(connection, &bundle->connections, bundle_links) + gb_connection_enable(connection); +} + +static int gb_bundle_suspend(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct dev_pm_ops *pm = dev->driver->pm; + int ret; + + if (pm && pm->runtime_suspend) { + ret = pm->runtime_suspend(&bundle->dev); + if (ret) + return ret; + } else { + gb_bundle_disable_all_connections(bundle); + } + + ret = gb_control_bundle_suspend(bundle->intf->control, bundle->id); + if (ret) { + if (pm && pm->runtime_resume) + ret = pm->runtime_resume(dev); + else + gb_bundle_enable_all_connections(bundle); + + return ret; + } + + return 0; +} + +static int gb_bundle_resume(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct dev_pm_ops *pm = dev->driver->pm; + int ret; + + ret = gb_control_bundle_resume(bundle->intf->control, bundle->id); + if (ret) + return ret; + + if (pm && pm->runtime_resume) { + ret = pm->runtime_resume(dev); + if (ret) + return ret; + } else { + gb_bundle_enable_all_connections(bundle); + } + + return 0; +} + +static int gb_bundle_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + + return 0; +} +#endif + +static const struct dev_pm_ops gb_bundle_pm_ops = { + SET_RUNTIME_PM_OPS(gb_bundle_suspend, gb_bundle_resume, gb_bundle_idle) +}; + +struct device_type greybus_bundle_type = { + .name = "greybus_bundle", + .release = gb_bundle_release, + .pm = &gb_bundle_pm_ops, +}; + +/* + * Create a gb_bundle structure to represent a discovered + * bundle. Returns a pointer to the new bundle or a null + * pointer if a failure occurs due to memory exhaustion. + */ +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, + u8 class) +{ + struct gb_bundle *bundle; + + if (bundle_id == BUNDLE_ID_NONE) { + dev_err(&intf->dev, "can't use bundle id %u\n", bundle_id); + return NULL; + } + + /* + * Reject any attempt to reuse a bundle id. We initialize + * these serially, so there's no need to worry about keeping + * the interface bundle list locked here. + */ + if (gb_bundle_find(intf, bundle_id)) { + dev_err(&intf->dev, "duplicate bundle id %u\n", bundle_id); + return NULL; + } + + bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); + if (!bundle) + return NULL; + + bundle->intf = intf; + bundle->id = bundle_id; + bundle->class = class; + INIT_LIST_HEAD(&bundle->connections); + + bundle->dev.parent = &intf->dev; + bundle->dev.bus = &greybus_bus_type; + bundle->dev.type = &greybus_bundle_type; + bundle->dev.groups = bundle_groups; + bundle->dev.dma_mask = intf->dev.dma_mask; + device_initialize(&bundle->dev); + dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id); + + list_add(&bundle->links, &intf->bundles); + + trace_gb_bundle_create(bundle); + + return bundle; +} + +int gb_bundle_add(struct gb_bundle *bundle) +{ + int ret; + + ret = device_add(&bundle->dev); + if (ret) { + dev_err(&bundle->dev, "failed to register bundle: %d\n", ret); + return ret; + } + + trace_gb_bundle_add(bundle); + + return 0; +} + +/* + * Tear down a previously set up bundle. + */ +void gb_bundle_destroy(struct gb_bundle *bundle) +{ + trace_gb_bundle_destroy(bundle); + + if (device_is_registered(&bundle->dev)) + device_del(&bundle->dev); + + list_del(&bundle->links); + + put_device(&bundle->dev); +} diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h new file mode 100644 index 000000000000..0c3491def96c --- /dev/null +++ b/drivers/staging/greybus/bundle.h @@ -0,0 +1,90 @@ +/* + * Greybus bundles + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __BUNDLE_H +#define __BUNDLE_H + +#include + +#define BUNDLE_ID_NONE U8_MAX + +/* Greybus "public" definitions" */ +struct gb_bundle { + struct device dev; + struct gb_interface *intf; + + u8 id; + u8 class; + u8 class_major; + u8 class_minor; + + size_t num_cports; + struct greybus_descriptor_cport *cport_desc; + + struct list_head connections; + u8 *state; + + struct list_head links; /* interface->bundles */ +}; +#define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) + +/* Greybus "private" definitions" */ +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, + u8 class); +int gb_bundle_add(struct gb_bundle *bundle); +void gb_bundle_destroy(struct gb_bundle *bundle); + +/* Bundle Runtime PM wrappers */ +#ifdef CONFIG_PM +static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) +{ + int retval; + + retval = pm_runtime_get_sync(&bundle->dev); + if (retval < 0) { + dev_err(&bundle->dev, + "pm_runtime_get_sync failed: %d\n", retval); + pm_runtime_put_noidle(&bundle->dev); + return retval; + } + + return 0; +} + +static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) +{ + int retval; + + pm_runtime_mark_last_busy(&bundle->dev); + retval = pm_runtime_put_autosuspend(&bundle->dev); + + return retval; +} + +static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) +{ + pm_runtime_get_noresume(&bundle->dev); +} + +static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) +{ + pm_runtime_put_noidle(&bundle->dev); +} + +#else +static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) +{ return 0; } +static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) +{ return 0; } + +static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) {} +static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) {} +#endif + +#endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c new file mode 100644 index 000000000000..491bdd720c0c --- /dev/null +++ b/drivers/staging/greybus/camera.c @@ -0,0 +1,1400 @@ +/* + * Greybus Camera protocol driver. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gb-camera.h" +#include "greybus.h" +#include "greybus_protocols.h" + +enum gb_camera_debugs_buffer_id { + GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES, + GB_CAMERA_DEBUGFS_BUFFER_STREAMS, + GB_CAMERA_DEBUGFS_BUFFER_CAPTURE, + GB_CAMERA_DEBUGFS_BUFFER_FLUSH, + GB_CAMERA_DEBUGFS_BUFFER_MAX, +}; + +struct gb_camera_debugfs_buffer { + char data[PAGE_SIZE]; + size_t length; +}; + +enum gb_camera_state { + GB_CAMERA_STATE_UNCONFIGURED, + GB_CAMERA_STATE_CONFIGURED, +}; + +/** + * struct gb_camera - A Greybus Camera Device + * @connection: the greybus connection for camera management + * @data_connection: the greybus connection for camera data + * @data_cport_id: the data CPort ID on the module side + * @mutex: protects the connection and state fields + * @state: the current module state + * @debugfs: debugfs entries for camera protocol operations testing + * @module: Greybus camera module registered to HOST processor. + */ +struct gb_camera { + struct gb_bundle *bundle; + struct gb_connection *connection; + struct gb_connection *data_connection; + u16 data_cport_id; + + struct mutex mutex; + enum gb_camera_state state; + + struct { + struct dentry *root; + struct gb_camera_debugfs_buffer *buffers; + } debugfs; + + struct gb_camera_module module; +}; + +struct gb_camera_stream_config { + unsigned int width; + unsigned int height; + unsigned int format; + unsigned int vc; + unsigned int dt[2]; + unsigned int max_size; +}; + +struct gb_camera_fmt_info { + enum v4l2_mbus_pixelcode mbus_code; + unsigned int gb_format; + unsigned int bpp; +}; + +/* GB format to media code map */ +static const struct gb_camera_fmt_info gb_fmt_info[] = { + { + .mbus_code = V4L2_MBUS_FMT_UYVY8_1X16, + .gb_format = 0x01, + .bpp = 16, + }, + { + .mbus_code = V4L2_MBUS_FMT_NV12_1x8, + .gb_format = 0x12, + .bpp = 12, + }, + { + .mbus_code = V4L2_MBUS_FMT_NV21_1x8, + .gb_format = 0x13, + .bpp = 12, + }, + { + .mbus_code = V4L2_MBUS_FMT_YU12_1x8, + .gb_format = 0x16, + .bpp = 12, + }, + { + .mbus_code = V4L2_MBUS_FMT_YV12_1x8, + .gb_format = 0x17, + .bpp = 12, + }, + { + .mbus_code = V4L2_MBUS_FMT_JPEG_1X8, + .gb_format = 0x40, + .bpp = 0, + }, + { + .mbus_code = V4L2_MBUS_FMT_GB_CAM_METADATA_1X8, + .gb_format = 0x41, + .bpp = 0, + }, + { + .mbus_code = V4L2_MBUS_FMT_GB_CAM_DEBUG_DATA_1X8, + .gb_format = 0x42, + .bpp = 0, + }, + { + .mbus_code = V4L2_MBUS_FMT_SBGGR10_1X10, + .gb_format = 0x80, + .bpp = 10, + }, + { + .mbus_code = V4L2_MBUS_FMT_SGBRG10_1X10, + .gb_format = 0x81, + .bpp = 10, + }, + { + .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10, + .gb_format = 0x82, + .bpp = 10, + }, + { + .mbus_code = V4L2_MBUS_FMT_SRGGB10_1X10, + .gb_format = 0x83, + .bpp = 10, + }, + { + .mbus_code = V4L2_MBUS_FMT_SBGGR12_1X12, + .gb_format = 0x84, + .bpp = 12, + }, + { + .mbus_code = V4L2_MBUS_FMT_SGBRG12_1X12, + .gb_format = 0x85, + .bpp = 12, + }, + { + .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12, + .gb_format = 0x86, + .bpp = 12, + }, + { + .mbus_code = V4L2_MBUS_FMT_SRGGB12_1X12, + .gb_format = 0x87, + .bpp = 12, + }, +}; + +static const struct gb_camera_fmt_info *gb_camera_get_format_info(u16 gb_fmt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gb_fmt_info); i++) { + if (gb_fmt_info[i].gb_format == gb_fmt) + return &gb_fmt_info[i]; + } + + return NULL; +} + +#define ES2_APB_CDSI0_CPORT 16 +#define ES2_APB_CDSI1_CPORT 17 + +#define GB_CAMERA_MAX_SETTINGS_SIZE 8192 + +#define gcam_dbg(gcam, format...) dev_dbg(&gcam->bundle->dev, format) +#define gcam_info(gcam, format...) dev_info(&gcam->bundle->dev, format) +#define gcam_err(gcam, format...) dev_err(&gcam->bundle->dev, format) + +static int gb_camera_operation_sync_flags(struct gb_connection *connection, + int type, unsigned int flags, + void *request, size_t request_size, + void *response, size_t *response_size) +{ + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_flags(connection, type, request_size, + *response_size, flags, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync(operation); + if (ret) { + dev_err(&connection->hd->dev, + "%s: synchronous operation of type 0x%02x failed: %d\n", + connection->name, type, ret); + } else { + *response_size = operation->response->payload_size; + + if (operation->response->payload_size) + memcpy(response, operation->response->payload, + operation->response->payload_size); + } + + gb_operation_put(operation); + + return ret; +} + +static int gb_camera_get_max_pkt_size(struct gb_camera *gcam, + struct gb_camera_configure_streams_response *resp) +{ + unsigned int max_pkt_size = 0; + unsigned int i; + + for (i = 0; i < resp->num_streams; i++) { + struct gb_camera_stream_config_response *cfg = &resp->config[i]; + const struct gb_camera_fmt_info *fmt_info; + unsigned int pkt_size; + + fmt_info = gb_camera_get_format_info(cfg->format); + if (!fmt_info) { + gcam_err(gcam, "unsupported greybus image format: %d\n", + cfg->format); + return -EIO; + } + + if (fmt_info->bpp == 0) { + pkt_size = le32_to_cpu(cfg->max_pkt_size); + + if (pkt_size == 0) { + gcam_err(gcam, + "Stream %u: invalid zero maximum packet size\n", + i); + return -EIO; + } + } else { + pkt_size = le16_to_cpu(cfg->width) * fmt_info->bpp / 8; + + if (pkt_size != le32_to_cpu(cfg->max_pkt_size)) { + gcam_err(gcam, + "Stream %u: maximum packet size mismatch (%u/%u)\n", + i, pkt_size, cfg->max_pkt_size); + return -EIO; + } + } + + max_pkt_size = max(pkt_size, max_pkt_size); + } + + return max_pkt_size; +} + +/* + * Validate the stream configuration response verifying padding is correctly + * set and the returned number of streams is supported + */ +static const int gb_camera_configure_streams_validate_response( + struct gb_camera *gcam, + struct gb_camera_configure_streams_response *resp, + unsigned int nstreams) +{ + unsigned int i; + + /* Validate the returned response structure */ + if (resp->padding[0] || resp->padding[1]) { + gcam_err(gcam, "response padding != 0\n"); + return -EIO; + } + + if (resp->num_streams > nstreams) { + gcam_err(gcam, "got #streams %u > request %u\n", + resp->num_streams, nstreams); + return -EIO; + } + + for (i = 0; i < resp->num_streams; i++) { + struct gb_camera_stream_config_response *cfg = &resp->config[i]; + if (cfg->padding) { + gcam_err(gcam, "stream #%u padding != 0\n", i); + return -EIO; + } + } + + return 0; +} + +/* ----------------------------------------------------------------------------- + * Hardware Configuration + */ + +static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id, + bool hs) +{ + struct gb_svc *svc = gcam->connection->hd->svc; + int ret; + + if (hs) + ret = gb_svc_intf_set_power_mode(svc, intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_SMALL_AMPLITUDE, + GB_SVC_NO_DE_EMPHASIS, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_PWRM_RXTERMINATION | + GB_SVC_PWRM_TXTERMINATION, 0, + NULL, NULL); + else + ret = gb_svc_intf_set_power_mode(svc, intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 2, 1, + GB_SVC_SMALL_AMPLITUDE, + GB_SVC_NO_DE_EMPHASIS, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 2, 1, + 0, 0, + NULL, NULL); + + return ret; +} + +static int gb_camera_set_power_mode(struct gb_camera *gcam, bool hs) +{ + struct gb_interface *intf = gcam->connection->intf; + struct gb_svc *svc = gcam->connection->hd->svc; + int ret; + + ret = gb_camera_set_intf_power_mode(gcam, intf->interface_id, hs); + if (ret < 0) { + gcam_err(gcam, "failed to set module interface to %s (%d)\n", + hs ? "HS" : "PWM", ret); + return ret; + } + + ret = gb_camera_set_intf_power_mode(gcam, svc->ap_intf_id, hs); + if (ret < 0) { + gb_camera_set_intf_power_mode(gcam, intf->interface_id, !hs); + gcam_err(gcam, "failed to set AP interface to %s (%d)\n", + hs ? "HS" : "PWM", ret); + return ret; + } + + return 0; +} + +struct ap_csi_config_request { + __u8 csi_id; + __u8 flags; +#define GB_CAMERA_CSI_FLAG_CLOCK_CONTINUOUS 0x01 + __u8 num_lanes; + __u8 padding; + __le32 csi_clk_freq; + __le32 max_pkt_size; +} __packed; + +/* + * TODO: Compute the number of lanes dynamically based on bandwidth + * requirements. + */ +#define GB_CAMERA_CSI_NUM_DATA_LANES 4 + +#define GB_CAMERA_CSI_CLK_FREQ_MAX 999000000U +#define GB_CAMERA_CSI_CLK_FREQ_MIN 100000000U +#define GB_CAMERA_CSI_CLK_FREQ_MARGIN 150000000U + +static int gb_camera_setup_data_connection(struct gb_camera *gcam, + struct gb_camera_configure_streams_response *resp, + struct gb_camera_csi_params *csi_params) +{ + struct ap_csi_config_request csi_cfg; + struct gb_connection *conn; + unsigned int clk_freq; + int ret; + + /* + * Create the data connection between the camera module data CPort and + * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge. + */ + conn = gb_connection_create_offloaded(gcam->bundle, gcam->data_cport_id, + GB_CONNECTION_FLAG_NO_FLOWCTRL | + GB_CONNECTION_FLAG_CDSI1); + if (IS_ERR(conn)) + return PTR_ERR(conn); + + gcam->data_connection = conn; + gb_connection_set_data(conn, gcam); + + ret = gb_connection_enable(conn); + if (ret) + goto error_conn_destroy; + + /* Set the UniPro link to high speed mode. */ + ret = gb_camera_set_power_mode(gcam, true); + if (ret < 0) + goto error_conn_disable; + + /* + * Configure the APB-A CSI-2 transmitter. + * + * Hardcode the number of lanes to 4 and compute the bus clock frequency + * based on the module bandwidth requirements with a safety margin. + */ + memset(&csi_cfg, 0, sizeof(csi_cfg)); + csi_cfg.csi_id = 1; + csi_cfg.flags = 0; + csi_cfg.num_lanes = GB_CAMERA_CSI_NUM_DATA_LANES; + + clk_freq = resp->data_rate / 2 / GB_CAMERA_CSI_NUM_DATA_LANES; + clk_freq = clamp(clk_freq + GB_CAMERA_CSI_CLK_FREQ_MARGIN, + GB_CAMERA_CSI_CLK_FREQ_MIN, + GB_CAMERA_CSI_CLK_FREQ_MAX); + csi_cfg.csi_clk_freq = clk_freq; + + ret = gb_camera_get_max_pkt_size(gcam, resp); + if (ret < 0) { + ret = -EIO; + goto error_power; + } + csi_cfg.max_pkt_size = ret; + + ret = gb_hd_output(gcam->connection->hd, &csi_cfg, + sizeof(csi_cfg), + GB_APB_REQUEST_CSI_TX_CONTROL, false); + if (ret < 0) { + gcam_err(gcam, "failed to start the CSI transmitter\n"); + goto error_power; + } + + if (csi_params) { + csi_params->clk_freq = csi_cfg.csi_clk_freq; + csi_params->num_lanes = csi_cfg.num_lanes; + } + + return 0; + +error_power: + gb_camera_set_power_mode(gcam, false); +error_conn_disable: + gb_connection_disable(gcam->data_connection); +error_conn_destroy: + gb_connection_destroy(gcam->data_connection); + gcam->data_connection = NULL; + return ret; +} + +static void gb_camera_teardown_data_connection(struct gb_camera *gcam) +{ + struct ap_csi_config_request csi_cfg; + int ret; + + /* Stop the APB1 CSI transmitter. */ + memset(&csi_cfg, 0, sizeof(csi_cfg)); + csi_cfg.csi_id = 1; + + ret = gb_hd_output(gcam->connection->hd, &csi_cfg, + sizeof(csi_cfg), + GB_APB_REQUEST_CSI_TX_CONTROL, false); + + if (ret < 0) + gcam_err(gcam, "failed to stop the CSI transmitter\n"); + + /* Set the UniPro link to low speed mode. */ + gb_camera_set_power_mode(gcam, false); + + /* Destroy the data connection. */ + gb_connection_disable(gcam->data_connection); + gb_connection_destroy(gcam->data_connection); + gcam->data_connection = NULL; +} + +/* ----------------------------------------------------------------------------- + * Camera Protocol Operations + */ + +static int gb_camera_capabilities(struct gb_camera *gcam, + u8 *capabilities, size_t *size) +{ + int ret; + + ret = gb_pm_runtime_get_sync(gcam->bundle); + if (ret) + return ret; + + mutex_lock(&gcam->mutex); + + if (!gcam->connection) { + ret = -EINVAL; + goto done; + } + + ret = gb_camera_operation_sync_flags(gcam->connection, + GB_CAMERA_TYPE_CAPABILITIES, + GB_OPERATION_FLAG_SHORT_RESPONSE, + NULL, 0, + (void *)capabilities, size); + if (ret) + gcam_err(gcam, "failed to retrieve capabilities: %d\n", ret); + +done: + mutex_unlock(&gcam->mutex); + + gb_pm_runtime_put_autosuspend(gcam->bundle); + + return ret; +} + +static int gb_camera_configure_streams(struct gb_camera *gcam, + unsigned int *num_streams, + unsigned int *flags, + struct gb_camera_stream_config *streams, + struct gb_camera_csi_params *csi_params) +{ + struct gb_camera_configure_streams_request *req; + struct gb_camera_configure_streams_response *resp; + unsigned int nstreams = *num_streams; + unsigned int i; + size_t req_size; + size_t resp_size; + int ret; + + if (nstreams > GB_CAMERA_MAX_STREAMS) + return -EINVAL; + + req_size = sizeof(*req) + nstreams * sizeof(req->config[0]); + resp_size = sizeof(*resp) + nstreams * sizeof(resp->config[0]); + + req = kmalloc(req_size, GFP_KERNEL); + resp = kmalloc(resp_size, GFP_KERNEL); + if (!req || !resp) { + kfree(req); + kfree(resp); + return -ENOMEM; + } + + req->num_streams = nstreams; + req->flags = *flags; + req->padding = 0; + + for (i = 0; i < nstreams; ++i) { + struct gb_camera_stream_config_request *cfg = &req->config[i]; + + cfg->width = cpu_to_le16(streams[i].width); + cfg->height = cpu_to_le16(streams[i].height); + cfg->format = cpu_to_le16(streams[i].format); + cfg->padding = 0; + } + + mutex_lock(&gcam->mutex); + + ret = gb_pm_runtime_get_sync(gcam->bundle); + if (ret) + goto done_skip_pm_put; + + if (!gcam->connection) { + ret = -EINVAL; + goto done; + } + + ret = gb_camera_operation_sync_flags(gcam->connection, + GB_CAMERA_TYPE_CONFIGURE_STREAMS, + GB_OPERATION_FLAG_SHORT_RESPONSE, + req, req_size, + resp, &resp_size); + if (ret < 0) + goto done; + + ret = gb_camera_configure_streams_validate_response(gcam, resp, + nstreams); + if (ret < 0) + goto done; + + *flags = resp->flags; + *num_streams = resp->num_streams; + + for (i = 0; i < resp->num_streams; ++i) { + struct gb_camera_stream_config_response *cfg = &resp->config[i]; + + streams[i].width = le16_to_cpu(cfg->width); + streams[i].height = le16_to_cpu(cfg->height); + streams[i].format = le16_to_cpu(cfg->format); + streams[i].vc = cfg->virtual_channel; + streams[i].dt[0] = cfg->data_type[0]; + streams[i].dt[1] = cfg->data_type[1]; + streams[i].max_size = le32_to_cpu(cfg->max_size); + } + + if ((resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) || + (req->flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) + goto done; + + if (gcam->state == GB_CAMERA_STATE_CONFIGURED) { + gb_camera_teardown_data_connection(gcam); + gcam->state = GB_CAMERA_STATE_UNCONFIGURED; + + /* + * When unconfiguring streams release the PM runtime reference + * that was acquired when streams were configured. The bundle + * won't be suspended until the PM runtime reference acquired at + * the beginning of this function gets released right before + * returning. + */ + gb_pm_runtime_put_noidle(gcam->bundle); + } + + if (resp->num_streams == 0) + goto done; + + /* + * Make sure the bundle won't be suspended until streams get + * unconfigured after the stream is configured successfully + */ + gb_pm_runtime_get_noresume(gcam->bundle); + + /* Setup CSI-2 connection from APB-A to AP */ + ret = gb_camera_setup_data_connection(gcam, resp, csi_params); + if (ret < 0) { + memset(req, 0, sizeof(*req)); + gb_operation_sync(gcam->connection, + GB_CAMERA_TYPE_CONFIGURE_STREAMS, + req, sizeof(*req), + resp, sizeof(*resp)); + *flags = 0; + *num_streams = 0; + gb_pm_runtime_put_noidle(gcam->bundle); + goto done; + } + + gcam->state = GB_CAMERA_STATE_CONFIGURED; + +done: + gb_pm_runtime_put_autosuspend(gcam->bundle); + +done_skip_pm_put: + mutex_unlock(&gcam->mutex); + kfree(req); + kfree(resp); + return ret; +} + +static int gb_camera_capture(struct gb_camera *gcam, u32 request_id, + unsigned int streams, unsigned int num_frames, + size_t settings_size, const void *settings) +{ + struct gb_camera_capture_request *req; + size_t req_size; + int ret; + + if (settings_size > GB_CAMERA_MAX_SETTINGS_SIZE) + return -EINVAL; + + req_size = sizeof(*req) + settings_size; + req = kmalloc(req_size, GFP_KERNEL); + if (!req) + return -ENOMEM; + + req->request_id = cpu_to_le32(request_id); + req->streams = streams; + req->padding = 0; + req->num_frames = cpu_to_le16(num_frames); + memcpy(req->settings, settings, settings_size); + + mutex_lock(&gcam->mutex); + + if (!gcam->connection) { + ret = -EINVAL; + goto done; + } + + ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CAPTURE, + req, req_size, NULL, 0); +done: + mutex_unlock(&gcam->mutex); + + kfree(req); + + return ret; +} + +static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id) +{ + struct gb_camera_flush_response resp; + int ret; + + mutex_lock(&gcam->mutex); + + if (!gcam->connection) { + ret = -EINVAL; + goto done; + } + + ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_FLUSH, NULL, 0, + &resp, sizeof(resp)); + + if (ret < 0) + goto done; + + if (request_id) + *request_id = le32_to_cpu(resp.request_id); + +done: + mutex_unlock(&gcam->mutex); + + return ret; +} + +static int gb_camera_request_handler(struct gb_operation *op) +{ + struct gb_camera *gcam = gb_connection_get_data(op->connection); + struct gb_camera_metadata_request *payload; + struct gb_message *request; + + if (op->type != GB_CAMERA_TYPE_METADATA) { + gcam_err(gcam, "Unsupported unsolicited event: %u\n", op->type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size < sizeof(*payload)) { + gcam_err(gcam, "Wrong event size received (%zu < %zu)\n", + request->payload_size, sizeof(*payload)); + return -EINVAL; + } + + payload = request->payload; + + gcam_dbg(gcam, "received metadata for request %u, frame %u, stream %u\n", + payload->request_id, payload->frame_number, payload->stream); + + return 0; +} + +/* ----------------------------------------------------------------------------- + * Interface with HOST gmp camera. + */ +static unsigned int gb_camera_mbus_to_gb(enum v4l2_mbus_pixelcode mbus_code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gb_fmt_info); i++) { + if (gb_fmt_info[i].mbus_code == mbus_code) + return gb_fmt_info[i].gb_format; + } + return gb_fmt_info[0].gb_format; +} + +static enum v4l2_mbus_pixelcode gb_camera_gb_to_mbus(u16 gb_fmt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gb_fmt_info); i++) { + if (gb_fmt_info[i].gb_format == gb_fmt) + return gb_fmt_info[i].mbus_code; + } + return gb_fmt_info[0].mbus_code; +} + +static ssize_t gb_camera_op_capabilities(void *priv, char *data, size_t len) +{ + struct gb_camera *gcam = priv; + size_t capabilities_len = len; + int ret; + + ret = gb_camera_capabilities(gcam, data, &capabilities_len); + if (ret) + return ret; + + return capabilities_len; +} + +static int gb_camera_op_configure_streams(void *priv, unsigned int *nstreams, + unsigned int *flags, struct gb_camera_stream *streams, + struct gb_camera_csi_params *csi_params) +{ + struct gb_camera *gcam = priv; + struct gb_camera_stream_config *gb_streams; + unsigned int gb_flags = 0; + unsigned int gb_nstreams = *nstreams; + unsigned int i; + int ret; + + if (gb_nstreams > GB_CAMERA_MAX_STREAMS) + return -EINVAL; + + gb_streams = kzalloc(gb_nstreams * sizeof(*gb_streams), GFP_KERNEL); + if (!gb_streams) + return -ENOMEM; + + for (i = 0; i < gb_nstreams; i++) { + gb_streams[i].width = streams[i].width; + gb_streams[i].height = streams[i].height; + gb_streams[i].format = + gb_camera_mbus_to_gb(streams[i].pixel_code); + } + + if (*flags & GB_CAMERA_IN_FLAG_TEST) + gb_flags |= GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY; + + ret = gb_camera_configure_streams(gcam, &gb_nstreams, + &gb_flags, gb_streams, csi_params); + if (ret < 0) + goto done; + if (gb_nstreams > *nstreams) { + ret = -EINVAL; + goto done; + } + + *flags = 0; + if (gb_flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) + *flags |= GB_CAMERA_OUT_FLAG_ADJUSTED; + + for (i = 0; i < gb_nstreams; i++) { + streams[i].width = gb_streams[i].width; + streams[i].height = gb_streams[i].height; + streams[i].vc = gb_streams[i].vc; + streams[i].dt[0] = gb_streams[i].dt[0]; + streams[i].dt[1] = gb_streams[i].dt[1]; + streams[i].max_size = gb_streams[i].max_size; + streams[i].pixel_code = + gb_camera_gb_to_mbus(gb_streams[i].format); + } + *nstreams = gb_nstreams; + +done: + kfree(gb_streams); + return ret; +} + +static int gb_camera_op_capture(void *priv, u32 request_id, + unsigned int streams, unsigned int num_frames, + size_t settings_size, const void *settings) +{ + struct gb_camera *gcam = priv; + + return gb_camera_capture(gcam, request_id, streams, num_frames, + settings_size, settings); +} + +static int gb_camera_op_flush(void *priv, u32 *request_id) +{ + struct gb_camera *gcam = priv; + + return gb_camera_flush(gcam, request_id); +} + +static const struct gb_camera_ops gb_cam_ops = { + .capabilities = gb_camera_op_capabilities, + .configure_streams = gb_camera_op_configure_streams, + .capture = gb_camera_op_capture, + .flush = gb_camera_op_flush, +}; + +/* ----------------------------------------------------------------------------- + * DebugFS + */ + +static ssize_t gb_camera_debugfs_capabilities(struct gb_camera *gcam, + char *buf, size_t len) +{ + struct gb_camera_debugfs_buffer *buffer = + &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES]; + size_t size = 1024; + unsigned int i; + u8 *caps; + int ret; + + caps = kmalloc(size, GFP_KERNEL); + if (!caps) + return -ENOMEM; + + ret = gb_camera_capabilities(gcam, caps, &size); + if (ret < 0) + goto done; + + /* + * hex_dump_to_buffer() doesn't return the number of bytes dumped prior + * to v4.0, we need our own implementation :-( + */ + buffer->length = 0; + + for (i = 0; i < size; i += 16) { + unsigned int nbytes = min_t(unsigned int, size - i, 16); + + buffer->length += sprintf(buffer->data + buffer->length, + "%*ph\n", nbytes, caps + i); + } + +done: + kfree(caps); + return ret; +} + +static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, + char *buf, size_t len) +{ + struct gb_camera_debugfs_buffer *buffer = + &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_STREAMS]; + struct gb_camera_stream_config *streams; + unsigned int nstreams; + unsigned int flags; + unsigned int i; + char *token; + int ret; + + /* Retrieve number of streams to configure */ + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + + ret = kstrtouint(token, 10, &nstreams); + if (ret < 0) + return ret; + + if (nstreams > GB_CAMERA_MAX_STREAMS) + return -EINVAL; + + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + + ret = kstrtouint(token, 10, &flags); + if (ret < 0) + return ret; + + /* For each stream to configure parse width, height and format */ + streams = kzalloc(nstreams * sizeof(*streams), GFP_KERNEL); + if (!streams) + return -ENOMEM; + + for (i = 0; i < nstreams; ++i) { + struct gb_camera_stream_config *stream = &streams[i]; + + /* width */ + token = strsep(&buf, ";"); + if (token == NULL) { + ret = -EINVAL; + goto done; + } + ret = kstrtouint(token, 10, &stream->width); + if (ret < 0) + goto done; + + /* height */ + token = strsep(&buf, ";"); + if (token == NULL) + goto done; + + ret = kstrtouint(token, 10, &stream->height); + if (ret < 0) + goto done; + + /* Image format code */ + token = strsep(&buf, ";"); + if (token == NULL) + goto done; + + ret = kstrtouint(token, 16, &stream->format); + if (ret < 0) + goto done; + } + + ret = gb_camera_configure_streams(gcam, &nstreams, &flags, streams, + NULL); + if (ret < 0) + goto done; + + buffer->length = sprintf(buffer->data, "%u;%u;", nstreams, flags); + + for (i = 0; i < nstreams; ++i) { + struct gb_camera_stream_config *stream = &streams[i]; + + buffer->length += sprintf(buffer->data + buffer->length, + "%u;%u;%u;%u;%u;%u;%u;", + stream->width, stream->height, + stream->format, stream->vc, + stream->dt[0], stream->dt[1], + stream->max_size); + } + + ret = len; + +done: + kfree(streams); + return ret; +}; + +static ssize_t gb_camera_debugfs_capture(struct gb_camera *gcam, + char *buf, size_t len) +{ + unsigned int request_id; + unsigned int streams_mask; + unsigned int num_frames; + char *token; + int ret; + + /* Request id */ + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + ret = kstrtouint(token, 10, &request_id); + if (ret < 0) + return ret; + + /* Stream mask */ + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + ret = kstrtouint(token, 16, &streams_mask); + if (ret < 0) + return ret; + + /* number of frames */ + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + ret = kstrtouint(token, 10, &num_frames); + if (ret < 0) + return ret; + + ret = gb_camera_capture(gcam, request_id, streams_mask, num_frames, 0, + NULL); + if (ret < 0) + return ret; + + return len; +} + +static ssize_t gb_camera_debugfs_flush(struct gb_camera *gcam, + char *buf, size_t len) +{ + struct gb_camera_debugfs_buffer *buffer = + &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_FLUSH]; + unsigned int req_id; + int ret; + + ret = gb_camera_flush(gcam, &req_id); + if (ret < 0) + return ret; + + buffer->length = sprintf(buffer->data, "%u", req_id); + + return len; +} + +struct gb_camera_debugfs_entry { + const char *name; + unsigned int mask; + unsigned int buffer; + ssize_t (*execute)(struct gb_camera *gcam, char *buf, size_t len); +}; + +static const struct gb_camera_debugfs_entry gb_camera_debugfs_entries[] = { + { + .name = "capabilities", + .mask = S_IFREG | S_IRUGO, + .buffer = GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES, + .execute = gb_camera_debugfs_capabilities, + }, { + .name = "configure_streams", + .mask = S_IFREG | S_IRUGO | S_IWUGO, + .buffer = GB_CAMERA_DEBUGFS_BUFFER_STREAMS, + .execute = gb_camera_debugfs_configure_streams, + }, { + .name = "capture", + .mask = S_IFREG | S_IRUGO | S_IWUGO, + .buffer = GB_CAMERA_DEBUGFS_BUFFER_CAPTURE, + .execute = gb_camera_debugfs_capture, + }, { + .name = "flush", + .mask = S_IFREG | S_IRUGO | S_IWUGO, + .buffer = GB_CAMERA_DEBUGFS_BUFFER_FLUSH, + .execute = gb_camera_debugfs_flush, + }, +}; + +static ssize_t gb_camera_debugfs_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + const struct gb_camera_debugfs_entry *op = file->private_data; + struct gb_camera *gcam = file->f_inode->i_private; + struct gb_camera_debugfs_buffer *buffer; + ssize_t ret; + + /* For read-only entries the operation is triggered by a read. */ + if (!(op->mask & S_IWUGO)) { + ret = op->execute(gcam, NULL, 0); + if (ret < 0) + return ret; + } + + buffer = &gcam->debugfs.buffers[op->buffer]; + + return simple_read_from_buffer(buf, len, offset, buffer->data, + buffer->length); +} + +static ssize_t gb_camera_debugfs_write(struct file *file, + const char __user *buf, size_t len, + loff_t *offset) +{ + const struct gb_camera_debugfs_entry *op = file->private_data; + struct gb_camera *gcam = file->f_inode->i_private; + ssize_t ret; + char *kbuf; + + if (len > 1024) + return -EINVAL; + + kbuf = kmalloc(len + 1, GFP_KERNEL); + if (!kbuf) + return -ENOMEM; + + if (copy_from_user(kbuf, buf, len)) { + ret = -EFAULT; + goto done; + } + + kbuf[len] = '\0'; + + ret = op->execute(gcam, kbuf, len); + +done: + kfree(kbuf); + return ret; +} + +static int gb_camera_debugfs_open(struct inode *inode, struct file *file) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gb_camera_debugfs_entries); ++i) { + const struct gb_camera_debugfs_entry *entry = + &gb_camera_debugfs_entries[i]; + + if (!strcmp(file->f_path.dentry->d_iname, entry->name)) { + file->private_data = (void *)entry; + break; + } + } + + return 0; +} + +static const struct file_operations gb_camera_debugfs_ops = { + .open = gb_camera_debugfs_open, + .read = gb_camera_debugfs_read, + .write = gb_camera_debugfs_write, +}; + +static int gb_camera_debugfs_init(struct gb_camera *gcam) +{ + struct gb_connection *connection = gcam->connection; + char dirname[27]; + unsigned int i; + + /* + * Create root debugfs entry and a file entry for each camera operation. + */ + snprintf(dirname, 27, "camera-%u.%u", connection->intf->interface_id, + gcam->bundle->id); + + gcam->debugfs.root = debugfs_create_dir(dirname, gb_debugfs_get()); + if (IS_ERR(gcam->debugfs.root)) { + gcam_err(gcam, "debugfs root create failed (%ld)\n", + PTR_ERR(gcam->debugfs.root)); + return PTR_ERR(gcam->debugfs.root); + } + + gcam->debugfs.buffers = vmalloc(sizeof(*gcam->debugfs.buffers) * + GB_CAMERA_DEBUGFS_BUFFER_MAX); + if (!gcam->debugfs.buffers) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(gb_camera_debugfs_entries); ++i) { + const struct gb_camera_debugfs_entry *entry = + &gb_camera_debugfs_entries[i]; + struct dentry *dentry; + + gcam->debugfs.buffers[i].length = 0; + + dentry = debugfs_create_file(entry->name, entry->mask, + gcam->debugfs.root, gcam, + &gb_camera_debugfs_ops); + if (IS_ERR(dentry)) { + gcam_err(gcam, + "debugfs operation %s create failed (%ld)\n", + entry->name, PTR_ERR(dentry)); + return PTR_ERR(dentry); + } + } + + return 0; +} + +static void gb_camera_debugfs_cleanup(struct gb_camera *gcam) +{ + debugfs_remove_recursive(gcam->debugfs.root); + + vfree(gcam->debugfs.buffers); +} + +/* ----------------------------------------------------------------------------- + * Init & Cleanup + */ + +static void gb_camera_cleanup(struct gb_camera *gcam) +{ + gb_camera_debugfs_cleanup(gcam); + + mutex_lock(&gcam->mutex); + if (gcam->data_connection) { + gb_connection_disable(gcam->data_connection); + gb_connection_destroy(gcam->data_connection); + gcam->data_connection = NULL; + } + + if (gcam->connection) { + gb_connection_disable(gcam->connection); + gb_connection_destroy(gcam->connection); + gcam->connection = NULL; + } + mutex_unlock(&gcam->mutex); +} + +static void gb_camera_release_module(struct kref *ref) +{ + struct gb_camera_module *cam_mod = + container_of(ref, struct gb_camera_module, refcount); + kfree(cam_mod->priv); +} + +static int gb_camera_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct gb_connection *conn; + struct gb_camera *gcam; + u16 mgmt_cport_id = 0; + u16 data_cport_id = 0; + unsigned int i; + int ret; + + /* + * The camera bundle must contain exactly two CPorts, one for the + * camera management protocol and one for the camera data protocol. + */ + if (bundle->num_cports != 2) + return -ENODEV; + + for (i = 0; i < bundle->num_cports; ++i) { + struct greybus_descriptor_cport *desc = &bundle->cport_desc[i]; + + switch (desc->protocol_id) { + case GREYBUS_PROTOCOL_CAMERA_MGMT: + mgmt_cport_id = le16_to_cpu(desc->id); + break; + case GREYBUS_PROTOCOL_CAMERA_DATA: + data_cport_id = le16_to_cpu(desc->id); + break; + default: + return -ENODEV; + } + } + + if (!mgmt_cport_id || !data_cport_id) + return -ENODEV; + + gcam = kzalloc(sizeof(*gcam), GFP_KERNEL); + if (!gcam) + return -ENOMEM; + + mutex_init(&gcam->mutex); + + gcam->bundle = bundle; + gcam->state = GB_CAMERA_STATE_UNCONFIGURED; + gcam->data_cport_id = data_cport_id; + + conn = gb_connection_create(bundle, mgmt_cport_id, + gb_camera_request_handler); + if (IS_ERR(conn)) { + ret = PTR_ERR(conn); + goto error; + } + + gcam->connection = conn; + gb_connection_set_data(conn, gcam); + + ret = gb_connection_enable(conn); + if (ret) + goto error; + + ret = gb_camera_debugfs_init(gcam); + if (ret < 0) + goto error; + + gcam->module.priv = gcam; + gcam->module.ops = &gb_cam_ops; + gcam->module.interface_id = gcam->connection->intf->interface_id; + gcam->module.release = gb_camera_release_module; + ret = gb_camera_register(&gcam->module); + if (ret < 0) + goto error; + + greybus_set_drvdata(bundle, gcam); + + gb_pm_runtime_put_autosuspend(gcam->bundle); + + return 0; + +error: + gb_camera_cleanup(gcam); + kfree(gcam); + return ret; +} + +static void gb_camera_disconnect(struct gb_bundle *bundle) +{ + struct gb_camera *gcam = greybus_get_drvdata(bundle); + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); + + gb_camera_cleanup(gcam); + gb_camera_unregister(&gcam->module); +} + +static const struct greybus_bundle_id gb_camera_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, + { }, +}; + +#ifdef CONFIG_PM +static int gb_camera_suspend(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_camera *gcam = greybus_get_drvdata(bundle); + + if (gcam->data_connection) + gb_connection_disable(gcam->data_connection); + + gb_connection_disable(gcam->connection); + + return 0; +} + +static int gb_camera_resume(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_camera *gcam = greybus_get_drvdata(bundle); + int ret; + + ret = gb_connection_enable(gcam->connection); + if (ret) { + gcam_err(gcam, "failed to enable connection: %d\n", ret); + return ret; + } + + if (gcam->data_connection) { + ret = gb_connection_enable(gcam->data_connection); + if (ret) { + gcam_err(gcam, + "failed to enable data connection: %d\n", ret); + return ret; + } + } + + return 0; +} +#endif + +static const struct dev_pm_ops gb_camera_pm_ops = { + SET_RUNTIME_PM_OPS(gb_camera_suspend, gb_camera_resume, NULL) +}; + +static struct greybus_driver gb_camera_driver = { + .name = "camera", + .probe = gb_camera_probe, + .disconnect = gb_camera_disconnect, + .id_table = gb_camera_id_table, + .driver.pm = &gb_camera_pm_ops, +}; + +module_greybus_driver(gb_camera_driver); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c new file mode 100644 index 000000000000..557075147f2d --- /dev/null +++ b/drivers/staging/greybus/connection.c @@ -0,0 +1,938 @@ +/* + * Greybus connections + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include + +#include "greybus.h" +#include "greybus_trace.h" + + +#define GB_CONNECTION_CPORT_QUIESCE_TIMEOUT 1000 + + +static void gb_connection_kref_release(struct kref *kref); + + +static DEFINE_SPINLOCK(gb_connections_lock); +static DEFINE_MUTEX(gb_connection_mutex); + + +/* Caller holds gb_connection_mutex. */ +static bool gb_connection_cport_in_use(struct gb_interface *intf, u16 cport_id) +{ + struct gb_host_device *hd = intf->hd; + struct gb_connection *connection; + + list_for_each_entry(connection, &hd->connections, hd_links) { + if (connection->intf == intf && + connection->intf_cport_id == cport_id) + return true; + } + + return false; +} + +static void gb_connection_get(struct gb_connection *connection) +{ + kref_get(&connection->kref); + + trace_gb_connection_get(connection); +} + +static void gb_connection_put(struct gb_connection *connection) +{ + trace_gb_connection_put(connection); + + kref_put(&connection->kref, gb_connection_kref_release); +} + +/* + * Returns a reference-counted pointer to the connection if found. + */ +static struct gb_connection * +gb_connection_hd_find(struct gb_host_device *hd, u16 cport_id) +{ + struct gb_connection *connection; + unsigned long flags; + + spin_lock_irqsave(&gb_connections_lock, flags); + list_for_each_entry(connection, &hd->connections, hd_links) + if (connection->hd_cport_id == cport_id) { + gb_connection_get(connection); + goto found; + } + connection = NULL; +found: + spin_unlock_irqrestore(&gb_connections_lock, flags); + + return connection; +} + +/* + * Callback from the host driver to let us know that data has been + * received on the bundle. + */ +void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, + u8 *data, size_t length) +{ + struct gb_connection *connection; + + trace_gb_hd_in(hd); + + connection = gb_connection_hd_find(hd, cport_id); + if (!connection) { + dev_err(&hd->dev, + "nonexistent connection (%zu bytes dropped)\n", length); + return; + } + gb_connection_recv(connection, data, length); + gb_connection_put(connection); +} +EXPORT_SYMBOL_GPL(greybus_data_rcvd); + +static void gb_connection_kref_release(struct kref *kref) +{ + struct gb_connection *connection; + + connection = container_of(kref, struct gb_connection, kref); + + trace_gb_connection_release(connection); + + kfree(connection); +} + +static void gb_connection_init_name(struct gb_connection *connection) +{ + u16 hd_cport_id = connection->hd_cport_id; + u16 cport_id = 0; + u8 intf_id = 0; + + if (connection->intf) { + intf_id = connection->intf->interface_id; + cport_id = connection->intf_cport_id; + } + + snprintf(connection->name, sizeof(connection->name), + "%u/%u:%u", hd_cport_id, intf_id, cport_id); +} + +/* + * _gb_connection_create() - create a Greybus connection + * @hd: host device of the connection + * @hd_cport_id: host-device cport id, or -1 for dynamic allocation + * @intf: remote interface, or NULL for static connections + * @bundle: remote-interface bundle (may be NULL) + * @cport_id: remote-interface cport id, or 0 for static connections + * @handler: request handler (may be NULL) + * @flags: connection flags + * + * Create a Greybus connection, representing the bidirectional link + * between a CPort on a (local) Greybus host device and a CPort on + * another Greybus interface. + * + * A connection also maintains the state of operations sent over the + * connection. + * + * Serialised against concurrent create and destroy using the + * gb_connection_mutex. + * + * Return: A pointer to the new connection if successful, or an ERR_PTR + * otherwise. + */ +static struct gb_connection * +_gb_connection_create(struct gb_host_device *hd, int hd_cport_id, + struct gb_interface *intf, + struct gb_bundle *bundle, int cport_id, + gb_request_handler_t handler, + unsigned long flags) +{ + struct gb_connection *connection; + int ret; + + mutex_lock(&gb_connection_mutex); + + if (intf && gb_connection_cport_in_use(intf, cport_id)) { + dev_err(&intf->dev, "cport %u already in use\n", cport_id); + ret = -EBUSY; + goto err_unlock; + } + + ret = gb_hd_cport_allocate(hd, hd_cport_id, flags); + if (ret < 0) { + dev_err(&hd->dev, "failed to allocate cport: %d\n", ret); + goto err_unlock; + } + hd_cport_id = ret; + + connection = kzalloc(sizeof(*connection), GFP_KERNEL); + if (!connection) { + ret = -ENOMEM; + goto err_hd_cport_release; + } + + connection->hd_cport_id = hd_cport_id; + connection->intf_cport_id = cport_id; + connection->hd = hd; + connection->intf = intf; + connection->bundle = bundle; + connection->handler = handler; + connection->flags = flags; + if (intf && (intf->quirks & GB_INTERFACE_QUIRK_NO_CPORT_FEATURES)) + connection->flags |= GB_CONNECTION_FLAG_NO_FLOWCTRL; + connection->state = GB_CONNECTION_STATE_DISABLED; + + atomic_set(&connection->op_cycle, 0); + mutex_init(&connection->mutex); + spin_lock_init(&connection->lock); + INIT_LIST_HEAD(&connection->operations); + + connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1, + dev_name(&hd->dev), hd_cport_id); + if (!connection->wq) { + ret = -ENOMEM; + goto err_free_connection; + } + + kref_init(&connection->kref); + + gb_connection_init_name(connection); + + spin_lock_irq(&gb_connections_lock); + list_add(&connection->hd_links, &hd->connections); + + if (bundle) + list_add(&connection->bundle_links, &bundle->connections); + else + INIT_LIST_HEAD(&connection->bundle_links); + + spin_unlock_irq(&gb_connections_lock); + + mutex_unlock(&gb_connection_mutex); + + trace_gb_connection_create(connection); + + return connection; + +err_free_connection: + kfree(connection); +err_hd_cport_release: + gb_hd_cport_release(hd, hd_cport_id); +err_unlock: + mutex_unlock(&gb_connection_mutex); + + return ERR_PTR(ret); +} + +struct gb_connection * +gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id, + gb_request_handler_t handler) +{ + return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, handler, + GB_CONNECTION_FLAG_HIGH_PRIO); +} + +struct gb_connection * +gb_connection_create_control(struct gb_interface *intf) +{ + return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL, + GB_CONNECTION_FLAG_CONTROL | + GB_CONNECTION_FLAG_HIGH_PRIO); +} + +struct gb_connection * +gb_connection_create(struct gb_bundle *bundle, u16 cport_id, + gb_request_handler_t handler) +{ + struct gb_interface *intf = bundle->intf; + + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, + handler, 0); +} +EXPORT_SYMBOL_GPL(gb_connection_create); + +struct gb_connection * +gb_connection_create_flags(struct gb_bundle *bundle, u16 cport_id, + gb_request_handler_t handler, + unsigned long flags) +{ + struct gb_interface *intf = bundle->intf; + + if (WARN_ON_ONCE(flags & GB_CONNECTION_FLAG_CORE_MASK)) + flags &= ~GB_CONNECTION_FLAG_CORE_MASK; + + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, + handler, flags); +} +EXPORT_SYMBOL_GPL(gb_connection_create_flags); + +struct gb_connection * +gb_connection_create_offloaded(struct gb_bundle *bundle, u16 cport_id, + unsigned long flags) +{ + flags |= GB_CONNECTION_FLAG_OFFLOADED; + + return gb_connection_create_flags(bundle, cport_id, NULL, flags); +} +EXPORT_SYMBOL_GPL(gb_connection_create_offloaded); + +static int gb_connection_hd_cport_enable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_enable) + return 0; + + ret = hd->driver->cport_enable(hd, connection->hd_cport_id, + connection->flags); + if (ret) { + dev_err(&hd->dev, "%s: failed to enable host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static void gb_connection_hd_cport_disable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_disable) + return; + + ret = hd->driver->cport_disable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to disable host cport: %d\n", + connection->name, ret); + } +} + +static int gb_connection_hd_cport_connected(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_connected) + return 0; + + ret = hd->driver->cport_connected(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to set connected state: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static int gb_connection_hd_cport_flush(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_flush) + return 0; + + ret = hd->driver->cport_flush(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to flush host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static int gb_connection_hd_cport_quiesce(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + size_t peer_space; + int ret; + + peer_space = sizeof(struct gb_operation_msg_hdr) + + sizeof(struct gb_cport_shutdown_request); + + if (connection->mode_switch) + peer_space += sizeof(struct gb_operation_msg_hdr); + + ret = hd->driver->cport_quiesce(hd, connection->hd_cport_id, + peer_space, + GB_CONNECTION_CPORT_QUIESCE_TIMEOUT); + if (ret) { + dev_err(&hd->dev, "%s: failed to quiesce host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static int gb_connection_hd_cport_clear(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + ret = hd->driver->cport_clear(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to clear host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +/* + * Request the SVC to create a connection from AP's cport to interface's + * cport. + */ +static int +gb_connection_svc_connection_create(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + struct gb_interface *intf; + u8 cport_flags; + int ret; + + if (gb_connection_is_static(connection)) + return 0; + + intf = connection->intf; + + /* + * Enable either E2EFC or CSD, unless no flow control is requested. + */ + cport_flags = GB_SVC_CPORT_FLAG_CSV_N; + if (gb_connection_flow_control_disabled(connection)) { + cport_flags |= GB_SVC_CPORT_FLAG_CSD_N; + } else if (gb_connection_e2efc_enabled(connection)) { + cport_flags |= GB_SVC_CPORT_FLAG_CSD_N | + GB_SVC_CPORT_FLAG_E2EFC; + } + + ret = gb_svc_connection_create(hd->svc, + hd->svc->ap_intf_id, + connection->hd_cport_id, + intf->interface_id, + connection->intf_cport_id, + cport_flags); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to create svc connection: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static void +gb_connection_svc_connection_destroy(struct gb_connection *connection) +{ + if (gb_connection_is_static(connection)) + return; + + gb_svc_connection_destroy(connection->hd->svc, + connection->hd->svc->ap_intf_id, + connection->hd_cport_id, + connection->intf->interface_id, + connection->intf_cport_id); +} + +/* Inform Interface about active CPorts */ +static int gb_connection_control_connected(struct gb_connection *connection) +{ + struct gb_control *control; + u16 cport_id = connection->intf_cport_id; + int ret; + + if (gb_connection_is_static(connection)) + return 0; + + if (gb_connection_is_control(connection)) + return 0; + + control = connection->intf->control; + + ret = gb_control_connected_operation(control, cport_id); + if (ret) { + dev_err(&connection->bundle->dev, + "failed to connect cport: %d\n", ret); + return ret; + } + + return 0; +} + +static void +gb_connection_control_disconnecting(struct gb_connection *connection) +{ + struct gb_control *control; + u16 cport_id = connection->intf_cport_id; + int ret; + + if (gb_connection_is_static(connection)) + return; + + control = connection->intf->control; + + ret = gb_control_disconnecting_operation(control, cport_id); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to send disconnecting: %d\n", + connection->name, ret); + } +} + +static void +gb_connection_control_disconnected(struct gb_connection *connection) +{ + struct gb_control *control; + u16 cport_id = connection->intf_cport_id; + int ret; + + if (gb_connection_is_static(connection)) + return; + + control = connection->intf->control; + + if (gb_connection_is_control(connection)) { + if (connection->mode_switch) { + ret = gb_control_mode_switch_operation(control); + if (ret) { + /* + * Allow mode switch to time out waiting for + * mailbox event. + */ + return; + } + } + + return; + } + + ret = gb_control_disconnected_operation(control, cport_id); + if (ret) { + dev_warn(&connection->bundle->dev, + "failed to disconnect cport: %d\n", ret); + } +} + +static int gb_connection_shutdown_operation(struct gb_connection *connection, + u8 phase) +{ + struct gb_cport_shutdown_request *req; + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_core(connection, + GB_REQUEST_TYPE_CPORT_SHUTDOWN, + sizeof(*req), 0, 0, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + req = operation->request->payload; + req->phase = phase; + + ret = gb_operation_request_send_sync(operation); + + gb_operation_put(operation); + + return ret; +} + +static int gb_connection_cport_shutdown(struct gb_connection *connection, + u8 phase) +{ + struct gb_host_device *hd = connection->hd; + const struct gb_hd_driver *drv = hd->driver; + int ret; + + if (gb_connection_is_static(connection)) + return 0; + + if (gb_connection_is_offloaded(connection)) { + if (!drv->cport_shutdown) + return 0; + + ret = drv->cport_shutdown(hd, connection->hd_cport_id, phase, + GB_OPERATION_TIMEOUT_DEFAULT); + } else { + ret = gb_connection_shutdown_operation(connection, phase); + } + + if (ret) { + dev_err(&hd->dev, "%s: failed to send cport shutdown (phase %d): %d\n", + connection->name, phase, ret); + return ret; + } + + return 0; +} + +static int +gb_connection_cport_shutdown_phase_1(struct gb_connection *connection) +{ + return gb_connection_cport_shutdown(connection, 1); +} + +static int +gb_connection_cport_shutdown_phase_2(struct gb_connection *connection) +{ + return gb_connection_cport_shutdown(connection, 2); +} + +/* + * Cancel all active operations on a connection. + * + * Locking: Called with connection lock held and state set to DISABLED or + * DISCONNECTING. + */ +static void gb_connection_cancel_operations(struct gb_connection *connection, + int errno) + __must_hold(&connection->lock) +{ + struct gb_operation *operation; + + while (!list_empty(&connection->operations)) { + operation = list_last_entry(&connection->operations, + struct gb_operation, links); + gb_operation_get(operation); + spin_unlock_irq(&connection->lock); + + if (gb_operation_is_incoming(operation)) + gb_operation_cancel_incoming(operation, errno); + else + gb_operation_cancel(operation, errno); + + gb_operation_put(operation); + + spin_lock_irq(&connection->lock); + } +} + +/* + * Cancel all active incoming operations on a connection. + * + * Locking: Called with connection lock held and state set to ENABLED_TX. + */ +static void +gb_connection_flush_incoming_operations(struct gb_connection *connection, + int errno) + __must_hold(&connection->lock) +{ + struct gb_operation *operation; + bool incoming; + + while (!list_empty(&connection->operations)) { + incoming = false; + list_for_each_entry(operation, &connection->operations, + links) { + if (gb_operation_is_incoming(operation)) { + gb_operation_get(operation); + incoming = true; + break; + } + } + + if (!incoming) + break; + + spin_unlock_irq(&connection->lock); + + /* FIXME: flush, not cancel? */ + gb_operation_cancel_incoming(operation, errno); + gb_operation_put(operation); + + spin_lock_irq(&connection->lock); + } +} + +/* + * _gb_connection_enable() - enable a connection + * @connection: connection to enable + * @rx: whether to enable incoming requests + * + * Connection-enable helper for DISABLED->ENABLED, DISABLED->ENABLED_TX, and + * ENABLED_TX->ENABLED state transitions. + * + * Locking: Caller holds connection->mutex. + */ +static int _gb_connection_enable(struct gb_connection *connection, bool rx) +{ + int ret; + + /* Handle ENABLED_TX -> ENABLED transitions. */ + if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) { + if (!(connection->handler && rx)) + return 0; + + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_ENABLED; + spin_unlock_irq(&connection->lock); + + return 0; + } + + ret = gb_connection_hd_cport_enable(connection); + if (ret) + return ret; + + ret = gb_connection_svc_connection_create(connection); + if (ret) + goto err_hd_cport_clear; + + ret = gb_connection_hd_cport_connected(connection); + if (ret) + goto err_svc_connection_destroy; + + spin_lock_irq(&connection->lock); + if (connection->handler && rx) + connection->state = GB_CONNECTION_STATE_ENABLED; + else + connection->state = GB_CONNECTION_STATE_ENABLED_TX; + spin_unlock_irq(&connection->lock); + + ret = gb_connection_control_connected(connection); + if (ret) + goto err_control_disconnecting; + + return 0; + +err_control_disconnecting: + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISCONNECTING; + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + /* Transmit queue should already be empty. */ + gb_connection_hd_cport_flush(connection); + + gb_connection_control_disconnecting(connection); + gb_connection_cport_shutdown_phase_1(connection); + gb_connection_hd_cport_quiesce(connection); + gb_connection_cport_shutdown_phase_2(connection); + gb_connection_control_disconnected(connection); + connection->state = GB_CONNECTION_STATE_DISABLED; +err_svc_connection_destroy: + gb_connection_svc_connection_destroy(connection); +err_hd_cport_clear: + gb_connection_hd_cport_clear(connection); + + gb_connection_hd_cport_disable(connection); + + return ret; +} + +int gb_connection_enable(struct gb_connection *connection) +{ + int ret = 0; + + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_ENABLED) + goto out_unlock; + + ret = _gb_connection_enable(connection, true); + if (!ret) + trace_gb_connection_enable(connection); + +out_unlock: + mutex_unlock(&connection->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_connection_enable); + +int gb_connection_enable_tx(struct gb_connection *connection) +{ + int ret = 0; + + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_ENABLED) { + ret = -EINVAL; + goto out_unlock; + } + + if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) + goto out_unlock; + + ret = _gb_connection_enable(connection, false); + if (!ret) + trace_gb_connection_enable(connection); + +out_unlock: + mutex_unlock(&connection->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_connection_enable_tx); + +void gb_connection_disable_rx(struct gb_connection *connection) +{ + mutex_lock(&connection->mutex); + + spin_lock_irq(&connection->lock); + if (connection->state != GB_CONNECTION_STATE_ENABLED) { + spin_unlock_irq(&connection->lock); + goto out_unlock; + } + connection->state = GB_CONNECTION_STATE_ENABLED_TX; + gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + trace_gb_connection_disable(connection); + +out_unlock: + mutex_unlock(&connection->mutex); +} +EXPORT_SYMBOL_GPL(gb_connection_disable_rx); + +void gb_connection_mode_switch_prepare(struct gb_connection *connection) +{ + connection->mode_switch = true; +} + +void gb_connection_mode_switch_complete(struct gb_connection *connection) +{ + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_clear(connection); + + gb_connection_hd_cport_disable(connection); + + connection->mode_switch = false; +} + +void gb_connection_disable(struct gb_connection *connection) +{ + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_DISABLED) + goto out_unlock; + + trace_gb_connection_disable(connection); + + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISCONNECTING; + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + gb_connection_hd_cport_flush(connection); + + gb_connection_control_disconnecting(connection); + gb_connection_cport_shutdown_phase_1(connection); + gb_connection_hd_cport_quiesce(connection); + gb_connection_cport_shutdown_phase_2(connection); + gb_connection_control_disconnected(connection); + + connection->state = GB_CONNECTION_STATE_DISABLED; + + /* control-connection tear down is deferred when mode switching */ + if (!connection->mode_switch) { + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_clear(connection); + + gb_connection_hd_cport_disable(connection); + } + +out_unlock: + mutex_unlock(&connection->mutex); +} +EXPORT_SYMBOL_GPL(gb_connection_disable); + +/* Disable a connection without communicating with the remote end. */ +void gb_connection_disable_forced(struct gb_connection *connection) +{ + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_DISABLED) + goto out_unlock; + + trace_gb_connection_disable(connection); + + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISABLED; + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + gb_connection_hd_cport_flush(connection); + + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_clear(connection); + + gb_connection_hd_cport_disable(connection); +out_unlock: + mutex_unlock(&connection->mutex); +} +EXPORT_SYMBOL_GPL(gb_connection_disable_forced); + +/* Caller must have disabled the connection before destroying it. */ +void gb_connection_destroy(struct gb_connection *connection) +{ + if (!connection) + return; + + if (WARN_ON(connection->state != GB_CONNECTION_STATE_DISABLED)) + gb_connection_disable(connection); + + mutex_lock(&gb_connection_mutex); + + spin_lock_irq(&gb_connections_lock); + list_del(&connection->bundle_links); + list_del(&connection->hd_links); + spin_unlock_irq(&gb_connections_lock); + + destroy_workqueue(connection->wq); + + gb_hd_cport_release(connection->hd, connection->hd_cport_id); + connection->hd_cport_id = CPORT_ID_BAD; + + mutex_unlock(&gb_connection_mutex); + + gb_connection_put(connection); +} +EXPORT_SYMBOL_GPL(gb_connection_destroy); + +void gb_connection_latency_tag_enable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->latency_tag_enable) + return; + + ret = hd->driver->latency_tag_enable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to enable latency tag: %d\n", + connection->name, ret); + } +} +EXPORT_SYMBOL_GPL(gb_connection_latency_tag_enable); + +void gb_connection_latency_tag_disable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->latency_tag_disable) + return; + + ret = hd->driver->latency_tag_disable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to disable latency tag: %d\n", + connection->name, ret); + } +} +EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h new file mode 100644 index 000000000000..4d9f4c64176c --- /dev/null +++ b/drivers/staging/greybus/connection.h @@ -0,0 +1,129 @@ +/* + * Greybus connections + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __CONNECTION_H +#define __CONNECTION_H + +#include +#include + +#define GB_CONNECTION_FLAG_CSD BIT(0) +#define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) +#define GB_CONNECTION_FLAG_OFFLOADED BIT(2) +#define GB_CONNECTION_FLAG_CDSI1 BIT(3) +#define GB_CONNECTION_FLAG_CONTROL BIT(4) +#define GB_CONNECTION_FLAG_HIGH_PRIO BIT(5) + +#define GB_CONNECTION_FLAG_CORE_MASK GB_CONNECTION_FLAG_CONTROL + +enum gb_connection_state { + GB_CONNECTION_STATE_DISABLED = 0, + GB_CONNECTION_STATE_ENABLED_TX = 1, + GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_DISCONNECTING = 3, +}; + +struct gb_operation; + +typedef int (*gb_request_handler_t)(struct gb_operation *); + +struct gb_connection { + struct gb_host_device *hd; + struct gb_interface *intf; + struct gb_bundle *bundle; + struct kref kref; + u16 hd_cport_id; + u16 intf_cport_id; + + struct list_head hd_links; + struct list_head bundle_links; + + gb_request_handler_t handler; + unsigned long flags; + + struct mutex mutex; + spinlock_t lock; + enum gb_connection_state state; + struct list_head operations; + + char name[16]; + struct workqueue_struct *wq; + + atomic_t op_cycle; + + void *private; + + bool mode_switch; +}; + +struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, + u16 hd_cport_id, gb_request_handler_t handler); +struct gb_connection *gb_connection_create_control(struct gb_interface *intf); +struct gb_connection *gb_connection_create(struct gb_bundle *bundle, + u16 cport_id, gb_request_handler_t handler); +struct gb_connection *gb_connection_create_flags(struct gb_bundle *bundle, + u16 cport_id, gb_request_handler_t handler, + unsigned long flags); +struct gb_connection *gb_connection_create_offloaded(struct gb_bundle *bundle, + u16 cport_id, unsigned long flags); +void gb_connection_destroy(struct gb_connection *connection); + +static inline bool gb_connection_is_static(struct gb_connection *connection) +{ + return !connection->intf; +} + +int gb_connection_enable(struct gb_connection *connection); +int gb_connection_enable_tx(struct gb_connection *connection); +void gb_connection_disable_rx(struct gb_connection *connection); +void gb_connection_disable(struct gb_connection *connection); +void gb_connection_disable_forced(struct gb_connection *connection); + +void gb_connection_mode_switch_prepare(struct gb_connection *connection); +void gb_connection_mode_switch_complete(struct gb_connection *connection); + +void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, + u8 *data, size_t length); + +void gb_connection_latency_tag_enable(struct gb_connection *connection); +void gb_connection_latency_tag_disable(struct gb_connection *connection); + +static inline bool gb_connection_e2efc_enabled(struct gb_connection *connection) +{ + return !(connection->flags & GB_CONNECTION_FLAG_CSD); +} + +static inline bool +gb_connection_flow_control_disabled(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_NO_FLOWCTRL; +} + +static inline bool gb_connection_is_offloaded(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_OFFLOADED; +} + +static inline bool gb_connection_is_control(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_CONTROL; +} + +static inline void *gb_connection_get_data(struct gb_connection *connection) +{ + return connection->private; +} + +static inline void gb_connection_set_data(struct gb_connection *connection, + void *data) +{ + connection->private = data; +} + +#endif /* __CONNECTION_H */ diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c new file mode 100644 index 000000000000..4716190e740a --- /dev/null +++ b/drivers/staging/greybus/control.c @@ -0,0 +1,635 @@ +/* + * Greybus CPort control protocol. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include "greybus.h" + +/* Highest control-protocol version supported */ +#define GB_CONTROL_VERSION_MAJOR 0 +#define GB_CONTROL_VERSION_MINOR 1 + + +static int gb_control_get_version(struct gb_control *control) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_control_version_request request; + struct gb_control_version_response response; + int ret; + + request.major = GB_CONTROL_VERSION_MAJOR; + request.minor = GB_CONTROL_VERSION_MINOR; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_VERSION, + &request, sizeof(request), &response, + sizeof(response)); + if (ret) { + dev_err(&intf->dev, + "failed to get control-protocol version: %d\n", + ret); + return ret; + } + + if (response.major > request.major) { + dev_err(&intf->dev, + "unsupported major control-protocol version (%u > %u)\n", + response.major, request.major); + return -ENOTSUPP; + } + + control->protocol_major = response.major; + control->protocol_minor = response.minor; + + dev_dbg(&intf->dev, "%s - %u.%u\n", __func__, response.major, + response.minor); + + return 0; +} + +static int gb_control_get_bundle_version(struct gb_control *control, + struct gb_bundle *bundle) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_control_bundle_version_request request; + struct gb_control_bundle_version_response response; + int ret; + + request.bundle_id = bundle->id; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_VERSION, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&intf->dev, + "failed to get bundle %u class version: %d\n", + bundle->id, ret); + return ret; + } + + bundle->class_major = response.major; + bundle->class_minor = response.minor; + + dev_dbg(&intf->dev, "%s - %u: %u.%u\n", __func__, bundle->id, + response.major, response.minor); + + return 0; +} + +int gb_control_get_bundle_versions(struct gb_control *control) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_bundle *bundle; + int ret; + + if (!control->has_bundle_version) + return 0; + + list_for_each_entry(bundle, &intf->bundles, links) { + ret = gb_control_get_bundle_version(control, bundle); + if (ret) + return ret; + } + + return 0; +} + +/* Get Manifest's size from the interface */ +int gb_control_get_manifest_size_operation(struct gb_interface *intf) +{ + struct gb_control_get_manifest_size_response response; + struct gb_connection *connection = intf->control->connection; + int ret; + + ret = gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST_SIZE, + NULL, 0, &response, sizeof(response)); + if (ret) { + dev_err(&connection->intf->dev, + "failed to get manifest size: %d\n", ret); + return ret; + } + + return le16_to_cpu(response.size); +} + +/* Reads Manifest from the interface */ +int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, + size_t size) +{ + struct gb_connection *connection = intf->control->connection; + + return gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST, + NULL, 0, manifest, size); +} + +int gb_control_connected_operation(struct gb_control *control, u16 cport_id) +{ + struct gb_control_connected_request request; + + request.cport_id = cpu_to_le16(cport_id); + return gb_operation_sync(control->connection, GB_CONTROL_TYPE_CONNECTED, + &request, sizeof(request), NULL, 0); +} + +int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) +{ + struct gb_control_disconnected_request request; + + request.cport_id = cpu_to_le16(cport_id); + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_DISCONNECTED, &request, + sizeof(request), NULL, 0); +} + +int gb_control_disconnecting_operation(struct gb_control *control, + u16 cport_id) +{ + struct gb_control_disconnecting_request *request; + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_core(control->connection, + GB_CONTROL_TYPE_DISCONNECTING, + sizeof(*request), 0, 0, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + request = operation->request->payload; + request->cport_id = cpu_to_le16(cport_id); + + ret = gb_operation_request_send_sync(operation); + if (ret) { + dev_err(&control->dev, "failed to send disconnecting: %d\n", + ret); + } + + gb_operation_put(operation); + + return ret; +} + +int gb_control_mode_switch_operation(struct gb_control *control) +{ + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_core(control->connection, + GB_CONTROL_TYPE_MODE_SWITCH, + 0, 0, GB_OPERATION_FLAG_UNIDIRECTIONAL, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + ret = gb_operation_request_send_sync(operation); + if (ret) + dev_err(&control->dev, "failed to send mode switch: %d\n", ret); + + gb_operation_put(operation); + + return ret; +} + +int gb_control_timesync_enable(struct gb_control *control, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk) +{ + struct gb_control_timesync_enable_request request; + + request.count = count; + request.frame_time = cpu_to_le64(frame_time); + request.strobe_delay = cpu_to_le32(strobe_delay); + request.refclk = cpu_to_le32(refclk); + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_ENABLE, &request, + sizeof(request), NULL, 0); +} + +int gb_control_timesync_disable(struct gb_control *control) +{ + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_DISABLE, NULL, 0, + NULL, 0); +} + +int gb_control_timesync_get_last_event(struct gb_control *control, + u64 *frame_time) +{ + struct gb_control_timesync_get_last_event_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT, + NULL, 0, &response, sizeof(response)); + if (!ret) + *frame_time = le64_to_cpu(response.frame_time); + return ret; +} + +int gb_control_timesync_authoritative(struct gb_control *control, + u64 *frame_time) +{ + struct gb_control_timesync_authoritative_request request; + int i; + + for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) + request.frame_time[i] = cpu_to_le64(frame_time[i]); + + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE, + &request, sizeof(request), + NULL, 0); +} + +static int gb_control_bundle_pm_status_map(u8 status) +{ + switch (status) { + case GB_CONTROL_BUNDLE_PM_INVAL: + return -EINVAL; + case GB_CONTROL_BUNDLE_PM_BUSY: + return -EBUSY; + case GB_CONTROL_BUNDLE_PM_NA: + return -ENOMSG; + case GB_CONTROL_BUNDLE_PM_FAIL: + default: + return -EREMOTEIO; + } +} + +int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_SUSPEND, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, "failed to send bundle %u suspend: %d\n", + bundle_id, ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, "failed to suspend bundle %u: %d\n", + bundle_id, response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_RESUME, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, "failed to send bundle %u resume: %d\n", + bundle_id, ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, "failed to resume bundle %u: %d\n", + bundle_id, response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_DEACTIVATE, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send bundle %u deactivate: %d\n", bundle_id, + ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, "failed to deactivate bundle %u: %d\n", + bundle_id, response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + if (!control->has_bundle_activate) + return 0; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_ACTIVATE, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send bundle %u activate: %d\n", bundle_id, + ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, "failed to activate bundle %u: %d\n", + bundle_id, response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +static int gb_control_interface_pm_status_map(u8 status) +{ + switch (status) { + case GB_CONTROL_INTF_PM_BUSY: + return -EBUSY; + case GB_CONTROL_INTF_PM_NA: + return -ENOMSG; + default: + return -EREMOTEIO; + } +} + +int gb_control_interface_suspend_prepare(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send interface suspend prepare: %d\n", ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while preparing suspend: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_interface_deactivate_prepare(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE, NULL, + 0, &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, "failed to send interface deactivate prepare: %d\n", + ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while preparing deactivate: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_interface_hibernate_abort(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send interface aborting hibernate: %d\n", + ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while aborting hibernate: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + +static ssize_t vendor_string_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_control *control = to_gb_control(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", control->vendor_string); +} +static DEVICE_ATTR_RO(vendor_string); + +static ssize_t product_string_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_control *control = to_gb_control(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", control->product_string); +} +static DEVICE_ATTR_RO(product_string); + +static struct attribute *control_attrs[] = { + &dev_attr_vendor_string.attr, + &dev_attr_product_string.attr, + NULL, +}; +ATTRIBUTE_GROUPS(control); + +static void gb_control_release(struct device *dev) +{ + struct gb_control *control = to_gb_control(dev); + + gb_connection_destroy(control->connection); + + kfree(control->vendor_string); + kfree(control->product_string); + + kfree(control); +} + +struct device_type greybus_control_type = { + .name = "greybus_control", + .release = gb_control_release, +}; + +struct gb_control *gb_control_create(struct gb_interface *intf) +{ + struct gb_connection *connection; + struct gb_control *control; + + control = kzalloc(sizeof(*control), GFP_KERNEL); + if (!control) + return ERR_PTR(-ENOMEM); + + control->intf = intf; + + connection = gb_connection_create_control(intf); + if (IS_ERR(connection)) { + dev_err(&intf->dev, + "failed to create control connection: %ld\n", + PTR_ERR(connection)); + kfree(control); + return ERR_CAST(connection); + } + + control->connection = connection; + + control->dev.parent = &intf->dev; + control->dev.bus = &greybus_bus_type; + control->dev.type = &greybus_control_type; + control->dev.groups = control_groups; + control->dev.dma_mask = intf->dev.dma_mask; + device_initialize(&control->dev); + dev_set_name(&control->dev, "%s.ctrl", dev_name(&intf->dev)); + + gb_connection_set_data(control->connection, control); + + return control; +} + +int gb_control_enable(struct gb_control *control) +{ + int ret; + + dev_dbg(&control->connection->intf->dev, "%s\n", __func__); + + ret = gb_connection_enable_tx(control->connection); + if (ret) { + dev_err(&control->connection->intf->dev, + "failed to enable control connection: %d\n", + ret); + return ret; + } + + ret = gb_control_get_version(control); + if (ret) + goto err_disable_connection; + + if (control->protocol_major > 0 || control->protocol_minor > 1) + control->has_bundle_version = true; + + /* FIXME: use protocol version instead */ + if (!(control->intf->quirks & GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE)) + control->has_bundle_activate = true; + + return 0; + +err_disable_connection: + gb_connection_disable(control->connection); + + return ret; +} + +void gb_control_disable(struct gb_control *control) +{ + dev_dbg(&control->connection->intf->dev, "%s\n", __func__); + + if (control->intf->disconnected) + gb_connection_disable_forced(control->connection); + else + gb_connection_disable(control->connection); +} + +int gb_control_suspend(struct gb_control *control) +{ + gb_connection_disable(control->connection); + + return 0; +} + +int gb_control_resume(struct gb_control *control) +{ + int ret; + + ret = gb_connection_enable_tx(control->connection); + if (ret) { + dev_err(&control->connection->intf->dev, + "failed to enable control connection: %d\n", ret); + return ret; + } + + return 0; +} + +int gb_control_add(struct gb_control *control) +{ + int ret; + + ret = device_add(&control->dev); + if (ret) { + dev_err(&control->dev, + "failed to register control device: %d\n", + ret); + return ret; + } + + return 0; +} + +void gb_control_del(struct gb_control *control) +{ + if (device_is_registered(&control->dev)) + device_del(&control->dev); +} + +struct gb_control *gb_control_get(struct gb_control *control) +{ + get_device(&control->dev); + + return control; +} + +void gb_control_put(struct gb_control *control) +{ + put_device(&control->dev); +} + +void gb_control_mode_switch_prepare(struct gb_control *control) +{ + gb_connection_mode_switch_prepare(control->connection); +} + +void gb_control_mode_switch_complete(struct gb_control *control) +{ + gb_connection_mode_switch_complete(control->connection); +} diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h new file mode 100644 index 000000000000..f9a60daf9a72 --- /dev/null +++ b/drivers/staging/greybus/control.h @@ -0,0 +1,65 @@ +/* + * Greybus CPort control protocol + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __CONTROL_H +#define __CONTROL_H + +struct gb_control { + struct device dev; + struct gb_interface *intf; + + struct gb_connection *connection; + + u8 protocol_major; + u8 protocol_minor; + + bool has_bundle_activate; + bool has_bundle_version; + + char *vendor_string; + char *product_string; +}; +#define to_gb_control(d) container_of(d, struct gb_control, dev) + +struct gb_control *gb_control_create(struct gb_interface *intf); +int gb_control_enable(struct gb_control *control); +void gb_control_disable(struct gb_control *control); +int gb_control_suspend(struct gb_control *control); +int gb_control_resume(struct gb_control *control); +int gb_control_add(struct gb_control *control); +void gb_control_del(struct gb_control *control); +struct gb_control *gb_control_get(struct gb_control *control); +void gb_control_put(struct gb_control *control); + +int gb_control_get_bundle_versions(struct gb_control *control); +int gb_control_connected_operation(struct gb_control *control, u16 cport_id); +int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); +int gb_control_disconnecting_operation(struct gb_control *control, + u16 cport_id); +int gb_control_mode_switch_operation(struct gb_control *control); +void gb_control_mode_switch_prepare(struct gb_control *control); +void gb_control_mode_switch_complete(struct gb_control *control); +int gb_control_get_manifest_size_operation(struct gb_interface *intf); +int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, + size_t size); +int gb_control_timesync_enable(struct gb_control *control, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk); +int gb_control_timesync_disable(struct gb_control *control); +int gb_control_timesync_get_last_event(struct gb_control *control, + u64 *frame_time); +int gb_control_timesync_authoritative(struct gb_control *control, + u64 *frame_time); +int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); +int gb_control_interface_suspend_prepare(struct gb_control *control); +int gb_control_interface_deactivate_prepare(struct gb_control *control); +int gb_control_interface_hibernate_abort(struct gb_control *control); +#endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c new file mode 100644 index 000000000000..1049e9c0edb0 --- /dev/null +++ b/drivers/staging/greybus/core.c @@ -0,0 +1,361 @@ +/* + * Greybus "Core" + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#define CREATE_TRACE_POINTS +#include "greybus.h" +#include "greybus_trace.h" + +#define GB_BUNDLE_AUTOSUSPEND_MS 3000 + +/* Allow greybus to be disabled at boot if needed */ +static bool nogreybus; +#ifdef MODULE +module_param(nogreybus, bool, 0444); +#else +core_param(nogreybus, nogreybus, bool, 0444); +#endif +int greybus_disabled(void) +{ + return nogreybus; +} +EXPORT_SYMBOL_GPL(greybus_disabled); + +static bool greybus_match_one_id(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && + (id->vendor != bundle->intf->vendor_id)) + return false; + + if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && + (id->product != bundle->intf->product_id)) + return false; + + if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && + (id->class != bundle->class)) + return false; + + return true; +} + +static const struct greybus_bundle_id * +greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) +{ + if (id == NULL) + return NULL; + + for (; id->vendor || id->product || id->class || id->driver_info; + id++) { + if (greybus_match_one_id(bundle, id)) + return id; + } + + return NULL; +} + +static int greybus_match_device(struct device *dev, struct device_driver *drv) +{ + struct greybus_driver *driver = to_greybus_driver(drv); + struct gb_bundle *bundle; + const struct greybus_bundle_id *id; + + if (!is_gb_bundle(dev)) + return 0; + + bundle = to_gb_bundle(dev); + + id = greybus_match_id(bundle, driver->id_table); + if (id) + return 1; + /* FIXME - Dynamic ids? */ + return 0; +} + +static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct gb_host_device *hd; + struct gb_module *module = NULL; + struct gb_interface *intf = NULL; + struct gb_control *control = NULL; + struct gb_bundle *bundle = NULL; + struct gb_svc *svc = NULL; + + if (is_gb_host_device(dev)) { + hd = to_gb_host_device(dev); + } else if (is_gb_module(dev)) { + module = to_gb_module(dev); + hd = module->hd; + } else if (is_gb_interface(dev)) { + intf = to_gb_interface(dev); + module = intf->module; + hd = intf->hd; + } else if (is_gb_control(dev)) { + control = to_gb_control(dev); + intf = control->intf; + module = intf->module; + hd = intf->hd; + } else if (is_gb_bundle(dev)) { + bundle = to_gb_bundle(dev); + intf = bundle->intf; + module = intf->module; + hd = intf->hd; + } else if (is_gb_svc(dev)) { + svc = to_gb_svc(dev); + hd = svc->hd; + } else { + dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); + return -EINVAL; + } + + if (add_uevent_var(env, "BUS=%u", hd->bus_id)) + return -ENOMEM; + + if (module) { + if (add_uevent_var(env, "MODULE=%u", module->module_id)) + return -ENOMEM; + } + + if (intf) { + if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) + return -ENOMEM; + if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", + intf->vendor_id, intf->product_id)) + return -ENOMEM; + } + + if (bundle) { + // FIXME + // add a uevent that can "load" a bundle type + // This is what we need to bind a driver to so use the info + // in gmod here as well + + if (add_uevent_var(env, "BUNDLE=%u", bundle->id)) + return -ENOMEM; + if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) + return -ENOMEM; + } + + return 0; +} + +static void greybus_shutdown(struct device *dev) +{ + if (is_gb_host_device(dev)) { + struct gb_host_device *hd; + + hd = to_gb_host_device(dev); + gb_hd_shutdown(hd); + } +} + +struct bus_type greybus_bus_type = { + .name = "greybus", + .match = greybus_match_device, + .uevent = greybus_uevent, + .shutdown = greybus_shutdown, +}; + +static int greybus_probe(struct device *dev) +{ + struct greybus_driver *driver = to_greybus_driver(dev->driver); + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct greybus_bundle_id *id; + int retval; + + /* match id */ + id = greybus_match_id(bundle, driver->id_table); + if (!id) + return -ENODEV; + + retval = pm_runtime_get_sync(&bundle->intf->dev); + if (retval < 0) { + pm_runtime_put_noidle(&bundle->intf->dev); + return retval; + } + + retval = gb_control_bundle_activate(bundle->intf->control, bundle->id); + if (retval) { + pm_runtime_put(&bundle->intf->dev); + return retval; + } + + /* + * Unbound bundle devices are always deactivated. During probe, the + * Runtime PM is set to enabled and active and the usage count is + * incremented. If the driver supports runtime PM, it should call + * pm_runtime_put() in its probe routine and pm_runtime_get_sync() + * in remove routine. + */ + pm_runtime_set_autosuspend_delay(dev, GB_BUNDLE_AUTOSUSPEND_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + retval = driver->probe(bundle, id); + if (retval) { + /* + * Catch buggy drivers that fail to destroy their connections. + */ + WARN_ON(!list_empty(&bundle->connections)); + + gb_control_bundle_deactivate(bundle->intf->control, bundle->id); + + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_put(&bundle->intf->dev); + + return retval; + } + + gb_timesync_schedule_synchronous(bundle->intf); + + pm_runtime_put(&bundle->intf->dev); + + return 0; +} + +static int greybus_remove(struct device *dev) +{ + struct greybus_driver *driver = to_greybus_driver(dev->driver); + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_connection *connection; + int retval; + + retval = pm_runtime_get_sync(dev); + if (retval < 0) + dev_err(dev, "failed to resume bundle: %d\n", retval); + + /* + * Disable (non-offloaded) connections early in case the interface is + * already gone to avoid unceccessary operation timeouts during + * driver disconnect. Otherwise, only disable incoming requests. + */ + list_for_each_entry(connection, &bundle->connections, bundle_links) { + if (gb_connection_is_offloaded(connection)) + continue; + + if (bundle->intf->disconnected) + gb_connection_disable_forced(connection); + else + gb_connection_disable_rx(connection); + } + + driver->disconnect(bundle); + + /* Catch buggy drivers that fail to destroy their connections. */ + WARN_ON(!list_empty(&bundle->connections)); + + if (!bundle->intf->disconnected) + gb_control_bundle_deactivate(bundle->intf->control, bundle->id); + + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_put_noidle(dev); + + return 0; +} + +int greybus_register_driver(struct greybus_driver *driver, struct module *owner, + const char *mod_name) +{ + int retval; + + if (greybus_disabled()) + return -ENODEV; + + driver->driver.bus = &greybus_bus_type; + driver->driver.name = driver->name; + driver->driver.probe = greybus_probe; + driver->driver.remove = greybus_remove; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + + retval = driver_register(&driver->driver); + if (retval) + return retval; + + pr_info("registered new driver %s\n", driver->name); + return 0; +} +EXPORT_SYMBOL_GPL(greybus_register_driver); + +void greybus_deregister_driver(struct greybus_driver *driver) +{ + driver_unregister(&driver->driver); +} +EXPORT_SYMBOL_GPL(greybus_deregister_driver); + +static int __init gb_init(void) +{ + int retval; + + if (greybus_disabled()) + return -ENODEV; + + BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD); + + gb_debugfs_init(); + + retval = bus_register(&greybus_bus_type); + if (retval) { + pr_err("bus_register failed (%d)\n", retval); + goto error_bus; + } + + retval = gb_hd_init(); + if (retval) { + pr_err("gb_hd_init failed (%d)\n", retval); + goto error_hd; + } + + retval = gb_operation_init(); + if (retval) { + pr_err("gb_operation_init failed (%d)\n", retval); + goto error_operation; + } + + retval = gb_timesync_init(); + if (retval) { + pr_err("gb_timesync_init failed\n"); + goto error_timesync; + } + return 0; /* Success */ + +error_timesync: + gb_operation_exit(); +error_operation: + gb_hd_exit(); +error_hd: + bus_unregister(&greybus_bus_type); +error_bus: + gb_debugfs_cleanup(); + + return retval; +} +module_init(gb_init); + +static void __exit gb_exit(void) +{ + gb_timesync_exit(); + gb_operation_exit(); + gb_hd_exit(); + bus_unregister(&greybus_bus_type); + gb_debugfs_cleanup(); + tracepoint_synchronize_unregister(); +} +module_exit(gb_exit); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c new file mode 100644 index 000000000000..a9d4d3da99a0 --- /dev/null +++ b/drivers/staging/greybus/debugfs.c @@ -0,0 +1,31 @@ +/* + * Greybus debugfs code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include + +#include "greybus.h" + +static struct dentry *gb_debug_root; + +void __init gb_debugfs_init(void) +{ + gb_debug_root = debugfs_create_dir("greybus", NULL); +} + +void gb_debugfs_cleanup(void) +{ + debugfs_remove_recursive(gb_debug_root); + gb_debug_root = NULL; +} + +struct dentry *gb_debugfs_get(void) +{ + return gb_debug_root; +} +EXPORT_SYMBOL_GPL(gb_debugfs_get); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c new file mode 100644 index 000000000000..071bb1cfd3ae --- /dev/null +++ b/drivers/staging/greybus/es2.c @@ -0,0 +1,1597 @@ +/* + * Greybus "AP" USB driver for "ES2" controller chips + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "arpc.h" +#include "greybus.h" +#include "greybus_trace.h" +#include "connection.h" + + +/* Default timeout for USB vendor requests. */ +#define ES2_USB_CTRL_TIMEOUT 500 + +/* Default timeout for ARPC CPort requests */ +#define ES2_ARPC_CPORT_TIMEOUT 500 + +/* Fixed CPort numbers */ +#define ES2_CPORT_CDSI0 16 +#define ES2_CPORT_CDSI1 17 + +/* Memory sizes for the buffers sent to/from the ES2 controller */ +#define ES2_GBUF_MSG_SIZE_MAX 2048 + +/* Memory sizes for the ARPC buffers */ +#define ARPC_OUT_SIZE_MAX U16_MAX +#define ARPC_IN_SIZE_MAX 128 + +static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x18d1, 0x1eaf) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +#define APB1_LOG_SIZE SZ_16K + +/* + * Number of CPort IN urbs in flight at any point in time. + * Adjust if we are having stalls in the USB buffer due to not enough urbs in + * flight. + */ +#define NUM_CPORT_IN_URB 4 + +/* Number of CPort OUT urbs in flight at any point in time. + * Adjust if we get messages saying we are out of urbs in the system log. + */ +#define NUM_CPORT_OUT_URB 8 + +/* + * Number of ARPC in urbs in flight at any point in time. + */ +#define NUM_ARPC_IN_URB 2 + +/* + * @endpoint: bulk in endpoint for CPort data + * @urb: array of urbs for the CPort in messages + * @buffer: array of buffers for the @cport_in_urb urbs + */ +struct es2_cport_in { + __u8 endpoint; + struct urb *urb[NUM_CPORT_IN_URB]; + u8 *buffer[NUM_CPORT_IN_URB]; +}; + +/** + * es2_ap_dev - ES2 USB Bridge to AP structure + * @usb_dev: pointer to the USB device we are. + * @usb_intf: pointer to the USB interface we are bound to. + * @hd: pointer to our gb_host_device structure + + * @cport_in: endpoint, urbs and buffer for cport in messages + * @cport_out_endpoint: endpoint for for cport out messages + * @cport_out_urb: array of urbs for the CPort out messages + * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or + * not. + * @cport_out_urb_cancelled: array of flags indicating whether the + * corresponding @cport_out_urb is being cancelled + * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" + * + * @apb_log_task: task pointer for logging thread + * @apb_log_dentry: file system entry for the log file interface + * @apb_log_enable_dentry: file system entry for enabling logging + * @apb_log_fifo: kernel FIFO to carry logged data + * @arpc_urb: array of urbs for the ARPC in messages + * @arpc_buffer: array of buffers for the @arpc_urb urbs + * @arpc_endpoint_in: bulk in endpoint for APBridgeA RPC + * @arpc_id_cycle: gives an unique id to ARPC + * @arpc_lock: locks ARPC list + * @arpcs: list of in progress ARPCs + */ +struct es2_ap_dev { + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + struct gb_host_device *hd; + + struct es2_cport_in cport_in; + __u8 cport_out_endpoint; + struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; + bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; + spinlock_t cport_out_urb_lock; + + bool cdsi1_in_use; + + struct task_struct *apb_log_task; + struct dentry *apb_log_dentry; + struct dentry *apb_log_enable_dentry; + DECLARE_KFIFO(apb_log_fifo, char, APB1_LOG_SIZE); + + __u8 arpc_endpoint_in; + struct urb *arpc_urb[NUM_ARPC_IN_URB]; + u8 *arpc_buffer[NUM_ARPC_IN_URB]; + + int arpc_id_cycle; + spinlock_t arpc_lock; + struct list_head arpcs; +}; + +/** + * timesync_enable_request - Enable timesync in an APBridge + * @count: number of TimeSync Pulses to expect + * @frame_time: the initial FrameTime at the first TimeSync Pulse + * @strobe_delay: the expected delay in microseconds between each TimeSync Pulse + * @refclk: The AP mandated reference clock to run FrameTime at + */ +struct timesync_enable_request { + __u8 count; + __le64 frame_time; + __le32 strobe_delay; + __le32 refclk; +} __packed; + +/** + * timesync_authoritative_request - Transmit authoritative FrameTime to APBridge + * @frame_time: An array of authoritative FrameTimes provided by the SVC + * and relayed to the APBridge by the AP + */ +struct timesync_authoritative_request { + __le64 frame_time[GB_TIMESYNC_MAX_STROBES]; +} __packed; + +struct arpc { + struct list_head list; + struct arpc_request_message *req; + struct arpc_response_message *resp; + struct completion response_received; + bool active; +}; + +static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) +{ + return (struct es2_ap_dev *)&hd->hd_priv; +} + +static void cport_out_callback(struct urb *urb); +static void usb_log_enable(struct es2_ap_dev *es2); +static void usb_log_disable(struct es2_ap_dev *es2); +static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, + size_t size, int *result, unsigned int timeout); + +static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) +{ + struct usb_device *udev = es2->usb_dev; + u8 *data; + int retval; + + data = kmalloc(size, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, req, size); + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + cmd, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, + 0, 0, data, size, ES2_USB_CTRL_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "%s: return error %d\n", __func__, retval); + else + retval = 0; + + kfree(data); + return retval; +} + +static void ap_urb_complete(struct urb *urb) +{ + struct usb_ctrlrequest *dr = urb->context; + + kfree(dr); + usb_free_urb(urb); +} + +static int output_async(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) +{ + struct usb_device *udev = es2->usb_dev; + struct urb *urb; + struct usb_ctrlrequest *dr; + u8 *buf; + int retval; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) + return -ENOMEM; + + dr = kmalloc(sizeof(*dr) + size, GFP_ATOMIC); + if (!dr) { + usb_free_urb(urb); + return -ENOMEM; + } + + buf = (u8 *)dr + sizeof(*dr); + memcpy(buf, req, size); + + dr->bRequest = cmd; + dr->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE; + dr->wValue = 0; + dr->wIndex = 0; + dr->wLength = cpu_to_le16(size); + + usb_fill_control_urb(urb, udev, usb_sndctrlpipe(udev, 0), + (unsigned char *)dr, buf, size, + ap_urb_complete, dr); + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) { + usb_free_urb(urb); + kfree(dr); + } + return retval; +} + +static int output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + + if (async) + return output_async(es2, req, size, cmd); + + return output_sync(es2, req, size, cmd); +} + +static int es2_cport_in_enable(struct es2_ap_dev *es2, + struct es2_cport_in *cport_in) +{ + struct urb *urb; + int ret; + int i; + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + urb = cport_in->urb[i]; + + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + dev_err(&es2->usb_dev->dev, + "failed to submit in-urb: %d\n", ret); + goto err_kill_urbs; + } + } + + return 0; + +err_kill_urbs: + for (--i; i >= 0; --i) { + urb = cport_in->urb[i]; + usb_kill_urb(urb); + } + + return ret; +} + +static void es2_cport_in_disable(struct es2_ap_dev *es2, + struct es2_cport_in *cport_in) +{ + struct urb *urb; + int i; + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + urb = cport_in->urb[i]; + usb_kill_urb(urb); + } +} + +static int es2_arpc_in_enable(struct es2_ap_dev *es2) +{ + struct urb *urb; + int ret; + int i; + + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + urb = es2->arpc_urb[i]; + + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + dev_err(&es2->usb_dev->dev, + "failed to submit arpc in-urb: %d\n", ret); + goto err_kill_urbs; + } + } + + return 0; + +err_kill_urbs: + for (--i; i >= 0; --i) { + urb = es2->arpc_urb[i]; + usb_kill_urb(urb); + } + + return ret; +} + +static void es2_arpc_in_disable(struct es2_ap_dev *es2) +{ + struct urb *urb; + int i; + + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + urb = es2->arpc_urb[i]; + usb_kill_urb(urb); + } +} + +static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) +{ + struct urb *urb = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + + /* Look in our pool of allocated urbs first, as that's the "fastest" */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (es2->cport_out_urb_busy[i] == false && + es2->cport_out_urb_cancelled[i] == false) { + es2->cport_out_urb_busy[i] = true; + urb = es2->cport_out_urb[i]; + break; + } + } + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + if (urb) + return urb; + + /* + * Crap, pool is empty, complain to the syslog and go allocate one + * dynamically as we have to succeed. + */ + dev_dbg(&es2->usb_dev->dev, + "No free CPort OUT urbs, having to dynamically allocate one!\n"); + return usb_alloc_urb(0, gfp_mask); +} + +static void free_urb(struct es2_ap_dev *es2, struct urb *urb) +{ + unsigned long flags; + int i; + /* + * See if this was an urb in our pool, if so mark it "free", otherwise + * we need to free it ourselves. + */ + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es2->cport_out_urb[i]) { + es2->cport_out_urb_busy[i] = false; + urb = NULL; + break; + } + } + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + + /* If urb is not NULL, then we need to free this urb */ + usb_free_urb(urb); +} + +/* + * We (ab)use the operation-message header pad bytes to transfer the + * cport id in order to minimise overhead. + */ +static void +gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id) +{ + header->pad[0] = cport_id; +} + +/* Clear the pad bytes used for the CPort id */ +static void gb_message_cport_clear(struct gb_operation_msg_hdr *header) +{ + header->pad[0] = 0; +} + +/* Extract the CPort id packed into the header, and clear it */ +static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) +{ + u16 cport_id = header->pad[0]; + + gb_message_cport_clear(header); + + return cport_id; +} + +/* + * Returns zero if the message was successfully queued, or a negative errno + * otherwise. + */ +static int message_send(struct gb_host_device *hd, u16 cport_id, + struct gb_message *message, gfp_t gfp_mask) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + size_t buffer_size; + int retval; + struct urb *urb; + unsigned long flags; + + /* + * The data actually transferred will include an indication + * of where the data should be sent. Do one last check of + * the target CPort id before filling it in. + */ + if (!cport_id_valid(hd, cport_id)) { + dev_err(&udev->dev, "invalid cport %u\n", cport_id); + return -EINVAL; + } + + /* Find a free urb */ + urb = next_free_urb(es2, gfp_mask); + if (!urb) + return -ENOMEM; + + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + message->hcpriv = urb; + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + + /* Pack the cport id into the message header */ + gb_message_cport_pack(message->header, cport_id); + + buffer_size = sizeof(*message->header) + message->payload_size; + + usb_fill_bulk_urb(urb, udev, + usb_sndbulkpipe(udev, + es2->cport_out_endpoint), + message->buffer, buffer_size, + cport_out_callback, message); + urb->transfer_flags |= URB_ZERO_PACKET; + + trace_gb_message_submit(message); + + retval = usb_submit_urb(urb, gfp_mask); + if (retval) { + dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); + + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + + free_urb(es2, urb); + gb_message_cport_clear(message->header); + + return retval; + } + + return 0; +} + +/* + * Can not be called in atomic context. + */ +static void message_cancel(struct gb_message *message) +{ + struct gb_host_device *hd = message->operation->connection->hd; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct urb *urb; + int i; + + might_sleep(); + + spin_lock_irq(&es2->cport_out_urb_lock); + urb = message->hcpriv; + + /* Prevent dynamically allocated urb from being deallocated. */ + usb_get_urb(urb); + + /* Prevent pre-allocated urb from being reused. */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es2->cport_out_urb[i]) { + es2->cport_out_urb_cancelled[i] = true; + break; + } + } + spin_unlock_irq(&es2->cport_out_urb_lock); + + usb_kill_urb(urb); + + if (i < NUM_CPORT_OUT_URB) { + spin_lock_irq(&es2->cport_out_urb_lock); + es2->cport_out_urb_cancelled[i] = false; + spin_unlock_irq(&es2->cport_out_urb_lock); + } + + usb_free_urb(urb); +} + +static int es2_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct ida *id_map = &hd->cport_id_map; + int ida_start, ida_end; + + switch (cport_id) { + case ES2_CPORT_CDSI0: + case ES2_CPORT_CDSI1: + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EBUSY; + } + + if (flags & GB_CONNECTION_FLAG_OFFLOADED && + flags & GB_CONNECTION_FLAG_CDSI1) { + if (es2->cdsi1_in_use) { + dev_err(&hd->dev, "CDSI1 already in use\n"); + return -EBUSY; + } + + es2->cdsi1_in_use = true; + + return ES2_CPORT_CDSI1; + } + + if (cport_id < 0) { + ida_start = 0; + ida_end = hd->num_cports; + } else if (cport_id < hd->num_cports) { + ida_start = cport_id; + ida_end = cport_id + 1; + } else { + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EINVAL; + } + + return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); +} + +static void es2_cport_release(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + + switch (cport_id) { + case ES2_CPORT_CDSI1: + es2->cdsi1_in_use = false; + return; + } + + ida_simple_remove(&hd->cport_id_map, cport_id); +} + +static int cport_enable(struct gb_host_device *hd, u16 cport_id, + unsigned long flags) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + struct gb_apb_request_cport_flags *req; + u32 connection_flags; + int ret; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + connection_flags = 0; + if (flags & GB_CONNECTION_FLAG_CONTROL) + connection_flags |= GB_APB_CPORT_FLAG_CONTROL; + if (flags & GB_CONNECTION_FLAG_HIGH_PRIO) + connection_flags |= GB_APB_CPORT_FLAG_HIGH_PRIO; + + req->flags = cpu_to_le32(connection_flags); + + dev_dbg(&hd->dev, "%s - cport = %u, flags = %02x\n", __func__, + cport_id, connection_flags); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_CPORT_FLAGS, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, + req, sizeof(*req), ES2_USB_CTRL_TIMEOUT); + if (ret != sizeof(*req)) { + dev_err(&udev->dev, "failed to set cport flags for port %d\n", + cport_id); + if (ret >= 0) + ret = -EIO; + + goto out; + } + + ret = 0; +out: + kfree(req); + + return ret; +} + +static int es2_cport_connected(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_connected_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_CONNECTED, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to set connected state for cport %u: %d\n", + cport_id, ret); + return ret; + } + + return 0; +} + +static int es2_cport_flush(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_flush_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_FLUSH, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to flush cport %u: %d\n", cport_id, ret); + return ret; + } + + return 0; +} + +static int es2_cport_shutdown(struct gb_host_device *hd, u16 cport_id, + u8 phase, unsigned int timeout) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_shutdown_req req; + int result; + int ret; + + if (timeout > U16_MAX) + return -EINVAL; + + req.cport_id = cpu_to_le16(cport_id); + req.timeout = cpu_to_le16(timeout); + req.phase = phase; + ret = arpc_sync(es2, ARPC_TYPE_CPORT_SHUTDOWN, &req, sizeof(req), + &result, ES2_ARPC_CPORT_TIMEOUT + timeout); + if (ret) { + dev_err(dev, "failed to send shutdown over cport %u: %d (%d)\n", + cport_id, ret, result); + return ret; + } + + return 0; +} + +static int es2_cport_quiesce(struct gb_host_device *hd, u16 cport_id, + size_t peer_space, unsigned int timeout) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_quiesce_req req; + int result; + int ret; + + if (peer_space > U16_MAX) + return -EINVAL; + + if (timeout > U16_MAX) + return -EINVAL; + + req.cport_id = cpu_to_le16(cport_id); + req.peer_space = cpu_to_le16(peer_space); + req.timeout = cpu_to_le16(timeout); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_QUIESCE, &req, sizeof(req), + &result, ES2_ARPC_CPORT_TIMEOUT + timeout); + if (ret) { + dev_err(dev, "failed to quiesce cport %u: %d (%d)\n", + cport_id, ret, result); + return ret; + } + + return 0; +} + +static int es2_cport_clear(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_clear_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_CLEAR, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to clear cport %u: %d\n", cport_id, ret); + return ret; + } + + return 0; +} + +static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_LATENCY_TAG_EN, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES2_USB_CTRL_TIMEOUT); + + if (retval < 0) + dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n", + cport_id); + return retval; +} + +static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_LATENCY_TAG_DIS, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES2_USB_CTRL_TIMEOUT); + + if (retval < 0) + dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n", + cport_id); + return retval; +} + +static int timesync_enable(struct gb_host_device *hd, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + struct gb_control_timesync_enable_request *request; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->count = count; + request->frame_time = cpu_to_le64(frame_time); + request->strobe_delay = cpu_to_le32(strobe_delay); + request->refclk = cpu_to_le32(refclk); + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_TIMESYNC_ENABLE, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, request, + sizeof(*request), ES2_USB_CTRL_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "Cannot enable timesync %d\n", retval); + + kfree(request); + return retval; +} + +static int timesync_disable(struct gb_host_device *hd) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_TIMESYNC_DISABLE, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, NULL, + 0, ES2_USB_CTRL_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "Cannot disable timesync %d\n", retval); + + return retval; +} + +static int timesync_authoritative(struct gb_host_device *hd, u64 *frame_time) +{ + int retval, i; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + struct timesync_authoritative_request *request; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) + request->frame_time[i] = cpu_to_le64(frame_time[i]); + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_TIMESYNC_AUTHORITATIVE, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, request, + sizeof(*request), ES2_USB_CTRL_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "Cannot timesync authoritative out %d\n", retval); + + kfree(request); + return retval; +} + +static int timesync_get_last_event(struct gb_host_device *hd, u64 *frame_time) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + __le64 *response_frame_time; + + response_frame_time = kzalloc(sizeof(*response_frame_time), GFP_KERNEL); + if (!response_frame_time) + return -ENOMEM; + + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + GB_APB_REQUEST_TIMESYNC_GET_LAST_EVENT, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, response_frame_time, + sizeof(*response_frame_time), + ES2_USB_CTRL_TIMEOUT); + + if (retval != sizeof(*response_frame_time)) { + dev_err(&udev->dev, "Cannot get last TimeSync event: %d\n", + retval); + + if (retval >= 0) + retval = -EIO; + + goto out; + } + *frame_time = le64_to_cpu(*response_frame_time); + retval = 0; +out: + kfree(response_frame_time); + return retval; +} + +static struct gb_hd_driver es2_driver = { + .hd_priv_size = sizeof(struct es2_ap_dev), + .message_send = message_send, + .message_cancel = message_cancel, + .cport_allocate = es2_cport_allocate, + .cport_release = es2_cport_release, + .cport_enable = cport_enable, + .cport_connected = es2_cport_connected, + .cport_flush = es2_cport_flush, + .cport_shutdown = es2_cport_shutdown, + .cport_quiesce = es2_cport_quiesce, + .cport_clear = es2_cport_clear, + .latency_tag_enable = latency_tag_enable, + .latency_tag_disable = latency_tag_disable, + .output = output, + .timesync_enable = timesync_enable, + .timesync_disable = timesync_disable, + .timesync_authoritative = timesync_authoritative, + .timesync_get_last_event = timesync_get_last_event, +}; + +/* Common function to report consistent warnings based on URB status */ +static int check_urb_status(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + + switch (status) { + case 0: + return 0; + + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + case -EPROTO: + /* device is gone, stop sending */ + return status; + } + dev_err(dev, "%s: unknown status %d\n", __func__, status); + + return -EAGAIN; +} + +static void es2_destroy(struct es2_ap_dev *es2) +{ + struct usb_device *udev; + struct urb *urb; + int i; + + debugfs_remove(es2->apb_log_enable_dentry); + usb_log_disable(es2); + + /* Tear down everything! */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + urb = es2->cport_out_urb[i]; + usb_kill_urb(urb); + usb_free_urb(urb); + es2->cport_out_urb[i] = NULL; + es2->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + usb_free_urb(es2->arpc_urb[i]); + kfree(es2->arpc_buffer[i]); + es2->arpc_buffer[i] = NULL; + } + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + usb_free_urb(es2->cport_in.urb[i]); + kfree(es2->cport_in.buffer[i]); + es2->cport_in.buffer[i] = NULL; + } + + /* release reserved CDSI0 and CDSI1 cports */ + gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI1); + gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI0); + + udev = es2->usb_dev; + gb_hd_put(es2->hd); + + usb_put_dev(udev); +} + +static void cport_in_callback(struct urb *urb) +{ + struct gb_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + struct gb_operation_msg_hdr *header; + int status = check_urb_status(urb); + int retval; + u16 cport_id; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + + /* The urb is being unlinked */ + if (status == -ENOENT || status == -ESHUTDOWN) + return; + + dev_err(dev, "urb cport in error %d (dropped)\n", status); + return; + } + + if (urb->actual_length < sizeof(*header)) { + dev_err(dev, "short message received\n"); + goto exit; + } + + /* Extract the CPort id, which is packed in the message header */ + header = urb->transfer_buffer; + cport_id = gb_message_cport_unpack(header); + + if (cport_id_valid(hd, cport_id)) { + greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, + urb->actual_length); + } else { + dev_err(dev, "invalid cport id %u received\n", cport_id); + } +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "failed to resubmit in-urb: %d\n", retval); +} + +static void cport_out_callback(struct urb *urb) +{ + struct gb_message *message = urb->context; + struct gb_host_device *hd = message->operation->connection->hd; + struct es2_ap_dev *es2 = hd_to_es2(hd); + int status = check_urb_status(urb); + unsigned long flags; + + gb_message_cport_clear(message->header); + + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + + /* + * Tell the submitter that the message send (attempt) is + * complete, and report the status. + */ + greybus_message_sent(hd, message, status); + + free_urb(es2, urb); +} + +static struct arpc *arpc_alloc(void *payload, u16 size, u8 type) +{ + struct arpc *rpc; + + if (size + sizeof(*rpc->req) > ARPC_OUT_SIZE_MAX) + return NULL; + + rpc = kzalloc(sizeof(*rpc), GFP_KERNEL); + if (!rpc) + return NULL; + + INIT_LIST_HEAD(&rpc->list); + rpc->req = kzalloc(sizeof(*rpc->req) + size, GFP_KERNEL); + if (!rpc->req) + goto err_free_rpc; + + rpc->resp = kzalloc(sizeof(*rpc->resp), GFP_KERNEL); + if (!rpc->resp) + goto err_free_req; + + rpc->req->type = type; + rpc->req->size = cpu_to_le16(sizeof(rpc->req) + size); + memcpy(rpc->req->data, payload, size); + + init_completion(&rpc->response_received); + + return rpc; + +err_free_req: + kfree(rpc->req); +err_free_rpc: + kfree(rpc); + + return NULL; +} + +static void arpc_free(struct arpc *rpc) +{ + kfree(rpc->req); + kfree(rpc->resp); + kfree(rpc); +} + +static struct arpc *arpc_find(struct es2_ap_dev *es2, __le16 id) +{ + struct arpc *rpc; + + list_for_each_entry(rpc, &es2->arpcs, list) { + if (rpc->req->id == id) + return rpc; + } + + return NULL; +} + +static void arpc_add(struct es2_ap_dev *es2, struct arpc *rpc) +{ + rpc->active = true; + rpc->req->id = cpu_to_le16(es2->arpc_id_cycle++); + list_add_tail(&rpc->list, &es2->arpcs); +} + +static void arpc_del(struct es2_ap_dev *es2, struct arpc *rpc) +{ + if (rpc->active) { + rpc->active = false; + list_del(&rpc->list); + } +} + +static int arpc_send(struct es2_ap_dev *es2, struct arpc *rpc, int timeout) +{ + struct usb_device *udev = es2->usb_dev; + int retval; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_ARPC_RUN, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, + 0, 0, + rpc->req, le16_to_cpu(rpc->req->size), + ES2_USB_CTRL_TIMEOUT); + if (retval != le16_to_cpu(rpc->req->size)) { + dev_err(&udev->dev, + "failed to send ARPC request %d: %d\n", + rpc->req->type, retval); + if (retval > 0) + retval = -EIO; + return retval; + } + + return 0; +} + +static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, + size_t size, int *result, unsigned int timeout) +{ + struct arpc *rpc; + unsigned long flags; + int retval; + + if (result) + *result = 0; + + rpc = arpc_alloc(payload, size, type); + if (!rpc) + return -ENOMEM; + + spin_lock_irqsave(&es2->arpc_lock, flags); + arpc_add(es2, rpc); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + + retval = arpc_send(es2, rpc, timeout); + if (retval) + goto out_arpc_del; + + retval = wait_for_completion_interruptible_timeout( + &rpc->response_received, + msecs_to_jiffies(timeout)); + if (retval <= 0) { + if (!retval) + retval = -ETIMEDOUT; + goto out_arpc_del; + } + + if (rpc->resp->result) { + retval = -EREMOTEIO; + if (result) + *result = rpc->resp->result; + } else { + retval = 0; + } + +out_arpc_del: + spin_lock_irqsave(&es2->arpc_lock, flags); + arpc_del(es2, rpc); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + arpc_free(rpc); + + if (retval < 0 && retval != -EREMOTEIO) { + dev_err(&es2->usb_dev->dev, + "failed to execute ARPC: %d\n", retval); + } + + return retval; +} + +static void arpc_in_callback(struct urb *urb) +{ + struct es2_ap_dev *es2 = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + struct arpc *rpc; + struct arpc_response_message *resp; + unsigned long flags; + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + + /* The urb is being unlinked */ + if (status == -ENOENT || status == -ESHUTDOWN) + return; + + dev_err(dev, "arpc in-urb error %d (dropped)\n", status); + return; + } + + if (urb->actual_length < sizeof(*resp)) { + dev_err(dev, "short aprc response received\n"); + goto exit; + } + + resp = urb->transfer_buffer; + spin_lock_irqsave(&es2->arpc_lock, flags); + rpc = arpc_find(es2, resp->id); + if (!rpc) { + dev_err(dev, "invalid arpc response id received: %u\n", + le16_to_cpu(resp->id)); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + goto exit; + } + + arpc_del(es2, rpc); + memcpy(rpc->resp, resp, sizeof(*resp)); + complete(&rpc->response_received); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "failed to resubmit arpc in-urb: %d\n", retval); +} + +#define APB1_LOG_MSG_SIZE 64 +static void apb_log_get(struct es2_ap_dev *es2, char *buf) +{ + int retval; + + do { + retval = usb_control_msg(es2->usb_dev, + usb_rcvctrlpipe(es2->usb_dev, 0), + GB_APB_REQUEST_LOG, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + buf, + APB1_LOG_MSG_SIZE, + ES2_USB_CTRL_TIMEOUT); + if (retval > 0) + kfifo_in(&es2->apb_log_fifo, buf, retval); + } while (retval > 0); +} + +static int apb_log_poll(void *data) +{ + struct es2_ap_dev *es2 = data; + char *buf; + + buf = kmalloc(APB1_LOG_MSG_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + while (!kthread_should_stop()) { + msleep(1000); + apb_log_get(es2, buf); + } + + kfree(buf); + + return 0; +} + +static ssize_t apb_log_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + struct es2_ap_dev *es2 = f->f_inode->i_private; + ssize_t ret; + size_t copied; + char *tmp_buf; + + if (count > APB1_LOG_SIZE) + count = APB1_LOG_SIZE; + + tmp_buf = kmalloc(count, GFP_KERNEL); + if (!tmp_buf) + return -ENOMEM; + + copied = kfifo_out(&es2->apb_log_fifo, tmp_buf, count); + ret = simple_read_from_buffer(buf, count, ppos, tmp_buf, copied); + + kfree(tmp_buf); + + return ret; +} + +static const struct file_operations apb_log_fops = { + .read = apb_log_read, +}; + +static void usb_log_enable(struct es2_ap_dev *es2) +{ + if (!IS_ERR_OR_NULL(es2->apb_log_task)) + return; + + /* get log from APB1 */ + es2->apb_log_task = kthread_run(apb_log_poll, es2, "apb_log"); + if (IS_ERR(es2->apb_log_task)) + return; + /* XXX We will need to rename this per APB */ + es2->apb_log_dentry = debugfs_create_file("apb_log", S_IRUGO, + gb_debugfs_get(), es2, + &apb_log_fops); +} + +static void usb_log_disable(struct es2_ap_dev *es2) +{ + if (IS_ERR_OR_NULL(es2->apb_log_task)) + return; + + debugfs_remove(es2->apb_log_dentry); + es2->apb_log_dentry = NULL; + + kthread_stop(es2->apb_log_task); + es2->apb_log_task = NULL; +} + +static ssize_t apb_log_enable_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + struct es2_ap_dev *es2 = f->f_inode->i_private; + int enable = !IS_ERR_OR_NULL(es2->apb_log_task); + char tmp_buf[3]; + + sprintf(tmp_buf, "%d\n", enable); + return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); +} + +static ssize_t apb_log_enable_write(struct file *f, const char __user *buf, + size_t count, loff_t *ppos) +{ + int enable; + ssize_t retval; + struct es2_ap_dev *es2 = f->f_inode->i_private; + + retval = kstrtoint_from_user(buf, count, 10, &enable); + if (retval) + return retval; + + if (enable) + usb_log_enable(es2); + else + usb_log_disable(es2); + + return count; +} + +static const struct file_operations apb_log_enable_fops = { + .read = apb_log_enable_read, + .write = apb_log_enable_write, +}; + +static int apb_get_cport_count(struct usb_device *udev) +{ + int retval; + __le16 *cport_count; + + cport_count = kzalloc(sizeof(*cport_count), GFP_KERNEL); + if (!cport_count) + return -ENOMEM; + + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + GB_APB_REQUEST_CPORT_COUNT, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, cport_count, + sizeof(*cport_count), ES2_USB_CTRL_TIMEOUT); + if (retval != sizeof(*cport_count)) { + dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", + retval); + + if (retval >= 0) + retval = -EIO; + + goto out; + } + + retval = le16_to_cpu(*cport_count); + + /* We need to fit a CPort ID in one byte of a message header */ + if (retval > U8_MAX) { + retval = U8_MAX; + dev_warn(&udev->dev, "Limiting number of CPorts to U8_MAX\n"); + } + +out: + kfree(cport_count); + return retval; +} + +/* + * The ES2 USB Bridge device has 15 endpoints + * 1 Control - usual USB stuff + AP -> APBridgeA messages + * 7 Bulk IN - CPort data in + * 7 Bulk OUT - CPort data out + */ +static int ap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct es2_ap_dev *es2; + struct gb_host_device *hd; + struct usb_device *udev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + __u8 ep_addr; + int retval; + int i; + int num_cports; + bool bulk_out_found = false; + bool bulk_in_found = false; + bool arpc_in_found = false; + + udev = usb_get_dev(interface_to_usbdev(interface)); + + num_cports = apb_get_cport_count(udev); + if (num_cports < 0) { + usb_put_dev(udev); + dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", + num_cports); + return num_cports; + } + + hd = gb_hd_create(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX, + num_cports); + if (IS_ERR(hd)) { + usb_put_dev(udev); + return PTR_ERR(hd); + } + + es2 = hd_to_es2(hd); + es2->hd = hd; + es2->usb_intf = interface; + es2->usb_dev = udev; + spin_lock_init(&es2->cport_out_urb_lock); + INIT_KFIFO(es2->apb_log_fifo); + usb_set_intfdata(interface, es2); + + /* + * Reserve the CDSI0 and CDSI1 CPorts so they won't be allocated + * dynamically. + */ + retval = gb_hd_cport_reserve(hd, ES2_CPORT_CDSI0); + if (retval) + goto error; + retval = gb_hd_cport_reserve(hd, ES2_CPORT_CDSI1); + if (retval) + goto error; + + /* find all bulk endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + ep_addr = endpoint->bEndpointAddress; + + if (usb_endpoint_is_bulk_in(endpoint)) { + if (!bulk_in_found) { + es2->cport_in.endpoint = ep_addr; + bulk_in_found = true; + } else if (!arpc_in_found) { + es2->arpc_endpoint_in = ep_addr; + arpc_in_found = true; + } else { + dev_warn(&udev->dev, + "Unused bulk IN endpoint found: 0x%02x\n", + ep_addr); + } + continue; + } + if (usb_endpoint_is_bulk_out(endpoint)) { + if (!bulk_out_found) { + es2->cport_out_endpoint = ep_addr; + bulk_out_found = true; + } else { + dev_warn(&udev->dev, + "Unused bulk OUT endpoint found: 0x%02x\n", + ep_addr); + } + continue; + } + dev_warn(&udev->dev, + "Unknown endpoint type found, address 0x%02x\n", + ep_addr); + } + if (!bulk_in_found || !arpc_in_found || !bulk_out_found) { + dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); + retval = -ENODEV; + goto error; + } + + /* Allocate buffers for our cport in messages */ + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + es2->cport_in.urb[i] = urb; + + buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + if (!buffer) { + retval = -ENOMEM; + goto error; + } + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, es2->cport_in.endpoint), + buffer, ES2_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); + + es2->cport_in.buffer[i] = buffer; + } + + /* Allocate buffers for ARPC in messages */ + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + es2->arpc_urb[i] = urb; + + buffer = kmalloc(ARPC_IN_SIZE_MAX, GFP_KERNEL); + if (!buffer) { + retval = -ENOMEM; + goto error; + } + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, + es2->arpc_endpoint_in), + buffer, ARPC_IN_SIZE_MAX, + arpc_in_callback, es2); + + es2->arpc_buffer[i] = buffer; + } + + /* Allocate urbs for our CPort OUT messages */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + + es2->cport_out_urb[i] = urb; + es2->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + /* XXX We will need to rename this per APB */ + es2->apb_log_enable_dentry = debugfs_create_file("apb_log_enable", + (S_IWUSR | S_IRUGO), + gb_debugfs_get(), es2, + &apb_log_enable_fops); + + INIT_LIST_HEAD(&es2->arpcs); + spin_lock_init(&es2->arpc_lock); + + if (es2_arpc_in_enable(es2)) + goto error; + + retval = gb_hd_add(hd); + if (retval) + goto err_disable_arpc_in; + + retval = es2_cport_in_enable(es2, &es2->cport_in); + if (retval) + goto err_hd_del; + + return 0; + +err_hd_del: + gb_hd_del(hd); +err_disable_arpc_in: + es2_arpc_in_disable(es2); +error: + es2_destroy(es2); + + return retval; +} + +static void ap_disconnect(struct usb_interface *interface) +{ + struct es2_ap_dev *es2 = usb_get_intfdata(interface); + + gb_hd_del(es2->hd); + + es2_cport_in_disable(es2, &es2->cport_in); + es2_arpc_in_disable(es2); + + es2_destroy(es2); +} + +static struct usb_driver es2_ap_driver = { + .name = "es2_ap_driver", + .probe = ap_probe, + .disconnect = ap_disconnect, + .id_table = id_table, + .soft_unbind = 1, +}; + +module_usb_driver(es2_ap_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h new file mode 100644 index 000000000000..f4f0db1cefe8 --- /dev/null +++ b/drivers/staging/greybus/firmware.h @@ -0,0 +1,42 @@ +/* + * Greybus Firmware Management Header + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __FIRMWARE_H +#define __FIRMWARE_H + +#include "greybus.h" + +#define FW_NAME_PREFIX "gmp_" + +/* + * Length of the string in format: "FW_NAME_PREFIX""%08x_%08x_%08x_%08x_%s.tftf" + * (3 + 1 + 4 * (8 + 1) + 10 + 1 + 4 + 1) + */ +#define FW_NAME_SIZE 56 + +/* Firmware Management Protocol specific functions */ +int fw_mgmt_init(void); +void fw_mgmt_exit(void); +struct gb_connection *to_fw_mgmt_connection(struct device *dev); +int gb_fw_mgmt_request_handler(struct gb_operation *op); +int gb_fw_mgmt_connection_init(struct gb_connection *connection); +void gb_fw_mgmt_connection_exit(struct gb_connection *connection); + +/* Firmware Download Protocol specific functions */ +int gb_fw_download_request_handler(struct gb_operation *op); +int gb_fw_download_connection_init(struct gb_connection *connection); +void gb_fw_download_connection_exit(struct gb_connection *connection); + +/* CAP Protocol specific functions */ +int cap_init(void); +void cap_exit(void); +int gb_cap_connection_init(struct gb_connection *connection); +void gb_cap_connection_exit(struct gb_connection *connection); + +#endif /* __FIRMWARE_H */ diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c new file mode 100644 index 000000000000..454a98957ba5 --- /dev/null +++ b/drivers/staging/greybus/fw-core.c @@ -0,0 +1,312 @@ +/* + * Greybus Firmware Core Bundle Driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include "firmware.h" +#include "greybus.h" +#include "spilib.h" + +struct gb_fw_core { + struct gb_connection *download_connection; + struct gb_connection *mgmt_connection; + struct gb_connection *spi_connection; + struct gb_connection *cap_connection; +}; + +static struct spilib_ops *spilib_ops; + +struct gb_connection *to_fw_mgmt_connection(struct device *dev) +{ + struct gb_fw_core *fw_core = dev_get_drvdata(dev); + + return fw_core->mgmt_connection; +} + +static int gb_fw_spi_connection_init(struct gb_connection *connection) +{ + int ret; + + if (!connection) + return 0; + + ret = gb_connection_enable(connection); + if (ret) + return ret; + + ret = gb_spilib_master_init(connection, &connection->bundle->dev, + spilib_ops); + if (ret) { + gb_connection_disable(connection); + return ret; + } + + return 0; +} + +static void gb_fw_spi_connection_exit(struct gb_connection *connection) +{ + if (!connection) + return; + + gb_spilib_master_exit(connection); + gb_connection_disable(connection); +} + +static int gb_fw_core_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_fw_core *fw_core; + int ret, i; + u16 cport_id; + u8 protocol_id; + + fw_core = kzalloc(sizeof(*fw_core), GFP_KERNEL); + if (!fw_core) + return -ENOMEM; + + /* Parse CPorts and create connections */ + for (i = 0; i < bundle->num_cports; i++) { + cport_desc = &bundle->cport_desc[i]; + cport_id = le16_to_cpu(cport_desc->id); + protocol_id = cport_desc->protocol_id; + + switch (protocol_id) { + case GREYBUS_PROTOCOL_FW_MANAGEMENT: + /* Disallow multiple Firmware Management CPorts */ + if (fw_core->mgmt_connection) { + dev_err(&bundle->dev, + "multiple management CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + gb_fw_mgmt_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + dev_err(&bundle->dev, + "failed to create management connection (%d)\n", + ret); + goto err_destroy_connections; + } + + fw_core->mgmt_connection = connection; + break; + case GREYBUS_PROTOCOL_FW_DOWNLOAD: + /* Disallow multiple Firmware Download CPorts */ + if (fw_core->download_connection) { + dev_err(&bundle->dev, + "multiple download CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + gb_fw_download_request_handler); + if (IS_ERR(connection)) { + dev_err(&bundle->dev, "failed to create download connection (%ld)\n", + PTR_ERR(connection)); + } else { + fw_core->download_connection = connection; + } + + break; + case GREYBUS_PROTOCOL_SPI: + /* Disallow multiple SPI CPorts */ + if (fw_core->spi_connection) { + dev_err(&bundle->dev, + "multiple SPI CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + NULL); + if (IS_ERR(connection)) { + dev_err(&bundle->dev, "failed to create SPI connection (%ld)\n", + PTR_ERR(connection)); + } else { + fw_core->spi_connection = connection; + } + + break; + case GREYBUS_PROTOCOL_AUTHENTICATION: + /* Disallow multiple CAP CPorts */ + if (fw_core->cap_connection) { + dev_err(&bundle->dev, "multiple Authentication CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + NULL); + if (IS_ERR(connection)) { + dev_err(&bundle->dev, "failed to create Authentication connection (%ld)\n", + PTR_ERR(connection)); + } else { + fw_core->cap_connection = connection; + } + + break; + default: + dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n", + protocol_id); + ret = -EINVAL; + goto err_destroy_connections; + } + } + + /* Firmware Management connection is mandatory */ + if (!fw_core->mgmt_connection) { + dev_err(&bundle->dev, "missing management connection\n"); + ret = -ENODEV; + goto err_destroy_connections; + } + + ret = gb_fw_download_connection_init(fw_core->download_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize firmware download connection, disable it (%d)\n", + ret); + gb_connection_destroy(fw_core->download_connection); + fw_core->download_connection = NULL; + } + + ret = gb_fw_spi_connection_init(fw_core->spi_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize SPI connection, disable it (%d)\n", + ret); + gb_connection_destroy(fw_core->spi_connection); + fw_core->spi_connection = NULL; + } + + ret = gb_cap_connection_init(fw_core->cap_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize CAP connection, disable it (%d)\n", + ret); + gb_connection_destroy(fw_core->cap_connection); + fw_core->cap_connection = NULL; + } + + ret = gb_fw_mgmt_connection_init(fw_core->mgmt_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize firmware management connection, disable it (%d)\n", + ret); + goto err_exit_connections; + } + + greybus_set_drvdata(bundle, fw_core); + + /* FIXME: Remove this after S2 Loader gets runtime PM support */ + if (!(bundle->intf->quirks & GB_INTERFACE_QUIRK_NO_PM)) + gb_pm_runtime_put_autosuspend(bundle); + + return 0; + +err_exit_connections: + gb_cap_connection_exit(fw_core->cap_connection); + gb_fw_spi_connection_exit(fw_core->spi_connection); + gb_fw_download_connection_exit(fw_core->download_connection); +err_destroy_connections: + gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->cap_connection); + gb_connection_destroy(fw_core->spi_connection); + gb_connection_destroy(fw_core->download_connection); + kfree(fw_core); + + return ret; +} + +static void gb_fw_core_disconnect(struct gb_bundle *bundle) +{ + struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); + int ret; + + /* FIXME: Remove this after S2 Loader gets runtime PM support */ + if (!(bundle->intf->quirks & GB_INTERFACE_QUIRK_NO_PM)) { + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); + } + + gb_fw_mgmt_connection_exit(fw_core->mgmt_connection); + gb_cap_connection_exit(fw_core->cap_connection); + gb_fw_spi_connection_exit(fw_core->spi_connection); + gb_fw_download_connection_exit(fw_core->download_connection); + + gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->cap_connection); + gb_connection_destroy(fw_core->spi_connection); + gb_connection_destroy(fw_core->download_connection); + + kfree(fw_core); +} + +static const struct greybus_bundle_id gb_fw_core_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FW_MANAGEMENT) }, + { } +}; + +static struct greybus_driver gb_fw_core_driver = { + .name = "gb-firmware", + .probe = gb_fw_core_probe, + .disconnect = gb_fw_core_disconnect, + .id_table = gb_fw_core_id_table, +}; + +static int fw_core_init(void) +{ + int ret; + + ret = fw_mgmt_init(); + if (ret) { + pr_err("Failed to initialize fw-mgmt core (%d)\n", ret); + return ret; + } + + ret = cap_init(); + if (ret) { + pr_err("Failed to initialize component authentication core (%d)\n", + ret); + goto fw_mgmt_exit; + } + + ret = greybus_register(&gb_fw_core_driver); + if (ret) + goto cap_exit; + + return 0; + +cap_exit: + cap_exit(); +fw_mgmt_exit: + fw_mgmt_exit(); + + return ret; +} +module_init(fw_core_init); + +static void __exit fw_core_exit(void) +{ + greybus_deregister(&gb_fw_core_driver); + cap_exit(); + fw_mgmt_exit(); +} +module_exit(fw_core_exit); + +MODULE_ALIAS("greybus:firmware"); +MODULE_AUTHOR("Viresh Kumar "); +MODULE_DESCRIPTION("Greybus Firmware Bundle Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c new file mode 100644 index 000000000000..2d7246887547 --- /dev/null +++ b/drivers/staging/greybus/fw-download.c @@ -0,0 +1,465 @@ +/* + * Greybus Firmware Download Protocol Driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "firmware.h" +#include "greybus.h" + +/* Estimated minimum buffer size, actual size can be smaller than this */ +#define MIN_FETCH_SIZE 512 +/* Timeout, in jiffies, within which fetch or release firmware must be called */ +#define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000) + +struct fw_request { + u8 firmware_id; + bool disabled; + bool timedout; + char name[FW_NAME_SIZE]; + const struct firmware *fw; + struct list_head node; + + struct delayed_work dwork; + /* Timeout, in jiffies, within which the firmware shall download */ + unsigned long release_timeout_j; + struct kref kref; + struct fw_download *fw_download; +}; + +struct fw_download { + struct device *parent; + struct gb_connection *connection; + struct list_head fw_requests; + struct ida id_map; + struct mutex mutex; +}; + +static void fw_req_release(struct kref *kref) +{ + struct fw_request *fw_req = container_of(kref, struct fw_request, kref); + + dev_dbg(fw_req->fw_download->parent, "firmware %s released\n", + fw_req->name); + + release_firmware(fw_req->fw); + + /* + * The request timed out and the module may send a fetch-fw or + * release-fw request later. Lets block the id we allocated for this + * request, so that the AP doesn't refer to a later fw-request (with + * same firmware_id) for the old timedout fw-request. + * + * NOTE: + * + * This also means that after 255 timeouts we will fail to service new + * firmware downloads. But what else can we do in that case anyway? Lets + * just hope that it never happens. + */ + if (!fw_req->timedout) + ida_simple_remove(&fw_req->fw_download->id_map, + fw_req->firmware_id); + + kfree(fw_req); +} + +/* + * Incoming requests are serialized for a connection, and the only race possible + * is between the timeout handler freeing this and an incoming request. + * + * The operations on the fw-request list are protected by the mutex and + * get_fw_req() increments the reference count before returning a fw_req pointer + * to the users. + * + * free_firmware() also takes the mutex while removing an entry from the list, + * it guarantees that every user of fw_req has taken a kref-reference by now and + * we wouldn't have any new users. + * + * Once the last user drops the reference, the fw_req structure is freed. + */ +static void put_fw_req(struct fw_request *fw_req) +{ + kref_put(&fw_req->kref, fw_req_release); +} + +/* Caller must call put_fw_req() after using struct fw_request */ +static struct fw_request *get_fw_req(struct fw_download *fw_download, + u8 firmware_id) +{ + struct fw_request *fw_req; + + mutex_lock(&fw_download->mutex); + + list_for_each_entry(fw_req, &fw_download->fw_requests, node) { + if (fw_req->firmware_id == firmware_id) { + kref_get(&fw_req->kref); + goto unlock; + } + } + + fw_req = NULL; + +unlock: + mutex_unlock(&fw_download->mutex); + + return fw_req; +} + +static void free_firmware(struct fw_download *fw_download, + struct fw_request *fw_req) +{ + /* Already disabled from timeout handlers */ + if (fw_req->disabled) + return; + + mutex_lock(&fw_download->mutex); + list_del(&fw_req->node); + mutex_unlock(&fw_download->mutex); + + fw_req->disabled = true; + put_fw_req(fw_req); +} + +static void fw_request_timedout(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct fw_request *fw_req = container_of(dwork, struct fw_request, dwork); + struct fw_download *fw_download = fw_req->fw_download; + + dev_err(fw_download->parent, + "Timed out waiting for fetch / release firmware requests: %u\n", + fw_req->firmware_id); + + fw_req->timedout = true; + free_firmware(fw_download, fw_req); +} + +static int exceeds_release_timeout(struct fw_request *fw_req) +{ + struct fw_download *fw_download = fw_req->fw_download; + + if (time_before(jiffies, fw_req->release_timeout_j)) + return 0; + + dev_err(fw_download->parent, + "Firmware download didn't finish in time, abort: %d\n", + fw_req->firmware_id); + + fw_req->timedout = true; + free_firmware(fw_download, fw_req); + + return -ETIMEDOUT; +} + +/* This returns path of the firmware blob on the disk */ +static struct fw_request *find_firmware(struct fw_download *fw_download, + const char *tag) +{ + struct gb_interface *intf = fw_download->connection->bundle->intf; + struct fw_request *fw_req; + int ret, req_count; + + fw_req = kzalloc(sizeof(*fw_req), GFP_KERNEL); + if (!fw_req) + return ERR_PTR(-ENOMEM); + + /* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */ + ret = ida_simple_get(&fw_download->id_map, 1, 256, GFP_KERNEL); + if (ret < 0) { + dev_err(fw_download->parent, + "failed to allocate firmware id (%d)\n", ret); + goto err_free_req; + } + fw_req->firmware_id = ret; + + snprintf(fw_req->name, sizeof(fw_req->name), + FW_NAME_PREFIX "%08x_%08x_%08x_%08x_%s.tftf", + intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, + intf->vendor_id, intf->product_id, tag); + + dev_info(fw_download->parent, "Requested firmware package '%s'\n", + fw_req->name); + + ret = request_firmware(&fw_req->fw, fw_req->name, fw_download->parent); + if (ret) { + dev_err(fw_download->parent, + "firmware request failed for %s (%d)\n", fw_req->name, + ret); + goto err_free_id; + } + + fw_req->fw_download = fw_download; + kref_init(&fw_req->kref); + + mutex_lock(&fw_download->mutex); + list_add(&fw_req->node, &fw_download->fw_requests); + mutex_unlock(&fw_download->mutex); + + /* Timeout, in jiffies, within which firmware should get loaded */ + req_count = DIV_ROUND_UP(fw_req->fw->size, MIN_FETCH_SIZE); + fw_req->release_timeout_j = jiffies + req_count * NEXT_REQ_TIMEOUT_J; + + INIT_DELAYED_WORK(&fw_req->dwork, fw_request_timedout); + schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J); + + return fw_req; + +err_free_id: + ida_simple_remove(&fw_download->id_map, fw_req->firmware_id); +err_free_req: + kfree(fw_req); + + return ERR_PTR(ret); +} + +static int fw_download_find_firmware(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_download *fw_download = gb_connection_get_data(connection); + struct gb_fw_download_find_firmware_request *request; + struct gb_fw_download_find_firmware_response *response; + struct fw_request *fw_req; + const char *tag; + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_download->parent, + "illegal size of find firmware request (%zu != %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + tag = (const char *)request->firmware_tag; + + /* firmware_tag must be null-terminated */ + if (strnlen(tag, GB_FIRMWARE_TAG_MAX_SIZE) == GB_FIRMWARE_TAG_MAX_SIZE) { + dev_err(fw_download->parent, + "firmware-tag is not null-terminated\n"); + return -EINVAL; + } + + fw_req = find_firmware(fw_download, tag); + if (IS_ERR(fw_req)) + return PTR_ERR(fw_req); + + if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) { + dev_err(fw_download->parent, "error allocating response\n"); + free_firmware(fw_download, fw_req); + return -ENOMEM; + } + + response = op->response->payload; + response->firmware_id = fw_req->firmware_id; + response->size = cpu_to_le32(fw_req->fw->size); + + dev_dbg(fw_download->parent, + "firmware size is %zu bytes\n", fw_req->fw->size); + + return 0; +} + +static int fw_download_fetch_firmware(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_download *fw_download = gb_connection_get_data(connection); + struct gb_fw_download_fetch_firmware_request *request; + struct gb_fw_download_fetch_firmware_response *response; + struct fw_request *fw_req; + const struct firmware *fw; + unsigned int offset, size; + u8 firmware_id; + int ret = 0; + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_download->parent, + "Illegal size of fetch firmware request (%zu %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + offset = le32_to_cpu(request->offset); + size = le32_to_cpu(request->size); + firmware_id = request->firmware_id; + + fw_req = get_fw_req(fw_download, firmware_id); + if (!fw_req) { + dev_err(fw_download->parent, + "firmware not available for id: %02u\n", firmware_id); + return -EINVAL; + } + + /* Make sure work handler isn't running in parallel */ + cancel_delayed_work_sync(&fw_req->dwork); + + /* We timed-out before reaching here ? */ + if (fw_req->disabled) { + ret = -ETIMEDOUT; + goto put_fw; + } + + /* + * Firmware download must finish within a limited time interval. If it + * doesn't, then we might have a buggy Module on the other side. Abort + * download. + */ + ret = exceeds_release_timeout(fw_req); + if (ret) + goto put_fw; + + fw = fw_req->fw; + + if (offset >= fw->size || size > fw->size - offset) { + dev_err(fw_download->parent, + "bad fetch firmware request (offs = %u, size = %u)\n", + offset, size); + ret = -EINVAL; + goto put_fw; + } + + if (!gb_operation_response_alloc(op, sizeof(*response) + size, + GFP_KERNEL)) { + dev_err(fw_download->parent, + "error allocating fetch firmware response\n"); + ret = -ENOMEM; + goto put_fw; + } + + response = op->response->payload; + memcpy(response->data, fw->data + offset, size); + + dev_dbg(fw_download->parent, + "responding with firmware (offs = %u, size = %u)\n", offset, + size); + + /* Refresh timeout */ + schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J); + +put_fw: + put_fw_req(fw_req); + + return ret; +} + +static int fw_download_release_firmware(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_download *fw_download = gb_connection_get_data(connection); + struct gb_fw_download_release_firmware_request *request; + struct fw_request *fw_req; + u8 firmware_id; + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_download->parent, + "Illegal size of release firmware request (%zu %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + firmware_id = request->firmware_id; + + fw_req = get_fw_req(fw_download, firmware_id); + if (!fw_req) { + dev_err(fw_download->parent, + "firmware not available for id: %02u\n", firmware_id); + return -EINVAL; + } + + cancel_delayed_work_sync(&fw_req->dwork); + + free_firmware(fw_download, fw_req); + put_fw_req(fw_req); + + dev_dbg(fw_download->parent, "release firmware\n"); + + return 0; +} + +int gb_fw_download_request_handler(struct gb_operation *op) +{ + u8 type = op->type; + + switch (type) { + case GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE: + return fw_download_find_firmware(op); + case GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE: + return fw_download_fetch_firmware(op); + case GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE: + return fw_download_release_firmware(op); + default: + dev_err(&op->connection->bundle->dev, + "unsupported request: %u\n", type); + return -EINVAL; + } +} + +int gb_fw_download_connection_init(struct gb_connection *connection) +{ + struct fw_download *fw_download; + int ret; + + if (!connection) + return 0; + + fw_download = kzalloc(sizeof(*fw_download), GFP_KERNEL); + if (!fw_download) + return -ENOMEM; + + fw_download->parent = &connection->bundle->dev; + INIT_LIST_HEAD(&fw_download->fw_requests); + ida_init(&fw_download->id_map); + gb_connection_set_data(connection, fw_download); + fw_download->connection = connection; + mutex_init(&fw_download->mutex); + + ret = gb_connection_enable(connection); + if (ret) + goto err_destroy_id_map; + + return 0; + +err_destroy_id_map: + ida_destroy(&fw_download->id_map); + kfree(fw_download); + + return ret; +} + +void gb_fw_download_connection_exit(struct gb_connection *connection) +{ + struct fw_download *fw_download; + struct fw_request *fw_req, *tmp; + + if (!connection) + return; + + fw_download = gb_connection_get_data(connection); + gb_connection_disable(fw_download->connection); + + /* + * Make sure we have a reference to the pending requests, before they + * are freed from the timeout handler. + */ + mutex_lock(&fw_download->mutex); + list_for_each_entry(fw_req, &fw_download->fw_requests, node) + kref_get(&fw_req->kref); + mutex_unlock(&fw_download->mutex); + + /* Release pending firmware packages */ + list_for_each_entry_safe(fw_req, tmp, &fw_download->fw_requests, node) { + cancel_delayed_work_sync(&fw_req->dwork); + free_firmware(fw_download, fw_req); + put_fw_req(fw_req); + } + + ida_destroy(&fw_download->id_map); + kfree(fw_download); +} diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c new file mode 100644 index 000000000000..3cd6cf0a656b --- /dev/null +++ b/drivers/staging/greybus/fw-management.c @@ -0,0 +1,721 @@ +/* + * Greybus Firmware Management Protocol Driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "firmware.h" +#include "greybus_firmware.h" +#include "greybus.h" + +#define FW_MGMT_TIMEOUT_MS 1000 + +struct fw_mgmt { + struct device *parent; + struct gb_connection *connection; + struct kref kref; + struct list_head node; + + /* Common id-map for interface and backend firmware requests */ + struct ida id_map; + struct mutex mutex; + struct completion completion; + struct cdev cdev; + struct device *class_device; + dev_t dev_num; + unsigned int timeout_jiffies; + bool disabled; /* connection getting disabled */ + + /* Interface Firmware specific fields */ + bool mode_switch_started; + bool intf_fw_loaded; + u8 intf_fw_request_id; + u8 intf_fw_status; + u16 intf_fw_major; + u16 intf_fw_minor; + + /* Backend Firmware specific fields */ + u8 backend_fw_request_id; + u8 backend_fw_status; +}; + +/* + * Number of minor devices this driver supports. + * There will be exactly one required per Interface. + */ +#define NUM_MINORS U8_MAX + +static struct class *fw_mgmt_class; +static dev_t fw_mgmt_dev_num; +static DEFINE_IDA(fw_mgmt_minors_map); +static LIST_HEAD(fw_mgmt_list); +static DEFINE_MUTEX(list_mutex); + +static void fw_mgmt_kref_release(struct kref *kref) +{ + struct fw_mgmt *fw_mgmt = container_of(kref, struct fw_mgmt, kref); + + ida_destroy(&fw_mgmt->id_map); + kfree(fw_mgmt); +} + +/* + * All users of fw_mgmt take a reference (from within list_mutex lock), before + * they get a pointer to play with. And the structure will be freed only after + * the last user has put the reference to it. + */ +static void put_fw_mgmt(struct fw_mgmt *fw_mgmt) +{ + kref_put(&fw_mgmt->kref, fw_mgmt_kref_release); +} + +/* Caller must call put_fw_mgmt() after using struct fw_mgmt */ +static struct fw_mgmt *get_fw_mgmt(struct cdev *cdev) +{ + struct fw_mgmt *fw_mgmt; + + mutex_lock(&list_mutex); + + list_for_each_entry(fw_mgmt, &fw_mgmt_list, node) { + if (&fw_mgmt->cdev == cdev) { + kref_get(&fw_mgmt->kref); + goto unlock; + } + } + + fw_mgmt = NULL; + +unlock: + mutex_unlock(&list_mutex); + + return fw_mgmt; +} + +static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt, + struct fw_mgmt_ioc_get_intf_version *fw_info) +{ + struct gb_connection *connection = fw_mgmt->connection; + struct gb_fw_mgmt_interface_fw_version_response response; + int ret; + + ret = gb_operation_sync(connection, + GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(fw_mgmt->parent, + "failed to get interface firmware version (%d)\n", ret); + return ret; + } + + fw_info->major = le16_to_cpu(response.major); + fw_info->minor = le16_to_cpu(response.minor); + + strncpy(fw_info->firmware_tag, response.firmware_tag, + GB_FIRMWARE_TAG_MAX_SIZE); + + /* + * The firmware-tag should be NULL terminated, otherwise throw error but + * don't fail. + */ + if (fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') { + dev_err(fw_mgmt->parent, + "fw-version: firmware-tag is not NULL terminated\n"); + fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] = '\0'; + } + + return 0; +} + +static int fw_mgmt_load_and_validate_operation(struct fw_mgmt *fw_mgmt, + u8 load_method, const char *tag) +{ + struct gb_fw_mgmt_load_and_validate_fw_request request; + int ret; + + if (load_method != GB_FW_LOAD_METHOD_UNIPRO && + load_method != GB_FW_LOAD_METHOD_INTERNAL) { + dev_err(fw_mgmt->parent, + "invalid load-method (%d)\n", load_method); + return -EINVAL; + } + + request.load_method = load_method; + strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_SIZE); + + /* + * The firmware-tag should be NULL terminated, otherwise throw error and + * fail. + */ + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') { + dev_err(fw_mgmt->parent, "load-and-validate: firmware-tag is not NULL terminated\n"); + return -EINVAL; + } + + /* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */ + ret = ida_simple_get(&fw_mgmt->id_map, 1, 256, GFP_KERNEL); + if (ret < 0) { + dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n", + ret); + return ret; + } + + fw_mgmt->intf_fw_request_id = ret; + fw_mgmt->intf_fw_loaded = false; + request.request_id = ret; + + ret = gb_operation_sync(fw_mgmt->connection, + GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW, &request, + sizeof(request), NULL, 0); + if (ret) { + ida_simple_remove(&fw_mgmt->id_map, + fw_mgmt->intf_fw_request_id); + fw_mgmt->intf_fw_request_id = 0; + dev_err(fw_mgmt->parent, + "load and validate firmware request failed (%d)\n", + ret); + return ret; + } + + return 0; +} + +static int fw_mgmt_interface_fw_loaded_operation(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection); + struct gb_fw_mgmt_loaded_fw_request *request; + + /* No pending load and validate request ? */ + if (!fw_mgmt->intf_fw_request_id) { + dev_err(fw_mgmt->parent, + "unexpected firmware loaded request received\n"); + return -ENODEV; + } + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_mgmt->parent, "illegal size of firmware loaded request (%zu != %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + /* Invalid request-id ? */ + if (request->request_id != fw_mgmt->intf_fw_request_id) { + dev_err(fw_mgmt->parent, "invalid request id for firmware loaded request (%02u != %02u)\n", + fw_mgmt->intf_fw_request_id, request->request_id); + return -ENODEV; + } + + ida_simple_remove(&fw_mgmt->id_map, fw_mgmt->intf_fw_request_id); + fw_mgmt->intf_fw_request_id = 0; + fw_mgmt->intf_fw_status = request->status; + fw_mgmt->intf_fw_major = le16_to_cpu(request->major); + fw_mgmt->intf_fw_minor = le16_to_cpu(request->minor); + + if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_FAILED) + dev_err(fw_mgmt->parent, + "failed to load interface firmware, status:%02x\n", + fw_mgmt->intf_fw_status); + else if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_VALIDATION_FAILED) + dev_err(fw_mgmt->parent, + "failed to validate interface firmware, status:%02x\n", + fw_mgmt->intf_fw_status); + else + fw_mgmt->intf_fw_loaded = true; + + complete(&fw_mgmt->completion); + + return 0; +} + +static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt, + struct fw_mgmt_ioc_get_backend_version *fw_info) +{ + struct gb_connection *connection = fw_mgmt->connection; + struct gb_fw_mgmt_backend_fw_version_request request; + struct gb_fw_mgmt_backend_fw_version_response response; + int ret; + + strncpy(request.firmware_tag, fw_info->firmware_tag, + GB_FIRMWARE_TAG_MAX_SIZE); + + /* + * The firmware-tag should be NULL terminated, otherwise throw error and + * fail. + */ + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') { + dev_err(fw_mgmt->parent, "backend-version: firmware-tag is not NULL terminated\n"); + return -EINVAL; + } + + ret = gb_operation_sync(connection, + GB_FW_MGMT_TYPE_BACKEND_FW_VERSION, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(fw_mgmt->parent, "failed to get version of %s backend firmware (%d)\n", + fw_info->firmware_tag, ret); + return ret; + } + + fw_info->status = response.status; + + /* Reset version as that should be non-zero only for success case */ + fw_info->major = 0; + fw_info->minor = 0; + + switch (fw_info->status) { + case GB_FW_BACKEND_VERSION_STATUS_SUCCESS: + fw_info->major = le16_to_cpu(response.major); + fw_info->minor = le16_to_cpu(response.minor); + break; + case GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE: + case GB_FW_BACKEND_VERSION_STATUS_RETRY: + break; + case GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED: + dev_err(fw_mgmt->parent, + "Firmware with tag %s is not supported by Interface\n", + fw_info->firmware_tag); + break; + default: + dev_err(fw_mgmt->parent, "Invalid status received: %u\n", + fw_info->status); + } + + return 0; +} + +static int fw_mgmt_backend_fw_update_operation(struct fw_mgmt *fw_mgmt, + char *tag) +{ + struct gb_fw_mgmt_backend_fw_update_request request; + int ret; + + strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_SIZE); + + /* + * The firmware-tag should be NULL terminated, otherwise throw error and + * fail. + */ + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') { + dev_err(fw_mgmt->parent, "backend-update: firmware-tag is not NULL terminated\n"); + return -EINVAL; + } + + /* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */ + ret = ida_simple_get(&fw_mgmt->id_map, 1, 256, GFP_KERNEL); + if (ret < 0) { + dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n", + ret); + return ret; + } + + fw_mgmt->backend_fw_request_id = ret; + request.request_id = ret; + + ret = gb_operation_sync(fw_mgmt->connection, + GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE, &request, + sizeof(request), NULL, 0); + if (ret) { + ida_simple_remove(&fw_mgmt->id_map, + fw_mgmt->backend_fw_request_id); + fw_mgmt->backend_fw_request_id = 0; + dev_err(fw_mgmt->parent, + "backend %s firmware update request failed (%d)\n", tag, + ret); + return ret; + } + + return 0; +} + +static int fw_mgmt_backend_fw_updated_operation(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection); + struct gb_fw_mgmt_backend_fw_updated_request *request; + + /* No pending load and validate request ? */ + if (!fw_mgmt->backend_fw_request_id) { + dev_err(fw_mgmt->parent, "unexpected backend firmware updated request received\n"); + return -ENODEV; + } + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_mgmt->parent, "illegal size of backend firmware updated request (%zu != %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + /* Invalid request-id ? */ + if (request->request_id != fw_mgmt->backend_fw_request_id) { + dev_err(fw_mgmt->parent, "invalid request id for backend firmware updated request (%02u != %02u)\n", + fw_mgmt->backend_fw_request_id, request->request_id); + return -ENODEV; + } + + ida_simple_remove(&fw_mgmt->id_map, fw_mgmt->backend_fw_request_id); + fw_mgmt->backend_fw_request_id = 0; + fw_mgmt->backend_fw_status = request->status; + + if ((fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_SUCCESS) && + (fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_RETRY)) + dev_err(fw_mgmt->parent, + "failed to load backend firmware: %02x\n", + fw_mgmt->backend_fw_status); + + complete(&fw_mgmt->completion); + + return 0; +} + +/* Char device fops */ + +static int fw_mgmt_open(struct inode *inode, struct file *file) +{ + struct fw_mgmt *fw_mgmt = get_fw_mgmt(inode->i_cdev); + + /* fw_mgmt structure can't get freed until file descriptor is closed */ + if (fw_mgmt) { + file->private_data = fw_mgmt; + return 0; + } + + return -ENODEV; +} + +static int fw_mgmt_release(struct inode *inode, struct file *file) +{ + struct fw_mgmt *fw_mgmt = file->private_data; + + put_fw_mgmt(fw_mgmt); + return 0; +} + +static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, + void __user *buf) +{ + struct fw_mgmt_ioc_get_intf_version intf_fw_info; + struct fw_mgmt_ioc_get_backend_version backend_fw_info; + struct fw_mgmt_ioc_intf_load_and_validate intf_load; + struct fw_mgmt_ioc_backend_fw_update backend_update; + unsigned int timeout; + int ret; + + /* Reject any operations after mode-switch has started */ + if (fw_mgmt->mode_switch_started) + return -EBUSY; + + switch (cmd) { + case FW_MGMT_IOC_GET_INTF_FW: + ret = fw_mgmt_interface_fw_version_operation(fw_mgmt, + &intf_fw_info); + if (ret) + return ret; + + if (copy_to_user(buf, &intf_fw_info, sizeof(intf_fw_info))) + return -EFAULT; + + return 0; + case FW_MGMT_IOC_GET_BACKEND_FW: + if (copy_from_user(&backend_fw_info, buf, + sizeof(backend_fw_info))) + return -EFAULT; + + ret = fw_mgmt_backend_fw_version_operation(fw_mgmt, + &backend_fw_info); + if (ret) + return ret; + + if (copy_to_user(buf, &backend_fw_info, + sizeof(backend_fw_info))) + return -EFAULT; + + return 0; + case FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE: + if (copy_from_user(&intf_load, buf, sizeof(intf_load))) + return -EFAULT; + + ret = fw_mgmt_load_and_validate_operation(fw_mgmt, + intf_load.load_method, intf_load.firmware_tag); + if (ret) + return ret; + + if (!wait_for_completion_timeout(&fw_mgmt->completion, + fw_mgmt->timeout_jiffies)) { + dev_err(fw_mgmt->parent, "timed out waiting for firmware load and validation to finish\n"); + return -ETIMEDOUT; + } + + intf_load.status = fw_mgmt->intf_fw_status; + intf_load.major = fw_mgmt->intf_fw_major; + intf_load.minor = fw_mgmt->intf_fw_minor; + + if (copy_to_user(buf, &intf_load, sizeof(intf_load))) + return -EFAULT; + + return 0; + case FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE: + if (copy_from_user(&backend_update, buf, + sizeof(backend_update))) + return -EFAULT; + + ret = fw_mgmt_backend_fw_update_operation(fw_mgmt, + backend_update.firmware_tag); + if (ret) + return ret; + + if (!wait_for_completion_timeout(&fw_mgmt->completion, + fw_mgmt->timeout_jiffies)) { + dev_err(fw_mgmt->parent, "timed out waiting for backend firmware update to finish\n"); + return -ETIMEDOUT; + } + + backend_update.status = fw_mgmt->backend_fw_status; + + if (copy_to_user(buf, &backend_update, sizeof(backend_update))) + return -EFAULT; + + return 0; + case FW_MGMT_IOC_SET_TIMEOUT_MS: + if (get_user(timeout, (unsigned int __user *)buf)) + return -EFAULT; + + if (!timeout) { + dev_err(fw_mgmt->parent, "timeout can't be zero\n"); + return -EINVAL; + } + + fw_mgmt->timeout_jiffies = msecs_to_jiffies(timeout); + + return 0; + case FW_MGMT_IOC_MODE_SWITCH: + if (!fw_mgmt->intf_fw_loaded) { + dev_err(fw_mgmt->parent, + "Firmware not loaded for mode-switch\n"); + return -EPERM; + } + + /* + * Disallow new ioctls as the fw-core bundle driver is going to + * get disconnected soon and the character device will get + * removed. + */ + fw_mgmt->mode_switch_started = true; + + ret = gb_interface_request_mode_switch(fw_mgmt->connection->intf); + if (ret) { + dev_err(fw_mgmt->parent, "Mode-switch failed: %d\n", + ret); + fw_mgmt->mode_switch_started = false; + return ret; + } + + return 0; + default: + return -ENOTTY; + } +} + +static long fw_mgmt_ioctl_unlocked(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct fw_mgmt *fw_mgmt = file->private_data; + struct gb_bundle *bundle = fw_mgmt->connection->bundle; + int ret = -ENODEV; + + /* + * Serialize ioctls. + * + * We don't want the user to do few operations in parallel. For example, + * updating Interface firmware in parallel for the same Interface. There + * is no need to do things in parallel for speed and we can avoid having + * complicated code for now. + * + * This is also used to protect ->disabled, which is used to check if + * the connection is getting disconnected, so that we don't start any + * new operations. + */ + mutex_lock(&fw_mgmt->mutex); + if (!fw_mgmt->disabled) { + ret = gb_pm_runtime_get_sync(bundle); + if (!ret) { + ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg); + gb_pm_runtime_put_autosuspend(bundle); + } + } + mutex_unlock(&fw_mgmt->mutex); + + return ret; +} + +static const struct file_operations fw_mgmt_fops = { + .owner = THIS_MODULE, + .open = fw_mgmt_open, + .release = fw_mgmt_release, + .unlocked_ioctl = fw_mgmt_ioctl_unlocked, +}; + +int gb_fw_mgmt_request_handler(struct gb_operation *op) +{ + u8 type = op->type; + + switch (type) { + case GB_FW_MGMT_TYPE_LOADED_FW: + return fw_mgmt_interface_fw_loaded_operation(op); + case GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED: + return fw_mgmt_backend_fw_updated_operation(op); + default: + dev_err(&op->connection->bundle->dev, + "unsupported request: %u\n", type); + return -EINVAL; + } +} + +int gb_fw_mgmt_connection_init(struct gb_connection *connection) +{ + struct fw_mgmt *fw_mgmt; + int ret, minor; + + if (!connection) + return 0; + + fw_mgmt = kzalloc(sizeof(*fw_mgmt), GFP_KERNEL); + if (!fw_mgmt) + return -ENOMEM; + + fw_mgmt->parent = &connection->bundle->dev; + fw_mgmt->timeout_jiffies = msecs_to_jiffies(FW_MGMT_TIMEOUT_MS); + fw_mgmt->connection = connection; + + gb_connection_set_data(connection, fw_mgmt); + init_completion(&fw_mgmt->completion); + ida_init(&fw_mgmt->id_map); + mutex_init(&fw_mgmt->mutex); + kref_init(&fw_mgmt->kref); + + mutex_lock(&list_mutex); + list_add(&fw_mgmt->node, &fw_mgmt_list); + mutex_unlock(&list_mutex); + + ret = gb_connection_enable(connection); + if (ret) + goto err_list_del; + + minor = ida_simple_get(&fw_mgmt_minors_map, 0, NUM_MINORS, GFP_KERNEL); + if (minor < 0) { + ret = minor; + goto err_connection_disable; + } + + /* Add a char device to allow userspace to interact with fw-mgmt */ + fw_mgmt->dev_num = MKDEV(MAJOR(fw_mgmt_dev_num), minor); + cdev_init(&fw_mgmt->cdev, &fw_mgmt_fops); + + ret = cdev_add(&fw_mgmt->cdev, fw_mgmt->dev_num, 1); + if (ret) + goto err_remove_ida; + + /* Add a soft link to the previously added char-dev within the bundle */ + fw_mgmt->class_device = device_create(fw_mgmt_class, fw_mgmt->parent, + fw_mgmt->dev_num, NULL, + "gb-fw-mgmt-%d", minor); + if (IS_ERR(fw_mgmt->class_device)) { + ret = PTR_ERR(fw_mgmt->class_device); + goto err_del_cdev; + } + + return 0; + +err_del_cdev: + cdev_del(&fw_mgmt->cdev); +err_remove_ida: + ida_simple_remove(&fw_mgmt_minors_map, minor); +err_connection_disable: + gb_connection_disable(connection); +err_list_del: + mutex_lock(&list_mutex); + list_del(&fw_mgmt->node); + mutex_unlock(&list_mutex); + + put_fw_mgmt(fw_mgmt); + + return ret; +} + +void gb_fw_mgmt_connection_exit(struct gb_connection *connection) +{ + struct fw_mgmt *fw_mgmt; + + if (!connection) + return; + + fw_mgmt = gb_connection_get_data(connection); + + device_destroy(fw_mgmt_class, fw_mgmt->dev_num); + cdev_del(&fw_mgmt->cdev); + ida_simple_remove(&fw_mgmt_minors_map, MINOR(fw_mgmt->dev_num)); + + /* + * Disallow any new ioctl operations on the char device and wait for + * existing ones to finish. + */ + mutex_lock(&fw_mgmt->mutex); + fw_mgmt->disabled = true; + mutex_unlock(&fw_mgmt->mutex); + + /* All pending greybus operations should have finished by now */ + gb_connection_disable(fw_mgmt->connection); + + /* Disallow new users to get access to the fw_mgmt structure */ + mutex_lock(&list_mutex); + list_del(&fw_mgmt->node); + mutex_unlock(&list_mutex); + + /* + * All current users of fw_mgmt would have taken a reference to it by + * now, we can drop our reference and wait the last user will get + * fw_mgmt freed. + */ + put_fw_mgmt(fw_mgmt); +} + +int fw_mgmt_init(void) +{ + int ret; + + fw_mgmt_class = class_create(THIS_MODULE, "gb_fw_mgmt"); + if (IS_ERR(fw_mgmt_class)) + return PTR_ERR(fw_mgmt_class); + + ret = alloc_chrdev_region(&fw_mgmt_dev_num, 0, NUM_MINORS, + "gb_fw_mgmt"); + if (ret) + goto err_remove_class; + + return 0; + +err_remove_class: + class_destroy(fw_mgmt_class); + return ret; +} + +void fw_mgmt_exit(void) +{ + unregister_chrdev_region(fw_mgmt_dev_num, NUM_MINORS); + class_destroy(fw_mgmt_class); + ida_destroy(&fw_mgmt_minors_map); +} diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h new file mode 100644 index 000000000000..d45dabc5b367 --- /dev/null +++ b/drivers/staging/greybus/gb-camera.h @@ -0,0 +1,127 @@ +/* + * Greybus Camera protocol driver. + * + * Copyright 2015 Google Inc. + * + * Released under the GPLv2 only. + */ +#ifndef __GB_CAMERA_H +#define __GB_CAMERA_H + +#include + +/* Input flags need to be set from the caller */ +#define GB_CAMERA_IN_FLAG_TEST (1 << 0) +/* Output flags returned */ +#define GB_CAMERA_OUT_FLAG_ADJUSTED (1 << 0) + +/** + * struct gb_camera_stream - Represents greybus camera stream. + * @width: Stream width in pixels. + * @height: Stream height in pixels. + * @pixel_code: Media bus pixel code. + * @vc: MIPI CSI virtual channel. + * @dt: MIPI CSI data types. Most formats use a single data type, in which case + * the second element will be ignored. + * @max_size: Maximum size of a frame in bytes. The camera module guarantees + * that all data between the Frame Start and Frame End packet for + * the associated virtual channel and data type(s) will not exceed + * this size. + */ +struct gb_camera_stream { + unsigned int width; + unsigned int height; + enum v4l2_mbus_pixelcode pixel_code; + unsigned int vc; + unsigned int dt[2]; + unsigned int max_size; +}; + +/** + * struct gb_camera_csi_params - CSI configuration parameters + * @num_lanes: number of CSI data lanes + * @clk_freq: CSI clock frequency in Hz + */ +struct gb_camera_csi_params { + unsigned int num_lanes; + unsigned int clk_freq; +}; + +/** + * struct gb_camera_ops - Greybus camera operations, used by the Greybus camera + * driver to expose operations to the host camera driver. + * @capabilities: Retrieve camera capabilities and store them in the buffer + * 'buf' capabilities. The buffer maximum size is specified by + * the caller in the 'size' parameter, and the effective + * capabilities size is returned from the function. If the buffer + * size is too small to hold the capabilities an error is + * returned and the buffer is left untouched. + * + * @configure_streams: Negotiate configuration and prepare the module for video + * capture. The caller specifies the number of streams it + * requests in the 'nstreams' argument and the associated + * streams configurations in the 'streams' argument. The + * GB_CAMERA_IN_FLAG_TEST 'flag' can be set to test a + * configuration without applying it, otherwise the + * configuration is applied by the module. The module can + * decide to modify the requested configuration, including + * using a different number of streams. In that case the + * modified configuration won't be applied, the + * GB_CAMERA_OUT_FLAG_ADJUSTED 'flag' will be set upon + * return, and the modified configuration and number of + * streams stored in 'streams' and 'array'. The module + * returns its CSI-2 bus parameters in the 'csi_params' + * structure in all cases. + * + * @capture: Submit a capture request. The supplied 'request_id' must be unique + * and higher than the IDs of all the previously submitted requests. + * The 'streams' argument specifies which streams are affected by the + * request in the form of a bitmask, with bits corresponding to the + * configured streams indexes. If the request contains settings, the + * 'settings' argument points to the settings buffer and its size is + * specified by the 'settings_size' argument. Otherwise the 'settings' + * argument should be set to NULL and 'settings_size' to 0. + * + * @flush: Flush the capture requests queue. Return the ID of the last request + * that will processed by the device before it stops transmitting video + * frames. All queued capture requests with IDs higher than the returned + * ID will be dropped without being processed. + */ +struct gb_camera_ops { + ssize_t (*capabilities)(void *priv, char *buf, size_t len); + int (*configure_streams)(void *priv, unsigned int *nstreams, + unsigned int *flags, struct gb_camera_stream *streams, + struct gb_camera_csi_params *csi_params); + int (*capture)(void *priv, u32 request_id, + unsigned int streams, unsigned int num_frames, + size_t settings_size, const void *settings); + int (*flush)(void *priv, u32 *request_id); +}; + +/** + * struct gb_camera_module - Represents greybus camera module. + * @priv: Module private data, passed to all camera operations. + * @ops: Greybus camera operation callbacks. + * @interface_id: Interface id of the module. + * @refcount: Reference counting object. + * @release: Module release function. + * @list: List entry in the camera modules list. + */ +struct gb_camera_module { + void *priv; + const struct gb_camera_ops *ops; + + unsigned int interface_id; + struct kref refcount; + void (*release)(struct kref *kref); + struct list_head list; /* Global list */ +}; + +#define gb_camera_call(f, op, args...) \ + (!(f) ? -ENODEV : (((f)->ops->op) ? \ + (f)->ops->op((f)->priv, ##args) : -ENOIOCTLCMD)) + +int gb_camera_register(struct gb_camera_module *module); +int gb_camera_unregister(struct gb_camera_module *module); + +#endif /* __GB_CAMERA_H */ diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c new file mode 100644 index 000000000000..bcde7c9a0f17 --- /dev/null +++ b/drivers/staging/greybus/gbphy.c @@ -0,0 +1,360 @@ +/* + * Greybus Bridged-Phy Bus driver + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "gbphy.h" + +#define GB_GBPHY_AUTOSUSPEND_MS 3000 + +struct gbphy_host { + struct gb_bundle *bundle; + struct list_head devices; +}; + +static DEFINE_IDA(gbphy_id); + +static ssize_t protocol_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + + return sprintf(buf, "0x%02x\n", gbphy_dev->cport_desc->protocol_id); +} +static DEVICE_ATTR_RO(protocol_id); + +static struct attribute *gbphy_dev_attrs[] = { + &dev_attr_protocol_id.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(gbphy_dev); + +static void gbphy_dev_release(struct device *dev) +{ + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + + ida_simple_remove(&gbphy_id, gbphy_dev->id); + kfree(gbphy_dev); +} + +#ifdef CONFIG_PM +static int gb_gbphy_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + return 0; +} +#endif + +static const struct dev_pm_ops gb_gbphy_pm_ops = { + SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, + pm_generic_runtime_resume, + gb_gbphy_idle) +}; + +static struct device_type greybus_gbphy_dev_type = { + .name = "gbphy_device", + .release = gbphy_dev_release, + .pm = &gb_gbphy_pm_ops, +}; + +static int gbphy_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + struct greybus_descriptor_cport *cport_desc = gbphy_dev->cport_desc; + struct gb_bundle *bundle = gbphy_dev->bundle; + struct gb_interface *intf = bundle->intf; + struct gb_module *module = intf->module; + struct gb_host_device *hd = intf->hd; + + if (add_uevent_var(env, "BUS=%u", hd->bus_id)) + return -ENOMEM; + if (add_uevent_var(env, "MODULE=%u", module->module_id)) + return -ENOMEM; + if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) + return -ENOMEM; + if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", + intf->vendor_id, intf->product_id)) + return -ENOMEM; + if (add_uevent_var(env, "BUNDLE=%u", gbphy_dev->bundle->id)) + return -ENOMEM; + if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) + return -ENOMEM; + if (add_uevent_var(env, "GBPHY=%u", gbphy_dev->id)) + return -ENOMEM; + if (add_uevent_var(env, "PROTOCOL_ID=%02x", cport_desc->protocol_id)) + return -ENOMEM; + + return 0; +} + +static const struct gbphy_device_id * +gbphy_dev_match_id(struct gbphy_device *gbphy_dev, struct gbphy_driver *gbphy_drv) +{ + const struct gbphy_device_id *id = gbphy_drv->id_table; + + if (!id) + return NULL; + + for (; id->protocol_id; id++) + if (id->protocol_id == gbphy_dev->cport_desc->protocol_id) + return id; + + return NULL; +} + +static int gbphy_dev_match(struct device *dev, struct device_driver *drv) +{ + struct gbphy_driver *gbphy_drv = to_gbphy_driver(drv); + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + const struct gbphy_device_id *id; + + id = gbphy_dev_match_id(gbphy_dev, gbphy_drv); + if (id) + return 1; + + return 0; +} + +static int gbphy_dev_probe(struct device *dev) +{ + struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver); + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + const struct gbphy_device_id *id; + int ret; + + id = gbphy_dev_match_id(gbphy_dev, gbphy_drv); + if (!id) + return -ENODEV; + + /* for old kernels we need get_sync to resume parent devices */ + ret = gb_pm_runtime_get_sync(gbphy_dev->bundle); + if (ret < 0) + return ret; + + pm_runtime_set_autosuspend_delay(dev, GB_GBPHY_AUTOSUSPEND_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + /* + * Drivers should call put on the gbphy dev before returning + * from probe if they support runtime pm. + */ + ret = gbphy_drv->probe(gbphy_dev, id); + if (ret) { + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + pm_runtime_dont_use_autosuspend(dev); + } + + gb_pm_runtime_put_autosuspend(gbphy_dev->bundle); + + return ret; +} + +static int gbphy_dev_remove(struct device *dev) +{ + struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver); + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + + gbphy_drv->remove(gbphy_dev); + + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + pm_runtime_dont_use_autosuspend(dev); + + return 0; +} + +static struct bus_type gbphy_bus_type = { + .name = "gbphy", + .match = gbphy_dev_match, + .probe = gbphy_dev_probe, + .remove = gbphy_dev_remove, + .uevent = gbphy_dev_uevent, +}; + +int gb_gbphy_register_driver(struct gbphy_driver *driver, + struct module *owner, const char *mod_name) +{ + int retval; + + if (greybus_disabled()) + return -ENODEV; + + driver->driver.bus = &gbphy_bus_type; + driver->driver.name = driver->name; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + + retval = driver_register(&driver->driver); + if (retval) + return retval; + + pr_info("registered new driver %s\n", driver->name); + return 0; +} +EXPORT_SYMBOL_GPL(gb_gbphy_register_driver); + +void gb_gbphy_deregister_driver(struct gbphy_driver *driver) +{ + driver_unregister(&driver->driver); +} +EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver); + +static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle, + struct greybus_descriptor_cport *cport_desc) +{ + struct gbphy_device *gbphy_dev; + int retval; + int id; + + id = ida_simple_get(&gbphy_id, 1, 0, GFP_KERNEL); + if (id < 0) + return ERR_PTR(id); + + gbphy_dev = kzalloc(sizeof(*gbphy_dev), GFP_KERNEL); + if (!gbphy_dev) { + ida_simple_remove(&gbphy_id, id); + return ERR_PTR(-ENOMEM); + } + + gbphy_dev->id = id; + gbphy_dev->bundle = bundle; + gbphy_dev->cport_desc = cport_desc; + gbphy_dev->dev.parent = &bundle->dev; + gbphy_dev->dev.bus = &gbphy_bus_type; + gbphy_dev->dev.type = &greybus_gbphy_dev_type; + gbphy_dev->dev.groups = gbphy_dev_groups; + gbphy_dev->dev.dma_mask = bundle->dev.dma_mask; + dev_set_name(&gbphy_dev->dev, "gbphy%d", id); + + retval = device_register(&gbphy_dev->dev); + if (retval) { + put_device(&gbphy_dev->dev); + return ERR_PTR(retval); + } + + return gbphy_dev; +} + +static void gb_gbphy_disconnect(struct gb_bundle *bundle) +{ + struct gbphy_host *gbphy_host = greybus_get_drvdata(bundle); + struct gbphy_device *gbphy_dev, *temp; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + gb_pm_runtime_get_noresume(bundle); + + list_for_each_entry_safe(gbphy_dev, temp, &gbphy_host->devices, list) { + list_del(&gbphy_dev->list); + device_unregister(&gbphy_dev->dev); + } + + kfree(gbphy_host); +} + +static int gb_gbphy_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct gbphy_host *gbphy_host; + struct gbphy_device *gbphy_dev; + int i; + + if (bundle->num_cports == 0) + return -ENODEV; + + gbphy_host = kzalloc(sizeof(*gbphy_host), GFP_KERNEL); + if (!gbphy_host) + return -ENOMEM; + + gbphy_host->bundle = bundle; + INIT_LIST_HEAD(&gbphy_host->devices); + greybus_set_drvdata(bundle, gbphy_host); + + /* + * Create a bunch of children devices, one per cport, and bind the + * bridged phy drivers to them. + */ + for (i = 0; i < bundle->num_cports; ++i) { + gbphy_dev = gb_gbphy_create_dev(bundle, &bundle->cport_desc[i]); + if (IS_ERR(gbphy_dev)) { + gb_gbphy_disconnect(bundle); + return PTR_ERR(gbphy_dev); + } + list_add(&gbphy_dev->list, &gbphy_host->devices); + } + + gb_pm_runtime_put_autosuspend(bundle); + + return 0; +} + +static const struct greybus_bundle_id gb_gbphy_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { }, +}; +MODULE_DEVICE_TABLE(greybus, gb_gbphy_id_table); + +static struct greybus_driver gb_gbphy_driver = { + .name = "gbphy", + .probe = gb_gbphy_probe, + .disconnect = gb_gbphy_disconnect, + .id_table = gb_gbphy_id_table, +}; + +static int __init gbphy_init(void) +{ + int retval; + + retval = bus_register(&gbphy_bus_type); + if (retval) { + pr_err("gbphy bus register failed (%d)\n", retval); + return retval; + } + + retval = greybus_register(&gb_gbphy_driver); + if (retval) { + pr_err("error registering greybus driver\n"); + goto error_gbphy; + } + + return 0; + +error_gbphy: + bus_unregister(&gbphy_bus_type); + ida_destroy(&gbphy_id); + return retval; +} +module_init(gbphy_init); + +static void __exit gbphy_exit(void) +{ + greybus_deregister(&gb_gbphy_driver); + bus_unregister(&gbphy_bus_type); + ida_destroy(&gbphy_id); +} +module_exit(gbphy_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gbphy.h b/drivers/staging/greybus/gbphy.h new file mode 100644 index 000000000000..8ee68055ccc4 --- /dev/null +++ b/drivers/staging/greybus/gbphy.h @@ -0,0 +1,110 @@ +/* + * Greybus Bridged-Phy Bus driver + * + * Copyright 2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __GBPHY_H +#define __GBPHY_H + +struct gbphy_device { + u32 id; + struct greybus_descriptor_cport *cport_desc; + struct gb_bundle *bundle; + struct list_head list; + struct device dev; +}; +#define to_gbphy_dev(d) container_of(d, struct gbphy_device, dev) + +static inline void *gb_gbphy_get_data(struct gbphy_device *gdev) +{ + return dev_get_drvdata(&gdev->dev); +} + +static inline void gb_gbphy_set_data(struct gbphy_device *gdev, void *data) +{ + dev_set_drvdata(&gdev->dev, data); +} + +struct gbphy_device_id { + __u8 protocol_id; +}; + +#define GBPHY_PROTOCOL(p) \ + .protocol_id = (p), + +struct gbphy_driver { + const char *name; + int (*probe)(struct gbphy_device *, + const struct gbphy_device_id *id); + void (*remove)(struct gbphy_device *); + const struct gbphy_device_id *id_table; + + struct device_driver driver; +}; +#define to_gbphy_driver(d) container_of(d, struct gbphy_driver, driver) + +int gb_gbphy_register_driver(struct gbphy_driver *driver, + struct module *owner, const char *mod_name); +void gb_gbphy_deregister_driver(struct gbphy_driver *driver); + +#define gb_gbphy_register(driver) \ + gb_gbphy_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) +#define gb_gbphy_deregister(driver) \ + gb_gbphy_deregister_driver(driver) + +/** + * module_gbphy_driver() - Helper macro for registering a gbphy driver + * @__gbphy_driver: gbphy_driver structure + * + * Helper macro for gbphy drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_gbphy_driver(__gbphy_driver) \ + module_driver(__gbphy_driver, gb_gbphy_register, gb_gbphy_deregister) + +#ifdef CONFIG_PM +static inline int gbphy_runtime_get_sync(struct gbphy_device *gbphy_dev) +{ + struct device *dev = &gbphy_dev->dev; + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "pm_runtime_get_sync failed: %d\n", ret); + pm_runtime_put_noidle(dev); + return ret; + } + + return 0; +} + +static inline void gbphy_runtime_put_autosuspend(struct gbphy_device *gbphy_dev) +{ + struct device *dev = &gbphy_dev->dev; + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); +} + +static inline void gbphy_runtime_get_noresume(struct gbphy_device *gbphy_dev) +{ + pm_runtime_get_noresume(&gbphy_dev->dev); +} + +static inline void gbphy_runtime_put_noidle(struct gbphy_device *gbphy_dev) +{ + pm_runtime_put_noidle(&gbphy_dev->dev); +} +#else +static inline int gbphy_runtime_get_sync(struct gbphy_device *gbphy_dev) { return 0; } +static inline void gbphy_runtime_put_autosuspend(struct gbphy_device *gbphy_dev) {} +static inline void gbphy_runtime_get_noresume(struct gbphy_device *gbphy_dev) {} +static inline void gbphy_runtime_put_noidle(struct gbphy_device *gbphy_dev) {} +#endif + +#endif /* __GBPHY_H */ + diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c new file mode 100644 index 000000000000..5e06e4229e42 --- /dev/null +++ b/drivers/staging/greybus/gpio.c @@ -0,0 +1,766 @@ +/* + * GPIO Greybus driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "gbphy.h" + +struct gb_gpio_line { + /* The following has to be an array of line_max entries */ + /* --> make them just a flags field */ + u8 active: 1, + direction: 1, /* 0 = output, 1 = input */ + value: 1; /* 0 = low, 1 = high */ + u16 debounce_usec; + + u8 irq_type; + bool irq_type_pending; + bool masked; + bool masked_pending; +}; + +struct gb_gpio_controller { + struct gbphy_device *gbphy_dev; + struct gb_connection *connection; + u8 line_max; /* max line number */ + struct gb_gpio_line *lines; + + struct gpio_chip chip; + struct irq_chip irqc; + struct irq_chip *irqchip; + struct irq_domain *irqdomain; + unsigned int irq_base; + irq_flow_handler_t irq_handler; + unsigned int irq_default_type; + struct mutex irq_lock; +}; +#define gpio_chip_to_gb_gpio_controller(chip) \ + container_of(chip, struct gb_gpio_controller, chip) +#define irq_data_to_gpio_chip(d) (d->domain->host_data) + +static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc) +{ + struct gb_gpio_line_count_response response; + int ret; + + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT, + NULL, 0, &response, sizeof(response)); + if (!ret) + ggc->line_max = response.count; + return ret; +} + +static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) +{ + struct gb_gpio_activate_request request; + struct gbphy_device *gbphy_dev = ggc->gbphy_dev; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, + &request, sizeof(request), NULL, 0); + if (ret) { + gbphy_runtime_put_autosuspend(gbphy_dev); + return ret; + } + + ggc->lines[which].active = true; + + return 0; +} + +static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, + u8 which) +{ + struct gbphy_device *gbphy_dev = ggc->gbphy_dev; + struct device *dev = &gbphy_dev->dev; + struct gb_gpio_deactivate_request request; + int ret; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, + &request, sizeof(request), NULL, 0); + if (ret) { + dev_err(dev, "failed to deactivate gpio %u\n", which); + goto out_pm_put; + } + + ggc->lines[which].active = false; + +out_pm_put: + gbphy_runtime_put_autosuspend(gbphy_dev); +} + +static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, + u8 which) +{ + struct device *dev = &ggc->gbphy_dev->dev; + struct gb_gpio_get_direction_request request; + struct gb_gpio_get_direction_response response; + int ret; + u8 direction; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_DIRECTION, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) + return ret; + + direction = response.direction; + if (direction && direction != 1) { + dev_warn(dev, "gpio %u direction was %u (should be 0 or 1)\n", + which, direction); + } + ggc->lines[which].direction = direction ? 1 : 0; + return 0; +} + +static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc, + u8 which) +{ + struct gb_gpio_direction_in_request request; + int ret; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_IN, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].direction = 1; + return ret; +} + +static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, + u8 which, bool value_high) +{ + struct gb_gpio_direction_out_request request; + int ret; + + request.which = which; + request.value = value_high ? 1 : 0; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_OUT, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].direction = 0; + return ret; +} + +static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, + u8 which) +{ + struct device *dev = &ggc->gbphy_dev->dev; + struct gb_gpio_get_value_request request; + struct gb_gpio_get_value_response response; + int ret; + u8 value; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_VALUE, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(dev, "failed to get value of gpio %u\n", which); + return ret; + } + + value = response.value; + if (value && value != 1) { + dev_warn(dev, "gpio %u value was %u (should be 0 or 1)\n", + which, value); + } + ggc->lines[which].value = value ? 1 : 0; + return 0; +} + +static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, + u8 which, bool value_high) +{ + struct device *dev = &ggc->gbphy_dev->dev; + struct gb_gpio_set_value_request request; + int ret; + + if (ggc->lines[which].direction == 1) { + dev_warn(dev, "refusing to set value of input gpio %u\n", + which); + return; + } + + request.which = which; + request.value = value_high ? 1 : 0; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, + &request, sizeof(request), NULL, 0); + if (ret) { + dev_err(dev, "failed to set value of gpio %u\n", which); + return; + } + + ggc->lines[which].value = request.value; +} + +static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, + u8 which, u16 debounce_usec) +{ + struct gb_gpio_set_debounce_request request; + int ret; + + request.which = which; + request.usec = cpu_to_le16(debounce_usec); + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_DEBOUNCE, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].debounce_usec = debounce_usec; + return ret; +} + +static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq) +{ + struct device *dev = &ggc->gbphy_dev->dev; + struct gb_gpio_irq_mask_request request; + int ret; + + request.which = hwirq; + ret = gb_operation_sync(ggc->connection, + GB_GPIO_TYPE_IRQ_MASK, + &request, sizeof(request), NULL, 0); + if (ret) + dev_err(dev, "failed to mask irq: %d\n", ret); +} + +static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) +{ + struct device *dev = &ggc->gbphy_dev->dev; + struct gb_gpio_irq_unmask_request request; + int ret; + + request.which = hwirq; + ret = gb_operation_sync(ggc->connection, + GB_GPIO_TYPE_IRQ_UNMASK, + &request, sizeof(request), NULL, 0); + if (ret) + dev_err(dev, "failed to unmask irq: %d\n", ret); +} + +static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, + u8 hwirq, u8 type) +{ + struct device *dev = &ggc->gbphy_dev->dev; + struct gb_gpio_irq_type_request request; + int ret; + + request.which = hwirq; + request.type = type; + + ret = gb_operation_sync(ggc->connection, + GB_GPIO_TYPE_IRQ_TYPE, + &request, sizeof(request), NULL, 0); + if (ret) + dev_err(dev, "failed to set irq type: %d\n", ret); +} + +static void gb_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + + line->masked = true; + line->masked_pending = true; +} + +static void gb_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + + line->masked = false; + line->masked_pending = true; +} + +static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + struct device *dev = &ggc->gbphy_dev->dev; + u8 irq_type; + + switch (type) { + case IRQ_TYPE_NONE: + irq_type = GB_GPIO_IRQ_TYPE_NONE; + break; + case IRQ_TYPE_EDGE_RISING: + irq_type = GB_GPIO_IRQ_TYPE_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_FALLING: + irq_type = GB_GPIO_IRQ_TYPE_EDGE_FALLING; + break; + case IRQ_TYPE_EDGE_BOTH: + irq_type = GB_GPIO_IRQ_TYPE_EDGE_BOTH; + break; + case IRQ_TYPE_LEVEL_LOW: + irq_type = GB_GPIO_IRQ_TYPE_LEVEL_LOW; + break; + case IRQ_TYPE_LEVEL_HIGH: + irq_type = GB_GPIO_IRQ_TYPE_LEVEL_HIGH; + break; + default: + dev_err(dev, "unsupported irq type: %u\n", type); + return -EINVAL; + } + + line->irq_type = irq_type; + line->irq_type_pending = true; + + return 0; +} + +static void gb_gpio_irq_bus_lock(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + mutex_lock(&ggc->irq_lock); +} + +static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + + if (line->irq_type_pending) { + _gb_gpio_irq_set_type(ggc, d->hwirq, line->irq_type); + line->irq_type_pending = false; + } + + if (line->masked_pending) { + if (line->masked) + _gb_gpio_irq_mask(ggc, d->hwirq); + else + _gb_gpio_irq_unmask(ggc, d->hwirq); + line->masked_pending = false; + } + + mutex_unlock(&ggc->irq_lock); +} + +static int gb_gpio_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_gpio_controller *ggc = gb_connection_get_data(connection); + struct device *dev = &ggc->gbphy_dev->dev; + struct gb_message *request; + struct gb_gpio_irq_event_request *event; + u8 type = op->type; + int irq; + struct irq_desc *desc; + + if (type != GB_GPIO_TYPE_IRQ_EVENT) { + dev_err(dev, "unsupported unsolicited request: %u\n", type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size < sizeof(*event)) { + dev_err(dev, "short event received (%zu < %zu)\n", + request->payload_size, sizeof(*event)); + return -EINVAL; + } + + event = request->payload; + if (event->which > ggc->line_max) { + dev_err(dev, "invalid hw irq: %d\n", event->which); + return -EINVAL; + } + + irq = irq_find_mapping(ggc->irqdomain, event->which); + if (!irq) { + dev_err(dev, "failed to find IRQ\n"); + return -EINVAL; + } + desc = irq_to_desc(irq); + if (!desc) { + dev_err(dev, "failed to look up irq\n"); + return -EINVAL; + } + + local_irq_disable(); + generic_handle_irq_desc(desc); + local_irq_enable(); + + return 0; +} + +static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + return gb_gpio_activate_operation(ggc, (u8)offset); +} + +static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + gb_gpio_deactivate_operation(ggc, (u8)offset); +} + +static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + which = (u8)offset; + ret = gb_gpio_get_direction_operation(ggc, which); + if (ret) + return ret; + + return ggc->lines[which].direction ? 1 : 0; +} + +static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + return gb_gpio_direction_in_operation(ggc, (u8)offset); +} + +static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + return gb_gpio_direction_out_operation(ggc, (u8)offset, !!value); +} + +static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + which = (u8)offset; + ret = gb_gpio_get_value_operation(ggc, which); + if (ret) + return ret; + + return ggc->lines[which].value; +} + +static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + gb_gpio_set_value_operation(ggc, (u8)offset, !!value); +} + +static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, + unsigned debounce) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + u16 usec; + + if (debounce > U16_MAX) + return -EINVAL; + usec = (u16)debounce; + + return gb_gpio_set_debounce_operation(ggc, (u8)offset, usec); +} + +static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) +{ + int ret; + + /* Now find out how many lines there are */ + ret = gb_gpio_line_count_operation(ggc); + if (ret) + return ret; + + ggc->lines = kcalloc(ggc->line_max + 1, sizeof(*ggc->lines), + GFP_KERNEL); + if (!ggc->lines) + return -ENOMEM; + + return ret; +} + +/** + * gb_gpio_irq_map() - maps an IRQ into a GB gpio irqchip + * @d: the irqdomain used by this irqchip + * @irq: the global irq number used by this GB gpio irqchip irq + * @hwirq: the local IRQ/GPIO line offset on this GB gpio + * + * This function will set up the mapping for a certain IRQ line on a + * GB gpio by assigning the GB gpio as chip data, and using the irqchip + * stored inside the GB gpio. + */ +static int gb_gpio_irq_map(struct irq_domain *domain, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct gpio_chip *chip = domain->host_data; + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + irq_set_chip_data(irq, ggc); + irq_set_chip_and_handler(irq, ggc->irqchip, ggc->irq_handler); + irq_set_noprobe(irq); + /* + * No set-up of the hardware will happen if IRQ_TYPE_NONE + * is passed as default type. + */ + if (ggc->irq_default_type != IRQ_TYPE_NONE) + irq_set_irq_type(irq, ggc->irq_default_type); + + return 0; +} + +static void gb_gpio_irq_unmap(struct irq_domain *d, unsigned int irq) +{ + irq_set_chip_and_handler(irq, NULL, NULL); + irq_set_chip_data(irq, NULL); +} + +static const struct irq_domain_ops gb_gpio_domain_ops = { + .map = gb_gpio_irq_map, + .unmap = gb_gpio_irq_unmap, +}; + +/** + * gb_gpio_irqchip_remove() - removes an irqchip added to a gb_gpio_controller + * @ggc: the gb_gpio_controller to remove the irqchip from + * + * This is called only from gb_gpio_remove() + */ +static void gb_gpio_irqchip_remove(struct gb_gpio_controller *ggc) +{ + unsigned int offset; + + /* Remove all IRQ mappings and delete the domain */ + if (ggc->irqdomain) { + for (offset = 0; offset < (ggc->line_max + 1); offset++) + irq_dispose_mapping(irq_find_mapping(ggc->irqdomain, offset)); + irq_domain_remove(ggc->irqdomain); + } + + if (ggc->irqchip) + ggc->irqchip = NULL; +} + +/** + * gb_gpio_irqchip_add() - adds an irqchip to a gpio chip + * @chip: the gpio chip to add the irqchip to + * @irqchip: the irqchip to add to the adapter + * @first_irq: if not dynamically assigned, the base (first) IRQ to + * allocate gpio irqs from + * @handler: the irq handler to use (often a predefined irq core function) + * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE + * to have the core avoid setting up any default type in the hardware. + * + * This function closely associates a certain irqchip with a certain + * gpio chip, providing an irq domain to translate the local IRQs to + * global irqs, and making sure that the gpio chip + * is passed as chip data to all related functions. Driver callbacks + * need to use container_of() to get their local state containers back + * from the gpio chip passed as chip data. An irqdomain will be stored + * in the gpio chip that shall be used by the driver to handle IRQ number + * translation. The gpio chip will need to be initialized and registered + * before calling this function. + */ +static int gb_gpio_irqchip_add(struct gpio_chip *chip, + struct irq_chip *irqchip, + unsigned int first_irq, + irq_flow_handler_t handler, + unsigned int type) +{ + struct gb_gpio_controller *ggc; + unsigned int offset; + unsigned irq_base; + + if (!chip || !irqchip) + return -EINVAL; + + ggc = gpio_chip_to_gb_gpio_controller(chip); + + ggc->irqchip = irqchip; + ggc->irq_handler = handler; + ggc->irq_default_type = type; + ggc->irqdomain = irq_domain_add_simple(NULL, + ggc->line_max + 1, first_irq, + &gb_gpio_domain_ops, chip); + if (!ggc->irqdomain) { + ggc->irqchip = NULL; + return -EINVAL; + } + + /* + * Prepare the mapping since the irqchip shall be orthogonal to + * any gpio calls. If the first_irq was zero, this is + * necessary to allocate descriptors for all IRQs. + */ + for (offset = 0; offset < (ggc->line_max + 1); offset++) { + irq_base = irq_create_mapping(ggc->irqdomain, offset); + if (offset == 0) + ggc->irq_base = irq_base; + } + + return 0; +} + +static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + return irq_find_mapping(ggc->irqdomain, offset); +} + +static int gb_gpio_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) +{ + struct gb_connection *connection; + struct gb_gpio_controller *ggc; + struct gpio_chip *gpio; + struct irq_chip *irqc; + int ret; + + ggc = kzalloc(sizeof(*ggc), GFP_KERNEL); + if (!ggc) + return -ENOMEM; + + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), + gb_gpio_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_ggc_free; + } + + ggc->connection = connection; + gb_connection_set_data(connection, ggc); + ggc->gbphy_dev = gbphy_dev; + gb_gbphy_set_data(gbphy_dev, ggc); + + ret = gb_connection_enable_tx(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpio_controller_setup(ggc); + if (ret) + goto exit_connection_disable; + + irqc = &ggc->irqc; + irqc->irq_mask = gb_gpio_irq_mask; + irqc->irq_unmask = gb_gpio_irq_unmask; + irqc->irq_set_type = gb_gpio_irq_set_type; + irqc->irq_bus_lock = gb_gpio_irq_bus_lock; + irqc->irq_bus_sync_unlock = gb_gpio_irq_bus_sync_unlock; + irqc->name = "greybus_gpio"; + + mutex_init(&ggc->irq_lock); + + gpio = &ggc->chip; + + gpio->label = "greybus_gpio"; + gpio->parent = &gbphy_dev->dev; + gpio->owner = THIS_MODULE; + + gpio->request = gb_gpio_request; + gpio->free = gb_gpio_free; + gpio->get_direction = gb_gpio_get_direction; + gpio->direction_input = gb_gpio_direction_input; + gpio->direction_output = gb_gpio_direction_output; + gpio->get = gb_gpio_get; + gpio->set = gb_gpio_set; + gpio->set_debounce = gb_gpio_set_debounce; + gpio->to_irq = gb_gpio_to_irq; + gpio->base = -1; /* Allocate base dynamically */ + gpio->ngpio = ggc->line_max + 1; + gpio->can_sleep = true; + + ret = gb_connection_enable(connection); + if (ret) + goto exit_line_free; + + ret = gb_gpio_irqchip_add(gpio, irqc, 0, + handle_level_irq, IRQ_TYPE_NONE); + if (ret) { + dev_err(&connection->bundle->dev, + "failed to add irq chip: %d\n", ret); + goto exit_line_free; + } + + ret = gpiochip_add(gpio); + if (ret) { + dev_err(&connection->bundle->dev, + "failed to add gpio chip: %d\n", ret); + goto exit_gpio_irqchip_remove; + } + + gbphy_runtime_put_autosuspend(gbphy_dev); + return 0; + +exit_gpio_irqchip_remove: + gb_gpio_irqchip_remove(ggc); +exit_line_free: + kfree(ggc->lines); +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_ggc_free: + kfree(ggc); + return ret; +} + +static void gb_gpio_remove(struct gbphy_device *gbphy_dev) +{ + struct gb_gpio_controller *ggc = gb_gbphy_get_data(gbphy_dev); + struct gb_connection *connection = ggc->connection; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); + + gb_connection_disable_rx(connection); + gpiochip_remove(&ggc->chip); + gb_gpio_irqchip_remove(ggc); + gb_connection_disable(connection); + gb_connection_destroy(connection); + kfree(ggc->lines); + kfree(ggc); +} + +static const struct gbphy_device_id gb_gpio_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_GPIO) }, + { }, +}; +MODULE_DEVICE_TABLE(gbphy, gb_gpio_id_table); + +static struct gbphy_driver gpio_driver = { + .name = "gpio", + .probe = gb_gpio_probe, + .remove = gb_gpio_remove, + .id_table = gb_gpio_id_table, +}; + +module_gbphy_driver(gpio_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h new file mode 100644 index 000000000000..12526887ae2e --- /dev/null +++ b/drivers/staging/greybus/greybus.h @@ -0,0 +1,154 @@ +/* + * Greybus driver and device API + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __LINUX_GREYBUS_H +#define __LINUX_GREYBUS_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "timesync.h" + +/* Matches up with the Greybus Protocol specification document */ +#define GREYBUS_VERSION_MAJOR 0x00 +#define GREYBUS_VERSION_MINOR 0x01 + +#define GREYBUS_ID_MATCH_DEVICE \ + (GREYBUS_ID_MATCH_VENDOR | GREYBUS_ID_MATCH_PRODUCT) + +#define GREYBUS_DEVICE(v, p) \ + .match_flags = GREYBUS_ID_MATCH_DEVICE, \ + .vendor = (v), \ + .product = (p), + +#define GREYBUS_DEVICE_CLASS(c) \ + .match_flags = GREYBUS_ID_MATCH_CLASS, \ + .class = (c), + +/* Maximum number of CPorts */ +#define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ +#define CPORT_ID_BAD U16_MAX + +struct greybus_driver { + const char *name; + + int (*probe)(struct gb_bundle *bundle, + const struct greybus_bundle_id *id); + void (*disconnect)(struct gb_bundle *bundle); + + const struct greybus_bundle_id *id_table; + + struct device_driver driver; +}; +#define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) + +static inline void greybus_set_drvdata(struct gb_bundle *bundle, void *data) +{ + dev_set_drvdata(&bundle->dev, data); +} + +static inline void *greybus_get_drvdata(struct gb_bundle *bundle) +{ + return dev_get_drvdata(&bundle->dev); +} + +/* Don't call these directly, use the module_greybus_driver() macro instead */ +int greybus_register_driver(struct greybus_driver *driver, + struct module *module, const char *mod_name); +void greybus_deregister_driver(struct greybus_driver *driver); + +/* define to get proper THIS_MODULE and KBUILD_MODNAME values */ +#define greybus_register(driver) \ + greybus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) +#define greybus_deregister(driver) \ + greybus_deregister_driver(driver) + +/** + * module_greybus_driver() - Helper macro for registering a Greybus driver + * @__greybus_driver: greybus_driver structure + * + * Helper macro for Greybus drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_greybus_driver(__greybus_driver) \ + module_driver(__greybus_driver, greybus_register, greybus_deregister) + +int greybus_disabled(void); + +void gb_debugfs_init(void); +void gb_debugfs_cleanup(void); +struct dentry *gb_debugfs_get(void); + +extern struct bus_type greybus_bus_type; + +extern struct device_type greybus_hd_type; +extern struct device_type greybus_module_type; +extern struct device_type greybus_interface_type; +extern struct device_type greybus_control_type; +extern struct device_type greybus_bundle_type; +extern struct device_type greybus_svc_type; + +static inline int is_gb_host_device(const struct device *dev) +{ + return dev->type == &greybus_hd_type; +} + +static inline int is_gb_module(const struct device *dev) +{ + return dev->type == &greybus_module_type; +} + +static inline int is_gb_interface(const struct device *dev) +{ + return dev->type == &greybus_interface_type; +} + +static inline int is_gb_control(const struct device *dev) +{ + return dev->type == &greybus_control_type; +} + +static inline int is_gb_bundle(const struct device *dev) +{ + return dev->type == &greybus_bundle_type; +} + +static inline int is_gb_svc(const struct device *dev) +{ + return dev->type == &greybus_svc_type; +} + +static inline bool cport_id_valid(struct gb_host_device *hd, u16 cport_id) +{ + return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; +} + +#endif /* __KERNEL__ */ +#endif /* __LINUX_GREYBUS_H */ diff --git a/drivers/staging/greybus/greybus_authentication.h b/drivers/staging/greybus/greybus_authentication.h new file mode 100644 index 000000000000..4784ed98e8a3 --- /dev/null +++ b/drivers/staging/greybus/greybus_authentication.h @@ -0,0 +1,120 @@ +/* + * 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 +#define __GREYBUS_AUTHENTICATION_USER_H + +#include +#include + +#define CAP_CERTIFICATE_MAX_SIZE 1600 +#define CAP_SIGNATURE_MAX_SIZE 320 + +/* Certificate class types */ +#define CAP_CERT_IMS_EAPC 0x00000001 +#define CAP_CERT_IMS_EASC 0x00000002 +#define CAP_CERT_IMS_EARC 0x00000003 +#define CAP_CERT_IMS_IAPC 0x00000004 +#define CAP_CERT_IMS_IASC 0x00000005 +#define CAP_CERT_IMS_IARC 0x00000006 + +/* IMS Certificate response result codes */ +#define CAP_IMS_RESULT_CERT_FOUND 0x00 +#define CAP_IMS_RESULT_CERT_CLASS_INVAL 0x01 +#define CAP_IMS_RESULT_CERT_CORRUPT 0x02 +#define CAP_IMS_RESULT_CERT_NOT_FOUND 0x03 + +/* Authentication types */ +#define CAP_AUTH_IMS_PRI 0x00000001 +#define CAP_AUTH_IMS_SEC 0x00000002 +#define CAP_AUTH_IMS_RSA 0x00000003 + +/* Authenticate response result codes */ +#define CAP_AUTH_RESULT_CR_SUCCESS 0x00 +#define CAP_AUTH_RESULT_CR_BAD_TYPE 0x01 +#define CAP_AUTH_RESULT_CR_WRONG_EP 0x02 +#define CAP_AUTH_RESULT_CR_NO_KEY 0x03 +#define CAP_AUTH_RESULT_CR_SIG_FAIL 0x04 + + +/* IOCTL support */ +struct cap_ioc_get_endpoint_uid { + __u8 uid[8]; +} __attribute__ ((__packed__)); + +struct cap_ioc_get_ims_certificate { + __u32 certificate_class; + __u32 certificate_id; + + __u8 result_code; + __u32 cert_size; + __u8 certificate[CAP_CERTIFICATE_MAX_SIZE]; +} __attribute__ ((__packed__)); + +struct cap_ioc_authenticate { + __u32 auth_type; + __u8 uid[8]; + __u8 challenge[32]; + + __u8 result_code; + __u8 response[64]; + __u32 signature_size; + __u8 signature[CAP_SIGNATURE_MAX_SIZE]; +} __attribute__ ((__packed__)); + +#define CAP_IOCTL_BASE 'C' +#define CAP_IOC_GET_ENDPOINT_UID _IOR(CAP_IOCTL_BASE, 0, struct cap_ioc_get_endpoint_uid) +#define CAP_IOC_GET_IMS_CERTIFICATE _IOWR(CAP_IOCTL_BASE, 1, struct cap_ioc_get_ims_certificate) +#define CAP_IOC_AUTHENTICATE _IOWR(CAP_IOCTL_BASE, 2, struct cap_ioc_authenticate) + +#endif /* __GREYBUS_AUTHENTICATION_USER_H */ diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h new file mode 100644 index 000000000000..277a2acce6fd --- /dev/null +++ b/drivers/staging/greybus/greybus_firmware.h @@ -0,0 +1,120 @@ +/* + * 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 +#define __GREYBUS_FIRMWARE_USER_H + +#include +#include + +#define GB_FIRMWARE_U_TAG_MAX_SIZE 10 + +#define GB_FW_U_LOAD_METHOD_UNIPRO 0x01 +#define GB_FW_U_LOAD_METHOD_INTERNAL 0x02 + +#define GB_FW_U_LOAD_STATUS_FAILED 0x00 +#define GB_FW_U_LOAD_STATUS_UNVALIDATED 0x01 +#define GB_FW_U_LOAD_STATUS_VALIDATED 0x02 +#define GB_FW_U_LOAD_STATUS_VALIDATION_FAILED 0x03 + +#define GB_FW_U_BACKEND_FW_STATUS_SUCCESS 0x01 +#define GB_FW_U_BACKEND_FW_STATUS_FAIL_FIND 0x02 +#define GB_FW_U_BACKEND_FW_STATUS_FAIL_FETCH 0x03 +#define GB_FW_U_BACKEND_FW_STATUS_FAIL_WRITE 0x04 +#define GB_FW_U_BACKEND_FW_STATUS_INT 0x05 +#define GB_FW_U_BACKEND_FW_STATUS_RETRY 0x06 +#define GB_FW_U_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 + +#define GB_FW_U_BACKEND_VERSION_STATUS_SUCCESS 0x01 +#define GB_FW_U_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 +#define GB_FW_U_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 +#define GB_FW_U_BACKEND_VERSION_STATUS_RETRY 0x04 +#define GB_FW_U_BACKEND_VERSION_STATUS_FAIL_INT 0x05 + +/* IOCTL support */ +struct fw_mgmt_ioc_get_intf_version { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; + __u16 major; + __u16 minor; +} __attribute__ ((__packed__)); + +struct fw_mgmt_ioc_get_backend_version { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; + __u16 major; + __u16 minor; + __u8 status; +} __attribute__ ((__packed__)); + +struct fw_mgmt_ioc_intf_load_and_validate { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; + __u8 load_method; + __u8 status; + __u16 major; + __u16 minor; +} __attribute__ ((__packed__)); + +struct fw_mgmt_ioc_backend_fw_update { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; + __u8 status; +} __attribute__ ((__packed__)); + +#define FW_MGMT_IOCTL_BASE 'F' +#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_intf_version) +#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_backend_version) +#define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate) +#define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update) +#define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int) +#define FW_MGMT_IOC_MODE_SWITCH _IO(FW_MGMT_IOCTL_BASE, 5) + +#endif /* __GREYBUS_FIRMWARE_USER_H */ + diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h new file mode 100644 index 000000000000..4bb1fc1b811d --- /dev/null +++ b/drivers/staging/greybus/greybus_id.h @@ -0,0 +1,26 @@ +/* FIXME + * move this to include/linux/mod_devicetable.h when merging + */ + +#ifndef __LINUX_GREYBUS_ID_H +#define __LINUX_GREYBUS_ID_H + +#include +#include + + +struct greybus_bundle_id { + __u16 match_flags; + __u32 vendor; + __u32 product; + __u8 class; + + kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); +}; + +/* Used to match the greybus_bundle_id */ +#define GREYBUS_ID_MATCH_VENDOR BIT(0) +#define GREYBUS_ID_MATCH_PRODUCT BIT(1) +#define GREYBUS_ID_MATCH_CLASS BIT(2) + +#endif /* __LINUX_GREYBUS_ID_H */ diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h new file mode 100644 index 000000000000..d135945cefe1 --- /dev/null +++ b/drivers/staging/greybus/greybus_manifest.h @@ -0,0 +1,177 @@ +/* + * Greybus manifest definition + * + * See "Greybus Application Protocol" document (version 0.1) for + * details on these values and structures. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 and BSD licenses. + */ + +#ifndef __GREYBUS_MANIFEST_H +#define __GREYBUS_MANIFEST_H + +enum greybus_descriptor_type { + GREYBUS_TYPE_INVALID = 0x00, + GREYBUS_TYPE_INTERFACE = 0x01, + GREYBUS_TYPE_STRING = 0x02, + GREYBUS_TYPE_BUNDLE = 0x03, + GREYBUS_TYPE_CPORT = 0x04, +}; + +enum greybus_protocol { + GREYBUS_PROTOCOL_CONTROL = 0x00, + /* 0x01 is unused */ + GREYBUS_PROTOCOL_GPIO = 0x02, + GREYBUS_PROTOCOL_I2C = 0x03, + GREYBUS_PROTOCOL_UART = 0x04, + GREYBUS_PROTOCOL_HID = 0x05, + GREYBUS_PROTOCOL_USB = 0x06, + GREYBUS_PROTOCOL_SDIO = 0x07, + GREYBUS_PROTOCOL_POWER_SUPPLY = 0x08, + GREYBUS_PROTOCOL_PWM = 0x09, + /* 0x0a is unused */ + GREYBUS_PROTOCOL_SPI = 0x0b, + GREYBUS_PROTOCOL_DISPLAY = 0x0c, + GREYBUS_PROTOCOL_CAMERA_MGMT = 0x0d, + GREYBUS_PROTOCOL_SENSOR = 0x0e, + GREYBUS_PROTOCOL_LIGHTS = 0x0f, + GREYBUS_PROTOCOL_VIBRATOR = 0x10, + GREYBUS_PROTOCOL_LOOPBACK = 0x11, + GREYBUS_PROTOCOL_AUDIO_MGMT = 0x12, + GREYBUS_PROTOCOL_AUDIO_DATA = 0x13, + GREYBUS_PROTOCOL_SVC = 0x14, + GREYBUS_PROTOCOL_BOOTROM = 0x15, + GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, + GREYBUS_PROTOCOL_FW_DOWNLOAD = 0x17, + GREYBUS_PROTOCOL_FW_MANAGEMENT = 0x18, + GREYBUS_PROTOCOL_AUTHENTICATION = 0x19, + GREYBUS_PROTOCOL_LOG = 0x1a, + /* ... */ + GREYBUS_PROTOCOL_RAW = 0xfe, + GREYBUS_PROTOCOL_VENDOR = 0xff, +}; + +enum greybus_class_type { + GREYBUS_CLASS_CONTROL = 0x00, + /* 0x01 is unused */ + /* 0x02 is unused */ + /* 0x03 is unused */ + /* 0x04 is unused */ + GREYBUS_CLASS_HID = 0x05, + /* 0x06 is unused */ + /* 0x07 is unused */ + GREYBUS_CLASS_POWER_SUPPLY = 0x08, + /* 0x09 is unused */ + GREYBUS_CLASS_BRIDGED_PHY = 0x0a, + /* 0x0b is unused */ + GREYBUS_CLASS_DISPLAY = 0x0c, + GREYBUS_CLASS_CAMERA = 0x0d, + GREYBUS_CLASS_SENSOR = 0x0e, + GREYBUS_CLASS_LIGHTS = 0x0f, + GREYBUS_CLASS_VIBRATOR = 0x10, + GREYBUS_CLASS_LOOPBACK = 0x11, + GREYBUS_CLASS_AUDIO = 0x12, + /* 0x13 is unused */ + /* 0x14 is unused */ + GREYBUS_CLASS_BOOTROM = 0x15, + GREYBUS_CLASS_FW_MANAGEMENT = 0x16, + GREYBUS_CLASS_LOG = 0x17, + /* ... */ + GREYBUS_CLASS_RAW = 0xfe, + GREYBUS_CLASS_VENDOR = 0xff, +}; + +enum { + GREYBUS_INTERFACE_FEATURE_TIMESYNC = BIT(0), +}; + +/* + * The string in a string descriptor is not NUL-terminated. The + * size of the descriptor will be rounded up to a multiple of 4 + * bytes, by padding the string with 0x00 bytes if necessary. + */ +struct greybus_descriptor_string { + __u8 length; + __u8 id; + __u8 string[0]; +} __packed; + +/* + * An interface descriptor describes information about an interface as a whole, + * *not* the functions within it. + */ +struct greybus_descriptor_interface { + __u8 vendor_stringid; + __u8 product_stringid; + __u8 features; + __u8 pad; +} __packed; + +/* + * An bundle descriptor defines an identification number and a class for + * each bundle. + * + * @id: Uniquely identifies a bundle within a interface, its sole purpose is to + * allow CPort descriptors to specify which bundle they are associated with. + * The first bundle will have id 0, second will have 1 and so on. + * + * The largest CPort id associated with an bundle (defined by a + * CPort descriptor in the manifest) is used to determine how to + * encode the device id and module number in UniPro packets + * that use the bundle. + * + * @class: It is used by kernel to know the functionality provided by the + * bundle and will be matched against drivers functinality while probing greybus + * driver. It should contain one of the values defined in + * 'enum greybus_class_type'. + * + */ +struct greybus_descriptor_bundle { + __u8 id; /* interface-relative id (0..) */ + __u8 class; + __u8 pad[2]; +} __packed; + +/* + * A CPort descriptor indicates the id of the bundle within the + * module it's associated with, along with the CPort id used to + * address the CPort. The protocol id defines the format of messages + * exchanged using the CPort. + */ +struct greybus_descriptor_cport { + __le16 id; + __u8 bundle; + __u8 protocol_id; /* enum greybus_protocol */ +} __packed; + +struct greybus_descriptor_header { + __le16 size; + __u8 type; /* enum greybus_descriptor_type */ + __u8 pad; +} __packed; + +struct greybus_descriptor { + struct greybus_descriptor_header header; + union { + struct greybus_descriptor_string string; + struct greybus_descriptor_interface interface; + struct greybus_descriptor_bundle bundle; + struct greybus_descriptor_cport cport; + }; +} __packed; + +struct greybus_manifest_header { + __le16 size; + __u8 version_major; + __u8 version_minor; +} __packed; + +struct greybus_manifest { + struct greybus_manifest_header header; + struct greybus_descriptor descriptors[0]; +} __packed; + +#endif /* __GREYBUS_MANIFEST_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h new file mode 100644 index 000000000000..639578309c2a --- /dev/null +++ b/drivers/staging/greybus/greybus_protocols.h @@ -0,0 +1,2268 @@ +/* + * 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 + +/* Fixed IDs for control/svc protocols */ + +/* SVC switch-port device ids */ +#define GB_SVC_DEVICE_ID_SVC 0 +#define GB_SVC_DEVICE_ID_AP 1 +#define GB_SVC_DEVICE_ID_MIN 2 +#define GB_SVC_DEVICE_ID_MAX 31 + +#define GB_SVC_CPORT_ID 0 +#define GB_CONTROL_BUNDLE_ID 0 +#define GB_CONTROL_CPORT_ID 0 + + +/* + * All operation messages (both requests and responses) begin with + * a header that encodes the size of the message (header included). + * This header also contains a unique identifier, that associates a + * response message with its operation. The header contains an + * operation type field, whose interpretation is dependent on what + * type of protocol is used over the connection. The high bit + * (0x80) of the operation type field is used to indicate whether + * the message is a request (clear) or a response (set). + * + * Response messages include an additional result byte, which + * communicates the result of the corresponding request. A zero + * result value means the operation completed successfully. Any + * other value indicates an error; in this case, the payload of the + * response message (if any) is ignored. The result byte must be + * zero in the header for a request message. + * + * The wire format for all numeric fields in the header is little + * endian. Any operation-specific data begins immediately after the + * header. + */ +struct gb_operation_msg_hdr { + __le16 size; /* Size in bytes of header + payload */ + __le16 operation_id; /* Operation unique id */ + __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ + __u8 result; /* Result of request (in responses only) */ + __u8 pad[2]; /* must be zero (ignore when read) */ +} __packed; + + +/* Generic request types */ +#define GB_REQUEST_TYPE_CPORT_SHUTDOWN 0x00 +#define GB_REQUEST_TYPE_INVALID 0x7f + +struct gb_cport_shutdown_request { + __u8 phase; +} __packed; + + +/* Control Protocol */ + +/* Greybus control request types */ +#define GB_CONTROL_TYPE_VERSION 0x01 +#define GB_CONTROL_TYPE_PROBE_AP 0x02 +#define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03 +#define GB_CONTROL_TYPE_GET_MANIFEST 0x04 +#define GB_CONTROL_TYPE_CONNECTED 0x05 +#define GB_CONTROL_TYPE_DISCONNECTED 0x06 +#define GB_CONTROL_TYPE_TIMESYNC_ENABLE 0x07 +#define GB_CONTROL_TYPE_TIMESYNC_DISABLE 0x08 +#define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 +/* Unused 0x0a */ +#define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b +#define GB_CONTROL_TYPE_DISCONNECTING 0x0c +#define GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT 0x0d +#define GB_CONTROL_TYPE_MODE_SWITCH 0x0e +#define GB_CONTROL_TYPE_BUNDLE_SUSPEND 0x0f +#define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10 +#define GB_CONTROL_TYPE_BUNDLE_DEACTIVATE 0x11 +#define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 +#define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13 +#define GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE 0x14 +#define GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT 0x15 + +struct gb_control_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_control_version_response { + __u8 major; + __u8 minor; +} __packed; + +struct gb_control_bundle_version_request { + __u8 bundle_id; +} __packed; + +struct gb_control_bundle_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* Control protocol manifest get size request has no payload*/ +struct gb_control_get_manifest_size_response { + __le16 size; +} __packed; + +/* Control protocol manifest get request has no payload */ +struct gb_control_get_manifest_response { + __u8 data[0]; +} __packed; + +/* Control protocol [dis]connected request */ +struct gb_control_connected_request { + __le16 cport_id; +} __packed; + +struct gb_control_disconnecting_request { + __le16 cport_id; +} __packed; +/* disconnecting response has no payload */ + +struct gb_control_disconnected_request { + __le16 cport_id; +} __packed; +/* Control protocol [dis]connected response has no payload */ + +#define GB_TIMESYNC_MAX_STROBES 0x04 + +struct gb_control_timesync_enable_request { + __u8 count; + __le64 frame_time; + __le32 strobe_delay; + __le32 refclk; +} __packed; +/* timesync enable response has no payload */ + +struct gb_control_timesync_authoritative_request { + __le64 frame_time[GB_TIMESYNC_MAX_STROBES]; +} __packed; +/* timesync authoritative response has no payload */ + +/* timesync get_last_event_request has no payload */ +struct gb_control_timesync_get_last_event_response { + __le64 frame_time; +} __packed; + +/* + * All Bundle power management operations use the same request and response + * layout and status codes. + */ + +#define GB_CONTROL_BUNDLE_PM_OK 0x00 +#define GB_CONTROL_BUNDLE_PM_INVAL 0x01 +#define GB_CONTROL_BUNDLE_PM_BUSY 0x02 +#define GB_CONTROL_BUNDLE_PM_FAIL 0x03 +#define GB_CONTROL_BUNDLE_PM_NA 0x04 + +struct gb_control_bundle_pm_request { + __u8 bundle_id; +} __packed; + +struct gb_control_bundle_pm_response { + __u8 status; +} __packed; + +/* + * Interface Suspend Prepare and Deactivate Prepare operations use the same + * response layout and error codes. Define a single response structure and reuse + * it. Both operations have no payload. + */ + +#define GB_CONTROL_INTF_PM_OK 0x00 +#define GB_CONTROL_INTF_PM_BUSY 0x01 +#define GB_CONTROL_INTF_PM_NA 0x02 + +struct gb_control_intf_pm_response { + __u8 status; +} __packed; + +/* APBridge protocol */ + +/* request APB1 log */ +#define GB_APB_REQUEST_LOG 0x02 + +/* request to map a cport to bulk in and bulk out endpoints */ +#define GB_APB_REQUEST_EP_MAPPING 0x03 + +/* request to get the number of cports available */ +#define GB_APB_REQUEST_CPORT_COUNT 0x04 + +/* request to reset a cport state */ +#define GB_APB_REQUEST_RESET_CPORT 0x05 + +/* request to time the latency of messages on a given cport */ +#define GB_APB_REQUEST_LATENCY_TAG_EN 0x06 +#define GB_APB_REQUEST_LATENCY_TAG_DIS 0x07 + +/* request to control the CSI transmitter */ +#define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 + +/* request to control audio streaming */ +#define GB_APB_REQUEST_AUDIO_CONTROL 0x09 + +/* TimeSync requests */ +#define GB_APB_REQUEST_TIMESYNC_ENABLE 0x0d +#define GB_APB_REQUEST_TIMESYNC_DISABLE 0x0e +#define GB_APB_REQUEST_TIMESYNC_AUTHORITATIVE 0x0f +#define GB_APB_REQUEST_TIMESYNC_GET_LAST_EVENT 0x10 + +/* requests to set Greybus CPort flags */ +#define GB_APB_REQUEST_CPORT_FLAGS 0x11 + +/* ARPC request */ +#define GB_APB_REQUEST_ARPC_RUN 0x12 + +struct gb_apb_request_cport_flags { + __le32 flags; +#define GB_APB_CPORT_FLAG_CONTROL 0x01 +#define GB_APB_CPORT_FLAG_HIGH_PRIO 0x02 +} __packed; + + +/* Firmware Download Protocol */ + +/* Request Types */ +#define GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE 0x01 +#define GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE 0x02 +#define GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE 0x03 + +#define GB_FIRMWARE_TAG_MAX_SIZE 10 + +/* firmware download find firmware request/response */ +struct gb_fw_download_find_firmware_request { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; + +struct gb_fw_download_find_firmware_response { + __u8 firmware_id; + __le32 size; +} __packed; + +/* firmware download fetch firmware request/response */ +struct gb_fw_download_fetch_firmware_request { + __u8 firmware_id; + __le32 offset; + __le32 size; +} __packed; + +struct gb_fw_download_fetch_firmware_response { + __u8 data[0]; +} __packed; + +/* firmware download release firmware request */ +struct gb_fw_download_release_firmware_request { + __u8 firmware_id; +} __packed; +/* firmware download release firmware response has no payload */ + + +/* Firmware Management Protocol */ + +/* Request Types */ +#define GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION 0x01 +#define GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW 0x02 +#define GB_FW_MGMT_TYPE_LOADED_FW 0x03 +#define GB_FW_MGMT_TYPE_BACKEND_FW_VERSION 0x04 +#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE 0x05 +#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED 0x06 + +#define GB_FW_LOAD_METHOD_UNIPRO 0x01 +#define GB_FW_LOAD_METHOD_INTERNAL 0x02 + +#define GB_FW_LOAD_STATUS_FAILED 0x00 +#define GB_FW_LOAD_STATUS_UNVALIDATED 0x01 +#define GB_FW_LOAD_STATUS_VALIDATED 0x02 +#define GB_FW_LOAD_STATUS_VALIDATION_FAILED 0x03 + +#define GB_FW_BACKEND_FW_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FIND 0x02 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 +#define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 +#define GB_FW_BACKEND_FW_STATUS_INT 0x05 +#define GB_FW_BACKEND_FW_STATUS_RETRY 0x06 +#define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 + +#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 +#define GB_FW_BACKEND_VERSION_STATUS_RETRY 0x04 +#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT 0x05 + +/* firmware management interface firmware version request has no payload */ +struct gb_fw_mgmt_interface_fw_version_response { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; + __le16 major; + __le16 minor; +} __packed; + +/* firmware management load and validate firmware request/response */ +struct gb_fw_mgmt_load_and_validate_fw_request { + __u8 request_id; + __u8 load_method; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; +/* firmware management load and validate firmware response has no payload*/ + +/* firmware management loaded firmware request */ +struct gb_fw_mgmt_loaded_fw_request { + __u8 request_id; + __u8 status; + __le16 major; + __le16 minor; +} __packed; +/* firmware management loaded firmware response has no payload */ + +/* firmware management backend firmware version request/response */ +struct gb_fw_mgmt_backend_fw_version_request { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; + +struct gb_fw_mgmt_backend_fw_version_response { + __le16 major; + __le16 minor; + __u8 status; +} __packed; + +/* firmware management backend firmware update request */ +struct gb_fw_mgmt_backend_fw_update_request { + __u8 request_id; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; +/* firmware management backend firmware update response has no payload */ + +/* firmware management backend firmware updated request */ +struct gb_fw_mgmt_backend_fw_updated_request { + __u8 request_id; + __u8 status; +} __packed; +/* firmware management backend firmware updated response has no payload */ + + +/* Component Authentication Protocol (CAP) */ + +/* Request Types */ +#define GB_CAP_TYPE_GET_ENDPOINT_UID 0x01 +#define GB_CAP_TYPE_GET_IMS_CERTIFICATE 0x02 +#define GB_CAP_TYPE_AUTHENTICATE 0x03 + +/* CAP get endpoint uid request has no payload */ +struct gb_cap_get_endpoint_uid_response { + __u8 uid[8]; +} __packed; + +/* CAP get endpoint ims certificate request/response */ +struct gb_cap_get_ims_certificate_request { + __le32 certificate_class; + __le32 certificate_id; +} __packed; + +struct gb_cap_get_ims_certificate_response { + __u8 result_code; + __u8 certificate[0]; +} __packed; + +/* CAP authenticate request/response */ +struct gb_cap_authenticate_request { + __le32 auth_type; + __u8 uid[8]; + __u8 challenge[32]; +} __packed; + +struct gb_cap_authenticate_response { + __u8 result_code; + __u8 response[64]; + __u8 signature[0]; +} __packed; + + +/* Bootrom Protocol */ + +/* Version of the Greybus bootrom protocol we support */ +#define GB_BOOTROM_VERSION_MAJOR 0x00 +#define GB_BOOTROM_VERSION_MINOR 0x01 + +/* Greybus bootrom request types */ +#define GB_BOOTROM_TYPE_VERSION 0x01 +#define GB_BOOTROM_TYPE_FIRMWARE_SIZE 0x02 +#define GB_BOOTROM_TYPE_GET_FIRMWARE 0x03 +#define GB_BOOTROM_TYPE_READY_TO_BOOT 0x04 +#define GB_BOOTROM_TYPE_AP_READY 0x05 /* Request with no-payload */ +#define GB_BOOTROM_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ + +/* Greybus bootrom boot stages */ +#define GB_BOOTROM_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ +#define GB_BOOTROM_BOOT_STAGE_TWO 0x02 /* Bootrom package to be loaded by the boot ROM */ +#define GB_BOOTROM_BOOT_STAGE_THREE 0x03 /* Module personality package loaded by Stage 2 firmware */ + +/* Greybus bootrom ready to boot status */ +#define GB_BOOTROM_BOOT_STATUS_INVALID 0x00 /* Firmware blob could not be validated */ +#define GB_BOOTROM_BOOT_STATUS_INSECURE 0x01 /* Firmware blob is valid but insecure */ +#define GB_BOOTROM_BOOT_STATUS_SECURE 0x02 /* Firmware blob is valid and secure */ + +/* Max bootrom data fetch size in bytes */ +#define GB_BOOTROM_FETCH_MAX 2000 + +struct gb_bootrom_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_bootrom_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* Bootrom protocol firmware size request/response */ +struct gb_bootrom_firmware_size_request { + __u8 stage; +} __packed; + +struct gb_bootrom_firmware_size_response { + __le32 size; +} __packed; + +/* Bootrom protocol get firmware request/response */ +struct gb_bootrom_get_firmware_request { + __le32 offset; + __le32 size; +} __packed; + +struct gb_bootrom_get_firmware_response { + __u8 data[0]; +} __packed; + +/* Bootrom protocol Ready to boot request */ +struct gb_bootrom_ready_to_boot_request { + __u8 status; +} __packed; +/* Bootrom protocol Ready to boot response has no payload */ + +/* Bootrom protocol get VID/PID request has no payload */ +struct gb_bootrom_get_vid_pid_response { + __le32 vendor_id; + __le32 product_id; +} __packed; + + +/* Power Supply */ + +/* Greybus power supply request types */ +#define GB_POWER_SUPPLY_TYPE_GET_SUPPLIES 0x02 +#define GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION 0x03 +#define GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS 0x04 +#define GB_POWER_SUPPLY_TYPE_GET_PROPERTY 0x05 +#define GB_POWER_SUPPLY_TYPE_SET_PROPERTY 0x06 +#define GB_POWER_SUPPLY_TYPE_EVENT 0x07 + +/* Greybus power supply battery technologies types */ +#define GB_POWER_SUPPLY_TECH_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_TECH_NiMH 0x0001 +#define GB_POWER_SUPPLY_TECH_LION 0x0002 +#define GB_POWER_SUPPLY_TECH_LIPO 0x0003 +#define GB_POWER_SUPPLY_TECH_LiFe 0x0004 +#define GB_POWER_SUPPLY_TECH_NiCd 0x0005 +#define GB_POWER_SUPPLY_TECH_LiMn 0x0006 + +/* Greybus power supply types */ +#define GB_POWER_SUPPLY_UNKNOWN_TYPE 0x0000 +#define GB_POWER_SUPPLY_BATTERY_TYPE 0x0001 +#define GB_POWER_SUPPLY_UPS_TYPE 0x0002 +#define GB_POWER_SUPPLY_MAINS_TYPE 0x0003 +#define GB_POWER_SUPPLY_USB_TYPE 0x0004 +#define GB_POWER_SUPPLY_USB_DCP_TYPE 0x0005 +#define GB_POWER_SUPPLY_USB_CDP_TYPE 0x0006 +#define GB_POWER_SUPPLY_USB_ACA_TYPE 0x0007 + +/* Greybus power supply health values */ +#define GB_POWER_SUPPLY_HEALTH_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_HEALTH_GOOD 0x0001 +#define GB_POWER_SUPPLY_HEALTH_OVERHEAT 0x0002 +#define GB_POWER_SUPPLY_HEALTH_DEAD 0x0003 +#define GB_POWER_SUPPLY_HEALTH_OVERVOLTAGE 0x0004 +#define GB_POWER_SUPPLY_HEALTH_UNSPEC_FAILURE 0x0005 +#define GB_POWER_SUPPLY_HEALTH_COLD 0x0006 +#define GB_POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE 0x0007 +#define GB_POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE 0x0008 + +/* Greybus power supply status values */ +#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 +#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 +#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 +#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 + +/* Greybus power supply capacity level values */ +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL 0x0001 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_LOW 0x0002 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_NORMAL 0x0003 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_HIGH 0x0004 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_FULL 0x0005 + +/* Greybus power supply scope values */ +#define GB_POWER_SUPPLY_SCOPE_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_SCOPE_SYSTEM 0x0001 +#define GB_POWER_SUPPLY_SCOPE_DEVICE 0x0002 + +struct gb_power_supply_get_supplies_response { + __u8 supplies_count; +} __packed; + +struct gb_power_supply_get_description_request { + __u8 psy_id; +} __packed; + +struct gb_power_supply_get_description_response { + __u8 manufacturer[32]; + __u8 model[32]; + __u8 serial_number[32]; + __le16 type; + __u8 properties_count; +} __packed; + +struct gb_power_supply_props_desc { + __u8 property; +#define GB_POWER_SUPPLY_PROP_STATUS 0x00 +#define GB_POWER_SUPPLY_PROP_CHARGE_TYPE 0x01 +#define GB_POWER_SUPPLY_PROP_HEALTH 0x02 +#define GB_POWER_SUPPLY_PROP_PRESENT 0x03 +#define GB_POWER_SUPPLY_PROP_ONLINE 0x04 +#define GB_POWER_SUPPLY_PROP_AUTHENTIC 0x05 +#define GB_POWER_SUPPLY_PROP_TECHNOLOGY 0x06 +#define GB_POWER_SUPPLY_PROP_CYCLE_COUNT 0x07 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX 0x08 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN 0x09 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN 0x0A +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN 0x0B +#define GB_POWER_SUPPLY_PROP_VOLTAGE_NOW 0x0C +#define GB_POWER_SUPPLY_PROP_VOLTAGE_AVG 0x0D +#define GB_POWER_SUPPLY_PROP_VOLTAGE_OCV 0x0E +#define GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT 0x0F +#define GB_POWER_SUPPLY_PROP_CURRENT_MAX 0x10 +#define GB_POWER_SUPPLY_PROP_CURRENT_NOW 0x11 +#define GB_POWER_SUPPLY_PROP_CURRENT_AVG 0x12 +#define GB_POWER_SUPPLY_PROP_CURRENT_BOOT 0x13 +#define GB_POWER_SUPPLY_PROP_POWER_NOW 0x14 +#define GB_POWER_SUPPLY_PROP_POWER_AVG 0x15 +#define GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN 0x16 +#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN 0x17 +#define GB_POWER_SUPPLY_PROP_CHARGE_FULL 0x18 +#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY 0x19 +#define GB_POWER_SUPPLY_PROP_CHARGE_NOW 0x1A +#define GB_POWER_SUPPLY_PROP_CHARGE_AVG 0x1B +#define GB_POWER_SUPPLY_PROP_CHARGE_COUNTER 0x1C +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT 0x1D +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX 0x1E +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE 0x1F +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX 0x20 +#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT 0x21 +#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX 0x22 +#define GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT 0x23 +#define GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN 0x24 +#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN 0x25 +#define GB_POWER_SUPPLY_PROP_ENERGY_FULL 0x26 +#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY 0x27 +#define GB_POWER_SUPPLY_PROP_ENERGY_NOW 0x28 +#define GB_POWER_SUPPLY_PROP_ENERGY_AVG 0x29 +#define GB_POWER_SUPPLY_PROP_CAPACITY 0x2A +#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN 0x2B +#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX 0x2C +#define GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL 0x2D +#define GB_POWER_SUPPLY_PROP_TEMP 0x2E +#define GB_POWER_SUPPLY_PROP_TEMP_MAX 0x2F +#define GB_POWER_SUPPLY_PROP_TEMP_MIN 0x30 +#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN 0x31 +#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX 0x32 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT 0x33 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN 0x34 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX 0x35 +#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW 0x36 +#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG 0x37 +#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW 0x38 +#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG 0x39 +#define GB_POWER_SUPPLY_PROP_TYPE 0x3A +#define GB_POWER_SUPPLY_PROP_SCOPE 0x3B +#define GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT 0x3C +#define GB_POWER_SUPPLY_PROP_CALIBRATE 0x3D + __u8 is_writeable; +} __packed; + +struct gb_power_supply_get_property_descriptors_request { + __u8 psy_id; +} __packed; + +struct gb_power_supply_get_property_descriptors_response { + __u8 properties_count; + struct gb_power_supply_props_desc props[]; +} __packed; + +struct gb_power_supply_get_property_request { + __u8 psy_id; + __u8 property; +} __packed; + +struct gb_power_supply_get_property_response { + __le32 prop_val; +}; + +struct gb_power_supply_set_property_request { + __u8 psy_id; + __u8 property; + __le32 prop_val; +} __packed; + +struct gb_power_supply_event_request { + __u8 psy_id; + __u8 event; +#define GB_POWER_SUPPLY_UPDATE 0x01 +} __packed; + + +/* HID */ + +/* Greybus HID operation types */ +#define GB_HID_TYPE_GET_DESC 0x02 +#define GB_HID_TYPE_GET_REPORT_DESC 0x03 +#define GB_HID_TYPE_PWR_ON 0x04 +#define GB_HID_TYPE_PWR_OFF 0x05 +#define GB_HID_TYPE_GET_REPORT 0x06 +#define GB_HID_TYPE_SET_REPORT 0x07 +#define GB_HID_TYPE_IRQ_EVENT 0x08 + +/* Report type */ +#define GB_HID_INPUT_REPORT 0 +#define GB_HID_OUTPUT_REPORT 1 +#define GB_HID_FEATURE_REPORT 2 + +/* Different request/response structures */ +/* HID get descriptor response */ +struct gb_hid_desc_response { + __u8 bLength; + __le16 wReportDescLength; + __le16 bcdHID; + __le16 wProductID; + __le16 wVendorID; + __u8 bCountryCode; +} __packed; + +/* HID get report request/response */ +struct gb_hid_get_report_request { + __u8 report_type; + __u8 report_id; +} __packed; + +/* HID set report request */ +struct gb_hid_set_report_request { + __u8 report_type; + __u8 report_id; + __u8 report[0]; +} __packed; + +/* HID input report request, via interrupt pipe */ +struct gb_hid_input_report_request { + __u8 report[0]; +} __packed; + + +/* I2C */ + +/* Greybus i2c request types */ +#define GB_I2C_TYPE_FUNCTIONALITY 0x02 +#define GB_I2C_TYPE_TRANSFER 0x05 + +/* functionality request has no payload */ +struct gb_i2c_functionality_response { + __le32 functionality; +} __packed; + +/* + * Outgoing data immediately follows the op count and ops array. + * The data for each write (master -> slave) op in the array is sent + * in order, with no (e.g. pad) bytes separating them. + * + * Short reads cause the entire transfer request to fail So response + * payload consists only of bytes read, and the number of bytes is + * exactly what was specified in the corresponding op. Like + * outgoing data, the incoming data is in order and contiguous. + */ +struct gb_i2c_transfer_op { + __le16 addr; + __le16 flags; + __le16 size; +} __packed; + +struct gb_i2c_transfer_request { + __le16 op_count; + struct gb_i2c_transfer_op ops[0]; /* op_count of these */ +} __packed; +struct gb_i2c_transfer_response { + __u8 data[0]; /* inbound data */ +} __packed; + + +/* GPIO */ + +/* Greybus GPIO request types */ +#define GB_GPIO_TYPE_LINE_COUNT 0x02 +#define GB_GPIO_TYPE_ACTIVATE 0x03 +#define GB_GPIO_TYPE_DEACTIVATE 0x04 +#define GB_GPIO_TYPE_GET_DIRECTION 0x05 +#define GB_GPIO_TYPE_DIRECTION_IN 0x06 +#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 +#define GB_GPIO_TYPE_GET_VALUE 0x08 +#define GB_GPIO_TYPE_SET_VALUE 0x09 +#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_IRQ_TYPE 0x0b +#define GB_GPIO_TYPE_IRQ_MASK 0x0c +#define GB_GPIO_TYPE_IRQ_UNMASK 0x0d +#define GB_GPIO_TYPE_IRQ_EVENT 0x0e + +#define GB_GPIO_IRQ_TYPE_NONE 0x00 +#define GB_GPIO_IRQ_TYPE_EDGE_RISING 0x01 +#define GB_GPIO_IRQ_TYPE_EDGE_FALLING 0x02 +#define GB_GPIO_IRQ_TYPE_EDGE_BOTH 0x03 +#define GB_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04 +#define GB_GPIO_IRQ_TYPE_LEVEL_LOW 0x08 + +/* line count request has no payload */ +struct gb_gpio_line_count_response { + __u8 count; +} __packed; + +struct gb_gpio_activate_request { + __u8 which; +} __packed; +/* activate response has no payload */ + +struct gb_gpio_deactivate_request { + __u8 which; +} __packed; +/* deactivate response has no payload */ + +struct gb_gpio_get_direction_request { + __u8 which; +} __packed; +struct gb_gpio_get_direction_response { + __u8 direction; +} __packed; + +struct gb_gpio_direction_in_request { + __u8 which; +} __packed; +/* direction in response has no payload */ + +struct gb_gpio_direction_out_request { + __u8 which; + __u8 value; +} __packed; +/* direction out response has no payload */ + +struct gb_gpio_get_value_request { + __u8 which; +} __packed; +struct gb_gpio_get_value_response { + __u8 value; +} __packed; + +struct gb_gpio_set_value_request { + __u8 which; + __u8 value; +} __packed; +/* set value response has no payload */ + +struct gb_gpio_set_debounce_request { + __u8 which; + __le16 usec; +} __packed; +/* debounce response has no payload */ + +struct gb_gpio_irq_type_request { + __u8 which; + __u8 type; +} __packed; +/* irq type response has no payload */ + +struct gb_gpio_irq_mask_request { + __u8 which; +} __packed; +/* irq mask response has no payload */ + +struct gb_gpio_irq_unmask_request { + __u8 which; +} __packed; +/* irq unmask response has no payload */ + +/* irq event requests originate on another module and are handled on the AP */ +struct gb_gpio_irq_event_request { + __u8 which; +} __packed; +/* irq event has no response */ + + +/* PWM */ + +/* Greybus PWM operation types */ +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 + +/* pwm count request has no payload */ +struct gb_pwm_count_response { + __u8 count; +} __packed; + +struct gb_pwm_activate_request { + __u8 which; +} __packed; + +struct gb_pwm_deactivate_request { + __u8 which; +} __packed; + +struct gb_pwm_config_request { + __u8 which; + __le32 duty; + __le32 period; +} __packed; + +struct gb_pwm_polarity_request { + __u8 which; + __u8 polarity; +} __packed; + +struct gb_pwm_enable_request { + __u8 which; +} __packed; + +struct gb_pwm_disable_request { + __u8 which; +} __packed; + +/* SPI */ + +/* Should match up with modes in linux/spi/spi.h */ +#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ +#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ +#define GB_SPI_MODE_MODE_0 (0|0) /* (original MicroWire) */ +#define GB_SPI_MODE_MODE_1 (0|GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL|0) +#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL|GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ +#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ +#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ +#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ +#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ +#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ + +/* Should match up with flags in linux/spi/spi.h */ +#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ +#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ +#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ + +/* Greybus spi operation types */ +#define GB_SPI_TYPE_MASTER_CONFIG 0x02 +#define GB_SPI_TYPE_DEVICE_CONFIG 0x03 +#define GB_SPI_TYPE_TRANSFER 0x04 + +/* mode request has no payload */ +struct gb_spi_master_config_response { + __le32 bits_per_word_mask; + __le32 min_speed_hz; + __le32 max_speed_hz; + __le16 mode; + __le16 flags; + __u8 num_chipselect; +} __packed; + +struct gb_spi_device_config_request { + __u8 chip_select; +} __packed; + +struct gb_spi_device_config_response { + __le16 mode; + __u8 bits_per_word; + __le32 max_speed_hz; + __u8 device_type; +#define GB_SPI_SPI_DEV 0x00 +#define GB_SPI_SPI_NOR 0x01 +#define GB_SPI_SPI_MODALIAS 0x02 + __u8 name[32]; +} __packed; + +/** + * struct gb_spi_transfer - a read/write buffer pair + * @speed_hz: Select a speed other than the device default for this transfer. If + * 0 the default (from @spi_device) is used. + * @len: size of rx and tx buffers (in bytes) + * @delay_usecs: microseconds to delay after this transfer before (optionally) + * changing the chipselect status, then starting the next transfer or + * completing this spi_message. + * @cs_change: affects chipselect after this transfer completes + * @bits_per_word: select a bits_per_word other than the device default for this + * transfer. If 0 the default (from @spi_device) is used. + */ +struct gb_spi_transfer { + __le32 speed_hz; + __le32 len; + __le16 delay_usecs; + __u8 cs_change; + __u8 bits_per_word; + __u8 xfer_flags; +#define GB_SPI_XFER_READ 0x01 +#define GB_SPI_XFER_WRITE 0x02 +#define GB_SPI_XFER_INPROGRESS 0x04 +} __packed; + +struct gb_spi_transfer_request { + __u8 chip_select; /* of the spi device */ + __u8 mode; /* of the spi device */ + __le16 count; + struct gb_spi_transfer transfers[0]; /* count of these */ +} __packed; + +struct gb_spi_transfer_response { + __u8 data[0]; /* inbound data */ +} __packed; + +/* Version of the Greybus SVC protocol we support */ +#define GB_SVC_VERSION_MAJOR 0x00 +#define GB_SVC_VERSION_MINOR 0x01 + +/* Greybus SVC request types */ +#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 +#define GB_SVC_TYPE_SVC_HELLO 0x02 +#define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 +#define GB_SVC_TYPE_INTF_RESET 0x06 +#define GB_SVC_TYPE_CONN_CREATE 0x07 +#define GB_SVC_TYPE_CONN_DESTROY 0x08 +#define GB_SVC_TYPE_DME_PEER_GET 0x09 +#define GB_SVC_TYPE_DME_PEER_SET 0x0a +#define GB_SVC_TYPE_ROUTE_CREATE 0x0b +#define GB_SVC_TYPE_ROUTE_DESTROY 0x0c +#define GB_SVC_TYPE_TIMESYNC_ENABLE 0x0d +#define GB_SVC_TYPE_TIMESYNC_DISABLE 0x0e +#define GB_SVC_TYPE_TIMESYNC_AUTHORITATIVE 0x0f +#define GB_SVC_TYPE_INTF_SET_PWRM 0x10 +#define GB_SVC_TYPE_INTF_EJECT 0x11 +#define GB_SVC_TYPE_PING 0x13 +#define GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET 0x14 +#define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 +#define GB_SVC_TYPE_PWRMON_SAMPLE_GET 0x16 +#define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 +#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE 0x18 +#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE 0x19 +#define GB_SVC_TYPE_TIMESYNC_PING 0x1a +#define GB_SVC_TYPE_MODULE_INSERTED 0x1f +#define GB_SVC_TYPE_MODULE_REMOVED 0x20 +#define GB_SVC_TYPE_INTF_VSYS_ENABLE 0x21 +#define GB_SVC_TYPE_INTF_VSYS_DISABLE 0x22 +#define GB_SVC_TYPE_INTF_REFCLK_ENABLE 0x23 +#define GB_SVC_TYPE_INTF_REFCLK_DISABLE 0x24 +#define GB_SVC_TYPE_INTF_UNIPRO_ENABLE 0x25 +#define GB_SVC_TYPE_INTF_UNIPRO_DISABLE 0x26 +#define GB_SVC_TYPE_INTF_ACTIVATE 0x27 +#define GB_SVC_TYPE_INTF_RESUME 0x28 +#define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 +#define GB_SVC_TYPE_INTF_OOPS 0x2a + +/* Greybus SVC protocol status values */ +#define GB_SVC_OP_SUCCESS 0x00 +#define GB_SVC_OP_UNKNOWN_ERROR 0x01 +#define GB_SVC_INTF_NOT_DETECTED 0x02 +#define GB_SVC_INTF_NO_UPRO_LINK 0x03 +#define GB_SVC_INTF_UPRO_NOT_DOWN 0x04 +#define GB_SVC_INTF_UPRO_NOT_HIBERNATED 0x05 +#define GB_SVC_INTF_NO_V_SYS 0x06 +#define GB_SVC_INTF_V_CHG 0x07 +#define GB_SVC_INTF_WAKE_BUSY 0x08 +#define GB_SVC_INTF_NO_REFCLK 0x09 +#define GB_SVC_INTF_RELEASING 0x0a +#define GB_SVC_INTF_NO_ORDER 0x0b +#define GB_SVC_INTF_MBOX_SET 0x0c +#define GB_SVC_INTF_BAD_MBOX 0x0d +#define GB_SVC_INTF_OP_TIMEOUT 0x0e +#define GB_SVC_PWRMON_OP_NOT_PRESENT 0x0f + +struct gb_svc_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_svc_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* SVC protocol hello request */ +struct gb_svc_hello_request { + __le16 endo_id; + __u8 interface_id; +} __packed; +/* hello response has no payload */ + +struct gb_svc_intf_device_id_request { + __u8 intf_id; + __u8 device_id; +} __packed; +/* device id response has no payload */ + +struct gb_svc_intf_reset_request { + __u8 intf_id; +} __packed; +/* interface reset response has no payload */ + +struct gb_svc_intf_eject_request { + __u8 intf_id; +} __packed; +/* interface eject response has no payload */ + +struct gb_svc_conn_create_request { + __u8 intf1_id; + __le16 cport1_id; + __u8 intf2_id; + __le16 cport2_id; + __u8 tc; + __u8 flags; +} __packed; +/* connection create response has no payload */ + +struct gb_svc_conn_destroy_request { + __u8 intf1_id; + __le16 cport1_id; + __u8 intf2_id; + __le16 cport2_id; +} __packed; +/* connection destroy response has no payload */ + +struct gb_svc_dme_peer_get_request { + __u8 intf_id; + __le16 attr; + __le16 selector; +} __packed; + +struct gb_svc_dme_peer_get_response { + __le16 result_code; + __le32 attr_value; +} __packed; + +struct gb_svc_dme_peer_set_request { + __u8 intf_id; + __le16 attr; + __le16 selector; + __le32 value; +} __packed; + +struct gb_svc_dme_peer_set_response { + __le16 result_code; +} __packed; + +/* Greybus init-status values, currently retrieved using DME peer gets. */ +#define GB_INIT_SPI_BOOT_STARTED 0x02 +#define GB_INIT_TRUSTED_SPI_BOOT_FINISHED 0x03 +#define GB_INIT_UNTRUSTED_SPI_BOOT_FINISHED 0x04 +#define GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED 0x06 +#define GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED 0x09 +#define GB_INIT_S2_LOADER_BOOT_STARTED 0x0D + +struct gb_svc_route_create_request { + __u8 intf1_id; + __u8 dev1_id; + __u8 intf2_id; + __u8 dev2_id; +} __packed; +/* route create response has no payload */ + +struct gb_svc_route_destroy_request { + __u8 intf1_id; + __u8 intf2_id; +} __packed; +/* route destroy response has no payload */ + +/* used for svc_intf_vsys_{enable,disable} */ +struct gb_svc_intf_vsys_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_vsys_response { + __u8 result_code; +#define GB_SVC_INTF_VSYS_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_VSYS_FAIL 0x02 +} __packed; + +/* used for svc_intf_refclk_{enable,disable} */ +struct gb_svc_intf_refclk_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_refclk_response { + __u8 result_code; +#define GB_SVC_INTF_REFCLK_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_REFCLK_FAIL 0x02 +} __packed; + +/* used for svc_intf_unipro_{enable,disable} */ +struct gb_svc_intf_unipro_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_unipro_response { + __u8 result_code; +#define GB_SVC_INTF_UNIPRO_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_UNIPRO_FAIL 0x02 +#define GB_SVC_INTF_UNIPRO_NOT_OFF 0x03 +} __packed; + +struct gb_svc_timesync_enable_request { + __u8 count; + __le64 frame_time; + __le32 strobe_delay; + __le32 refclk; +} __packed; +/* timesync enable response has no payload */ + +/* timesync authoritative request has no payload */ +struct gb_svc_timesync_authoritative_response { + __le64 frame_time[GB_TIMESYNC_MAX_STROBES]; +}; + +struct gb_svc_timesync_wake_pins_acquire_request { + __le32 strobe_mask; +}; + +/* timesync wake pins acquire response has no payload */ + +/* timesync wake pins release request has no payload */ +/* timesync wake pins release response has no payload */ + +/* timesync svc ping request has no payload */ +struct gb_svc_timesync_ping_response { + __le64 frame_time; +} __packed; + +#define GB_SVC_UNIPRO_FAST_MODE 0x01 +#define GB_SVC_UNIPRO_SLOW_MODE 0x02 +#define GB_SVC_UNIPRO_FAST_AUTO_MODE 0x04 +#define GB_SVC_UNIPRO_SLOW_AUTO_MODE 0x05 +#define GB_SVC_UNIPRO_MODE_UNCHANGED 0x07 +#define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 +#define GB_SVC_UNIPRO_OFF_MODE 0x12 + +#define GB_SVC_SMALL_AMPLITUDE 0x01 +#define GB_SVC_LARGE_AMPLITUDE 0x02 + +#define GB_SVC_NO_DE_EMPHASIS 0x00 +#define GB_SVC_SMALL_DE_EMPHASIS 0x01 +#define GB_SVC_LARGE_DE_EMPHASIS 0x02 + +#define GB_SVC_PWRM_RXTERMINATION 0x01 +#define GB_SVC_PWRM_TXTERMINATION 0x02 +#define GB_SVC_PWRM_LINE_RESET 0x04 +#define GB_SVC_PWRM_SCRAMBLING 0x20 + +#define GB_SVC_PWRM_QUIRK_HSSER 0x00000001 + +#define GB_SVC_UNIPRO_HS_SERIES_A 0x01 +#define GB_SVC_UNIPRO_HS_SERIES_B 0x02 + +#define GB_SVC_SETPWRM_PWR_OK 0x00 +#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 +#define GB_SVC_SETPWRM_PWR_REMOTE 0x02 +#define GB_SVC_SETPWRM_PWR_BUSY 0x03 +#define GB_SVC_SETPWRM_PWR_ERROR_CAP 0x04 +#define GB_SVC_SETPWRM_PWR_FATAL_ERROR 0x05 + +struct gb_svc_l2_timer_cfg { + __le16 tsb_fc0_protection_timeout; + __le16 tsb_tc0_replay_timeout; + __le16 tsb_afc0_req_timeout; + __le16 tsb_fc1_protection_timeout; + __le16 tsb_tc1_replay_timeout; + __le16 tsb_afc1_req_timeout; + __le16 reserved_for_tc2[3]; + __le16 reserved_for_tc3[3]; +} __packed; + +struct gb_svc_intf_set_pwrm_request { + __u8 intf_id; + __u8 hs_series; + __u8 tx_mode; + __u8 tx_gear; + __u8 tx_nlanes; + __u8 tx_amplitude; + __u8 tx_hs_equalizer; + __u8 rx_mode; + __u8 rx_gear; + __u8 rx_nlanes; + __u8 flags; + __le32 quirks; + struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata; +} __packed; + +struct gb_svc_intf_set_pwrm_response { + __u8 result_code; +} __packed; + +struct gb_svc_key_event_request { + __le16 key_code; +#define GB_KEYCODE_ARA 0x00 + + __u8 key_event; +#define GB_SVC_KEY_RELEASED 0x00 +#define GB_SVC_KEY_PRESSED 0x01 +} __packed; + +#define GB_SVC_PWRMON_MAX_RAIL_COUNT 254 + +struct gb_svc_pwrmon_rail_count_get_response { + __u8 rail_count; +} __packed; + +#define GB_SVC_PWRMON_RAIL_NAME_BUFSIZE 32 + +struct gb_svc_pwrmon_rail_names_get_response { + __u8 status; + __u8 name[0][GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; +} __packed; + +#define GB_SVC_PWRMON_TYPE_CURR 0x01 +#define GB_SVC_PWRMON_TYPE_VOL 0x02 +#define GB_SVC_PWRMON_TYPE_PWR 0x03 + +#define GB_SVC_PWRMON_GET_SAMPLE_OK 0x00 +#define GB_SVC_PWRMON_GET_SAMPLE_INVAL 0x01 +#define GB_SVC_PWRMON_GET_SAMPLE_NOSUPP 0x02 +#define GB_SVC_PWRMON_GET_SAMPLE_HWERR 0x03 + +struct gb_svc_pwrmon_sample_get_request { + __u8 rail_id; + __u8 measurement_type; +} __packed; + +struct gb_svc_pwrmon_sample_get_response { + __u8 result; + __le32 measurement; +} __packed; + +struct gb_svc_pwrmon_intf_sample_get_request { + __u8 intf_id; + __u8 measurement_type; +} __packed; + +struct gb_svc_pwrmon_intf_sample_get_response { + __u8 result; + __le32 measurement; +} __packed; + +#define GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY 0x0001 + +struct gb_svc_module_inserted_request { + __u8 primary_intf_id; + __u8 intf_count; + __le16 flags; +} __packed; +/* module_inserted response has no payload */ + +struct gb_svc_module_removed_request { + __u8 primary_intf_id; +} __packed; +/* module_removed response has no payload */ + +struct gb_svc_intf_activate_request { + __u8 intf_id; +} __packed; + +#define GB_SVC_INTF_TYPE_UNKNOWN 0x00 +#define GB_SVC_INTF_TYPE_DUMMY 0x01 +#define GB_SVC_INTF_TYPE_UNIPRO 0x02 +#define GB_SVC_INTF_TYPE_GREYBUS 0x03 + +struct gb_svc_intf_activate_response { + __u8 status; + __u8 intf_type; +} __packed; + +struct gb_svc_intf_resume_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_resume_response { + __u8 status; +} __packed; + +#define GB_SVC_INTF_MAILBOX_NONE 0x00 +#define GB_SVC_INTF_MAILBOX_AP 0x01 +#define GB_SVC_INTF_MAILBOX_GREYBUS 0x02 + +struct gb_svc_intf_mailbox_event_request { + __u8 intf_id; + __le16 result_code; + __le32 mailbox; +} __packed; +/* intf_mailbox_event response has no payload */ + +struct gb_svc_intf_oops_request { + __u8 intf_id; + __u8 reason; +} __packed; +/* intf_oops response has no payload */ + + +/* RAW */ + +/* Greybus raw request types */ +#define GB_RAW_TYPE_SEND 0x02 + +struct gb_raw_send_request { + __le32 len; + __u8 data[0]; +} __packed; + + +/* UART */ + +/* Greybus UART operation types */ +#define GB_UART_TYPE_SEND_DATA 0x02 +#define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ +#define GB_UART_TYPE_SET_LINE_CODING 0x04 +#define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 +#define GB_UART_TYPE_SEND_BREAK 0x06 +#define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ +#define GB_UART_TYPE_RECEIVE_CREDITS 0x08 +#define GB_UART_TYPE_FLUSH_FIFOS 0x09 + +/* Represents data from AP -> Module */ +struct gb_uart_send_data_request { + __le16 size; + __u8 data[0]; +} __packed; + +/* recv-data-request flags */ +#define GB_UART_RECV_FLAG_FRAMING 0x01 /* Framing error */ +#define GB_UART_RECV_FLAG_PARITY 0x02 /* Parity error */ +#define GB_UART_RECV_FLAG_OVERRUN 0x04 /* Overrun error */ +#define GB_UART_RECV_FLAG_BREAK 0x08 /* Break */ + +/* Represents data from Module -> AP */ +struct gb_uart_recv_data_request { + __le16 size; + __u8 flags; + __u8 data[0]; +} __packed; + +struct gb_uart_receive_credits_request { + __le16 count; +} __packed; + +struct gb_uart_set_line_coding_request { + __le32 rate; + __u8 format; +#define GB_SERIAL_1_STOP_BITS 0 +#define GB_SERIAL_1_5_STOP_BITS 1 +#define GB_SERIAL_2_STOP_BITS 2 + + __u8 parity; +#define GB_SERIAL_NO_PARITY 0 +#define GB_SERIAL_ODD_PARITY 1 +#define GB_SERIAL_EVEN_PARITY 2 +#define GB_SERIAL_MARK_PARITY 3 +#define GB_SERIAL_SPACE_PARITY 4 + + __u8 data_bits; + + __u8 flow_control; +#define GB_SERIAL_AUTO_RTSCTS_EN 0x1 +} __packed; + +/* output control lines */ +#define GB_UART_CTRL_DTR 0x01 +#define GB_UART_CTRL_RTS 0x02 + +struct gb_uart_set_control_line_state_request { + __u8 control; +} __packed; + +struct gb_uart_set_break_request { + __u8 state; +} __packed; + +/* input control lines and line errors */ +#define GB_UART_CTRL_DCD 0x01 +#define GB_UART_CTRL_DSR 0x02 +#define GB_UART_CTRL_RI 0x04 + +struct gb_uart_serial_state_request { + __u8 control; +} __packed; + +struct gb_uart_serial_flush_request { + __u8 flags; +#define GB_SERIAL_FLAG_FLUSH_TRANSMITTER 0x01 +#define GB_SERIAL_FLAG_FLUSH_RECEIVER 0x02 +} __packed; + +/* Loopback */ + +/* Greybus loopback request types */ +#define GB_LOOPBACK_TYPE_PING 0x02 +#define GB_LOOPBACK_TYPE_TRANSFER 0x03 +#define GB_LOOPBACK_TYPE_SINK 0x04 + +/* + * Loopback request/response header format should be identical + * to simplify bandwidth and data movement analysis. + */ +struct gb_loopback_transfer_request { + __le32 len; + __le32 reserved0; + __le32 reserved1; + __u8 data[0]; +} __packed; + +struct gb_loopback_transfer_response { + __le32 len; + __le32 reserved0; + __le32 reserved1; + __u8 data[0]; +} __packed; + +/* SDIO */ +/* Greybus SDIO operation types */ +#define GB_SDIO_TYPE_GET_CAPABILITIES 0x02 +#define GB_SDIO_TYPE_SET_IOS 0x03 +#define GB_SDIO_TYPE_COMMAND 0x04 +#define GB_SDIO_TYPE_TRANSFER 0x05 +#define GB_SDIO_TYPE_EVENT 0x06 + +/* get caps response: request has no payload */ +struct gb_sdio_get_caps_response { + __le32 caps; +#define GB_SDIO_CAP_NONREMOVABLE 0x00000001 +#define GB_SDIO_CAP_4_BIT_DATA 0x00000002 +#define GB_SDIO_CAP_8_BIT_DATA 0x00000004 +#define GB_SDIO_CAP_MMC_HS 0x00000008 +#define GB_SDIO_CAP_SD_HS 0x00000010 +#define GB_SDIO_CAP_ERASE 0x00000020 +#define GB_SDIO_CAP_1_2V_DDR 0x00000040 +#define GB_SDIO_CAP_1_8V_DDR 0x00000080 +#define GB_SDIO_CAP_POWER_OFF_CARD 0x00000100 +#define GB_SDIO_CAP_UHS_SDR12 0x00000200 +#define GB_SDIO_CAP_UHS_SDR25 0x00000400 +#define GB_SDIO_CAP_UHS_SDR50 0x00000800 +#define GB_SDIO_CAP_UHS_SDR104 0x00001000 +#define GB_SDIO_CAP_UHS_DDR50 0x00002000 +#define GB_SDIO_CAP_DRIVER_TYPE_A 0x00004000 +#define GB_SDIO_CAP_DRIVER_TYPE_C 0x00008000 +#define GB_SDIO_CAP_DRIVER_TYPE_D 0x00010000 +#define GB_SDIO_CAP_HS200_1_2V 0x00020000 +#define GB_SDIO_CAP_HS200_1_8V 0x00040000 +#define GB_SDIO_CAP_HS400_1_2V 0x00080000 +#define GB_SDIO_CAP_HS400_1_8V 0x00100000 + + /* see possible values below at vdd */ + __le32 ocr; + __le32 f_min; + __le32 f_max; + __le16 max_blk_count; + __le16 max_blk_size; +} __packed; + +/* set ios request: response has no payload */ +struct gb_sdio_set_ios_request { + __le32 clock; + __le32 vdd; +#define GB_SDIO_VDD_165_195 0x00000001 +#define GB_SDIO_VDD_20_21 0x00000002 +#define GB_SDIO_VDD_21_22 0x00000004 +#define GB_SDIO_VDD_22_23 0x00000008 +#define GB_SDIO_VDD_23_24 0x00000010 +#define GB_SDIO_VDD_24_25 0x00000020 +#define GB_SDIO_VDD_25_26 0x00000040 +#define GB_SDIO_VDD_26_27 0x00000080 +#define GB_SDIO_VDD_27_28 0x00000100 +#define GB_SDIO_VDD_28_29 0x00000200 +#define GB_SDIO_VDD_29_30 0x00000400 +#define GB_SDIO_VDD_30_31 0x00000800 +#define GB_SDIO_VDD_31_32 0x00001000 +#define GB_SDIO_VDD_32_33 0x00002000 +#define GB_SDIO_VDD_33_34 0x00004000 +#define GB_SDIO_VDD_34_35 0x00008000 +#define GB_SDIO_VDD_35_36 0x00010000 + + __u8 bus_mode; +#define GB_SDIO_BUSMODE_OPENDRAIN 0x00 +#define GB_SDIO_BUSMODE_PUSHPULL 0x01 + + __u8 power_mode; +#define GB_SDIO_POWER_OFF 0x00 +#define GB_SDIO_POWER_UP 0x01 +#define GB_SDIO_POWER_ON 0x02 +#define GB_SDIO_POWER_UNDEFINED 0x03 + + __u8 bus_width; +#define GB_SDIO_BUS_WIDTH_1 0x00 +#define GB_SDIO_BUS_WIDTH_4 0x02 +#define GB_SDIO_BUS_WIDTH_8 0x03 + + __u8 timing; +#define GB_SDIO_TIMING_LEGACY 0x00 +#define GB_SDIO_TIMING_MMC_HS 0x01 +#define GB_SDIO_TIMING_SD_HS 0x02 +#define GB_SDIO_TIMING_UHS_SDR12 0x03 +#define GB_SDIO_TIMING_UHS_SDR25 0x04 +#define GB_SDIO_TIMING_UHS_SDR50 0x05 +#define GB_SDIO_TIMING_UHS_SDR104 0x06 +#define GB_SDIO_TIMING_UHS_DDR50 0x07 +#define GB_SDIO_TIMING_MMC_DDR52 0x08 +#define GB_SDIO_TIMING_MMC_HS200 0x09 +#define GB_SDIO_TIMING_MMC_HS400 0x0A + + __u8 signal_voltage; +#define GB_SDIO_SIGNAL_VOLTAGE_330 0x00 +#define GB_SDIO_SIGNAL_VOLTAGE_180 0x01 +#define GB_SDIO_SIGNAL_VOLTAGE_120 0x02 + + __u8 drv_type; +#define GB_SDIO_SET_DRIVER_TYPE_B 0x00 +#define GB_SDIO_SET_DRIVER_TYPE_A 0x01 +#define GB_SDIO_SET_DRIVER_TYPE_C 0x02 +#define GB_SDIO_SET_DRIVER_TYPE_D 0x03 +} __packed; + +/* command request */ +struct gb_sdio_command_request { + __u8 cmd; + __u8 cmd_flags; +#define GB_SDIO_RSP_NONE 0x00 +#define GB_SDIO_RSP_PRESENT 0x01 +#define GB_SDIO_RSP_136 0x02 +#define GB_SDIO_RSP_CRC 0x04 +#define GB_SDIO_RSP_BUSY 0x08 +#define GB_SDIO_RSP_OPCODE 0x10 + + __u8 cmd_type; +#define GB_SDIO_CMD_AC 0x00 +#define GB_SDIO_CMD_ADTC 0x01 +#define GB_SDIO_CMD_BC 0x02 +#define GB_SDIO_CMD_BCR 0x03 + + __le32 cmd_arg; + __le16 data_blocks; + __le16 data_blksz; +} __packed; + +struct gb_sdio_command_response { + __le32 resp[4]; +} __packed; + +/* transfer request */ +struct gb_sdio_transfer_request { + __u8 data_flags; +#define GB_SDIO_DATA_WRITE 0x01 +#define GB_SDIO_DATA_READ 0x02 +#define GB_SDIO_DATA_STREAM 0x04 + + __le16 data_blocks; + __le16 data_blksz; + __u8 data[0]; +} __packed; + +struct gb_sdio_transfer_response { + __le16 data_blocks; + __le16 data_blksz; + __u8 data[0]; +} __packed; + +/* event request: generated by module and is defined as unidirectional */ +struct gb_sdio_event_request { + __u8 event; +#define GB_SDIO_CARD_INSERTED 0x01 +#define GB_SDIO_CARD_REMOVED 0x02 +#define GB_SDIO_WP 0x04 +} __packed; + +/* Camera */ + +/* Greybus Camera request types */ +#define GB_CAMERA_TYPE_CAPABILITIES 0x02 +#define GB_CAMERA_TYPE_CONFIGURE_STREAMS 0x03 +#define GB_CAMERA_TYPE_CAPTURE 0x04 +#define GB_CAMERA_TYPE_FLUSH 0x05 +#define GB_CAMERA_TYPE_METADATA 0x06 + +#define GB_CAMERA_MAX_STREAMS 4 +#define GB_CAMERA_MAX_SETTINGS_SIZE 8192 + +/* Greybus Camera Configure Streams request payload */ +struct gb_camera_stream_config_request { + __le16 width; + __le16 height; + __le16 format; + __le16 padding; +} __packed; + +struct gb_camera_configure_streams_request { + __u8 num_streams; + __u8 flags; +#define GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY 0x01 + __le16 padding; + struct gb_camera_stream_config_request config[0]; +} __packed; + +/* Greybus Camera Configure Streams response payload */ +struct gb_camera_stream_config_response { + __le16 width; + __le16 height; + __le16 format; + __u8 virtual_channel; + __u8 data_type[2]; + __le16 max_pkt_size; + __u8 padding; + __le32 max_size; +} __packed; + +struct gb_camera_configure_streams_response { + __u8 num_streams; +#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 + __u8 flags; + __u8 padding[2]; + __le32 data_rate; + struct gb_camera_stream_config_response config[0]; +}; + +/* Greybus Camera Capture request payload - response has no payload */ +struct gb_camera_capture_request { + __le32 request_id; + __u8 streams; + __u8 padding; + __le16 num_frames; + __u8 settings[0]; +} __packed; + +/* Greybus Camera Flush response payload - request has no payload */ +struct gb_camera_flush_response { + __le32 request_id; +} __packed; + +/* Greybus Camera Metadata request payload - operation has no response */ +struct gb_camera_metadata_request { + __le32 request_id; + __le16 frame_number; + __u8 stream; + __u8 padding; + __u8 metadata[0]; +} __packed; + +/* Lights */ + +/* Greybus Lights request types */ +#define GB_LIGHTS_TYPE_GET_LIGHTS 0x02 +#define GB_LIGHTS_TYPE_GET_LIGHT_CONFIG 0x03 +#define GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG 0x04 +#define GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG 0x05 +#define GB_LIGHTS_TYPE_SET_BRIGHTNESS 0x06 +#define GB_LIGHTS_TYPE_SET_BLINK 0x07 +#define GB_LIGHTS_TYPE_SET_COLOR 0x08 +#define GB_LIGHTS_TYPE_SET_FADE 0x09 +#define GB_LIGHTS_TYPE_EVENT 0x0A +#define GB_LIGHTS_TYPE_SET_FLASH_INTENSITY 0x0B +#define GB_LIGHTS_TYPE_SET_FLASH_STROBE 0x0C +#define GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT 0x0D +#define GB_LIGHTS_TYPE_GET_FLASH_FAULT 0x0E + +/* Greybus Light modes */ + +/* + * if you add any specific mode below, update also the + * GB_CHANNEL_MODE_DEFINED_RANGE value accordingly + */ +#define GB_CHANNEL_MODE_NONE 0x00000000 +#define GB_CHANNEL_MODE_BATTERY 0x00000001 +#define GB_CHANNEL_MODE_POWER 0x00000002 +#define GB_CHANNEL_MODE_WIRELESS 0x00000004 +#define GB_CHANNEL_MODE_BLUETOOTH 0x00000008 +#define GB_CHANNEL_MODE_KEYBOARD 0x00000010 +#define GB_CHANNEL_MODE_BUTTONS 0x00000020 +#define GB_CHANNEL_MODE_NOTIFICATION 0x00000040 +#define GB_CHANNEL_MODE_ATTENTION 0x00000080 +#define GB_CHANNEL_MODE_FLASH 0x00000100 +#define GB_CHANNEL_MODE_TORCH 0x00000200 +#define GB_CHANNEL_MODE_INDICATOR 0x00000400 + +/* Lights Mode valid bit values */ +#define GB_CHANNEL_MODE_DEFINED_RANGE 0x000004FF +#define GB_CHANNEL_MODE_VENDOR_RANGE 0x00F00000 + +/* Greybus Light Channels Flags */ +#define GB_LIGHT_CHANNEL_MULTICOLOR 0x00000001 +#define GB_LIGHT_CHANNEL_FADER 0x00000002 +#define GB_LIGHT_CHANNEL_BLINK 0x00000004 + +/* get count of lights in module */ +struct gb_lights_get_lights_response { + __u8 lights_count; +} __packed; + +/* light config request payload */ +struct gb_lights_get_light_config_request { + __u8 id; +} __packed; + +/* light config response payload */ +struct gb_lights_get_light_config_response { + __u8 channel_count; + __u8 name[32]; +} __packed; + +/* channel config request payload */ +struct gb_lights_get_channel_config_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* channel flash config request payload */ +struct gb_lights_get_channel_flash_config_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* channel config response payload */ +struct gb_lights_get_channel_config_response { + __u8 max_brightness; + __le32 flags; + __le32 color; + __u8 color_name[32]; + __le32 mode; + __u8 mode_name[32]; +} __packed; + +/* channel flash config response payload */ +struct gb_lights_get_channel_flash_config_response { + __le32 intensity_min_uA; + __le32 intensity_max_uA; + __le32 intensity_step_uA; + __le32 timeout_min_us; + __le32 timeout_max_us; + __le32 timeout_step_us; +} __packed; + +/* blink request payload: response have no payload */ +struct gb_lights_blink_request { + __u8 light_id; + __u8 channel_id; + __le16 time_on_ms; + __le16 time_off_ms; +} __packed; + +/* set brightness request payload: response have no payload */ +struct gb_lights_set_brightness_request { + __u8 light_id; + __u8 channel_id; + __u8 brightness; +} __packed; + +/* set color request payload: response have no payload */ +struct gb_lights_set_color_request { + __u8 light_id; + __u8 channel_id; + __le32 color; +} __packed; + +/* set fade request payload: response have no payload */ +struct gb_lights_set_fade_request { + __u8 light_id; + __u8 channel_id; + __u8 fade_in; + __u8 fade_out; +} __packed; + +/* event request: generated by module */ +struct gb_lights_event_request { + __u8 light_id; + __u8 event; +#define GB_LIGHTS_LIGHT_CONFIG 0x01 +} __packed; + +/* set flash intensity request payload: response have no payload */ +struct gb_lights_set_flash_intensity_request { + __u8 light_id; + __u8 channel_id; + __le32 intensity_uA; +} __packed; + +/* set flash strobe state request payload: response have no payload */ +struct gb_lights_set_flash_strobe_request { + __u8 light_id; + __u8 channel_id; + __u8 state; +} __packed; + +/* set flash timeout request payload: response have no payload */ +struct gb_lights_set_flash_timeout_request { + __u8 light_id; + __u8 channel_id; + __le32 timeout_us; +} __packed; + +/* get flash fault request payload */ +struct gb_lights_get_flash_fault_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* get flash fault response payload */ +struct gb_lights_get_flash_fault_response { + __le32 fault; +#define GB_LIGHTS_FLASH_FAULT_OVER_VOLTAGE 0x00000000 +#define GB_LIGHTS_FLASH_FAULT_TIMEOUT 0x00000001 +#define GB_LIGHTS_FLASH_FAULT_OVER_TEMPERATURE 0x00000002 +#define GB_LIGHTS_FLASH_FAULT_SHORT_CIRCUIT 0x00000004 +#define GB_LIGHTS_FLASH_FAULT_OVER_CURRENT 0x00000008 +#define GB_LIGHTS_FLASH_FAULT_INDICATOR 0x00000010 +#define GB_LIGHTS_FLASH_FAULT_UNDER_VOLTAGE 0x00000020 +#define GB_LIGHTS_FLASH_FAULT_INPUT_VOLTAGE 0x00000040 +#define GB_LIGHTS_FLASH_FAULT_LED_OVER_TEMPERATURE 0x00000080 +} __packed; + +/* Audio */ + +#define GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE 0x02 +#define GB_AUDIO_TYPE_GET_TOPOLOGY 0x03 +#define GB_AUDIO_TYPE_GET_CONTROL 0x04 +#define GB_AUDIO_TYPE_SET_CONTROL 0x05 +#define GB_AUDIO_TYPE_ENABLE_WIDGET 0x06 +#define GB_AUDIO_TYPE_DISABLE_WIDGET 0x07 +#define GB_AUDIO_TYPE_GET_PCM 0x08 +#define GB_AUDIO_TYPE_SET_PCM 0x09 +#define GB_AUDIO_TYPE_SET_TX_DATA_SIZE 0x0a + /* 0x0b unused */ +#define GB_AUDIO_TYPE_ACTIVATE_TX 0x0c +#define GB_AUDIO_TYPE_DEACTIVATE_TX 0x0d +#define GB_AUDIO_TYPE_SET_RX_DATA_SIZE 0x0e + /* 0x0f unused */ +#define GB_AUDIO_TYPE_ACTIVATE_RX 0x10 +#define GB_AUDIO_TYPE_DEACTIVATE_RX 0x11 +#define GB_AUDIO_TYPE_JACK_EVENT 0x12 +#define GB_AUDIO_TYPE_BUTTON_EVENT 0x13 +#define GB_AUDIO_TYPE_STREAMING_EVENT 0x14 +#define GB_AUDIO_TYPE_SEND_DATA 0x15 + +/* Module must be able to buffer 10ms of audio data, minimum */ +#define GB_AUDIO_SAMPLE_BUFFER_MIN_US 10000 + +#define GB_AUDIO_PCM_NAME_MAX 32 +#define AUDIO_DAI_NAME_MAX 32 +#define AUDIO_CONTROL_NAME_MAX 32 +#define AUDIO_CTL_ELEM_NAME_MAX 44 +#define AUDIO_ENUM_NAME_MAX 64 +#define AUDIO_WIDGET_NAME_MAX 32 + +/* See SNDRV_PCM_FMTBIT_* in Linux source */ +#define GB_AUDIO_PCM_FMT_S8 BIT(0) +#define GB_AUDIO_PCM_FMT_U8 BIT(1) +#define GB_AUDIO_PCM_FMT_S16_LE BIT(2) +#define GB_AUDIO_PCM_FMT_S16_BE BIT(3) +#define GB_AUDIO_PCM_FMT_U16_LE BIT(4) +#define GB_AUDIO_PCM_FMT_U16_BE BIT(5) +#define GB_AUDIO_PCM_FMT_S24_LE BIT(6) +#define GB_AUDIO_PCM_FMT_S24_BE BIT(7) +#define GB_AUDIO_PCM_FMT_U24_LE BIT(8) +#define GB_AUDIO_PCM_FMT_U24_BE BIT(9) +#define GB_AUDIO_PCM_FMT_S32_LE BIT(10) +#define GB_AUDIO_PCM_FMT_S32_BE BIT(11) +#define GB_AUDIO_PCM_FMT_U32_LE BIT(12) +#define GB_AUDIO_PCM_FMT_U32_BE BIT(13) + +/* See SNDRV_PCM_RATE_* in Linux source */ +#define GB_AUDIO_PCM_RATE_5512 BIT(0) +#define GB_AUDIO_PCM_RATE_8000 BIT(1) +#define GB_AUDIO_PCM_RATE_11025 BIT(2) +#define GB_AUDIO_PCM_RATE_16000 BIT(3) +#define GB_AUDIO_PCM_RATE_22050 BIT(4) +#define GB_AUDIO_PCM_RATE_32000 BIT(5) +#define GB_AUDIO_PCM_RATE_44100 BIT(6) +#define GB_AUDIO_PCM_RATE_48000 BIT(7) +#define GB_AUDIO_PCM_RATE_64000 BIT(8) +#define GB_AUDIO_PCM_RATE_88200 BIT(9) +#define GB_AUDIO_PCM_RATE_96000 BIT(10) +#define GB_AUDIO_PCM_RATE_176400 BIT(11) +#define GB_AUDIO_PCM_RATE_192000 BIT(12) + +#define GB_AUDIO_STREAM_TYPE_CAPTURE 0x1 +#define GB_AUDIO_STREAM_TYPE_PLAYBACK 0x2 + +#define GB_AUDIO_CTL_ELEM_ACCESS_READ BIT(0) +#define GB_AUDIO_CTL_ELEM_ACCESS_WRITE BIT(1) + +/* See SNDRV_CTL_ELEM_TYPE_* in Linux source */ +#define GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN 0x01 +#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER 0x02 +#define GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED 0x03 +#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER64 0x06 + +/* See SNDRV_CTL_ELEM_IFACE_* in Linux source */ +#define GB_AUDIO_CTL_ELEM_IFACE_CARD 0x00 +#define GB_AUDIO_CTL_ELEM_IFACE_HWDEP 0x01 +#define GB_AUDIO_CTL_ELEM_IFACE_MIXER 0x02 +#define GB_AUDIO_CTL_ELEM_IFACE_PCM 0x03 +#define GB_AUDIO_CTL_ELEM_IFACE_RAWMIDI 0x04 +#define GB_AUDIO_CTL_ELEM_IFACE_TIMER 0x05 +#define GB_AUDIO_CTL_ELEM_IFACE_SEQUENCER 0x06 + +/* SNDRV_CTL_ELEM_ACCESS_* in Linux source */ +#define GB_AUDIO_ACCESS_READ BIT(0) +#define GB_AUDIO_ACCESS_WRITE BIT(1) +#define GB_AUDIO_ACCESS_VOLATILE BIT(2) +#define GB_AUDIO_ACCESS_TIMESTAMP BIT(3) +#define GB_AUDIO_ACCESS_TLV_READ BIT(4) +#define GB_AUDIO_ACCESS_TLV_WRITE BIT(5) +#define GB_AUDIO_ACCESS_TLV_COMMAND BIT(6) +#define GB_AUDIO_ACCESS_INACTIVE BIT(7) +#define GB_AUDIO_ACCESS_LOCK BIT(8) +#define GB_AUDIO_ACCESS_OWNER BIT(9) + +/* enum snd_soc_dapm_type */ +#define GB_AUDIO_WIDGET_TYPE_INPUT 0x0 +#define GB_AUDIO_WIDGET_TYPE_OUTPUT 0x1 +#define GB_AUDIO_WIDGET_TYPE_MUX 0x2 +#define GB_AUDIO_WIDGET_TYPE_VIRT_MUX 0x3 +#define GB_AUDIO_WIDGET_TYPE_VALUE_MUX 0x4 +#define GB_AUDIO_WIDGET_TYPE_MIXER 0x5 +#define GB_AUDIO_WIDGET_TYPE_MIXER_NAMED_CTL 0x6 +#define GB_AUDIO_WIDGET_TYPE_PGA 0x7 +#define GB_AUDIO_WIDGET_TYPE_OUT_DRV 0x8 +#define GB_AUDIO_WIDGET_TYPE_ADC 0x9 +#define GB_AUDIO_WIDGET_TYPE_DAC 0xa +#define GB_AUDIO_WIDGET_TYPE_MICBIAS 0xb +#define GB_AUDIO_WIDGET_TYPE_MIC 0xc +#define GB_AUDIO_WIDGET_TYPE_HP 0xd +#define GB_AUDIO_WIDGET_TYPE_SPK 0xe +#define GB_AUDIO_WIDGET_TYPE_LINE 0xf +#define GB_AUDIO_WIDGET_TYPE_SWITCH 0x10 +#define GB_AUDIO_WIDGET_TYPE_VMID 0x11 +#define GB_AUDIO_WIDGET_TYPE_PRE 0x12 +#define GB_AUDIO_WIDGET_TYPE_POST 0x13 +#define GB_AUDIO_WIDGET_TYPE_SUPPLY 0x14 +#define GB_AUDIO_WIDGET_TYPE_REGULATOR_SUPPLY 0x15 +#define GB_AUDIO_WIDGET_TYPE_CLOCK_SUPPLY 0x16 +#define GB_AUDIO_WIDGET_TYPE_AIF_IN 0x17 +#define GB_AUDIO_WIDGET_TYPE_AIF_OUT 0x18 +#define GB_AUDIO_WIDGET_TYPE_SIGGEN 0x19 +#define GB_AUDIO_WIDGET_TYPE_DAI_IN 0x1a +#define GB_AUDIO_WIDGET_TYPE_DAI_OUT 0x1b +#define GB_AUDIO_WIDGET_TYPE_DAI_LINK 0x1c + +#define GB_AUDIO_WIDGET_STATE_DISABLED 0x01 +#define GB_AUDIO_WIDGET_STATE_ENAABLED 0x02 + +#define GB_AUDIO_JACK_EVENT_INSERTION 0x1 +#define GB_AUDIO_JACK_EVENT_REMOVAL 0x2 + +#define GB_AUDIO_BUTTON_EVENT_PRESS 0x1 +#define GB_AUDIO_BUTTON_EVENT_RELEASE 0x2 + +#define GB_AUDIO_STREAMING_EVENT_UNSPECIFIED 0x1 +#define GB_AUDIO_STREAMING_EVENT_HALT 0x2 +#define GB_AUDIO_STREAMING_EVENT_INTERNAL_ERROR 0x3 +#define GB_AUDIO_STREAMING_EVENT_PROTOCOL_ERROR 0x4 +#define GB_AUDIO_STREAMING_EVENT_FAILURE 0x5 +#define GB_AUDIO_STREAMING_EVENT_UNDERRUN 0x6 +#define GB_AUDIO_STREAMING_EVENT_OVERRUN 0x7 +#define GB_AUDIO_STREAMING_EVENT_CLOCKING 0x8 +#define GB_AUDIO_STREAMING_EVENT_DATA_LEN 0x9 + +#define GB_AUDIO_INVALID_INDEX 0xff + +/* enum snd_jack_types */ +#define GB_AUDIO_JACK_HEADPHONE 0x0000001 +#define GB_AUDIO_JACK_MICROPHONE 0x0000002 +#define GB_AUDIO_JACK_HEADSET (GB_AUDIO_JACK_HEADPHONE | \ + GB_AUDIO_JACK_MICROPHONE) +#define GB_AUDIO_JACK_LINEOUT 0x0000004 +#define GB_AUDIO_JACK_MECHANICAL 0x0000008 +#define GB_AUDIO_JACK_VIDEOOUT 0x0000010 +#define GB_AUDIO_JACK_AVOUT (GB_AUDIO_JACK_LINEOUT | \ + GB_AUDIO_JACK_VIDEOOUT) +#define GB_AUDIO_JACK_LINEIN 0x0000020 +#define GB_AUDIO_JACK_OC_HPHL 0x0000040 +#define GB_AUDIO_JACK_OC_HPHR 0x0000080 +#define GB_AUDIO_JACK_MICROPHONE2 0x0000200 +#define GB_AUDIO_JACK_ANC_HEADPHONE (GB_AUDIO_JACK_HEADPHONE | \ + GB_AUDIO_JACK_MICROPHONE | \ + GB_AUDIO_JACK_MICROPHONE2) +/* Kept separate from switches to facilitate implementation */ +#define GB_AUDIO_JACK_BTN_0 0x4000000 +#define GB_AUDIO_JACK_BTN_1 0x2000000 +#define GB_AUDIO_JACK_BTN_2 0x1000000 +#define GB_AUDIO_JACK_BTN_3 0x0800000 + +struct gb_audio_pcm { + __u8 stream_name[GB_AUDIO_PCM_NAME_MAX]; + __le32 formats; /* GB_AUDIO_PCM_FMT_* */ + __le32 rates; /* GB_AUDIO_PCM_RATE_* */ + __u8 chan_min; + __u8 chan_max; + __u8 sig_bits; /* number of bits of content */ +} __packed; + +struct gb_audio_dai { + __u8 name[AUDIO_DAI_NAME_MAX]; + __le16 data_cport; + struct gb_audio_pcm capture; + struct gb_audio_pcm playback; +} __packed; + +struct gb_audio_integer { + __le32 min; + __le32 max; + __le32 step; +} __packed; + +struct gb_audio_integer64 { + __le64 min; + __le64 max; + __le64 step; +} __packed; + +struct gb_audio_enumerated { + __le32 items; + __le16 names_length; + __u8 names[0]; +} __packed; + +struct gb_audio_ctl_elem_info { /* See snd_ctl_elem_info in Linux source */ + __u8 type; /* GB_AUDIO_CTL_ELEM_TYPE_* */ + __le16 dimen[4]; + union { + struct gb_audio_integer integer; + struct gb_audio_integer64 integer64; + struct gb_audio_enumerated enumerated; + } value; +} __packed; + +struct gb_audio_ctl_elem_value { /* See snd_ctl_elem_value in Linux source */ + __le64 timestamp; /* XXX needed? */ + union { + __le32 integer_value[2]; /* consider CTL_DOUBLE_xxx */ + __le64 integer64_value[2]; + __le32 enumerated_item[2]; + } value; +} __packed; + +struct gb_audio_control { + __u8 name[AUDIO_CONTROL_NAME_MAX]; + __u8 id; /* 0-63 */ + __u8 iface; /* GB_AUDIO_IFACE_* */ + __le16 data_cport; + __le32 access; /* GB_AUDIO_ACCESS_* */ + __u8 count; /* count of same elements */ + __u8 count_values; /* count of values, max=2 for CTL_DOUBLE_xxx */ + struct gb_audio_ctl_elem_info info; +} __packed; + +struct gb_audio_widget { + __u8 name[AUDIO_WIDGET_NAME_MAX]; + __u8 sname[AUDIO_WIDGET_NAME_MAX]; + __u8 id; + __u8 type; /* GB_AUDIO_WIDGET_TYPE_* */ + __u8 state; /* GB_AUDIO_WIDGET_STATE_* */ + __u8 ncontrols; + struct gb_audio_control ctl[0]; /* 'ncontrols' entries */ +} __packed; + +struct gb_audio_route { + __u8 source_id; /* widget id */ + __u8 destination_id; /* widget id */ + __u8 control_id; /* 0-63 */ + __u8 index; /* Selection within the control */ +} __packed; + +struct gb_audio_topology { + __u8 num_dais; + __u8 num_controls; + __u8 num_widgets; + __u8 num_routes; + __le32 size_dais; + __le32 size_controls; + __le32 size_widgets; + __le32 size_routes; + __le32 jack_type; + /* + * struct gb_audio_dai dai[num_dais]; + * struct gb_audio_control controls[num_controls]; + * struct gb_audio_widget widgets[num_widgets]; + * struct gb_audio_route routes[num_routes]; + */ + __u8 data[0]; +} __packed; + +struct gb_audio_get_topology_size_response { + __le16 size; +} __packed; + +struct gb_audio_get_topology_response { + struct gb_audio_topology topology; +} __packed; + +struct gb_audio_get_control_request { + __u8 control_id; + __u8 index; +} __packed; + +struct gb_audio_get_control_response { + struct gb_audio_ctl_elem_value value; +} __packed; + +struct gb_audio_set_control_request { + __u8 control_id; + __u8 index; + struct gb_audio_ctl_elem_value value; +} __packed; + +struct gb_audio_enable_widget_request { + __u8 widget_id; +} __packed; + +struct gb_audio_disable_widget_request { + __u8 widget_id; +} __packed; + +struct gb_audio_get_pcm_request { + __le16 data_cport; +} __packed; + +struct gb_audio_get_pcm_response { + __le32 format; + __le32 rate; + __u8 channels; + __u8 sig_bits; +} __packed; + +struct gb_audio_set_pcm_request { + __le16 data_cport; + __le32 format; + __le32 rate; + __u8 channels; + __u8 sig_bits; +} __packed; + +struct gb_audio_set_tx_data_size_request { + __le16 data_cport; + __le16 size; +} __packed; + +struct gb_audio_activate_tx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_deactivate_tx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_set_rx_data_size_request { + __le16 data_cport; + __le16 size; +} __packed; + +struct gb_audio_activate_rx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_deactivate_rx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_jack_event_request { + __u8 widget_id; + __u8 jack_attribute; + __u8 event; +} __packed; + +struct gb_audio_button_event_request { + __u8 widget_id; + __u8 button_id; + __u8 event; +} __packed; + +struct gb_audio_streaming_event_request { + __le16 data_cport; + __u8 event; +} __packed; + +struct gb_audio_send_data_request { + __le64 timestamp; + __u8 data[0]; +} __packed; + + +/* Log */ + +/* operations */ +#define GB_LOG_TYPE_SEND_LOG 0x02 + +/* length */ +#define GB_LOG_MAX_LEN 1024 + +struct gb_log_send_log_request { + __le16 len; + __u8 msg[0]; +} __packed; + +#endif /* __GREYBUS_PROTOCOLS_H */ + diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h new file mode 100644 index 000000000000..6f8692da9ec8 --- /dev/null +++ b/drivers/staging/greybus/greybus_trace.h @@ -0,0 +1,531 @@ +/* + * Greybus driver and device API + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM greybus + +#if !defined(_TRACE_GREYBUS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_GREYBUS_H + +#include + +struct gb_message; +struct gb_operation; +struct gb_connection; +struct gb_bundle; +struct gb_host_device; + +DECLARE_EVENT_CLASS(gb_message, + + TP_PROTO(struct gb_message *message), + + TP_ARGS(message), + + TP_STRUCT__entry( + __field(u16, size) + __field(u16, operation_id) + __field(u8, type) + __field(u8, result) + ), + + TP_fast_assign( + __entry->size = le16_to_cpu(message->header->size); + __entry->operation_id = + le16_to_cpu(message->header->operation_id); + __entry->type = message->header->type; + __entry->result = message->header->result; + ), + + TP_printk("size=%hu operation_id=0x%04x type=0x%02x result=0x%02x", + __entry->size, __entry->operation_id, + __entry->type, __entry->result) +); + +#define DEFINE_MESSAGE_EVENT(name) \ + DEFINE_EVENT(gb_message, name, \ + TP_PROTO(struct gb_message *message), \ + TP_ARGS(message)) + +/* + * Occurs immediately before calling a host device's message_send() + * method. + */ +DEFINE_MESSAGE_EVENT(gb_message_send); + +/* + * Occurs after an incoming request message has been received + */ +DEFINE_MESSAGE_EVENT(gb_message_recv_request); + +/* + * Occurs after an incoming response message has been received, + * after its matching request has been found. + */ +DEFINE_MESSAGE_EVENT(gb_message_recv_response); + +/* + * Occurs after an operation has been canceled, possibly before the + * cancellation is complete. + */ +DEFINE_MESSAGE_EVENT(gb_message_cancel_outgoing); + +/* + * Occurs when an incoming request is cancelled; if the response has + * been queued for sending, this occurs after it is sent. + */ +DEFINE_MESSAGE_EVENT(gb_message_cancel_incoming); + +/* + * Occurs in the host driver message_send() function just prior to + * handing off the data to be processed by hardware. + */ +DEFINE_MESSAGE_EVENT(gb_message_submit); + +#undef DEFINE_MESSAGE_EVENT + +DECLARE_EVENT_CLASS(gb_operation, + + TP_PROTO(struct gb_operation *operation), + + TP_ARGS(operation), + + TP_STRUCT__entry( + __field(u16, cport_id) /* CPort of HD side of connection */ + __field(u16, id) /* Operation ID */ + __field(u8, type) + __field(unsigned long, flags) + __field(int, active) + __field(int, waiters) + __field(int, errno) + ), + + TP_fast_assign( + __entry->cport_id = operation->connection->hd_cport_id; + __entry->id = operation->id; + __entry->type = operation->type; + __entry->flags = operation->flags; + __entry->active = operation->active; + __entry->waiters = atomic_read(&operation->waiters); + __entry->errno = operation->errno; + ), + + TP_printk("id=%04x type=0x%02x cport_id=%04x flags=0x%lx active=%d waiters=%d errno=%d", + __entry->id, __entry->cport_id, __entry->type, __entry->flags, + __entry->active, __entry->waiters, __entry->errno) +); + +#define DEFINE_OPERATION_EVENT(name) \ + DEFINE_EVENT(gb_operation, name, \ + TP_PROTO(struct gb_operation *operation), \ + TP_ARGS(operation)) + +/* + * Occurs after a new operation is created for an outgoing request + * has been successfully created. + */ +DEFINE_OPERATION_EVENT(gb_operation_create); + +/* + * Occurs after a new core operation has been created. + */ +DEFINE_OPERATION_EVENT(gb_operation_create_core); + +/* + * Occurs after a new operation has been created for an incoming + * request has been successfully created and initialized. + */ +DEFINE_OPERATION_EVENT(gb_operation_create_incoming); + +/* + * Occurs when the last reference to an operation has been dropped, + * prior to freeing resources. + */ +DEFINE_OPERATION_EVENT(gb_operation_destroy); + +/* + * Occurs when an operation has been marked active, after updating + * its active count. + */ +DEFINE_OPERATION_EVENT(gb_operation_get_active); + +/* + * Occurs when an operation has been marked active, before updating + * its active count. + */ +DEFINE_OPERATION_EVENT(gb_operation_put_active); + +#undef DEFINE_OPERATION_EVENT + +DECLARE_EVENT_CLASS(gb_connection, + + TP_PROTO(struct gb_connection *connection), + + TP_ARGS(connection), + + TP_STRUCT__entry( + __field(int, hd_bus_id) + __field(u8, bundle_id) + /* name contains "hd_cport_id/intf_id:cport_id" */ + __dynamic_array(char, name, sizeof(connection->name)) + __field(enum gb_connection_state, state) + __field(unsigned long, flags) + ), + + TP_fast_assign( + __entry->hd_bus_id = connection->hd->bus_id; + __entry->bundle_id = connection->bundle ? + connection->bundle->id : BUNDLE_ID_NONE; + memcpy(__get_str(name), connection->name, + sizeof(connection->name)); + __entry->state = connection->state; + __entry->flags = connection->flags; + ), + + TP_printk("hd_bus_id=%d bundle_id=0x%02x name=\"%s\" state=%u flags=0x%lx", + __entry->hd_bus_id, __entry->bundle_id, __get_str(name), + (unsigned int)__entry->state, __entry->flags) +); + +#define DEFINE_CONNECTION_EVENT(name) \ + DEFINE_EVENT(gb_connection, name, \ + TP_PROTO(struct gb_connection *connection), \ + TP_ARGS(connection)) + +/* + * Occurs after a new connection is successfully created. + */ +DEFINE_CONNECTION_EVENT(gb_connection_create); + +/* + * Occurs when the last reference to a connection has been dropped, + * before its resources are freed. + */ +DEFINE_CONNECTION_EVENT(gb_connection_release); + +/* + * Occurs when a new reference to connection is added, currently + * only when a message over the connection is received. + */ +DEFINE_CONNECTION_EVENT(gb_connection_get); + +/* + * Occurs when a new reference to connection is dropped, after a + * a received message is handled, or when the connection is + * destroyed. + */ +DEFINE_CONNECTION_EVENT(gb_connection_put); + +/* + * Occurs when a request to enable a connection is made, either for + * transmit only, or for both transmit and receive. + */ +DEFINE_CONNECTION_EVENT(gb_connection_enable); + +/* + * Occurs when a request to disable a connection is made, either for + * receive only, or for both transmit and receive. Also occurs when + * a request to forcefully disable a connection is made. + */ +DEFINE_CONNECTION_EVENT(gb_connection_disable); + +#undef DEFINE_CONNECTION_EVENT + +DECLARE_EVENT_CLASS(gb_bundle, + + TP_PROTO(struct gb_bundle *bundle), + + TP_ARGS(bundle), + + TP_STRUCT__entry( + __field(u8, intf_id) + __field(u8, id) + __field(u8, class) + __field(size_t, num_cports) + ), + + TP_fast_assign( + __entry->intf_id = bundle->intf->interface_id; + __entry->id = bundle->id; + __entry->class = bundle->class; + __entry->num_cports = bundle->num_cports; + ), + + TP_printk("intf_id=0x%02x id=%02x class=0x%02x num_cports=%zu", + __entry->intf_id, __entry->id, __entry->class, + __entry->num_cports) +); + +#define DEFINE_BUNDLE_EVENT(name) \ + DEFINE_EVENT(gb_bundle, name, \ + TP_PROTO(struct gb_bundle *bundle), \ + TP_ARGS(bundle)) + +/* + * Occurs after a new bundle is successfully created. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_create); + +/* + * Occurs when the last reference to a bundle has been dropped, + * before its resources are freed. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_release); + +/* + * Occurs when a bundle is added to an interface when the interface + * is enabled. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_add); + +/* + * Occurs when a registered bundle gets destroyed, normally at the + * time an interface is disabled. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_destroy); + +#undef DEFINE_BUNDLE_EVENT + +DECLARE_EVENT_CLASS(gb_interface, + + TP_PROTO(struct gb_interface *intf), + + TP_ARGS(intf), + + TP_STRUCT__entry( + __field(u8, module_id) + __field(u8, id) /* Interface id */ + __field(u8, device_id) + __field(int, disconnected) /* bool */ + __field(int, ejected) /* bool */ + __field(int, active) /* bool */ + __field(int, enabled) /* bool */ + __field(int, mode_switch) /* bool */ + ), + + TP_fast_assign( + __entry->module_id = intf->module->module_id; + __entry->id = intf->interface_id; + __entry->device_id = intf->device_id; + __entry->disconnected = intf->disconnected; + __entry->ejected = intf->ejected; + __entry->active = intf->active; + __entry->enabled = intf->enabled; + __entry->mode_switch = intf->mode_switch; + ), + + TP_printk("intf_id=%hhu device_id=%hhu module_id=%hhu D=%d J=%d A=%d E=%d M=%d", + __entry->id, __entry->device_id, __entry->module_id, + __entry->disconnected, __entry->ejected, __entry->active, + __entry->enabled, __entry->mode_switch) +); + +#define DEFINE_INTERFACE_EVENT(name) \ + DEFINE_EVENT(gb_interface, name, \ + TP_PROTO(struct gb_interface *intf), \ + TP_ARGS(intf)) + +/* + * Occurs after a new interface is successfully created. + */ +DEFINE_INTERFACE_EVENT(gb_interface_create); + +/* + * Occurs after the last reference to an interface has been dropped. + */ +DEFINE_INTERFACE_EVENT(gb_interface_release); + +/* + * Occurs after an interface been registerd. + */ +DEFINE_INTERFACE_EVENT(gb_interface_add); + +/* + * Occurs when a registered interface gets deregisterd. + */ +DEFINE_INTERFACE_EVENT(gb_interface_del); + +/* + * Occurs when a registered interface has been successfully + * activated. + */ +DEFINE_INTERFACE_EVENT(gb_interface_activate); + +/* + * Occurs when an activated interface is being deactivated. + */ +DEFINE_INTERFACE_EVENT(gb_interface_deactivate); + +/* + * Occurs when an interface has been successfully enabled. + */ +DEFINE_INTERFACE_EVENT(gb_interface_enable); + +/* + * Occurs when an enabled interface is being disabled. + */ +DEFINE_INTERFACE_EVENT(gb_interface_disable); + +#undef DEFINE_INTERFACE_EVENT + +DECLARE_EVENT_CLASS(gb_module, + + TP_PROTO(struct gb_module *module), + + TP_ARGS(module), + + TP_STRUCT__entry( + __field(int, hd_bus_id) + __field(u8, module_id) + __field(size_t, num_interfaces) + __field(int, disconnected) /* bool */ + ), + + TP_fast_assign( + __entry->hd_bus_id = module->hd->bus_id; + __entry->module_id = module->module_id; + __entry->num_interfaces = module->num_interfaces; + __entry->disconnected = module->disconnected; + ), + + TP_printk("hd_bus_id=%d module_id=%hhu num_interfaces=%zu disconnected=%d", + __entry->hd_bus_id, __entry->module_id, + __entry->num_interfaces, __entry->disconnected) +); + +#define DEFINE_MODULE_EVENT(name) \ + DEFINE_EVENT(gb_module, name, \ + TP_PROTO(struct gb_module *module), \ + TP_ARGS(module)) + +/* + * Occurs after a new module is successfully created, before + * creating any of its interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_create); + +/* + * Occurs after the last reference to a module has been dropped. + */ +DEFINE_MODULE_EVENT(gb_module_release); + +/* + * Occurs after a module is successfully created, before registering + * any of its interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_add); + +/* + * Occurs when a module is deleted, before deregistering its + * interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_del); + +#undef DEFINE_MODULE_EVENT + +DECLARE_EVENT_CLASS(gb_host_device, + + TP_PROTO(struct gb_host_device *hd), + + TP_ARGS(hd), + + TP_STRUCT__entry( + __field(int, bus_id) + __field(size_t, num_cports) + __field(size_t, buffer_size_max) + ), + + TP_fast_assign( + __entry->bus_id = hd->bus_id; + __entry->num_cports = hd->num_cports; + __entry->buffer_size_max = hd->buffer_size_max; + ), + + TP_printk("bus_id=%d num_cports=%zu mtu=%zu", + __entry->bus_id, __entry->num_cports, + __entry->buffer_size_max) +); + +#define DEFINE_HD_EVENT(name) \ + DEFINE_EVENT(gb_host_device, name, \ + TP_PROTO(struct gb_host_device *hd), \ + TP_ARGS(hd)) + +/* + * Occurs after a new host device is successfully created, before + * its SVC has been set up. + */ +DEFINE_HD_EVENT(gb_hd_create); + +/* + * Occurs after the last reference to a host device has been + * dropped. + */ +DEFINE_HD_EVENT(gb_hd_release); + +/* + * Occurs after a new host device has been added, after the + * connection to its SVC has been enabled. + */ +DEFINE_HD_EVENT(gb_hd_add); + +/* + * Occurs when a host device is being disconnected from the AP USB + * host controller. + */ +DEFINE_HD_EVENT(gb_hd_del); + +/* + * Occurs when a host device has passed received data to the Greybus + * core, after it has been determined it is destined for a valid + * CPort. + */ +DEFINE_HD_EVENT(gb_hd_in); + +#undef DEFINE_HD_EVENT + +/* + * Occurs on a TimeSync synchronization event or a TimeSync ping event. + */ +TRACE_EVENT(gb_timesync_irq, + + TP_PROTO(u8 ping, u8 strobe, u8 count, u64 frame_time), + + TP_ARGS(ping, strobe, count, frame_time), + + TP_STRUCT__entry( + __field(u8, ping) + __field(u8, strobe) + __field(u8, count) + __field(u64, frame_time) + ), + + TP_fast_assign( + __entry->ping = ping; + __entry->strobe = strobe; + __entry->count = count; + __entry->frame_time = frame_time; + ), + + TP_printk("%s %d/%d frame-time %llu\n", + __entry->ping ? "ping" : "strobe", __entry->strobe, + __entry->count, __entry->frame_time) +); + +#endif /* _TRACE_GREYBUS_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +/* + * TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal + */ +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE greybus_trace +#include + diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c new file mode 100644 index 000000000000..185ae3fa10fd --- /dev/null +++ b/drivers/staging/greybus/hd.c @@ -0,0 +1,257 @@ +/* + * Greybus Host Device + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include + +#include "greybus.h" +#include "greybus_trace.h" + +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_release); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_add); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_del); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_in); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_message_submit); + +static struct ida gb_hd_bus_id_map; + +int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async) +{ + if (!hd || !hd->driver || !hd->driver->output) + return -EINVAL; + return hd->driver->output(hd, req, size, cmd, async); +} +EXPORT_SYMBOL_GPL(gb_hd_output); + +static ssize_t bus_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_host_device *hd = to_gb_host_device(dev); + + return sprintf(buf, "%d\n", hd->bus_id); +} +static DEVICE_ATTR_RO(bus_id); + +static struct attribute *bus_attrs[] = { + &dev_attr_bus_id.attr, + NULL +}; +ATTRIBUTE_GROUPS(bus); + +int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id) +{ + struct ida *id_map = &hd->cport_id_map; + int ret; + + ret = ida_simple_get(id_map, cport_id, cport_id + 1, GFP_KERNEL); + if (ret < 0) { + dev_err(&hd->dev, "failed to reserve cport %u\n", cport_id); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(gb_hd_cport_reserve); + +void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id) +{ + struct ida *id_map = &hd->cport_id_map; + + ida_simple_remove(id_map, cport_id); +} +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) +{ + struct ida *id_map = &hd->cport_id_map; + int ida_start, ida_end; + + if (hd->driver->cport_allocate) + return hd->driver->cport_allocate(hd, cport_id, flags); + + if (cport_id < 0) { + ida_start = 0; + ida_end = hd->num_cports; + } else if (cport_id < hd->num_cports) { + ida_start = cport_id; + ida_end = cport_id + 1; + } else { + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EINVAL; + } + + return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); +} + +/* Locking: Caller guarantees serialisation */ +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) +{ + if (hd->driver->cport_release) { + hd->driver->cport_release(hd, cport_id); + return; + } + + ida_simple_remove(&hd->cport_id_map, cport_id); +} + +static void gb_hd_release(struct device *dev) +{ + struct gb_host_device *hd = to_gb_host_device(dev); + + trace_gb_hd_release(hd); + + if (hd->svc) + gb_svc_put(hd->svc); + ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); + ida_destroy(&hd->cport_id_map); + kfree(hd); +} + +struct device_type greybus_hd_type = { + .name = "greybus_host_device", + .release = gb_hd_release, +}; + +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 gb_host_device *hd; + int ret; + + /* + * Validate that the driver implements all of the callbacks + * so that we don't have to every time we make them. + */ + if ((!driver->message_send) || (!driver->message_cancel)) { + dev_err(parent, "mandatory hd-callbacks missing\n"); + return ERR_PTR(-EINVAL); + } + + if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) { + dev_err(parent, "greybus host-device buffers too small\n"); + return ERR_PTR(-EINVAL); + } + + if (num_cports == 0 || num_cports > CPORT_ID_MAX + 1) { + dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports); + return ERR_PTR(-EINVAL); + } + + /* + * Make sure to never allocate messages larger than what the Greybus + * protocol supports. + */ + if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { + dev_warn(parent, "limiting buffer size to %u\n", + GB_OPERATION_MESSAGE_SIZE_MAX); + buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; + } + + hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); + if (!hd) + return ERR_PTR(-ENOMEM); + + ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL); + if (ret < 0) { + kfree(hd); + return ERR_PTR(ret); + } + hd->bus_id = ret; + + hd->driver = driver; + INIT_LIST_HEAD(&hd->modules); + INIT_LIST_HEAD(&hd->connections); + ida_init(&hd->cport_id_map); + hd->buffer_size_max = buffer_size_max; + hd->num_cports = num_cports; + + hd->dev.parent = parent; + hd->dev.bus = &greybus_bus_type; + hd->dev.type = &greybus_hd_type; + hd->dev.groups = bus_groups; + hd->dev.dma_mask = hd->dev.parent->dma_mask; + device_initialize(&hd->dev); + dev_set_name(&hd->dev, "greybus%d", hd->bus_id); + + trace_gb_hd_create(hd); + + hd->svc = gb_svc_create(hd); + if (!hd->svc) { + dev_err(&hd->dev, "failed to create svc\n"); + put_device(&hd->dev); + return ERR_PTR(-ENOMEM); + } + + return hd; +} +EXPORT_SYMBOL_GPL(gb_hd_create); + +int gb_hd_add(struct gb_host_device *hd) +{ + int ret; + + ret = device_add(&hd->dev); + if (ret) + return ret; + + ret = gb_svc_add(hd->svc); + if (ret) { + device_del(&hd->dev); + return ret; + } + + trace_gb_hd_add(hd); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_hd_add); + +void gb_hd_del(struct gb_host_device *hd) +{ + trace_gb_hd_del(hd); + + /* + * Tear down the svc and flush any on-going hotplug processing before + * removing the remaining interfaces. + */ + gb_svc_del(hd->svc); + + device_del(&hd->dev); +} +EXPORT_SYMBOL_GPL(gb_hd_del); + +void gb_hd_shutdown(struct gb_host_device *hd) +{ + gb_svc_del(hd->svc); +} +EXPORT_SYMBOL_GPL(gb_hd_shutdown); + +void gb_hd_put(struct gb_host_device *hd) +{ + put_device(&hd->dev); +} +EXPORT_SYMBOL_GPL(gb_hd_put); + +int __init gb_hd_init(void) +{ + ida_init(&gb_hd_bus_id_map); + + return 0; +} + +void gb_hd_exit(void) +{ + ida_destroy(&gb_hd_bus_id_map); +} diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h new file mode 100644 index 000000000000..c4250cfe595f --- /dev/null +++ b/drivers/staging/greybus/hd.h @@ -0,0 +1,90 @@ +/* + * Greybus Host Device + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __HD_H +#define __HD_H + +struct gb_host_device; +struct gb_message; + +struct gb_hd_driver { + size_t hd_priv_size; + + int (*cport_allocate)(struct gb_host_device *hd, int cport_id, + unsigned long flags); + void (*cport_release)(struct gb_host_device *hd, u16 cport_id); + int (*cport_enable)(struct gb_host_device *hd, u16 cport_id, + unsigned long flags); + int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); + int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); + int (*cport_shutdown)(struct gb_host_device *hd, u16 cport_id, + u8 phase, unsigned int timeout); + int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, + size_t peer_space, unsigned int timeout); + int (*cport_clear)(struct gb_host_device *hd, u16 cport_id); + + int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, + struct gb_message *message, gfp_t gfp_mask); + void (*message_cancel)(struct gb_message *message); + int (*latency_tag_enable)(struct gb_host_device *hd, u16 cport_id); + int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); + int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async); + int (*timesync_enable)(struct gb_host_device *hd, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk); + int (*timesync_disable)(struct gb_host_device *hd); + int (*timesync_authoritative)(struct gb_host_device *hd, + u64 *frame_time); + int (*timesync_get_last_event)(struct gb_host_device *hd, + u64 *frame_time); +}; + +struct gb_host_device { + struct device dev; + int bus_id; + const struct gb_hd_driver *driver; + + struct list_head modules; + struct list_head connections; + struct ida cport_id_map; + + /* Number of CPorts supported by the UniPro IP */ + size_t num_cports; + + /* Host device buffer constraints */ + size_t buffer_size_max; + + struct gb_svc *svc; + /* Private data for the host driver */ + unsigned long hd_priv[0] __aligned(sizeof(s64)); +}; +#define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) + +int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id); +void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id); +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags); +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); + +struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, + struct device *parent, + size_t buffer_size_max, + size_t num_cports); +int gb_hd_add(struct gb_host_device *hd); +void gb_hd_del(struct gb_host_device *hd); +void gb_hd_shutdown(struct gb_host_device *hd); +void gb_hd_put(struct gb_host_device *hd); +int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool in_irq); + +int gb_hd_init(void); +void gb_hd_exit(void); + +#endif /* __HD_H */ diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c new file mode 100644 index 000000000000..730d746fc4c2 --- /dev/null +++ b/drivers/staging/greybus/hid.c @@ -0,0 +1,536 @@ +/* + * HID class driver for the Greybus. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + +/* Greybus HID device's structure */ +struct gb_hid { + struct gb_bundle *bundle; + struct gb_connection *connection; + + struct hid_device *hid; + struct gb_hid_desc_response hdesc; + + unsigned long flags; +#define GB_HID_STARTED 0x01 +#define GB_HID_READ_PENDING 0x04 + + unsigned int bufsize; + char *inbuf; +}; + +static DEFINE_MUTEX(gb_hid_open_mutex); + +/* Routines to get controller's information over greybus */ + +/* Operations performed on greybus */ +static int gb_hid_get_desc(struct gb_hid *ghid) +{ + return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_DESC, NULL, + 0, &ghid->hdesc, sizeof(ghid->hdesc)); +} + +static int gb_hid_get_report_desc(struct gb_hid *ghid, char *rdesc) +{ + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + + ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC, + NULL, 0, rdesc, + le16_to_cpu(ghid->hdesc.wReportDescLength)); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; +} + +static int gb_hid_set_power(struct gb_hid *ghid, int type) +{ + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + + ret = gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; +} + +static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id, + unsigned char *buf, int len) +{ + struct gb_hid_get_report_request request; + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + + request.report_type = report_type; + request.report_id = report_id; + + ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT, + &request, sizeof(request), buf, len); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; +} + +static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, + unsigned char *buf, int len) +{ + struct gb_hid_set_report_request *request; + struct gb_operation *operation; + int ret, size = sizeof(*request) + len - 1; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + + operation = gb_operation_create(ghid->connection, + GB_HID_TYPE_SET_REPORT, size, 0, + GFP_KERNEL); + if (!operation) { + gb_pm_runtime_put_autosuspend(ghid->bundle); + return -ENOMEM; + } + + request = operation->request->payload; + request->report_type = report_type; + request->report_id = report_id; + memcpy(request->report, buf, len); + + ret = gb_operation_request_send_sync(operation); + if (ret) { + dev_err(&operation->connection->bundle->dev, + "failed to set report: %d\n", ret); + } else { + ret = len; + } + + gb_operation_put(operation); + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; +} + +static int gb_hid_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_hid *ghid = gb_connection_get_data(connection); + struct gb_hid_input_report_request *request = op->request->payload; + + if (op->type != GB_HID_TYPE_IRQ_EVENT) { + dev_err(&connection->bundle->dev, + "unsupported unsolicited request\n"); + return -EINVAL; + } + + if (test_bit(GB_HID_STARTED, &ghid->flags)) + hid_input_report(ghid->hid, HID_INPUT_REPORT, + request->report, op->request->payload_size, 1); + + return 0; +} + +static int gb_hid_report_len(struct hid_report *report) +{ + return ((report->size - 1) >> 3) + 1 + + report->device->report_enum[report->type].numbered; +} + +static void gb_hid_find_max_report(struct hid_device *hid, unsigned int type, + unsigned int *max) +{ + struct hid_report *report; + unsigned int size; + + list_for_each_entry(report, &hid->report_enum[type].report_list, list) { + size = gb_hid_report_len(report); + if (*max < size) + *max = size; + } +} + +static void gb_hid_free_buffers(struct gb_hid *ghid) +{ + kfree(ghid->inbuf); + ghid->inbuf = NULL; + ghid->bufsize = 0; +} + +static int gb_hid_alloc_buffers(struct gb_hid *ghid, size_t bufsize) +{ + ghid->inbuf = kzalloc(bufsize, GFP_KERNEL); + if (!ghid->inbuf) + return -ENOMEM; + + ghid->bufsize = bufsize; + + return 0; +} + +/* Routines dealing with reports */ +static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report) +{ + unsigned int size; + + size = gb_hid_report_len(report); + if (gb_hid_get_report(ghid, report->type, report->id, ghid->inbuf, + size)) + return; + + /* + * hid->driver_lock is held as we are in probe function, + * we just need to setup the input fields, so using + * hid_report_raw_event is safe. + */ + hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1); +} + +static void gb_hid_init_reports(struct gb_hid *ghid) +{ + struct hid_device *hid = ghid->hid; + struct hid_report *report; + + list_for_each_entry(report, + &hid->report_enum[HID_INPUT_REPORT].report_list, list) + gb_hid_init_report(ghid, report); + + list_for_each_entry(report, + &hid->report_enum[HID_FEATURE_REPORT].report_list, list) + gb_hid_init_report(ghid, report); +} + +static int __gb_hid_get_raw_report(struct hid_device *hid, + unsigned char report_number, __u8 *buf, size_t count, + unsigned char report_type) +{ + struct gb_hid *ghid = hid->driver_data; + int ret; + + if (report_type == HID_OUTPUT_REPORT) + return -EINVAL; + + ret = gb_hid_get_report(ghid, report_type, report_number, buf, count); + if (!ret) + ret = count; + + return ret; +} + +static int __gb_hid_output_raw_report(struct hid_device *hid, __u8 *buf, + size_t len, unsigned char report_type) +{ + struct gb_hid *ghid = hid->driver_data; + int report_id = buf[0]; + int ret; + + if (report_type == HID_INPUT_REPORT) + return -EINVAL; + + if (report_id) { + buf++; + len--; + } + + ret = gb_hid_set_report(ghid, report_type, report_id, buf, len); + if (report_id && ret >= 0) + ret++; /* add report_id to the number of transfered bytes */ + + return 0; +} + +static int gb_hid_raw_request(struct hid_device *hid, unsigned char reportnum, + __u8 *buf, size_t len, unsigned char rtype, + int reqtype) +{ + switch (reqtype) { + case HID_REQ_GET_REPORT: + return __gb_hid_get_raw_report(hid, reportnum, buf, len, rtype); + case HID_REQ_SET_REPORT: + if (buf[0] != reportnum) + return -EINVAL; + return __gb_hid_output_raw_report(hid, buf, len, rtype); + default: + return -EIO; + } +} + +/* HID Callbacks */ +static int gb_hid_parse(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + unsigned int rsize; + char *rdesc; + int ret; + + rsize = le16_to_cpu(ghid->hdesc.wReportDescLength); + if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { + dbg_hid("weird size of report descriptor (%u)\n", rsize); + return -EINVAL; + } + + rdesc = kzalloc(rsize, GFP_KERNEL); + if (!rdesc) { + dbg_hid("couldn't allocate rdesc memory\n"); + return -ENOMEM; + } + + ret = gb_hid_get_report_desc(ghid, rdesc); + if (ret) { + hid_err(hid, "reading report descriptor failed\n"); + goto free_rdesc; + } + + ret = hid_parse_report(hid, rdesc, rsize); + if (ret) + dbg_hid("parsing report descriptor failed\n"); + +free_rdesc: + kfree(rdesc); + + return ret; +} + +static int gb_hid_start(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + unsigned int bufsize = HID_MIN_BUFFER_SIZE; + int ret; + + gb_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize); + gb_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize); + gb_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); + + if (bufsize > HID_MAX_BUFFER_SIZE) + bufsize = HID_MAX_BUFFER_SIZE; + + ret = gb_hid_alloc_buffers(ghid, bufsize); + if (ret) + return ret; + + if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) + gb_hid_init_reports(ghid); + + return 0; +} + +static void gb_hid_stop(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + + gb_hid_free_buffers(ghid); +} + +static int gb_hid_open(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + int ret = 0; + + mutex_lock(&gb_hid_open_mutex); + if (!hid->open++) { + ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON); + if (ret < 0) + hid->open--; + else + set_bit(GB_HID_STARTED, &ghid->flags); + } + mutex_unlock(&gb_hid_open_mutex); + + return ret; +} + +static void gb_hid_close(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + int ret; + + /* + * Protecting hid->open to make sure we don't restart data acquistion + * due to a resumption we no longer care about.. + */ + mutex_lock(&gb_hid_open_mutex); + if (!--hid->open) { + clear_bit(GB_HID_STARTED, &ghid->flags); + + /* Save some power */ + ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF); + if (ret) + dev_err(&ghid->connection->bundle->dev, + "failed to power off (%d)\n", ret); + } + mutex_unlock(&gb_hid_open_mutex); +} + +static int gb_hid_power(struct hid_device *hid, int lvl) +{ + struct gb_hid *ghid = hid->driver_data; + + switch (lvl) { + case PM_HINT_FULLON: + return gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON); + case PM_HINT_NORMAL: + return gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF); + } + + return 0; +} + +/* HID structure to pass callbacks */ +static struct hid_ll_driver gb_hid_ll_driver = { + .parse = gb_hid_parse, + .start = gb_hid_start, + .stop = gb_hid_stop, + .open = gb_hid_open, + .close = gb_hid_close, + .power = gb_hid_power, + .raw_request = gb_hid_raw_request, +}; + +static int gb_hid_init(struct gb_hid *ghid) +{ + struct hid_device *hid = ghid->hid; + int ret; + + ret = gb_hid_get_desc(ghid); + if (ret) + return ret; + + hid->version = le16_to_cpu(ghid->hdesc.bcdHID); + hid->vendor = le16_to_cpu(ghid->hdesc.wVendorID); + hid->product = le16_to_cpu(ghid->hdesc.wProductID); + hid->country = ghid->hdesc.bCountryCode; + + hid->driver_data = ghid; + hid->ll_driver = &gb_hid_ll_driver; + hid->dev.parent = &ghid->connection->bundle->dev; +// hid->bus = BUS_GREYBUS; /* Need a bustype for GREYBUS in */ + + /* Set HID device's name */ + snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", + dev_name(&ghid->connection->bundle->dev), + hid->vendor, hid->product); + + return 0; +} + +static int gb_hid_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct hid_device *hid; + struct gb_hid *ghid; + int ret; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_HID) + return -ENODEV; + + ghid = kzalloc(sizeof(*ghid), GFP_KERNEL); + if (!ghid) + return -ENOMEM; + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_hid_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto err_free_ghid; + } + + gb_connection_set_data(connection, ghid); + ghid->connection = connection; + + hid = hid_allocate_device(); + if (IS_ERR(hid)) { + ret = PTR_ERR(hid); + goto err_connection_destroy; + } + + ghid->hid = hid; + ghid->bundle = bundle; + + greybus_set_drvdata(bundle, ghid); + + ret = gb_connection_enable(connection); + if (ret) + goto err_destroy_hid; + + ret = gb_hid_init(ghid); + if (ret) + goto err_connection_disable; + + ret = hid_add_device(hid); + if (ret) { + hid_err(hid, "can't add hid device: %d\n", ret); + goto err_connection_disable; + } + + gb_pm_runtime_put_autosuspend(bundle); + + return 0; + +err_connection_disable: + gb_connection_disable(connection); +err_destroy_hid: + hid_destroy_device(hid); +err_connection_destroy: + gb_connection_destroy(connection); +err_free_ghid: + kfree(ghid); + + return ret; +} + +static void gb_hid_disconnect(struct gb_bundle *bundle) +{ + struct gb_hid *ghid = greybus_get_drvdata(bundle); + + if (gb_pm_runtime_get_sync(bundle)) + gb_pm_runtime_get_noresume(bundle); + + hid_destroy_device(ghid->hid); + gb_connection_disable(ghid->connection); + gb_connection_destroy(ghid->connection); + kfree(ghid); +} + +static const struct greybus_bundle_id gb_hid_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_HID) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_hid_id_table); + +static struct greybus_driver gb_hid_driver = { + .name = "hid", + .probe = gb_hid_probe, + .disconnect = gb_hid_disconnect, + .id_table = gb_hid_id_table, +}; +module_greybus_driver(gb_hid_driver); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c new file mode 100644 index 000000000000..c2a50087000c --- /dev/null +++ b/drivers/staging/greybus/i2c.c @@ -0,0 +1,343 @@ +/* + * I2C bridge driver for the Greybus "generic" I2C module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include + +#include "greybus.h" +#include "gbphy.h" + +struct gb_i2c_device { + struct gb_connection *connection; + struct gbphy_device *gbphy_dev; + + u32 functionality; + + struct i2c_adapter adapter; +}; + +/* + * Map Greybus i2c functionality bits into Linux ones + */ +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) +{ + struct gb_i2c_functionality_response response; + u32 functionality; + int ret; + + ret = gb_operation_sync(gb_i2c_dev->connection, + GB_I2C_TYPE_FUNCTIONALITY, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + functionality = le32_to_cpu(response.functionality); + gb_i2c_dev->functionality = gb_i2c_functionality_map(functionality); + + return 0; +} + +/* + * Map Linux i2c_msg flags into Greybus i2c transfer op flags. + */ +static u16 gb_i2c_transfer_op_flags_map(u16 flags) +{ + return flags; /* All flags the same for now */ +} + +static void +gb_i2c_fill_transfer_op(struct gb_i2c_transfer_op *op, struct i2c_msg *msg) +{ + u16 flags = gb_i2c_transfer_op_flags_map(msg->flags); + + op->addr = cpu_to_le16(msg->addr); + op->flags = cpu_to_le16(flags); + op->size = cpu_to_le16(msg->len); +} + +static struct gb_operation * +gb_i2c_operation_create(struct gb_connection *connection, + struct i2c_msg *msgs, u32 msg_count) +{ + struct gb_i2c_device *gb_i2c_dev = gb_connection_get_data(connection); + struct gb_i2c_transfer_request *request; + struct gb_operation *operation; + struct gb_i2c_transfer_op *op; + struct i2c_msg *msg; + u32 data_out_size = 0; + u32 data_in_size = 0; + size_t request_size; + void *data; + u16 op_count; + u32 i; + + if (msg_count > (u32)U16_MAX) { + dev_err(&gb_i2c_dev->gbphy_dev->dev, "msg_count (%u) too big\n", + msg_count); + return NULL; + } + op_count = (u16)msg_count; + + /* + * In addition to space for all message descriptors we need + * to have enough to hold all outbound message data. + */ + msg = msgs; + for (i = 0; i < msg_count; i++, msg++) + if (msg->flags & I2C_M_RD) + data_in_size += (u32)msg->len; + else + data_out_size += (u32)msg->len; + + request_size = sizeof(*request); + request_size += msg_count * sizeof(*op); + request_size += data_out_size; + + /* Response consists only of incoming data */ + operation = gb_operation_create(connection, GB_I2C_TYPE_TRANSFER, + request_size, data_in_size, GFP_KERNEL); + if (!operation) + return NULL; + + request = operation->request->payload; + request->op_count = cpu_to_le16(op_count); + /* Fill in the ops array */ + op = &request->ops[0]; + msg = msgs; + for (i = 0; i < msg_count; i++) + gb_i2c_fill_transfer_op(op++, msg++); + + if (!data_out_size) + return operation; + + /* Copy over the outgoing data; it starts after the last op */ + data = op; + msg = msgs; + for (i = 0; i < msg_count; i++) { + if (!(msg->flags & I2C_M_RD)) { + memcpy(data, msg->buf, msg->len); + data += msg->len; + } + msg++; + } + + return operation; +} + +static void gb_i2c_decode_response(struct i2c_msg *msgs, u32 msg_count, + struct gb_i2c_transfer_response *response) +{ + struct i2c_msg *msg = msgs; + u8 *data; + u32 i; + + if (!response) + return; + data = response->data; + for (i = 0; i < msg_count; i++) { + if (msg->flags & I2C_M_RD) { + memcpy(msg->buf, data, msg->len); + data += msg->len; + } + msg++; + } +} + +/* + * Some i2c transfer operations return results that are expected. + */ +static bool gb_i2c_expected_transfer_error(int errno) +{ + return errno == -EAGAIN || errno == -ENODEV; +} + +static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, + struct i2c_msg *msgs, u32 msg_count) +{ + struct gb_connection *connection = gb_i2c_dev->connection; + struct device *dev = &gb_i2c_dev->gbphy_dev->dev; + struct gb_operation *operation; + int ret; + + operation = gb_i2c_operation_create(connection, msgs, msg_count); + if (!operation) + return -ENOMEM; + + ret = gbphy_runtime_get_sync(gb_i2c_dev->gbphy_dev); + if (ret) + goto exit_operation_put; + + ret = gb_operation_request_send_sync(operation); + if (!ret) { + struct gb_i2c_transfer_response *response; + + response = operation->response->payload; + gb_i2c_decode_response(msgs, msg_count, response); + ret = msg_count; + } else if (!gb_i2c_expected_transfer_error(ret)) { + dev_err(dev, "transfer operation failed (%d)\n", ret); + } + + gbphy_runtime_put_autosuspend(gb_i2c_dev->gbphy_dev); + +exit_operation_put: + gb_operation_put(operation); + + return ret; +} + +static int gb_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int msg_count) +{ + struct gb_i2c_device *gb_i2c_dev; + + gb_i2c_dev = i2c_get_adapdata(adap); + + return gb_i2c_transfer_operation(gb_i2c_dev, msgs, msg_count); +} + +#if 0 +/* Later */ +static int gb_i2c_smbus_xfer(struct i2c_adapter *adap, + u16 addr, unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + struct gb_i2c_device *gb_i2c_dev; + + gb_i2c_dev = i2c_get_adapdata(adap); + + return 0; +} +#endif + +static u32 gb_i2c_functionality(struct i2c_adapter *adap) +{ + struct gb_i2c_device *gb_i2c_dev = i2c_get_adapdata(adap); + + return gb_i2c_dev->functionality; +} + +static const struct i2c_algorithm gb_i2c_algorithm = { + .master_xfer = gb_i2c_master_xfer, + /* .smbus_xfer = gb_i2c_smbus_xfer, */ + .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) +{ + struct gb_connection *connection; + struct gb_i2c_device *gb_i2c_dev; + struct i2c_adapter *adapter; + int ret; + + gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL); + if (!gb_i2c_dev) + return -ENOMEM; + + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), + NULL); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_i2cdev_free; + } + + gb_i2c_dev->connection = connection; + gb_connection_set_data(connection, gb_i2c_dev); + gb_i2c_dev->gbphy_dev = gbphy_dev; + gb_gbphy_set_data(gbphy_dev, gb_i2c_dev); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_i2c_device_setup(gb_i2c_dev); + if (ret) + goto exit_connection_disable; + + /* Looks good; up our i2c adapter */ + adapter = &gb_i2c_dev->adapter; + adapter->owner = THIS_MODULE; + adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + adapter->algo = &gb_i2c_algorithm; + /* adapter->algo_data = what? */ + + adapter->dev.parent = &gbphy_dev->dev; + snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); + i2c_set_adapdata(adapter, gb_i2c_dev); + + ret = i2c_add_adapter(adapter); + if (ret) + goto exit_connection_disable; + + gbphy_runtime_put_autosuspend(gbphy_dev); + return 0; + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_i2cdev_free: + kfree(gb_i2c_dev); + + return ret; +} + +static void gb_i2c_remove(struct gbphy_device *gbphy_dev) +{ + struct gb_i2c_device *gb_i2c_dev = gb_gbphy_get_data(gbphy_dev); + struct gb_connection *connection = gb_i2c_dev->connection; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); + + i2c_del_adapter(&gb_i2c_dev->adapter); + gb_connection_disable(connection); + gb_connection_destroy(connection); + kfree(gb_i2c_dev); +} + +static const struct gbphy_device_id gb_i2c_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_I2C) }, + { }, +}; +MODULE_DEVICE_TABLE(gbphy, gb_i2c_id_table); + +static struct gbphy_driver i2c_driver = { + .name = "i2c", + .probe = gb_i2c_probe, + .remove = gb_i2c_remove, + .id_table = gb_i2c_id_table, +}; + +module_gbphy_driver(i2c_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c new file mode 100644 index 000000000000..546b090e2d51 --- /dev/null +++ b/drivers/staging/greybus/interface.c @@ -0,0 +1,1316 @@ +/* + * Greybus interface code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include + +#include "greybus.h" +#include "greybus_trace.h" + +#define GB_INTERFACE_MODE_SWITCH_TIMEOUT 2000 + +#define GB_INTERFACE_DEVICE_ID_BAD 0xff + +#define GB_INTERFACE_AUTOSUSPEND_MS 3000 + +/* Time required for interface to enter standby before disabling REFCLK */ +#define GB_INTERFACE_SUSPEND_HIBERNATE_DELAY_MS 20 + +/* Don't-care selector index */ +#define DME_SELECTOR_INDEX_NULL 0 + +/* DME attributes */ +/* FIXME: remove ES2 support and DME_T_TST_SRC_INCREMENT */ +#define DME_T_TST_SRC_INCREMENT 0x4083 + +#define DME_DDBL1_MANUFACTURERID 0x5003 +#define DME_DDBL1_PRODUCTID 0x5004 + +#define DME_TOSHIBA_GMP_VID 0x6000 +#define DME_TOSHIBA_GMP_PID 0x6001 +#define DME_TOSHIBA_GMP_SN0 0x6002 +#define DME_TOSHIBA_GMP_SN1 0x6003 +#define DME_TOSHIBA_GMP_INIT_STATUS 0x6101 + +/* DDBL1 Manufacturer and Product ids */ +#define TOSHIBA_DMID 0x0126 +#define TOSHIBA_ES2_BRIDGE_DPID 0x1000 +#define TOSHIBA_ES3_APBRIDGE_DPID 0x1001 +#define TOSHIBA_ES3_GBPHY_DPID 0x1002 + +static int gb_interface_hibernate_link(struct gb_interface *intf); +static int gb_interface_refclk_set(struct gb_interface *intf, bool enable); + +static int gb_interface_dme_attr_get(struct gb_interface *intf, + u16 attr, u32 *val) +{ + return gb_svc_dme_peer_get(intf->hd->svc, intf->interface_id, + attr, DME_SELECTOR_INDEX_NULL, val); +} + +static int gb_interface_read_ara_dme(struct gb_interface *intf) +{ + u32 sn0, sn1; + int ret; + + /* + * Unless this is a Toshiba bridge, bail out until we have defined + * standard GMP attributes. + */ + if (intf->ddbl1_manufacturer_id != TOSHIBA_DMID) { + dev_err(&intf->dev, "unknown manufacturer %08x\n", + intf->ddbl1_manufacturer_id); + return -ENODEV; + } + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_VID, + &intf->vendor_id); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_PID, + &intf->product_id); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_SN0, &sn0); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_SN1, &sn1); + if (ret) + return ret; + + intf->serial_number = (u64)sn1 << 32 | sn0; + + return 0; +} + +static int gb_interface_read_dme(struct gb_interface *intf) +{ + int ret; + + /* DME attributes have already been read */ + if (intf->dme_read) + return 0; + + ret = gb_interface_dme_attr_get(intf, DME_DDBL1_MANUFACTURERID, + &intf->ddbl1_manufacturer_id); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_DDBL1_PRODUCTID, + &intf->ddbl1_product_id); + if (ret) + return ret; + + if (intf->ddbl1_manufacturer_id == TOSHIBA_DMID && + intf->ddbl1_product_id == TOSHIBA_ES2_BRIDGE_DPID) { + intf->quirks |= GB_INTERFACE_QUIRK_NO_GMP_IDS; + intf->quirks |= GB_INTERFACE_QUIRK_NO_INIT_STATUS; + } + + ret = gb_interface_read_ara_dme(intf); + if (ret) + return ret; + + intf->dme_read = true; + + return 0; +} + +static int gb_interface_route_create(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + u8 intf_id = intf->interface_id; + u8 device_id; + int ret; + + /* Allocate an interface device id. */ + ret = ida_simple_get(&svc->device_id_map, + GB_SVC_DEVICE_ID_MIN, GB_SVC_DEVICE_ID_MAX + 1, + GFP_KERNEL); + if (ret < 0) { + dev_err(&intf->dev, "failed to allocate device id: %d\n", ret); + return ret; + } + device_id = ret; + + ret = gb_svc_intf_device_id(svc, intf_id, device_id); + if (ret) { + dev_err(&intf->dev, "failed to set device id %u: %d\n", + device_id, ret); + goto err_ida_remove; + } + + /* FIXME: Hard-coded AP device id. */ + ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_SVC_DEVICE_ID_AP, + intf_id, device_id); + if (ret) { + dev_err(&intf->dev, "failed to create route: %d\n", ret); + goto err_svc_id_free; + } + + intf->device_id = device_id; + + return 0; + +err_svc_id_free: + /* + * XXX Should we tell SVC that this id doesn't belong to interface + * XXX anymore. + */ +err_ida_remove: + ida_simple_remove(&svc->device_id_map, device_id); + + return ret; +} + +static void gb_interface_route_destroy(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + + if (intf->device_id == GB_INTERFACE_DEVICE_ID_BAD) + return; + + gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id); + ida_simple_remove(&svc->device_id_map, intf->device_id); + intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; +} + +/* Locking: Caller holds the interface mutex. */ +static int gb_interface_legacy_mode_switch(struct gb_interface *intf) +{ + int ret; + + dev_info(&intf->dev, "legacy mode switch detected\n"); + + /* Mark as disconnected to prevent I/O during disable. */ + intf->disconnected = true; + gb_interface_disable(intf); + intf->disconnected = false; + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, "failed to re-enable interface: %d\n", ret); + gb_interface_deactivate(intf); + } + + return ret; +} + +void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, + u32 mailbox) +{ + mutex_lock(&intf->mutex); + + if (result) { + dev_warn(&intf->dev, + "mailbox event with UniPro error: 0x%04x\n", + result); + goto err_disable; + } + + if (mailbox != GB_SVC_INTF_MAILBOX_GREYBUS) { + dev_warn(&intf->dev, + "mailbox event with unexpected value: 0x%08x\n", + mailbox); + goto err_disable; + } + + if (intf->quirks & GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH) { + gb_interface_legacy_mode_switch(intf); + goto out_unlock; + } + + if (!intf->mode_switch) { + dev_warn(&intf->dev, "unexpected mailbox event: 0x%08x\n", + mailbox); + goto err_disable; + } + + dev_info(&intf->dev, "mode switch detected\n"); + + complete(&intf->mode_switch_completion); + +out_unlock: + mutex_unlock(&intf->mutex); + + return; + +err_disable: + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); +} + +static void gb_interface_mode_switch_work(struct work_struct *work) +{ + struct gb_interface *intf; + struct gb_control *control; + unsigned long timeout; + int ret; + + intf = container_of(work, struct gb_interface, mode_switch_work); + + mutex_lock(&intf->mutex); + /* Make sure interface is still enabled. */ + if (!intf->enabled) { + dev_dbg(&intf->dev, "mode switch aborted\n"); + intf->mode_switch = false; + mutex_unlock(&intf->mutex); + goto out_interface_put; + } + + /* + * Prepare the control device for mode switch and make sure to get an + * extra reference before it goes away during interface disable. + */ + control = gb_control_get(intf->control); + gb_control_mode_switch_prepare(control); + gb_interface_disable(intf); + mutex_unlock(&intf->mutex); + + timeout = msecs_to_jiffies(GB_INTERFACE_MODE_SWITCH_TIMEOUT); + ret = wait_for_completion_interruptible_timeout( + &intf->mode_switch_completion, timeout); + + /* Finalise control-connection mode switch. */ + gb_control_mode_switch_complete(control); + gb_control_put(control); + + if (ret < 0) { + dev_err(&intf->dev, "mode switch interrupted\n"); + goto err_deactivate; + } else if (ret == 0) { + dev_err(&intf->dev, "mode switch timed out\n"); + goto err_deactivate; + } + + /* Re-enable (re-enumerate) interface if still active. */ + mutex_lock(&intf->mutex); + intf->mode_switch = false; + if (intf->active) { + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, "failed to re-enable interface: %d\n", + ret); + gb_interface_deactivate(intf); + } + } + mutex_unlock(&intf->mutex); + +out_interface_put: + gb_interface_put(intf); + + return; + +err_deactivate: + mutex_lock(&intf->mutex); + intf->mode_switch = false; + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); + + gb_interface_put(intf); +} + +int gb_interface_request_mode_switch(struct gb_interface *intf) +{ + int ret = 0; + + mutex_lock(&intf->mutex); + if (intf->mode_switch) { + ret = -EBUSY; + goto out_unlock; + } + + intf->mode_switch = true; + reinit_completion(&intf->mode_switch_completion); + + /* + * Get a reference to the interface device, which will be put once the + * mode switch is complete. + */ + get_device(&intf->dev); + + if (!queue_work(system_long_wq, &intf->mode_switch_work)) { + put_device(&intf->dev); + ret = -EBUSY; + goto out_unlock; + } + +out_unlock: + mutex_unlock(&intf->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_interface_request_mode_switch); + +/* + * T_TstSrcIncrement is written by the module on ES2 as a stand-in for the + * init-status attribute DME_TOSHIBA_INIT_STATUS. The AP needs to read and + * clear it after reading a non-zero value from it. + * + * FIXME: This is module-hardware dependent and needs to be extended for every + * type of module we want to support. + */ +static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) +{ + struct gb_host_device *hd = intf->hd; + unsigned long bootrom_quirks; + unsigned long s2l_quirks; + int ret; + u32 value; + u16 attr; + u8 init_status; + + /* + * ES2 bridges use T_TstSrcIncrement for the init status. + * + * FIXME: Remove ES2 support + */ + if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) + attr = DME_T_TST_SRC_INCREMENT; + else + attr = DME_TOSHIBA_GMP_INIT_STATUS; + + ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, + DME_SELECTOR_INDEX_NULL, &value); + if (ret) + return ret; + + /* + * A nonzero init status indicates the module has finished + * initializing. + */ + if (!value) { + dev_err(&intf->dev, "invalid init status\n"); + return -ENODEV; + } + + /* + * Extract the init status. + * + * For ES2: We need to check lowest 8 bits of 'value'. + * For ES3: We need to check highest 8 bits out of 32 of 'value'. + * + * FIXME: Remove ES2 support + */ + if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) + init_status = value & 0xff; + else + init_status = value >> 24; + + /* + * Check if the interface is executing the quirky ES3 bootrom that, + * for example, requires E2EFC, CSD and CSV to be disabled. + */ + bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES | + GB_INTERFACE_QUIRK_FORCED_DISABLE | + GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH | + GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE; + + s2l_quirks = GB_INTERFACE_QUIRK_NO_PM; + + switch (init_status) { + case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: + case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: + intf->quirks |= bootrom_quirks; + break; + case GB_INIT_S2_LOADER_BOOT_STARTED: + /* S2 Loader doesn't support runtime PM */ + intf->quirks &= ~bootrom_quirks; + intf->quirks |= s2l_quirks; + break; + default: + intf->quirks &= ~bootrom_quirks; + intf->quirks &= ~s2l_quirks; + } + + /* Clear the init status. */ + return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, + DME_SELECTOR_INDEX_NULL, 0); +} + +/* interface sysfs attributes */ +#define gb_interface_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_interface *intf = to_gb_interface(dev); \ + return scnprintf(buf, PAGE_SIZE, type"\n", intf->field); \ +} \ +static DEVICE_ATTR_RO(field) + +gb_interface_attr(ddbl1_manufacturer_id, "0x%08x"); +gb_interface_attr(ddbl1_product_id, "0x%08x"); +gb_interface_attr(interface_id, "%u"); +gb_interface_attr(vendor_id, "0x%08x"); +gb_interface_attr(product_id, "0x%08x"); +gb_interface_attr(serial_number, "0x%016llx"); + +static ssize_t voltage_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_VOL, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get voltage sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(voltage_now); + +static ssize_t current_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_CURR, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get current sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(current_now); + +static ssize_t power_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_PWR, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get power sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(power_now); + +static ssize_t power_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + if (intf->active) + return scnprintf(buf, PAGE_SIZE, "on\n"); + else + return scnprintf(buf, PAGE_SIZE, "off\n"); +} + +static ssize_t power_state_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_interface *intf = to_gb_interface(dev); + bool activate; + int ret = 0; + + if (kstrtobool(buf, &activate)) + return -EINVAL; + + mutex_lock(&intf->mutex); + + if (activate == intf->active) + goto unlock; + + if (activate) { + ret = gb_interface_activate(intf); + if (ret) { + dev_err(&intf->dev, + "failed to activate interface: %d\n", ret); + goto unlock; + } + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, + "failed to enable interface: %d\n", ret); + gb_interface_deactivate(intf); + goto unlock; + } + } else { + gb_interface_disable(intf); + gb_interface_deactivate(intf); + } + +unlock: + mutex_unlock(&intf->mutex); + + if (ret) + return ret; + + return len; +} +static DEVICE_ATTR_RW(power_state); + +static const char *gb_interface_type_string(struct gb_interface *intf) +{ + static const char * const types[] = { + [GB_INTERFACE_TYPE_INVALID] = "invalid", + [GB_INTERFACE_TYPE_UNKNOWN] = "unknown", + [GB_INTERFACE_TYPE_DUMMY] = "dummy", + [GB_INTERFACE_TYPE_UNIPRO] = "unipro", + [GB_INTERFACE_TYPE_GREYBUS] = "greybus", + }; + + return types[intf->type]; +} + +static ssize_t interface_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + return sprintf(buf, "%s\n", gb_interface_type_string(intf)); +} +static DEVICE_ATTR_RO(interface_type); + +static struct attribute *interface_unipro_attrs[] = { + &dev_attr_ddbl1_manufacturer_id.attr, + &dev_attr_ddbl1_product_id.attr, + NULL +}; + +static struct attribute *interface_greybus_attrs[] = { + &dev_attr_vendor_id.attr, + &dev_attr_product_id.attr, + &dev_attr_serial_number.attr, + NULL +}; + +static struct attribute *interface_power_attrs[] = { + &dev_attr_voltage_now.attr, + &dev_attr_current_now.attr, + &dev_attr_power_now.attr, + &dev_attr_power_state.attr, + NULL +}; + +static struct attribute *interface_common_attrs[] = { + &dev_attr_interface_id.attr, + &dev_attr_interface_type.attr, + NULL +}; + +static umode_t interface_unipro_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + +static umode_t interface_greybus_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_INTERFACE_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + +static umode_t interface_power_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + +static const struct attribute_group interface_unipro_group = { + .is_visible = interface_unipro_is_visible, + .attrs = interface_unipro_attrs, +}; + +static const struct attribute_group interface_greybus_group = { + .is_visible = interface_greybus_is_visible, + .attrs = interface_greybus_attrs, +}; + +static const struct attribute_group interface_power_group = { + .is_visible = interface_power_is_visible, + .attrs = interface_power_attrs, +}; + +static const struct attribute_group interface_common_group = { + .attrs = interface_common_attrs, +}; + +static const struct attribute_group *interface_groups[] = { + &interface_unipro_group, + &interface_greybus_group, + &interface_power_group, + &interface_common_group, + NULL +}; + +static void gb_interface_release(struct device *dev) +{ + struct gb_interface *intf = to_gb_interface(dev); + + trace_gb_interface_release(intf); + + kfree(intf); +} + +#ifdef CONFIG_PM +static int gb_interface_suspend(struct device *dev) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret, timesync_ret; + + ret = gb_control_interface_suspend_prepare(intf->control); + if (ret) + return ret; + + gb_timesync_interface_remove(intf); + + ret = gb_control_suspend(intf->control); + if (ret) + goto err_hibernate_abort; + + ret = gb_interface_hibernate_link(intf); + if (ret) + return ret; + + /* Delay to allow interface to enter standby before disabling refclk */ + msleep(GB_INTERFACE_SUSPEND_HIBERNATE_DELAY_MS); + + ret = gb_interface_refclk_set(intf, false); + if (ret) + return ret; + + return 0; + +err_hibernate_abort: + gb_control_interface_hibernate_abort(intf->control); + + timesync_ret = gb_timesync_interface_add(intf); + if (timesync_ret) { + dev_err(dev, "failed to add to timesync: %d\n", timesync_ret); + return timesync_ret; + } + + return ret; +} + +static int gb_interface_resume(struct device *dev) +{ + struct gb_interface *intf = to_gb_interface(dev); + struct gb_svc *svc = intf->hd->svc; + int ret; + + ret = gb_interface_refclk_set(intf, true); + if (ret) + return ret; + + ret = gb_svc_intf_resume(svc, intf->interface_id); + if (ret) + return ret; + + ret = gb_control_resume(intf->control); + if (ret) + return ret; + + ret = gb_timesync_interface_add(intf); + if (ret) { + dev_err(dev, "failed to add to timesync: %d\n", ret); + return ret; + } + + ret = gb_timesync_schedule_synchronous(intf); + if (ret) { + dev_err(dev, "failed to synchronize FrameTime: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_runtime_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + + return 0; +} +#endif + +static const struct dev_pm_ops gb_interface_pm_ops = { + SET_RUNTIME_PM_OPS(gb_interface_suspend, gb_interface_resume, + gb_interface_runtime_idle) +}; + +struct device_type greybus_interface_type = { + .name = "greybus_interface", + .release = gb_interface_release, + .pm = &gb_interface_pm_ops, +}; + +/* + * A Greybus module represents a user-replaceable component on a GMP + * phone. An interface is the physical connection on that module. A + * module may have more than one interface. + * + * Create a gb_interface structure to represent a discovered interface. + * The position of interface within the Endo is encoded in "interface_id" + * argument. + * + * Returns a pointer to the new interfce or a null pointer if a + * failure occurs due to memory exhaustion. + */ +struct gb_interface *gb_interface_create(struct gb_module *module, + u8 interface_id) +{ + struct gb_host_device *hd = module->hd; + struct gb_interface *intf; + + intf = kzalloc(sizeof(*intf), GFP_KERNEL); + if (!intf) + return NULL; + + intf->hd = hd; /* XXX refcount? */ + intf->module = module; + intf->interface_id = interface_id; + INIT_LIST_HEAD(&intf->bundles); + INIT_LIST_HEAD(&intf->manifest_descs); + mutex_init(&intf->mutex); + INIT_WORK(&intf->mode_switch_work, gb_interface_mode_switch_work); + init_completion(&intf->mode_switch_completion); + + /* Invalid device id to start with */ + intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; + + intf->dev.parent = &module->dev; + intf->dev.bus = &greybus_bus_type; + intf->dev.type = &greybus_interface_type; + intf->dev.groups = interface_groups; + intf->dev.dma_mask = module->dev.dma_mask; + device_initialize(&intf->dev); + dev_set_name(&intf->dev, "%s.%u", dev_name(&module->dev), + interface_id); + + pm_runtime_set_autosuspend_delay(&intf->dev, + GB_INTERFACE_AUTOSUSPEND_MS); + + trace_gb_interface_create(intf); + + return intf; +} + +static int gb_interface_vsys_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_vsys_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to set v_sys: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_refclk_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_refclk_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to set refclk: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_unipro_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_unipro_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to set UniPro: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_activate_operation(struct gb_interface *intf, + enum gb_interface_type *intf_type) +{ + struct gb_svc *svc = intf->hd->svc; + u8 type; + int ret; + + dev_dbg(&intf->dev, "%s\n", __func__); + + ret = gb_svc_intf_activate(svc, intf->interface_id, &type); + if (ret) { + dev_err(&intf->dev, "failed to activate: %d\n", ret); + return ret; + } + + switch (type) { + case GB_SVC_INTF_TYPE_DUMMY: + *intf_type = GB_INTERFACE_TYPE_DUMMY; + /* FIXME: handle as an error for now */ + return -ENODEV; + case GB_SVC_INTF_TYPE_UNIPRO: + *intf_type = GB_INTERFACE_TYPE_UNIPRO; + dev_err(&intf->dev, "interface type UniPro not supported\n"); + /* FIXME: handle as an error for now */ + return -ENODEV; + case GB_SVC_INTF_TYPE_GREYBUS: + *intf_type = GB_INTERFACE_TYPE_GREYBUS; + break; + default: + dev_err(&intf->dev, "unknown interface type: %u\n", type); + *intf_type = GB_INTERFACE_TYPE_UNKNOWN; + return -ENODEV; + } + + return 0; +} + +static int gb_interface_hibernate_link(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + + return gb_svc_intf_set_power_mode_hibernate(svc, intf->interface_id); +} + +static int _gb_interface_activate(struct gb_interface *intf, + enum gb_interface_type *type) +{ + int ret; + + *type = GB_INTERFACE_TYPE_UNKNOWN; + + if (intf->ejected || intf->removed) + return -ENODEV; + + ret = gb_interface_vsys_set(intf, true); + if (ret) + return ret; + + ret = gb_interface_refclk_set(intf, true); + if (ret) + goto err_vsys_disable; + + ret = gb_interface_unipro_set(intf, true); + if (ret) + goto err_refclk_disable; + + ret = gb_interface_activate_operation(intf, type); + if (ret) { + switch (*type) { + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: + goto err_hibernate_link; + default: + goto err_unipro_disable; + } + } + + ret = gb_interface_read_dme(intf); + if (ret) + goto err_hibernate_link; + + ret = gb_interface_route_create(intf); + if (ret) + goto err_hibernate_link; + + intf->active = true; + + trace_gb_interface_activate(intf); + + return 0; + +err_hibernate_link: + gb_interface_hibernate_link(intf); +err_unipro_disable: + gb_interface_unipro_set(intf, false); +err_refclk_disable: + gb_interface_refclk_set(intf, false); +err_vsys_disable: + gb_interface_vsys_set(intf, false); + + return ret; +} + +/* + * At present, we assume a UniPro-only module to be a Greybus module that + * failed to send its mailbox poke. There is some reason to believe that this + * is because of a bug in the ES3 bootrom. + * + * FIXME: Check if this is a Toshiba bridge before retrying? + */ +static int _gb_interface_activate_es3_hack(struct gb_interface *intf, + enum gb_interface_type *type) +{ + int retries = 3; + int ret; + + while (retries--) { + ret = _gb_interface_activate(intf, type); + if (ret == -ENODEV && *type == GB_INTERFACE_TYPE_UNIPRO) + continue; + + break; + } + + return ret; +} + +/* + * Activate an interface. + * + * Locking: Caller holds the interface mutex. + */ +int gb_interface_activate(struct gb_interface *intf) +{ + enum gb_interface_type type; + int ret; + + switch (intf->type) { + case GB_INTERFACE_TYPE_INVALID: + case GB_INTERFACE_TYPE_GREYBUS: + ret = _gb_interface_activate_es3_hack(intf, &type); + break; + default: + ret = _gb_interface_activate(intf, &type); + } + + /* Make sure type is detected correctly during reactivation. */ + if (intf->type != GB_INTERFACE_TYPE_INVALID) { + if (type != intf->type) { + dev_err(&intf->dev, "failed to detect interface type\n"); + + if (!ret) + gb_interface_deactivate(intf); + + return -EIO; + } + } else { + intf->type = type; + } + + return ret; +} + +/* + * Deactivate an interface. + * + * Locking: Caller holds the interface mutex. + */ +void gb_interface_deactivate(struct gb_interface *intf) +{ + if (!intf->active) + return; + + trace_gb_interface_deactivate(intf); + + /* Abort any ongoing mode switch. */ + if (intf->mode_switch) + complete(&intf->mode_switch_completion); + + gb_interface_route_destroy(intf); + gb_interface_hibernate_link(intf); + gb_interface_unipro_set(intf, false); + gb_interface_refclk_set(intf, false); + gb_interface_vsys_set(intf, false); + + intf->active = false; +} + +/* + * Enable an interface by enabling its control connection, fetching the + * manifest and other information over it, and finally registering its child + * devices. + * + * Locking: Caller holds the interface mutex. + */ +int gb_interface_enable(struct gb_interface *intf) +{ + struct gb_control *control; + struct gb_bundle *bundle, *tmp; + int ret, size; + void *manifest; + + ret = gb_interface_read_and_clear_init_status(intf); + if (ret) { + dev_err(&intf->dev, "failed to clear init status: %d\n", ret); + return ret; + } + + /* Establish control connection */ + control = gb_control_create(intf); + if (IS_ERR(control)) { + dev_err(&intf->dev, "failed to create control device: %ld\n", + PTR_ERR(control)); + return PTR_ERR(control); + } + intf->control = control; + + ret = gb_control_enable(intf->control); + if (ret) + goto err_put_control; + + /* Get manifest size using control protocol on CPort */ + size = gb_control_get_manifest_size_operation(intf); + if (size <= 0) { + dev_err(&intf->dev, "failed to get manifest size: %d\n", size); + + if (size) + ret = size; + else + ret = -EINVAL; + + goto err_disable_control; + } + + manifest = kmalloc(size, GFP_KERNEL); + if (!manifest) { + ret = -ENOMEM; + goto err_disable_control; + } + + /* Get manifest using control protocol on CPort */ + ret = gb_control_get_manifest_operation(intf, manifest, size); + if (ret) { + dev_err(&intf->dev, "failed to get manifest: %d\n", ret); + goto err_free_manifest; + } + + /* + * Parse the manifest and build up our data structures representing + * what's in it. + */ + if (!gb_manifest_parse(intf, manifest, size)) { + dev_err(&intf->dev, "failed to parse manifest\n"); + ret = -EINVAL; + goto err_destroy_bundles; + } + + ret = gb_control_get_bundle_versions(intf->control); + if (ret) + goto err_destroy_bundles; + + ret = gb_timesync_interface_add(intf); + if (ret) { + dev_err(&intf->dev, "failed to add to timesync: %d\n", ret); + goto err_destroy_bundles; + } + + /* Register the control device and any bundles */ + ret = gb_control_add(intf->control); + if (ret) + goto err_remove_timesync; + + pm_runtime_use_autosuspend(&intf->dev); + pm_runtime_get_noresume(&intf->dev); + pm_runtime_set_active(&intf->dev); + pm_runtime_enable(&intf->dev); + + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { + ret = gb_bundle_add(bundle); + if (ret) { + gb_bundle_destroy(bundle); + continue; + } + } + + kfree(manifest); + + intf->enabled = true; + + pm_runtime_put(&intf->dev); + + trace_gb_interface_enable(intf); + + return 0; + +err_remove_timesync: + gb_timesync_interface_remove(intf); +err_destroy_bundles: + list_for_each_entry_safe(bundle, tmp, &intf->bundles, links) + gb_bundle_destroy(bundle); +err_free_manifest: + kfree(manifest); +err_disable_control: + gb_control_disable(intf->control); +err_put_control: + gb_control_put(intf->control); + intf->control = NULL; + + return ret; +} + +/* + * Disable an interface and destroy its bundles. + * + * Locking: Caller holds the interface mutex. + */ +void gb_interface_disable(struct gb_interface *intf) +{ + struct gb_bundle *bundle; + struct gb_bundle *next; + + if (!intf->enabled) + return; + + trace_gb_interface_disable(intf); + + pm_runtime_get_sync(&intf->dev); + + /* Set disconnected flag to avoid I/O during connection tear down. */ + if (intf->quirks & GB_INTERFACE_QUIRK_FORCED_DISABLE) + intf->disconnected = true; + + list_for_each_entry_safe(bundle, next, &intf->bundles, links) + gb_bundle_destroy(bundle); + + if (!intf->mode_switch && !intf->disconnected) + gb_control_interface_deactivate_prepare(intf->control); + + gb_control_del(intf->control); + gb_timesync_interface_remove(intf); + gb_control_disable(intf->control); + gb_control_put(intf->control); + intf->control = NULL; + + intf->enabled = false; + + pm_runtime_disable(&intf->dev); + pm_runtime_set_suspended(&intf->dev); + pm_runtime_dont_use_autosuspend(&intf->dev); + pm_runtime_put_noidle(&intf->dev); +} + +/* Enable TimeSync on an Interface control connection. */ +int gb_interface_timesync_enable(struct gb_interface *intf, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk) +{ + return gb_control_timesync_enable(intf->control, count, + frame_time, strobe_delay, + refclk); +} + +/* Disable TimeSync on an Interface control connection. */ +int gb_interface_timesync_disable(struct gb_interface *intf) +{ + return gb_control_timesync_disable(intf->control); +} + +/* Transmit the Authoritative FrameTime via an Interface control connection. */ +int gb_interface_timesync_authoritative(struct gb_interface *intf, + u64 *frame_time) +{ + return gb_control_timesync_authoritative(intf->control, + frame_time); +} + +/* Register an interface. */ +int gb_interface_add(struct gb_interface *intf) +{ + int ret; + + ret = device_add(&intf->dev); + if (ret) { + dev_err(&intf->dev, "failed to register interface: %d\n", ret); + return ret; + } + + trace_gb_interface_add(intf); + + dev_info(&intf->dev, "Interface added (%s)\n", + gb_interface_type_string(intf)); + + switch (intf->type) { + case GB_INTERFACE_TYPE_GREYBUS: + dev_info(&intf->dev, "GMP VID=0x%08x, PID=0x%08x\n", + intf->vendor_id, intf->product_id); + /* fall-through */ + case GB_INTERFACE_TYPE_UNIPRO: + dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", + intf->ddbl1_manufacturer_id, + intf->ddbl1_product_id); + break; + default: + break; + } + + return 0; +} + +/* Deregister an interface. */ +void gb_interface_del(struct gb_interface *intf) +{ + if (device_is_registered(&intf->dev)) { + trace_gb_interface_del(intf); + + device_del(&intf->dev); + dev_info(&intf->dev, "Interface removed\n"); + } +} + +void gb_interface_put(struct gb_interface *intf) +{ + put_device(&intf->dev); +} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h new file mode 100644 index 000000000000..03299d2a8be5 --- /dev/null +++ b/drivers/staging/greybus/interface.h @@ -0,0 +1,88 @@ +/* + * Greybus Interface Block code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __INTERFACE_H +#define __INTERFACE_H + +enum gb_interface_type { + GB_INTERFACE_TYPE_INVALID = 0, + GB_INTERFACE_TYPE_UNKNOWN, + GB_INTERFACE_TYPE_DUMMY, + GB_INTERFACE_TYPE_UNIPRO, + GB_INTERFACE_TYPE_GREYBUS, +}; + +#define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) +#define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) +#define GB_INTERFACE_QUIRK_NO_GMP_IDS BIT(2) +#define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) +#define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) +#define GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE BIT(5) +#define GB_INTERFACE_QUIRK_NO_PM BIT(6) + +struct gb_interface { + struct device dev; + struct gb_control *control; + + struct list_head bundles; + struct list_head module_node; + struct list_head manifest_descs; + u8 interface_id; /* Physical location within the Endo */ + u8 device_id; + u8 features; /* Feature flags set in the manifest */ + + enum gb_interface_type type; + + u32 ddbl1_manufacturer_id; + u32 ddbl1_product_id; + u32 vendor_id; + u32 product_id; + u64 serial_number; + + struct gb_host_device *hd; + struct gb_module *module; + + unsigned long quirks; + + struct mutex mutex; + + bool disconnected; + + bool ejected; + bool removed; + bool active; + bool enabled; + bool mode_switch; + bool dme_read; + + struct work_struct mode_switch_work; + struct completion mode_switch_completion; +}; +#define to_gb_interface(d) container_of(d, struct gb_interface, dev) + +struct gb_interface *gb_interface_create(struct gb_module *module, + u8 interface_id); +int gb_interface_activate(struct gb_interface *intf); +void gb_interface_deactivate(struct gb_interface *intf); +int gb_interface_enable(struct gb_interface *intf); +void gb_interface_disable(struct gb_interface *intf); +int gb_interface_timesync_enable(struct gb_interface *intf, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk); +int gb_interface_timesync_authoritative(struct gb_interface *intf, + u64 *frame_time); +int gb_interface_timesync_disable(struct gb_interface *intf); +int gb_interface_add(struct gb_interface *intf); +void gb_interface_del(struct gb_interface *intf); +void gb_interface_put(struct gb_interface *intf); +void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, + u32 mailbox); + +int gb_interface_request_mode_switch(struct gb_interface *intf); + +#endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c new file mode 100644 index 000000000000..8dffd8a7e762 --- /dev/null +++ b/drivers/staging/greybus/light.c @@ -0,0 +1,1361 @@ +/* + * Greybus Lights protocol driver. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "greybus_protocols.h" + +#define NAMES_MAX 32 + +struct gb_channel { + u8 id; + u32 flags; + u32 color; + char *color_name; + u8 fade_in; + u8 fade_out; + u32 mode; + char *mode_name; + struct attribute **attrs; + struct attribute_group *attr_group; + const struct attribute_group **attr_groups; + struct led_classdev *led; +#if IS_REACHABLE(CONFIG_LEDS_CLASS_FLASH) + struct led_classdev_flash fled; + struct led_flash_setting intensity_uA; + struct led_flash_setting timeout_us; +#else + struct led_classdev cled; +#endif + struct gb_light *light; + bool is_registered; + bool releasing; + bool strobe_state; + bool active; + struct mutex lock; +}; + +struct gb_light { + u8 id; + char *name; + struct gb_lights *glights; + u32 flags; + u8 channels_count; + struct gb_channel *channels; + bool has_flash; + bool ready; +#if IS_REACHABLE(CONFIG_V4L2_FLASH_LED_CLASS) + struct v4l2_flash *v4l2_flash; +#endif +}; + +struct gb_lights { + struct gb_connection *connection; + u8 lights_count; + struct gb_light *lights; + struct mutex lights_lock; +}; + +static void gb_lights_channel_free(struct gb_channel *channel); + +static struct gb_connection *get_conn_from_channel(struct gb_channel *channel) +{ + return channel->light->glights->connection; +} + +static struct gb_connection *get_conn_from_light(struct gb_light *light) +{ + return light->glights->connection; +} + +static bool is_channel_flash(struct gb_channel *channel) +{ + return !!(channel->mode & (GB_CHANNEL_MODE_FLASH | GB_CHANNEL_MODE_TORCH + | GB_CHANNEL_MODE_INDICATOR)); +} + +#if IS_REACHABLE(CONFIG_LEDS_CLASS_FLASH) +static struct gb_channel *get_channel_from_cdev(struct led_classdev *cdev) +{ + struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev); + + return container_of(fled_cdev, struct gb_channel, fled); +} + +static struct led_classdev *get_channel_cdev(struct gb_channel *channel) +{ + return &channel->fled.led_cdev; +} + +static struct gb_channel *get_channel_from_mode(struct gb_light *light, + u32 mode) +{ + struct gb_channel *channel = NULL; + int i; + + for (i = 0; i < light->channels_count; i++) { + channel = &light->channels[i]; + if (channel && channel->mode == mode) + break; + } + return channel; +} + +static int __gb_lights_flash_intensity_set(struct gb_channel *channel, + u32 intensity) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + struct gb_lights_set_flash_intensity_request req; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.intensity_uA = cpu_to_le32(intensity); + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_INTENSITY, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; +} + +static int __gb_lights_flash_brightness_set(struct gb_channel *channel) +{ + u32 intensity; + + /* If the channel is flash we need to get the attached torch channel */ + if (channel->mode & GB_CHANNEL_MODE_FLASH) + channel = get_channel_from_mode(channel->light, + GB_CHANNEL_MODE_TORCH); + + /* For not flash we need to convert brightness to intensity */ + intensity = channel->intensity_uA.min + + (channel->intensity_uA.step * channel->led->brightness); + + return __gb_lights_flash_intensity_set(channel, intensity); +} +#else +static struct gb_channel *get_channel_from_cdev(struct led_classdev *cdev) +{ + return container_of(cdev, struct gb_channel, cled); +} + +static struct led_classdev *get_channel_cdev(struct gb_channel *channel) +{ + return &channel->cled; +} + +static int __gb_lights_flash_brightness_set(struct gb_channel *channel) +{ + return 0; +} +#endif + +static int gb_lights_color_set(struct gb_channel *channel, u32 color); +static int gb_lights_fade_set(struct gb_channel *channel); + +static void led_lock(struct led_classdev *cdev) +{ + mutex_lock(&cdev->led_access); +} + +static void led_unlock(struct led_classdev *cdev) +{ + mutex_unlock(&cdev->led_access); +} + +#define gb_lights_fade_attr(__dir) \ +static ssize_t fade_##__dir##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct led_classdev *cdev = dev_get_drvdata(dev); \ + struct gb_channel *channel = get_channel_from_cdev(cdev); \ + \ + return sprintf(buf, "%u\n", channel->fade_##__dir); \ +} \ + \ +static ssize_t fade_##__dir##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t size) \ +{ \ + struct led_classdev *cdev = dev_get_drvdata(dev); \ + struct gb_channel *channel = get_channel_from_cdev(cdev); \ + u8 fade; \ + int ret; \ + \ + led_lock(cdev); \ + if (led_sysfs_is_disabled(cdev)) { \ + ret = -EBUSY; \ + goto unlock; \ + } \ + \ + ret = kstrtou8(buf, 0, &fade); \ + if (ret < 0) { \ + dev_err(dev, "could not parse fade value %d\n", ret); \ + goto unlock; \ + } \ + if (channel->fade_##__dir == fade) \ + goto unlock; \ + channel->fade_##__dir = fade; \ + \ + ret = gb_lights_fade_set(channel); \ + if (ret < 0) \ + goto unlock; \ + \ + ret = size; \ +unlock: \ + led_unlock(cdev); \ + return ret; \ +} \ +static DEVICE_ATTR_RW(fade_##__dir) + +gb_lights_fade_attr(in); +gb_lights_fade_attr(out); + +static ssize_t color_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct gb_channel *channel = get_channel_from_cdev(cdev); + + return sprintf(buf, "0x%08x\n", channel->color); +} + +static ssize_t color_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct gb_channel *channel = get_channel_from_cdev(cdev); + u32 color; + int ret; + + led_lock(cdev); + if (led_sysfs_is_disabled(cdev)) { + ret = -EBUSY; + goto unlock; + } + ret = kstrtou32(buf, 0, &color); + if (ret < 0) { + dev_err(dev, "could not parse color value %d\n", ret); + goto unlock; + } + + ret = gb_lights_color_set(channel, color); + if (ret < 0) + goto unlock; + + channel->color = color; + ret = size; +unlock: + led_unlock(cdev); + return ret; +} +static DEVICE_ATTR_RW(color); + +static int channel_attr_groups_set(struct gb_channel *channel, + struct led_classdev *cdev) +{ + int attr = 0; + int size = 0; + + if (channel->flags & GB_LIGHT_CHANNEL_MULTICOLOR) + size++; + if (channel->flags & GB_LIGHT_CHANNEL_FADER) + size += 2; + + if (!size) + return 0; + + /* Set attributes based in the channel flags */ + channel->attrs = kcalloc(size + 1, sizeof(*channel->attrs), GFP_KERNEL); + if (!channel->attrs) + return -ENOMEM; + channel->attr_group = kcalloc(1, sizeof(*channel->attr_group), + GFP_KERNEL); + if (!channel->attr_group) + return -ENOMEM; + channel->attr_groups = kcalloc(2, sizeof(*channel->attr_groups), + GFP_KERNEL); + if (!channel->attr_groups) + return -ENOMEM; + + if (channel->flags & GB_LIGHT_CHANNEL_MULTICOLOR) + channel->attrs[attr++] = &dev_attr_color.attr; + if (channel->flags & GB_LIGHT_CHANNEL_FADER) { + channel->attrs[attr++] = &dev_attr_fade_in.attr; + channel->attrs[attr++] = &dev_attr_fade_out.attr; + } + + channel->attr_group->attrs = channel->attrs; + + channel->attr_groups[0] = channel->attr_group; + + cdev->groups = channel->attr_groups; + + return 0; +} + +static int gb_lights_fade_set(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + struct gb_lights_set_fade_request req; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.fade_in = channel->fade_in; + req.fade_out = channel->fade_out; + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FADE, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; +} + +static int gb_lights_color_set(struct gb_channel *channel, u32 color) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + struct gb_lights_set_color_request req; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.color = cpu_to_le32(color); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; +} + +static int __gb_lights_led_brightness_set(struct gb_channel *channel) +{ + struct gb_lights_set_brightness_request req; + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + bool old_active; + int ret; + + mutex_lock(&channel->lock); + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + goto out_unlock; + + old_active = channel->active; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.brightness = (u8)channel->led->brightness; + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, + &req, sizeof(req), NULL, 0); + if (ret < 0) + goto out_pm_put; + + if (channel->led->brightness) + channel->active = true; + else + channel->active = false; + + /* we need to keep module alive when turning to active state */ + if (!old_active && channel->active) + goto out_unlock; + + /* + * on the other hand if going to inactive we still hold a reference and + * need to put it, so we could go to suspend. + */ + if (old_active && !channel->active) + gb_pm_runtime_put_autosuspend(bundle); + +out_pm_put: + gb_pm_runtime_put_autosuspend(bundle); +out_unlock: + mutex_unlock(&channel->lock); + + return ret; +} + +static int __gb_lights_brightness_set(struct gb_channel *channel) +{ + int ret; + + if (channel->releasing) + return 0; + + if (is_channel_flash(channel)) + ret = __gb_lights_flash_brightness_set(channel); + else + ret = __gb_lights_led_brightness_set(channel); + + return ret; +} + +static int gb_brightness_set(struct led_classdev *cdev, + enum led_brightness value) +{ + struct gb_channel *channel = get_channel_from_cdev(cdev); + + channel->led->brightness = value; + + return __gb_lights_brightness_set(channel); +} + +static enum led_brightness gb_brightness_get(struct led_classdev *cdev) + +{ + struct gb_channel *channel = get_channel_from_cdev(cdev); + + return channel->led->brightness; +} + +static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, + unsigned long *delay_off) +{ + struct gb_channel *channel = get_channel_from_cdev(cdev); + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + struct gb_lights_blink_request req; + bool old_active; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + if (!delay_on || !delay_off) + return -EINVAL; + + mutex_lock(&channel->lock); + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + goto out_unlock; + + old_active = channel->active; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.time_on_ms = cpu_to_le16(*delay_on); + req.time_off_ms = cpu_to_le16(*delay_off); + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, + sizeof(req), NULL, 0); + if (ret < 0) + goto out_pm_put; + + if (*delay_on) + channel->active = true; + else + channel->active = false; + + /* we need to keep module alive when turning to active state */ + if (!old_active && channel->active) + goto out_unlock; + + /* + * on the other hand if going to inactive we still hold a reference and + * need to put it, so we could go to suspend. + */ + if (old_active && !channel->active) + gb_pm_runtime_put_autosuspend(bundle); + +out_pm_put: + gb_pm_runtime_put_autosuspend(bundle); +out_unlock: + mutex_unlock(&channel->lock); + + return ret; +} + +static void gb_lights_led_operations_set(struct gb_channel *channel, + struct led_classdev *cdev) +{ + cdev->brightness_get = gb_brightness_get; + cdev->brightness_set_blocking = gb_brightness_set; + + if (channel->flags & GB_LIGHT_CHANNEL_BLINK) + cdev->blink_set = gb_blink_set; +} + +#if IS_REACHABLE(CONFIG_V4L2_FLASH_LED_CLASS) +/* V4L2 specific helpers */ +static const struct v4l2_flash_ops v4l2_flash_ops; + +static void __gb_lights_channel_v4l2_config(struct led_flash_setting *channel_s, + struct led_flash_setting *v4l2_s) +{ + v4l2_s->min = channel_s->min; + v4l2_s->max = channel_s->max; + v4l2_s->step = channel_s->step; + /* For v4l2 val is the default value */ + v4l2_s->val = channel_s->max; +} + +static int gb_lights_light_v4l2_register(struct gb_light *light) +{ + struct gb_connection *connection = get_conn_from_light(light); + struct device *dev = &connection->bundle->dev; + struct v4l2_flash_config *sd_cfg; + struct led_classdev_flash *fled; + struct led_classdev_flash *iled = NULL; + struct gb_channel *channel_torch, *channel_ind, *channel_flash; + int ret = 0; + + sd_cfg = kcalloc(1, sizeof(*sd_cfg), GFP_KERNEL); + if (!sd_cfg) + return -ENOMEM; + + channel_torch = get_channel_from_mode(light, GB_CHANNEL_MODE_TORCH); + if (channel_torch) + __gb_lights_channel_v4l2_config(&channel_torch->intensity_uA, + &sd_cfg->torch_intensity); + + channel_ind = get_channel_from_mode(light, GB_CHANNEL_MODE_INDICATOR); + if (channel_ind) { + __gb_lights_channel_v4l2_config(&channel_ind->intensity_uA, + &sd_cfg->indicator_intensity); + iled = &channel_ind->fled; + } + + channel_flash = get_channel_from_mode(light, GB_CHANNEL_MODE_FLASH); + WARN_ON(!channel_flash); + + fled = &channel_flash->fled; + + snprintf(sd_cfg->dev_name, sizeof(sd_cfg->dev_name), "%s", light->name); + + /* Set the possible values to faults, in our case all faults */ + sd_cfg->flash_faults = LED_FAULT_OVER_VOLTAGE | LED_FAULT_TIMEOUT | + LED_FAULT_OVER_TEMPERATURE | LED_FAULT_SHORT_CIRCUIT | + LED_FAULT_OVER_CURRENT | LED_FAULT_INDICATOR | + LED_FAULT_UNDER_VOLTAGE | LED_FAULT_INPUT_VOLTAGE | + LED_FAULT_LED_OVER_TEMPERATURE; + + light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, iled, + &v4l2_flash_ops, sd_cfg); + if (IS_ERR_OR_NULL(light->v4l2_flash)) { + ret = PTR_ERR(light->v4l2_flash); + goto out_free; + } + + return ret; + +out_free: + kfree(sd_cfg); + return ret; +} + +static void gb_lights_light_v4l2_unregister(struct gb_light *light) +{ + v4l2_flash_release(light->v4l2_flash); +} +#else +static int gb_lights_light_v4l2_register(struct gb_light *light) +{ + struct gb_connection *connection = get_conn_from_light(light); + + dev_err(&connection->bundle->dev, "no support for v4l2 subdevices\n"); + return 0; +} + +static void gb_lights_light_v4l2_unregister(struct gb_light *light) +{ +} +#endif + +#if IS_REACHABLE(CONFIG_LEDS_CLASS_FLASH) +/* Flash specific operations */ +static int gb_lights_flash_intensity_set(struct led_classdev_flash *fcdev, + u32 brightness) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + int ret; + + ret = __gb_lights_flash_intensity_set(channel, brightness); + if (ret < 0) + return ret; + + fcdev->brightness.val = brightness; + + return 0; +} + +static int gb_lights_flash_intensity_get(struct led_classdev_flash *fcdev, + u32 *brightness) +{ + *brightness = fcdev->brightness.val; + + return 0; +} + +static int gb_lights_flash_strobe_set(struct led_classdev_flash *fcdev, + bool state) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + struct gb_lights_set_flash_strobe_request req; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.state = state ? 1 : 0; + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_STROBE, + &req, sizeof(req), NULL, 0); + if (!ret) + channel->strobe_state = state; + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; +} + +static int gb_lights_flash_strobe_get(struct led_classdev_flash *fcdev, + bool *state) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + + *state = channel->strobe_state; + return 0; +} + +static int gb_lights_flash_timeout_set(struct led_classdev_flash *fcdev, + u32 timeout) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + struct gb_lights_set_flash_timeout_request req; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.timeout_us = cpu_to_le32(timeout); + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT, + &req, sizeof(req), NULL, 0); + if (!ret) + fcdev->timeout.val = timeout; + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; +} + +static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, + u32 *fault) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + struct gb_lights_get_flash_fault_request req; + struct gb_lights_get_flash_fault_response resp; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_FLASH_FAULT, + &req, sizeof(req), &resp, sizeof(resp)); + if (!ret) + *fault = le32_to_cpu(resp.fault); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; +} + +static const struct led_flash_ops gb_lights_flash_ops = { + .flash_brightness_set = gb_lights_flash_intensity_set, + .flash_brightness_get = gb_lights_flash_intensity_get, + .strobe_set = gb_lights_flash_strobe_set, + .strobe_get = gb_lights_flash_strobe_get, + .timeout_set = gb_lights_flash_timeout_set, + .fault_get = gb_lights_flash_fault_get, +}; + +static int __gb_lights_channel_torch_attach(struct gb_channel *channel, + struct gb_channel *channel_torch) +{ + char *name; + + /* we can only attach torch to a flash channel */ + if (!(channel->mode & GB_CHANNEL_MODE_FLASH)) + return 0; + + /* Move torch brightness to the destination */ + channel->led->max_brightness = channel_torch->led->max_brightness; + + /* append mode name to flash name */ + name = kasprintf(GFP_KERNEL, "%s_%s", channel->led->name, + channel_torch->mode_name); + if (!name) + return -ENOMEM; + kfree(channel->led->name); + channel->led->name = name; + + channel_torch->led = channel->led; + + return 0; +} + +static int __gb_lights_flash_led_register(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct led_classdev_flash *fled = &channel->fled; + struct led_flash_setting *fset; + struct gb_channel *channel_torch; + int ret; + + fled->ops = &gb_lights_flash_ops; + + fled->led_cdev.flags |= LED_DEV_CAP_FLASH; + + fset = &fled->brightness; + fset->min = channel->intensity_uA.min; + fset->max = channel->intensity_uA.max; + fset->step = channel->intensity_uA.step; + fset->val = channel->intensity_uA.max; + + /* Only the flash mode have the timeout constraints settings */ + if (channel->mode & GB_CHANNEL_MODE_FLASH) { + fset = &fled->timeout; + fset->min = channel->timeout_us.min; + fset->max = channel->timeout_us.max; + fset->step = channel->timeout_us.step; + fset->val = channel->timeout_us.max; + } + + /* + * If light have torch mode channel, this channel will be the led + * classdev of the registered above flash classdev + */ + channel_torch = get_channel_from_mode(channel->light, + GB_CHANNEL_MODE_TORCH); + if (channel_torch) { + ret = __gb_lights_channel_torch_attach(channel, channel_torch); + if (ret < 0) + goto fail; + } + + ret = led_classdev_flash_register(&connection->bundle->dev, fled); + if (ret < 0) + goto fail; + + channel->is_registered = true; + return 0; +fail: + channel->led = NULL; + return ret; +} + +static void __gb_lights_flash_led_unregister(struct gb_channel *channel) +{ + if (!channel->is_registered) + return; + + led_classdev_flash_unregister(&channel->fled); +} + +static int gb_lights_channel_flash_config(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_get_channel_flash_config_request req; + struct gb_lights_get_channel_flash_config_response conf; + struct led_flash_setting *fset; + int ret; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + + ret = gb_operation_sync(connection, + GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG, + &req, sizeof(req), &conf, sizeof(conf)); + if (ret < 0) + return ret; + + /* + * Intensity constraints for flash related modes: flash, torch, + * indicator. They will be needed for v4l2 registration. + */ + fset = &channel->intensity_uA; + fset->min = le32_to_cpu(conf.intensity_min_uA); + fset->max = le32_to_cpu(conf.intensity_max_uA); + fset->step = le32_to_cpu(conf.intensity_step_uA); + + /* + * On flash type, max brightness is set as the number of intensity steps + * available. + */ + channel->led->max_brightness = (fset->max - fset->min) / fset->step; + + /* Only the flash mode have the timeout constraints settings */ + if (channel->mode & GB_CHANNEL_MODE_FLASH) { + fset = &channel->timeout_us; + fset->min = le32_to_cpu(conf.timeout_min_us); + fset->max = le32_to_cpu(conf.timeout_max_us); + fset->step = le32_to_cpu(conf.timeout_step_us); + } + + return 0; +} +#else +static int gb_lights_channel_flash_config(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + + dev_err(&connection->bundle->dev, "no support for flash devices\n"); + return 0; +} + +static int __gb_lights_flash_led_register(struct gb_channel *channel) +{ + return 0; +} + +static void __gb_lights_flash_led_unregister(struct gb_channel *channel) +{ +} + +#endif + +static int __gb_lights_led_register(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct led_classdev *cdev = get_channel_cdev(channel); + int ret; + + ret = led_classdev_register(&connection->bundle->dev, cdev); + if (ret < 0) + channel->led = NULL; + else + channel->is_registered = true; + return ret; +} + +static int gb_lights_channel_register(struct gb_channel *channel) +{ + /* Normal LED channel, just register in led classdev and we are done */ + if (!is_channel_flash(channel)) + return __gb_lights_led_register(channel); + + /* + * Flash Type need more work, register flash classdev, indicator as + * flash classdev, torch will be led classdev of the flash classdev. + */ + if (!(channel->mode & GB_CHANNEL_MODE_TORCH)) + return __gb_lights_flash_led_register(channel); + + return 0; +} + +static void __gb_lights_led_unregister(struct gb_channel *channel) +{ + struct led_classdev *cdev = get_channel_cdev(channel); + + if (!channel->is_registered) + return; + + led_classdev_unregister(cdev); + channel->led = NULL; +} + +static void gb_lights_channel_unregister(struct gb_channel *channel) +{ + /* The same as register, handle channels differently */ + if (!is_channel_flash(channel)) { + __gb_lights_led_unregister(channel); + return; + } + + if (channel->mode & GB_CHANNEL_MODE_TORCH) + __gb_lights_led_unregister(channel); + else + __gb_lights_flash_led_unregister(channel); +} + +static int gb_lights_channel_config(struct gb_light *light, + struct gb_channel *channel) +{ + struct gb_lights_get_channel_config_response conf; + struct gb_lights_get_channel_config_request req; + struct gb_connection *connection = get_conn_from_light(light); + struct led_classdev *cdev = get_channel_cdev(channel); + char *name; + int ret; + + req.light_id = light->id; + req.channel_id = channel->id; + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG, + &req, sizeof(req), &conf, sizeof(conf)); + if (ret < 0) + return ret; + + channel->light = light; + channel->mode = le32_to_cpu(conf.mode); + channel->flags = le32_to_cpu(conf.flags); + channel->color = le32_to_cpu(conf.color); + channel->color_name = kstrndup(conf.color_name, NAMES_MAX, GFP_KERNEL); + if (!channel->color_name) + return -ENOMEM; + channel->mode_name = kstrndup(conf.mode_name, NAMES_MAX, GFP_KERNEL); + if (!channel->mode_name) + return -ENOMEM; + + channel->led = cdev; + + name = kasprintf(GFP_KERNEL, "%s:%s:%s", light->name, + channel->color_name, channel->mode_name); + if (!name) + return -ENOMEM; + + cdev->name = name; + + cdev->max_brightness = conf.max_brightness; + + ret = channel_attr_groups_set(channel, cdev); + if (ret < 0) + return ret; + + gb_lights_led_operations_set(channel, cdev); + + /* + * If it is not a flash related channel (flash, torch or indicator) we + * are done here. If not, continue and fetch flash related + * configurations. + */ + if (!is_channel_flash(channel)) + return ret; + + light->has_flash = true; + + ret = gb_lights_channel_flash_config(channel); + if (ret < 0) + return ret; + + return ret; +} + +static int gb_lights_light_config(struct gb_lights *glights, u8 id) +{ + struct gb_light *light = &glights->lights[id]; + struct gb_lights_get_light_config_request req; + struct gb_lights_get_light_config_response conf; + int ret; + int i; + + light->glights = glights; + light->id = id; + + req.id = id; + + ret = gb_operation_sync(glights->connection, + GB_LIGHTS_TYPE_GET_LIGHT_CONFIG, + &req, sizeof(req), &conf, sizeof(conf)); + if (ret < 0) + return ret; + + if (!conf.channel_count) + return -EINVAL; + if (!strlen(conf.name)) + return -EINVAL; + + light->channels_count = conf.channel_count; + light->name = kstrndup(conf.name, NAMES_MAX, GFP_KERNEL); + + light->channels = kzalloc(light->channels_count * + sizeof(struct gb_channel), GFP_KERNEL); + if (!light->channels) + return -ENOMEM; + + /* First we collect all the configurations for all channels */ + for (i = 0; i < light->channels_count; i++) { + light->channels[i].id = i; + ret = gb_lights_channel_config(light, &light->channels[i]); + if (ret < 0) + return ret; + } + + return 0; +} + +static int gb_lights_light_register(struct gb_light *light) +{ + int ret; + int i; + + /* + * Then, if everything went ok in getting configurations, we register + * the classdev, flash classdev and v4l2 subsystem, if a flash device is + * found. + */ + for (i = 0; i < light->channels_count; i++) { + ret = gb_lights_channel_register(&light->channels[i]); + if (ret < 0) + return ret; + + mutex_init(&light->channels[i].lock); + } + + light->ready = true; + + if (light->has_flash) { + ret = gb_lights_light_v4l2_register(light); + if (ret < 0) { + light->has_flash = false; + return ret; + } + } + + return 0; +} + +static void gb_lights_channel_free(struct gb_channel *channel) +{ + kfree(channel->attrs); + kfree(channel->attr_group); + kfree(channel->attr_groups); + kfree(channel->color_name); + kfree(channel->mode_name); + mutex_destroy(&channel->lock); +} + +static void gb_lights_channel_release(struct gb_channel *channel) +{ + channel->releasing = true; + + gb_lights_channel_unregister(channel); + + gb_lights_channel_free(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); + + for (i = 0; i < count; i++) { + gb_lights_channel_release(&light->channels[i]); + light->channels_count--; + } + kfree(light->channels); + kfree(light->name); +} + +static void gb_lights_release(struct gb_lights *glights) +{ + int i; + + if (!glights) + return; + + mutex_lock(&glights->lights_lock); + if (!glights->lights) + goto free_glights; + + for (i = 0; i < glights->lights_count; i++) + gb_lights_light_release(&glights->lights[i]); + + kfree(glights->lights); + +free_glights: + mutex_unlock(&glights->lights_lock); + mutex_destroy(&glights->lights_lock); + kfree(glights); +} + +static int gb_lights_get_count(struct gb_lights *glights) +{ + struct gb_lights_get_lights_response resp; + int ret; + + ret = gb_operation_sync(glights->connection, GB_LIGHTS_TYPE_GET_LIGHTS, + NULL, 0, &resp, sizeof(resp)); + if (ret < 0) + return ret; + + if (!resp.lights_count) + return -EINVAL; + + glights->lights_count = resp.lights_count; + + return 0; +} + +static int gb_lights_create_all(struct gb_lights *glights) +{ + struct gb_connection *connection = glights->connection; + int ret; + int i; + + mutex_lock(&glights->lights_lock); + ret = gb_lights_get_count(glights); + if (ret < 0) + goto out; + + glights->lights = kzalloc(glights->lights_count * + sizeof(struct gb_light), GFP_KERNEL); + if (!glights->lights) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < glights->lights_count; i++) { + ret = gb_lights_light_config(glights, i); + if (ret < 0) { + dev_err(&connection->bundle->dev, + "Fail to configure lights device\n"); + goto out; + } + } + +out: + mutex_unlock(&glights->lights_lock); + return ret; +} + +static int gb_lights_register_all(struct gb_lights *glights) +{ + struct gb_connection *connection = glights->connection; + int ret = 0; + int i; + + mutex_lock(&glights->lights_lock); + for (i = 0; i < glights->lights_count; i++) { + ret = gb_lights_light_register(&glights->lights[i]); + if (ret < 0) { + dev_err(&connection->bundle->dev, + "Fail to enable lights device\n"); + break; + } + } + + mutex_unlock(&glights->lights_lock); + return ret; +} + +static int gb_lights_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct device *dev = &connection->bundle->dev; + struct gb_lights *glights = gb_connection_get_data(connection); + struct gb_light *light; + struct gb_message *request; + struct gb_lights_event_request *payload; + int ret = 0; + u8 light_id; + u8 event; + + if (op->type != GB_LIGHTS_TYPE_EVENT) { + dev_err(dev, "Unsupported unsolicited event: %u\n", op->type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size < sizeof(*payload)) { + dev_err(dev, "Wrong event size received (%zu < %zu)\n", + request->payload_size, sizeof(*payload)); + return -EINVAL; + } + + payload = request->payload; + light_id = payload->light_id; + + if (light_id >= glights->lights_count || + !glights->lights[light_id].ready) { + dev_err(dev, "Event received for unconfigured light id: %d\n", + light_id); + return -EINVAL; + } + + event = payload->event; + + if (event & GB_LIGHTS_LIGHT_CONFIG) { + light = &glights->lights[light_id]; + + mutex_lock(&glights->lights_lock); + gb_lights_light_release(light); + ret = gb_lights_light_config(glights, light_id); + if (!ret) + ret = gb_lights_light_register(light); + if (ret < 0) + gb_lights_light_release(light); + mutex_unlock(&glights->lights_lock); + } + + return ret; +} + +static int gb_lights_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_lights *glights; + int ret; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LIGHTS) + return -ENODEV; + + glights = kzalloc(sizeof(*glights), GFP_KERNEL); + if (!glights) + return -ENOMEM; + + mutex_init(&glights->lights_lock); + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_lights_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto out; + } + + glights->connection = connection; + gb_connection_set_data(connection, glights); + + greybus_set_drvdata(bundle, glights); + + /* We aren't ready to receive an incoming request yet */ + ret = gb_connection_enable_tx(connection); + if (ret) + goto error_connection_destroy; + + /* + * Setup all the lights devices over this connection, if anything goes + * wrong tear down all lights + */ + ret = gb_lights_create_all(glights); + if (ret < 0) + goto error_connection_disable; + + /* We are ready to receive an incoming request now, enable RX as well */ + ret = gb_connection_enable(connection); + if (ret) + goto error_connection_disable; + + /* Enable & register lights */ + ret = gb_lights_register_all(glights); + if (ret < 0) + goto error_connection_disable; + + gb_pm_runtime_put_autosuspend(bundle); + + return 0; + +error_connection_disable: + gb_connection_disable(connection); +error_connection_destroy: + gb_connection_destroy(connection); +out: + gb_lights_release(glights); + return ret; +} + +static void gb_lights_disconnect(struct gb_bundle *bundle) +{ + struct gb_lights *glights = greybus_get_drvdata(bundle); + + if (gb_pm_runtime_get_sync(bundle)) + gb_pm_runtime_get_noresume(bundle); + + gb_connection_disable(glights->connection); + gb_connection_destroy(glights->connection); + + gb_lights_release(glights); +} + +static const struct greybus_bundle_id gb_lights_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_lights_id_table); + +static struct greybus_driver gb_lights_driver = { + .name = "lights", + .probe = gb_lights_probe, + .disconnect = gb_lights_disconnect, + .id_table = gb_lights_id_table, +}; +module_greybus_driver(gb_lights_driver); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/log.c b/drivers/staging/greybus/log.c new file mode 100644 index 000000000000..70dd9e5a1cf2 --- /dev/null +++ b/drivers/staging/greybus/log.c @@ -0,0 +1,132 @@ +/* + * Greybus driver for the log protocol + * + * Copyright 2016 Google Inc. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include + +#include "greybus.h" + +struct gb_log { + struct gb_connection *connection; +}; + +static int gb_log_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct device *dev = &connection->bundle->dev; + struct gb_log_send_log_request *receive; + u16 len; + + if (op->type != GB_LOG_TYPE_SEND_LOG) { + dev_err(dev, "unknown request type 0x%02x\n", op->type); + return -EINVAL; + } + + /* 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)); + return -EINVAL; + } + receive = op->request->payload; + len = le16_to_cpu(receive->len); + if (len != (int)(op->request->payload_size - sizeof(*receive))) { + dev_err(dev, "log request wrong size %d vs %d\n", len, + (int)(op->request->payload_size - sizeof(*receive))); + return -EINVAL; + } + if (len == 0) { + dev_err(dev, "log request of 0 bytes?\n"); + return -EINVAL; + } + + if (len > GB_LOG_MAX_LEN) { + dev_err(dev, "log request too big: %d\n", len); + return -EINVAL; + } + + /* Ensure the buffer is 0 terminated */ + receive->msg[len - 1] = '\0'; + + /* Print with dev_dbg() so that it can be easily turned off using + * dynamic debugging (and prevent any DoS) */ + dev_dbg(dev, "%s", receive->msg); + + return 0; +} + +static int gb_log_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_log *log; + int retval; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LOG) + return -ENODEV; + + log = kzalloc(sizeof(*log), GFP_KERNEL); + if (!log) + return -ENOMEM; + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_log_request_handler); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto error_free; + } + + log->connection = connection; + greybus_set_drvdata(bundle, log); + + retval = gb_connection_enable(connection); + if (retval) + goto error_connection_destroy; + + return 0; + +error_connection_destroy: + gb_connection_destroy(connection); +error_free: + kfree(log); + return retval; +} + +static void gb_log_disconnect(struct gb_bundle *bundle) +{ + struct gb_log *log = greybus_get_drvdata(bundle); + struct gb_connection *connection = log->connection; + + gb_connection_disable(connection); + gb_connection_destroy(connection); + + kfree(log); +} + +static const struct greybus_bundle_id gb_log_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOG) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_log_id_table); + +static struct greybus_driver gb_log_driver = { + .name = "log", + .probe = gb_log_probe, + .disconnect = gb_log_disconnect, + .id_table = gb_log_id_table, +}; +module_greybus_driver(gb_log_driver); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c new file mode 100644 index 000000000000..7882306adeca --- /dev/null +++ b/drivers/staging/greybus/loopback.c @@ -0,0 +1,1364 @@ +/* + * Loopback bridge driver for the Greybus loopback module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "greybus.h" +#include "connection.h" + +#define NSEC_PER_DAY 86400000000000ULL + +struct gb_loopback_stats { + u32 min; + u32 max; + u64 sum; + u32 count; +}; + +struct gb_loopback_device { + struct dentry *root; + u32 count; + size_t size_max; + + /* We need to take a lock in atomic context */ + spinlock_t lock; + struct list_head list; + struct list_head list_op_async; + wait_queue_head_t wq; +}; + +static struct gb_loopback_device gb_dev; + +struct gb_loopback_async_operation { + struct gb_loopback *gb; + struct gb_operation *operation; + struct timeval ts; + struct timer_list timer; + struct list_head entry; + struct work_struct work; + struct kref kref; + bool pending; + int (*completion)(struct gb_loopback_async_operation *op_async); +}; + +struct gb_loopback { + struct gb_connection *connection; + + struct dentry *file; + struct kfifo kfifo_lat; + struct kfifo kfifo_ts; + struct mutex mutex; + struct task_struct *task; + struct list_head entry; + struct device *dev; + wait_queue_head_t wq; + wait_queue_head_t wq_completion; + atomic_t outstanding_operations; + + /* Per connection stats */ + struct timeval ts; + struct gb_loopback_stats latency; + struct gb_loopback_stats throughput; + struct gb_loopback_stats requests_per_second; + struct gb_loopback_stats apbridge_unipro_latency; + struct gb_loopback_stats gbphy_firmware_latency; + + int type; + int async; + int id; + u32 size; + u32 iteration_max; + u32 iteration_count; + int us_wait; + u32 error; + u32 requests_completed; + u32 requests_timedout; + u32 timeout; + u32 jiffy_timeout; + u32 timeout_min; + u32 timeout_max; + u32 outstanding_operations_max; + u32 lbid; + u64 elapsed_nsecs; + u32 apbridge_latency_ts; + u32 gbphy_latency_ts; + + u32 send_count; +}; + +static struct class loopback_class = { + .name = "gb_loopback", + .owner = THIS_MODULE, +}; +static DEFINE_IDA(loopback_ida); + +/* Min/max values in jiffies */ +#define GB_LOOPBACK_TIMEOUT_MIN 1 +#define GB_LOOPBACK_TIMEOUT_MAX 10000 + +#define GB_LOOPBACK_FIFO_DEFAULT 8192 + +static unsigned kfifo_depth = GB_LOOPBACK_FIFO_DEFAULT; +module_param(kfifo_depth, uint, 0444); + +/* Maximum size of any one send data buffer we support */ +#define MAX_PACKET_SIZE (PAGE_SIZE * 2) + +#define GB_LOOPBACK_US_WAIT_MAX 1000000 + +/* interface sysfs attributes */ +#define gb_loopback_ro_attr(field) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ + return sprintf(buf, "%u\n", gb->field); \ +} \ +static DEVICE_ATTR_RO(field) + +#define gb_loopback_ro_stats_attr(name, field, type) \ +static ssize_t name##_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ + /* Report 0 for min and max if no transfer successed */ \ + if (!gb->requests_completed) \ + return sprintf(buf, "0\n"); \ + return sprintf(buf, "%"#type"\n", gb->name.field); \ +} \ +static DEVICE_ATTR_RO(name##_##field) + +#define gb_loopback_ro_avg_attr(name) \ +static ssize_t name##_avg_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_loopback_stats *stats; \ + struct gb_loopback *gb; \ + u64 avg, rem; \ + u32 count; \ + gb = dev_get_drvdata(dev); \ + stats = &gb->name; \ + count = stats->count ? stats->count : 1; \ + avg = stats->sum + count / 2000000; /* round closest */ \ + rem = do_div(avg, count); \ + rem *= 1000000; \ + do_div(rem, count); \ + return sprintf(buf, "%llu.%06u\n", avg, (u32)rem); \ +} \ +static DEVICE_ATTR_RO(name##_avg) + +#define gb_loopback_stats_attrs(field) \ + gb_loopback_ro_stats_attr(field, min, u); \ + gb_loopback_ro_stats_attr(field, max, u); \ + gb_loopback_ro_avg_attr(field) + +#define gb_loopback_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ + return sprintf(buf, "%"#type"\n", gb->field); \ +} \ +static ssize_t field##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, \ + size_t len) \ +{ \ + int ret; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ + mutex_lock(&gb->mutex); \ + ret = sscanf(buf, "%"#type, &gb->field); \ + if (ret != 1) \ + len = -EINVAL; \ + else \ + gb_loopback_check_attr(gb, bundle); \ + mutex_unlock(&gb->mutex); \ + return len; \ +} \ +static DEVICE_ATTR_RW(field) + +#define gb_dev_loopback_ro_attr(field, conn) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ + return sprintf(buf, "%u\n", gb->field); \ +} \ +static DEVICE_ATTR_RO(field) + +#define gb_dev_loopback_rw_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ + return sprintf(buf, "%"#type"\n", gb->field); \ +} \ +static ssize_t field##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, \ + size_t len) \ +{ \ + int ret; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ + mutex_lock(&gb->mutex); \ + ret = sscanf(buf, "%"#type, &gb->field); \ + if (ret != 1) \ + len = -EINVAL; \ + else \ + gb_loopback_check_attr(gb); \ + mutex_unlock(&gb->mutex); \ + return len; \ +} \ +static DEVICE_ATTR_RW(field) + +static void gb_loopback_reset_stats(struct gb_loopback *gb); +static void gb_loopback_check_attr(struct gb_loopback *gb) +{ + if (gb->us_wait > GB_LOOPBACK_US_WAIT_MAX) + gb->us_wait = GB_LOOPBACK_US_WAIT_MAX; + if (gb->size > gb_dev.size_max) + gb->size = gb_dev.size_max; + gb->requests_timedout = 0; + gb->requests_completed = 0; + gb->iteration_count = 0; + gb->send_count = 0; + gb->error = 0; + + if (kfifo_depth < gb->iteration_max) { + dev_warn(gb->dev, + "cannot log bytes %u kfifo_depth %u\n", + gb->iteration_max, kfifo_depth); + } + kfifo_reset_out(&gb->kfifo_lat); + kfifo_reset_out(&gb->kfifo_ts); + + switch (gb->type) { + case GB_LOOPBACK_TYPE_PING: + case GB_LOOPBACK_TYPE_TRANSFER: + case GB_LOOPBACK_TYPE_SINK: + gb->jiffy_timeout = usecs_to_jiffies(gb->timeout); + if (!gb->jiffy_timeout) + gb->jiffy_timeout = GB_LOOPBACK_TIMEOUT_MIN; + else if (gb->jiffy_timeout > GB_LOOPBACK_TIMEOUT_MAX) + gb->jiffy_timeout = GB_LOOPBACK_TIMEOUT_MAX; + gb_loopback_reset_stats(gb); + wake_up(&gb->wq); + break; + default: + gb->type = 0; + break; + } +} + +/* Time to send and receive one message */ +gb_loopback_stats_attrs(latency); +/* Number of requests sent per second on this cport */ +gb_loopback_stats_attrs(requests_per_second); +/* Quantity of data sent and received on this cport */ +gb_loopback_stats_attrs(throughput); +/* Latency across the UniPro link from APBridge's perspective */ +gb_loopback_stats_attrs(apbridge_unipro_latency); +/* Firmware induced overhead in the GPBridge */ +gb_loopback_stats_attrs(gbphy_firmware_latency); + +/* Number of errors encountered during loop */ +gb_loopback_ro_attr(error); +/* Number of requests successfully completed async */ +gb_loopback_ro_attr(requests_completed); +/* Number of requests timed out async */ +gb_loopback_ro_attr(requests_timedout); +/* Timeout minimum in useconds */ +gb_loopback_ro_attr(timeout_min); +/* Timeout minimum in useconds */ +gb_loopback_ro_attr(timeout_max); + +/* + * Type of loopback message to send based on protocol type definitions + * 0 => Don't send message + * 2 => Send ping message continuously (message without payload) + * 3 => Send transfer message continuously (message with payload, + * payload returned in response) + * 4 => Send a sink message (message with payload, no payload in response) + */ +gb_dev_loopback_rw_attr(type, d); +/* Size of transfer message payload: 0-4096 bytes */ +gb_dev_loopback_rw_attr(size, u); +/* Time to wait between two messages: 0-1000 ms */ +gb_dev_loopback_rw_attr(us_wait, d); +/* Maximum iterations for a given operation: 1-(2^32-1), 0 implies infinite */ +gb_dev_loopback_rw_attr(iteration_max, u); +/* The current index of the for (i = 0; i < iteration_max; i++) loop */ +gb_dev_loopback_ro_attr(iteration_count, false); +/* A flag to indicate synchronous or asynchronous operations */ +gb_dev_loopback_rw_attr(async, u); +/* Timeout of an individual asynchronous request */ +gb_dev_loopback_rw_attr(timeout, u); +/* Maximum number of in-flight operations before back-off */ +gb_dev_loopback_rw_attr(outstanding_operations_max, u); + +static struct attribute *loopback_attrs[] = { + &dev_attr_latency_min.attr, + &dev_attr_latency_max.attr, + &dev_attr_latency_avg.attr, + &dev_attr_requests_per_second_min.attr, + &dev_attr_requests_per_second_max.attr, + &dev_attr_requests_per_second_avg.attr, + &dev_attr_throughput_min.attr, + &dev_attr_throughput_max.attr, + &dev_attr_throughput_avg.attr, + &dev_attr_apbridge_unipro_latency_min.attr, + &dev_attr_apbridge_unipro_latency_max.attr, + &dev_attr_apbridge_unipro_latency_avg.attr, + &dev_attr_gbphy_firmware_latency_min.attr, + &dev_attr_gbphy_firmware_latency_max.attr, + &dev_attr_gbphy_firmware_latency_avg.attr, + &dev_attr_type.attr, + &dev_attr_size.attr, + &dev_attr_us_wait.attr, + &dev_attr_iteration_count.attr, + &dev_attr_iteration_max.attr, + &dev_attr_async.attr, + &dev_attr_error.attr, + &dev_attr_requests_completed.attr, + &dev_attr_requests_timedout.attr, + &dev_attr_timeout.attr, + &dev_attr_outstanding_operations_max.attr, + &dev_attr_timeout_min.attr, + &dev_attr_timeout_max.attr, + NULL, +}; +ATTRIBUTE_GROUPS(loopback); + +static void gb_loopback_calculate_stats(struct gb_loopback *gb, bool error); + +static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs) +{ + u32 lat; + + do_div(elapsed_nsecs, NSEC_PER_USEC); + lat = elapsed_nsecs; + return lat; +} + +static u64 __gb_loopback_calc_latency(u64 t1, u64 t2) +{ + if (t2 > t1) + return t2 - t1; + else + return NSEC_PER_DAY - t2 + t1; +} + +static u64 gb_loopback_calc_latency(struct timeval *ts, struct timeval *te) +{ + u64 t1, t2; + + t1 = timeval_to_ns(ts); + t2 = timeval_to_ns(te); + + return __gb_loopback_calc_latency(t1, t2); +} + +static void gb_loopback_push_latency_ts(struct gb_loopback *gb, + struct timeval *ts, struct timeval *te) +{ + kfifo_in(&gb->kfifo_ts, (unsigned char *)ts, sizeof(*ts)); + kfifo_in(&gb->kfifo_ts, (unsigned char *)te, sizeof(*te)); +} + +static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, + void *request, int request_size, + void *response, int response_size) +{ + struct gb_operation *operation; + struct timeval ts, te; + int ret; + + do_gettimeofday(&ts); + operation = gb_operation_create(gb->connection, type, request_size, + response_size, GFP_KERNEL); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync(operation); + if (ret) { + dev_err(&gb->connection->bundle->dev, + "synchronous operation failed: %d\n", ret); + goto out_put_operation; + } else { + if (response_size == operation->response->payload_size) { + memcpy(response, operation->response->payload, + response_size); + } else { + dev_err(&gb->connection->bundle->dev, + "response size %zu expected %d\n", + operation->response->payload_size, + response_size); + ret = -EINVAL; + goto out_put_operation; + } + } + + do_gettimeofday(&te); + + /* Calculate the total time the message took */ + gb_loopback_push_latency_ts(gb, &ts, &te); + gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); + +out_put_operation: + gb_operation_put(operation); + + return ret; +} + +static void __gb_loopback_async_operation_destroy(struct kref *kref) +{ + struct gb_loopback_async_operation *op_async; + + op_async = container_of(kref, struct gb_loopback_async_operation, kref); + + list_del(&op_async->entry); + if (op_async->operation) + gb_operation_put(op_async->operation); + atomic_dec(&op_async->gb->outstanding_operations); + wake_up(&op_async->gb->wq_completion); + kfree(op_async); +} + +static void gb_loopback_async_operation_get(struct gb_loopback_async_operation + *op_async) +{ + kref_get(&op_async->kref); +} + +static void gb_loopback_async_operation_put(struct gb_loopback_async_operation + *op_async) +{ + unsigned long flags; + + spin_lock_irqsave(&gb_dev.lock, flags); + kref_put(&op_async->kref, __gb_loopback_async_operation_destroy); + spin_unlock_irqrestore(&gb_dev.lock, flags); +} + +static struct gb_loopback_async_operation * + gb_loopback_operation_find(u16 id) +{ + struct gb_loopback_async_operation *op_async; + bool found = false; + unsigned long flags; + + spin_lock_irqsave(&gb_dev.lock, flags); + list_for_each_entry(op_async, &gb_dev.list_op_async, entry) { + if (op_async->operation->id == id) { + gb_loopback_async_operation_get(op_async); + found = true; + break; + } + } + spin_unlock_irqrestore(&gb_dev.lock, flags); + + return found ? op_async : NULL; +} + +static void gb_loopback_async_wait_all(struct gb_loopback *gb) +{ + wait_event(gb->wq_completion, + !atomic_read(&gb->outstanding_operations)); +} + +static void gb_loopback_async_operation_callback(struct gb_operation *operation) +{ + struct gb_loopback_async_operation *op_async; + struct gb_loopback *gb; + struct timeval te; + bool err = false; + + do_gettimeofday(&te); + op_async = gb_loopback_operation_find(operation->id); + if (!op_async) + return; + + gb = op_async->gb; + mutex_lock(&gb->mutex); + + if (!op_async->pending || gb_operation_result(operation)) { + err = true; + } else { + if (op_async->completion) + if (op_async->completion(op_async)) + err = true; + } + + if (!err) { + gb_loopback_push_latency_ts(gb, &op_async->ts, &te); + gb->elapsed_nsecs = gb_loopback_calc_latency(&op_async->ts, + &te); + } + + if (op_async->pending) { + if (err) + gb->error++; + gb->iteration_count++; + op_async->pending = false; + del_timer_sync(&op_async->timer); + gb_loopback_async_operation_put(op_async); + gb_loopback_calculate_stats(gb, err); + } + mutex_unlock(&gb->mutex); + + dev_dbg(&gb->connection->bundle->dev, "complete operation %d\n", + operation->id); + + gb_loopback_async_operation_put(op_async); +} + +static void gb_loopback_async_operation_work(struct work_struct *work) +{ + struct gb_loopback *gb; + struct gb_operation *operation; + struct gb_loopback_async_operation *op_async; + + op_async = container_of(work, struct gb_loopback_async_operation, work); + gb = op_async->gb; + operation = op_async->operation; + + mutex_lock(&gb->mutex); + if (op_async->pending) { + gb->requests_timedout++; + gb->error++; + gb->iteration_count++; + op_async->pending = false; + gb_loopback_async_operation_put(op_async); + gb_loopback_calculate_stats(gb, true); + } + mutex_unlock(&gb->mutex); + + dev_dbg(&gb->connection->bundle->dev, "timeout operation %d\n", + operation->id); + + gb_operation_cancel(operation, -ETIMEDOUT); + gb_loopback_async_operation_put(op_async); +} + +static void gb_loopback_async_operation_timeout(unsigned long data) +{ + struct gb_loopback_async_operation *op_async; + u16 id = data; + + op_async = gb_loopback_operation_find(id); + if (!op_async) { + pr_err("operation %d not found - time out ?\n", id); + return; + } + schedule_work(&op_async->work); +} + +static int gb_loopback_async_operation(struct gb_loopback *gb, int type, + void *request, int request_size, + int response_size, + void *completion) +{ + struct gb_loopback_async_operation *op_async; + struct gb_operation *operation; + int ret; + unsigned long flags; + + op_async = kzalloc(sizeof(*op_async), GFP_KERNEL); + if (!op_async) + return -ENOMEM; + + INIT_WORK(&op_async->work, gb_loopback_async_operation_work); + kref_init(&op_async->kref); + + operation = gb_operation_create(gb->connection, type, request_size, + response_size, GFP_KERNEL); + if (!operation) { + kfree(op_async); + return -ENOMEM; + } + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + op_async->gb = gb; + op_async->operation = operation; + op_async->completion = completion; + + spin_lock_irqsave(&gb_dev.lock, flags); + list_add_tail(&op_async->entry, &gb_dev.list_op_async); + spin_unlock_irqrestore(&gb_dev.lock, flags); + + do_gettimeofday(&op_async->ts); + op_async->pending = true; + atomic_inc(&gb->outstanding_operations); + mutex_lock(&gb->mutex); + ret = gb_operation_request_send(operation, + gb_loopback_async_operation_callback, + GFP_KERNEL); + if (ret) + goto error; + + setup_timer(&op_async->timer, gb_loopback_async_operation_timeout, + (unsigned long)operation->id); + op_async->timer.expires = jiffies + gb->jiffy_timeout; + add_timer(&op_async->timer); + + goto done; +error: + gb_loopback_async_operation_put(op_async); +done: + mutex_unlock(&gb->mutex); + return ret; +} + +static int gb_loopback_sync_sink(struct gb_loopback *gb, u32 len) +{ + struct gb_loopback_transfer_request *request; + int retval; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->len = cpu_to_le32(len); + retval = gb_loopback_operation_sync(gb, GB_LOOPBACK_TYPE_SINK, + request, len + sizeof(*request), + NULL, 0); + kfree(request); + return retval; +} + +static int gb_loopback_sync_transfer(struct gb_loopback *gb, u32 len) +{ + struct gb_loopback_transfer_request *request; + struct gb_loopback_transfer_response *response; + int retval; + + gb->apbridge_latency_ts = 0; + gb->gbphy_latency_ts = 0; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + response = kmalloc(len + sizeof(*response), GFP_KERNEL); + if (!response) { + kfree(request); + return -ENOMEM; + } + + memset(request->data, 0x5A, len); + + request->len = cpu_to_le32(len); + retval = gb_loopback_operation_sync(gb, GB_LOOPBACK_TYPE_TRANSFER, + request, len + sizeof(*request), + response, len + sizeof(*response)); + if (retval) + goto gb_error; + + if (memcmp(request->data, response->data, len)) { + dev_err(&gb->connection->bundle->dev, + "Loopback Data doesn't match\n"); + retval = -EREMOTEIO; + } + gb->apbridge_latency_ts = (u32)__le32_to_cpu(response->reserved0); + gb->gbphy_latency_ts = (u32)__le32_to_cpu(response->reserved1); + +gb_error: + kfree(request); + kfree(response); + + return retval; +} + +static int gb_loopback_sync_ping(struct gb_loopback *gb) +{ + return gb_loopback_operation_sync(gb, GB_LOOPBACK_TYPE_PING, + NULL, 0, NULL, 0); +} + +static int gb_loopback_async_sink(struct gb_loopback *gb, u32 len) +{ + struct gb_loopback_transfer_request *request; + int retval; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->len = cpu_to_le32(len); + retval = gb_loopback_async_operation(gb, GB_LOOPBACK_TYPE_SINK, + request, len + sizeof(*request), + 0, NULL); + kfree(request); + return retval; +} + +static int gb_loopback_async_transfer_complete( + struct gb_loopback_async_operation *op_async) +{ + struct gb_loopback *gb; + struct gb_operation *operation; + struct gb_loopback_transfer_request *request; + struct gb_loopback_transfer_response *response; + size_t len; + int retval = 0; + + gb = op_async->gb; + operation = op_async->operation; + request = operation->request->payload; + response = operation->response->payload; + len = le32_to_cpu(request->len); + + if (memcmp(request->data, response->data, len)) { + dev_err(&gb->connection->bundle->dev, + "Loopback Data doesn't match operation id %d\n", + operation->id); + retval = -EREMOTEIO; + } else { + gb->apbridge_latency_ts = + (u32)__le32_to_cpu(response->reserved0); + gb->gbphy_latency_ts = + (u32)__le32_to_cpu(response->reserved1); + } + + return retval; +} + +static int gb_loopback_async_transfer(struct gb_loopback *gb, u32 len) +{ + struct gb_loopback_transfer_request *request; + int retval, response_len; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + memset(request->data, 0x5A, len); + + request->len = cpu_to_le32(len); + response_len = sizeof(struct gb_loopback_transfer_response); + retval = gb_loopback_async_operation(gb, GB_LOOPBACK_TYPE_TRANSFER, + request, len + sizeof(*request), + len + response_len, + gb_loopback_async_transfer_complete); + if (retval) + goto gb_error; + +gb_error: + kfree(request); + return retval; +} + +static int gb_loopback_async_ping(struct gb_loopback *gb) +{ + return gb_loopback_async_operation(gb, GB_LOOPBACK_TYPE_PING, + NULL, 0, 0, NULL); +} + +static int gb_loopback_request_handler(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + struct gb_loopback_transfer_request *request; + struct gb_loopback_transfer_response *response; + struct device *dev = &connection->bundle->dev; + size_t len; + + /* By convention, the AP initiates the version operation */ + switch (operation->type) { + case GB_LOOPBACK_TYPE_PING: + case GB_LOOPBACK_TYPE_SINK: + return 0; + case GB_LOOPBACK_TYPE_TRANSFER: + if (operation->request->payload_size < sizeof(*request)) { + dev_err(dev, "transfer request too small (%zu < %zu)\n", + operation->request->payload_size, + sizeof(*request)); + return -EINVAL; /* -EMSGSIZE */ + } + request = operation->request->payload; + len = le32_to_cpu(request->len); + if (len > gb_dev.size_max) { + dev_err(dev, "transfer request too large (%zu > %zu)\n", + len, gb_dev.size_max); + return -EINVAL; + } + + if (!gb_operation_response_alloc(operation, + len + sizeof(*response), GFP_KERNEL)) { + dev_err(dev, "error allocating response\n"); + return -ENOMEM; + } + response = operation->response->payload; + response->len = cpu_to_le32(len); + if (len) + memcpy(response->data, request->data, len); + + return 0; + default: + dev_err(dev, "unsupported request: %u\n", operation->type); + return -EINVAL; + } +} + +static void gb_loopback_reset_stats(struct gb_loopback *gb) +{ + struct gb_loopback_stats reset = { + .min = U32_MAX, + }; + + /* Reset per-connection stats */ + memcpy(&gb->latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->throughput, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->requests_per_second, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->apbridge_unipro_latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->gbphy_firmware_latency, &reset, + sizeof(struct gb_loopback_stats)); + + /* Should be initialized at least once per transaction set */ + gb->apbridge_latency_ts = 0; + gb->gbphy_latency_ts = 0; + memset(&gb->ts, 0, sizeof(struct timeval)); +} + +static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) +{ + if (stats->min > val) + stats->min = val; + if (stats->max < val) + stats->max = val; + stats->sum += val; + stats->count++; +} + +static void gb_loopback_update_stats_window(struct gb_loopback_stats *stats, + u64 val, u32 count) +{ + stats->sum += val; + stats->count += count; + + do_div(val, count); + if (stats->min > val) + stats->min = val; + if (stats->max < val) + stats->max = val; +} + +static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) +{ + u64 req = gb->requests_completed * USEC_PER_SEC; + + gb_loopback_update_stats_window(&gb->requests_per_second, req, latency); +} + +static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) +{ + u64 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; + + switch (gb->type) { + case GB_LOOPBACK_TYPE_PING: + break; + case GB_LOOPBACK_TYPE_SINK: + aggregate_size += sizeof(struct gb_loopback_transfer_request) + + gb->size; + break; + case GB_LOOPBACK_TYPE_TRANSFER: + aggregate_size += sizeof(struct gb_loopback_transfer_request) + + sizeof(struct gb_loopback_transfer_response) + + gb->size * 2; + break; + default: + return; + } + + aggregate_size *= gb->requests_completed; + aggregate_size *= USEC_PER_SEC; + gb_loopback_update_stats_window(&gb->throughput, aggregate_size, + latency); +} + +static void gb_loopback_calculate_latency_stats(struct gb_loopback *gb) +{ + u32 lat; + + /* Express latency in terms of microseconds */ + lat = gb_loopback_nsec_to_usec_latency(gb->elapsed_nsecs); + + /* Log latency stastic */ + gb_loopback_update_stats(&gb->latency, lat); + + /* Raw latency log on a per thread basis */ + kfifo_in(&gb->kfifo_lat, (unsigned char *)&lat, sizeof(lat)); + + /* Log the firmware supplied latency values */ + gb_loopback_update_stats(&gb->apbridge_unipro_latency, + gb->apbridge_latency_ts); + gb_loopback_update_stats(&gb->gbphy_firmware_latency, + gb->gbphy_latency_ts); +} + +static void gb_loopback_calculate_stats(struct gb_loopback *gb, bool error) +{ + u64 nlat; + u32 lat; + struct timeval te; + + if (!error) { + gb->requests_completed++; + gb_loopback_calculate_latency_stats(gb); + } + + do_gettimeofday(&te); + nlat = gb_loopback_calc_latency(&gb->ts, &te); + if (nlat >= NSEC_PER_SEC || gb->iteration_count == gb->iteration_max) { + lat = gb_loopback_nsec_to_usec_latency(nlat); + + gb_loopback_throughput_update(gb, lat); + gb_loopback_requests_update(gb, lat); + + if (gb->iteration_count != gb->iteration_max) { + gb->ts = te; + gb->requests_completed = 0; + } + } +} + +static void gb_loopback_async_wait_to_send(struct gb_loopback *gb) +{ + if (!(gb->async && gb->outstanding_operations_max)) + return; + wait_event_interruptible(gb->wq_completion, + (atomic_read(&gb->outstanding_operations) < + gb->outstanding_operations_max) || + kthread_should_stop()); +} + +static int gb_loopback_fn(void *data) +{ + int error = 0; + int us_wait = 0; + int type; + int ret; + u32 size; + + struct gb_loopback *gb = data; + struct gb_bundle *bundle = gb->connection->bundle; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + while (1) { + if (!gb->type) { + gb_pm_runtime_put_autosuspend(bundle); + wait_event_interruptible(gb->wq, gb->type || + kthread_should_stop()); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + } + + if (kthread_should_stop()) + break; + + /* Limit the maximum number of in-flight async operations */ + gb_loopback_async_wait_to_send(gb); + if (kthread_should_stop()) + break; + + mutex_lock(&gb->mutex); + + /* Optionally terminate */ + if (gb->send_count == gb->iteration_max) { + if (gb->iteration_count == gb->iteration_max) { + gb->type = 0; + gb->send_count = 0; + sysfs_notify(&gb->dev->kobj, NULL, + "iteration_count"); + } + mutex_unlock(&gb->mutex); + continue; + } + size = gb->size; + us_wait = gb->us_wait; + type = gb->type; + if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) + do_gettimeofday(&gb->ts); + mutex_unlock(&gb->mutex); + + /* Else operations to perform */ + if (gb->async) { + if (type == GB_LOOPBACK_TYPE_PING) { + error = gb_loopback_async_ping(gb); + } else if (type == GB_LOOPBACK_TYPE_TRANSFER) { + error = gb_loopback_async_transfer(gb, size); + } else if (type == GB_LOOPBACK_TYPE_SINK) { + error = gb_loopback_async_sink(gb, size); + } + + if (error) + gb->error++; + } else { + /* We are effectively single threaded here */ + if (type == GB_LOOPBACK_TYPE_PING) + error = gb_loopback_sync_ping(gb); + else if (type == GB_LOOPBACK_TYPE_TRANSFER) + error = gb_loopback_sync_transfer(gb, size); + else if (type == GB_LOOPBACK_TYPE_SINK) + error = gb_loopback_sync_sink(gb, size); + + if (error) + gb->error++; + gb->iteration_count++; + gb_loopback_calculate_stats(gb, !!error); + } + gb->send_count++; + if (us_wait) + udelay(us_wait); + } + + gb_pm_runtime_put_autosuspend(bundle); + + return 0; +} + +static int gb_loopback_dbgfs_latency_show_common(struct seq_file *s, + struct kfifo *kfifo, + struct mutex *mutex) +{ + u32 latency; + int retval; + + if (kfifo_len(kfifo) == 0) { + retval = -EAGAIN; + goto done; + } + + mutex_lock(mutex); + retval = kfifo_out(kfifo, &latency, sizeof(latency)); + if (retval > 0) { + seq_printf(s, "%u", latency); + retval = 0; + } + mutex_unlock(mutex); +done: + return retval; +} + +static int gb_loopback_dbgfs_latency_show(struct seq_file *s, void *unused) +{ + struct gb_loopback *gb = s->private; + + return gb_loopback_dbgfs_latency_show_common(s, &gb->kfifo_lat, + &gb->mutex); +} + +static int gb_loopback_latency_open(struct inode *inode, struct file *file) +{ + return single_open(file, gb_loopback_dbgfs_latency_show, + inode->i_private); +} + +static const struct file_operations gb_loopback_debugfs_latency_ops = { + .open = gb_loopback_latency_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int gb_loopback_bus_id_compare(void *priv, struct list_head *lha, + struct list_head *lhb) +{ + struct gb_loopback *a = list_entry(lha, struct gb_loopback, entry); + struct gb_loopback *b = list_entry(lhb, struct gb_loopback, entry); + struct gb_connection *ca = a->connection; + struct gb_connection *cb = b->connection; + + if (ca->bundle->intf->interface_id < cb->bundle->intf->interface_id) + return -1; + if (cb->bundle->intf->interface_id < ca->bundle->intf->interface_id) + return 1; + if (ca->bundle->id < cb->bundle->id) + return -1; + if (cb->bundle->id < ca->bundle->id) + return 1; + if (ca->intf_cport_id < cb->intf_cport_id) + return -1; + else if (cb->intf_cport_id < ca->intf_cport_id) + return 1; + + return 0; +} + +static void gb_loopback_insert_id(struct gb_loopback *gb) +{ + struct gb_loopback *gb_list; + u32 new_lbid = 0; + + /* perform an insertion sort */ + list_add_tail(&gb->entry, &gb_dev.list); + list_sort(NULL, &gb_dev.list, gb_loopback_bus_id_compare); + list_for_each_entry(gb_list, &gb_dev.list, entry) { + gb_list->lbid = 1 << new_lbid; + new_lbid++; + } +} + +#define DEBUGFS_NAMELEN 32 + +static int gb_loopback_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_loopback *gb; + struct device *dev; + int retval; + char name[DEBUGFS_NAMELEN]; + unsigned long flags; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LOOPBACK) + return -ENODEV; + + gb = kzalloc(sizeof(*gb), GFP_KERNEL); + if (!gb) + return -ENOMEM; + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_loopback_request_handler); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto out_kzalloc; + } + + gb->connection = connection; + greybus_set_drvdata(bundle, gb); + + init_waitqueue_head(&gb->wq); + init_waitqueue_head(&gb->wq_completion); + atomic_set(&gb->outstanding_operations, 0); + gb_loopback_reset_stats(gb); + + /* Reported values to user-space for min/max timeouts */ + gb->timeout_min = jiffies_to_usecs(GB_LOOPBACK_TIMEOUT_MIN); + gb->timeout_max = jiffies_to_usecs(GB_LOOPBACK_TIMEOUT_MAX); + + if (!gb_dev.count) { + /* Calculate maximum payload */ + gb_dev.size_max = gb_operation_get_payload_size_max(connection); + if (gb_dev.size_max <= + sizeof(struct gb_loopback_transfer_request)) { + retval = -EINVAL; + goto out_connection_destroy; + } + gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); + } + + /* Create per-connection sysfs and debugfs data-points */ + snprintf(name, sizeof(name), "raw_latency_%s", + dev_name(&connection->bundle->dev)); + gb->file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, gb, + &gb_loopback_debugfs_latency_ops); + + gb->id = ida_simple_get(&loopback_ida, 0, 0, GFP_KERNEL); + if (gb->id < 0) { + retval = gb->id; + goto out_debugfs_remove; + } + + retval = gb_connection_enable(connection); + if (retval) + goto out_ida_remove; + + dev = device_create_with_groups(&loopback_class, + &connection->bundle->dev, + MKDEV(0, 0), gb, loopback_groups, + "gb_loopback%d", gb->id); + if (IS_ERR(dev)) { + retval = PTR_ERR(dev); + goto out_connection_disable; + } + gb->dev = dev; + + /* Allocate kfifo */ + if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32), + GFP_KERNEL)) { + retval = -ENOMEM; + goto out_conn; + } + if (kfifo_alloc(&gb->kfifo_ts, kfifo_depth * sizeof(struct timeval) * 2, + GFP_KERNEL)) { + retval = -ENOMEM; + goto out_kfifo0; + } + + /* Fork worker thread */ + mutex_init(&gb->mutex); + gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); + if (IS_ERR(gb->task)) { + retval = PTR_ERR(gb->task); + goto out_kfifo1; + } + + spin_lock_irqsave(&gb_dev.lock, flags); + gb_loopback_insert_id(gb); + gb_dev.count++; + spin_unlock_irqrestore(&gb_dev.lock, flags); + + gb_connection_latency_tag_enable(connection); + + gb_pm_runtime_put_autosuspend(bundle); + + return 0; + +out_kfifo1: + kfifo_free(&gb->kfifo_ts); +out_kfifo0: + kfifo_free(&gb->kfifo_lat); +out_conn: + device_unregister(dev); +out_connection_disable: + gb_connection_disable(connection); +out_ida_remove: + ida_simple_remove(&loopback_ida, gb->id); +out_debugfs_remove: + debugfs_remove(gb->file); +out_connection_destroy: + gb_connection_destroy(connection); +out_kzalloc: + kfree(gb); + + return retval; +} + +static void gb_loopback_disconnect(struct gb_bundle *bundle) +{ + struct gb_loopback *gb = greybus_get_drvdata(bundle); + unsigned long flags; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); + + gb_connection_disable(gb->connection); + + if (!IS_ERR_OR_NULL(gb->task)) + kthread_stop(gb->task); + + kfifo_free(&gb->kfifo_lat); + kfifo_free(&gb->kfifo_ts); + gb_connection_latency_tag_disable(gb->connection); + debugfs_remove(gb->file); + + /* + * FIXME: gb_loopback_async_wait_all() is redundant now, as connection + * is disabled at the beginning and so we can't have any more + * incoming/outgoing requests. + */ + gb_loopback_async_wait_all(gb); + + spin_lock_irqsave(&gb_dev.lock, flags); + gb_dev.count--; + list_del(&gb->entry); + spin_unlock_irqrestore(&gb_dev.lock, flags); + + device_unregister(gb->dev); + ida_simple_remove(&loopback_ida, gb->id); + + gb_connection_destroy(gb->connection); + kfree(gb); +} + +static const struct greybus_bundle_id gb_loopback_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_loopback_id_table); + +static struct greybus_driver gb_loopback_driver = { + .name = "loopback", + .probe = gb_loopback_probe, + .disconnect = gb_loopback_disconnect, + .id_table = gb_loopback_id_table, +}; + +static int loopback_init(void) +{ + int retval; + + INIT_LIST_HEAD(&gb_dev.list); + INIT_LIST_HEAD(&gb_dev.list_op_async); + spin_lock_init(&gb_dev.lock); + gb_dev.root = debugfs_create_dir("gb_loopback", NULL); + + retval = class_register(&loopback_class); + if (retval) + goto err; + + retval = greybus_register(&gb_loopback_driver); + if (retval) + goto err_unregister; + + return 0; + +err_unregister: + class_unregister(&loopback_class); +err: + debugfs_remove_recursive(gb_dev.root); + return retval; +} +module_init(loopback_init); + +static void __exit loopback_exit(void) +{ + debugfs_remove_recursive(gb_dev.root); + greybus_deregister(&gb_loopback_driver); + class_unregister(&loopback_class); + ida_destroy(&loopback_ida); +} +module_exit(loopback_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c new file mode 100644 index 000000000000..7b903770a684 --- /dev/null +++ b/drivers/staging/greybus/manifest.c @@ -0,0 +1,535 @@ +/* + * Greybus manifest parsing + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +static const char *get_descriptor_type_string(u8 type) +{ + switch (type) { + case GREYBUS_TYPE_INVALID: + return "invalid"; + case GREYBUS_TYPE_STRING: + return "string"; + case GREYBUS_TYPE_INTERFACE: + return "interface"; + case GREYBUS_TYPE_CPORT: + return "cport"; + case GREYBUS_TYPE_BUNDLE: + return "bundle"; + default: + WARN_ON(1); + return "unknown"; + } +} + +/* + * We scan the manifest once to identify where all the descriptors + * are. The result is a list of these manifest_desc structures. We + * then pick through them for what we're looking for (starting with + * the interface descriptor). As each is processed we remove it from + * the list. When we're done the list should (probably) be empty. + */ +struct manifest_desc { + struct list_head links; + + size_t size; + void *data; + enum greybus_descriptor_type type; +}; + +static void release_manifest_descriptor(struct manifest_desc *descriptor) +{ + list_del(&descriptor->links); + kfree(descriptor); +} + +static void release_manifest_descriptors(struct gb_interface *intf) +{ + struct manifest_desc *descriptor; + struct manifest_desc *next; + + list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) + release_manifest_descriptor(descriptor); +} + +static void release_cport_descriptors(struct list_head *head, u8 bundle_id) +{ + struct manifest_desc *desc, *tmp; + struct greybus_descriptor_cport *desc_cport; + + list_for_each_entry_safe(desc, tmp, head, links) { + desc_cport = desc->data; + + if (desc->type != GREYBUS_TYPE_CPORT) + continue; + + if (desc_cport->bundle == bundle_id) + release_manifest_descriptor(desc); + } +} + +static struct manifest_desc *get_next_bundle_desc(struct gb_interface *intf) +{ + struct manifest_desc *descriptor; + struct manifest_desc *next; + + list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) + if (descriptor->type == GREYBUS_TYPE_BUNDLE) + return descriptor; + + return NULL; +} + +/* + * Validate the given descriptor. Its reported size must fit within + * the number of bytes remaining, and it must have a recognized + * type. Check that the reported size is at least as big as what + * we expect to see. (It could be bigger, perhaps for a new version + * of the format.) + * + * Returns the (non-zero) number of bytes consumed by the descriptor, + * or a negative errno. + */ +static int identify_descriptor(struct gb_interface *intf, + struct greybus_descriptor *desc, size_t size) +{ + struct greybus_descriptor_header *desc_header = &desc->header; + struct manifest_desc *descriptor; + size_t desc_size; + size_t expected_size; + + if (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); + return -EINVAL; + } + + /* Descriptor needs to at least have a header */ + expected_size = sizeof(*desc_header); + + switch (desc_header->type) { + case GREYBUS_TYPE_STRING: + expected_size += sizeof(struct greybus_descriptor_string); + expected_size += desc->string.length; + + /* String descriptors are padded to 4 byte boundaries */ + expected_size = ALIGN(expected_size, 4); + break; + case GREYBUS_TYPE_INTERFACE: + expected_size += sizeof(struct greybus_descriptor_interface); + break; + case GREYBUS_TYPE_BUNDLE: + expected_size += sizeof(struct greybus_descriptor_bundle); + break; + case GREYBUS_TYPE_CPORT: + expected_size += sizeof(struct greybus_descriptor_cport); + break; + case GREYBUS_TYPE_INVALID: + default: + dev_err(&intf->dev, "invalid descriptor type (%u)\n", + 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); + 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); + } + + descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); + if (!descriptor) + return -ENOMEM; + + descriptor->size = desc_size; + descriptor->data = (char *)desc + sizeof(*desc_header); + descriptor->type = desc_header->type; + list_add_tail(&descriptor->links, &intf->manifest_descs); + + /* desc_size is positive and is known to fit in a signed int */ + + return desc_size; +} + +/* + * Find the string descriptor having the given id, validate it, and + * allocate a duplicate copy of it. The duplicate has an extra byte + * which guarantees the returned string is NUL-terminated. + * + * String index 0 is valid (it represents "no string"), and for + * that a null pointer is returned. + * + * Otherwise returns a pointer to a newly-allocated copy of the + * descriptor string, or an error-coded pointer on failure. + */ +static char *gb_string_get(struct gb_interface *intf, u8 string_id) +{ + struct greybus_descriptor_string *desc_string; + struct manifest_desc *descriptor; + bool found = false; + char *string; + + /* A zero string id means no string (but no error) */ + if (!string_id) + return NULL; + + list_for_each_entry(descriptor, &intf->manifest_descs, links) { + if (descriptor->type != GREYBUS_TYPE_STRING) + continue; + + desc_string = descriptor->data; + if (desc_string->id == string_id) { + found = true; + break; + } + } + if (!found) + return ERR_PTR(-ENOENT); + + /* Allocate an extra byte so we can guarantee it's NUL-terminated */ + string = kmemdup(&desc_string->string, desc_string->length + 1, + GFP_KERNEL); + if (!string) + return ERR_PTR(-ENOMEM); + string[desc_string->length] = '\0'; + + /* Ok we've used this string, so we're done with it */ + release_manifest_descriptor(descriptor); + + return string; +} + +/* + * Find cport descriptors in the manifest associated with the given + * bundle, and set up data structures for the functions that use + * them. Returns the number of cports set up for the bundle, or 0 + * if there is an error. + */ +static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) +{ + struct gb_interface *intf = bundle->intf; + struct greybus_descriptor_cport *desc_cport; + struct manifest_desc *desc, *next, *tmp; + LIST_HEAD(list); + u8 bundle_id = bundle->id; + u16 cport_id; + u32 count = 0; + int i; + + /* Set up all cport descriptors associated with this bundle */ + list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { + if (desc->type != GREYBUS_TYPE_CPORT) + continue; + + desc_cport = desc->data; + if (desc_cport->bundle != bundle_id) + continue; + + cport_id = le16_to_cpu(desc_cport->id); + if (cport_id > CPORT_ID_MAX) + goto exit; + + /* Nothing else should have its cport_id as control cport id */ + if (cport_id == GB_CONTROL_CPORT_ID) { + dev_err(&bundle->dev, "invalid cport id found (%02u)\n", + cport_id); + goto exit; + } + + /* + * Found one, move it to our temporary list after checking for + * duplicates. + */ + list_for_each_entry(tmp, &list, links) { + desc_cport = tmp->data; + if (cport_id == le16_to_cpu(desc_cport->id)) { + dev_err(&bundle->dev, + "duplicate CPort %u found\n", + cport_id); + goto exit; + } + } + list_move_tail(&desc->links, &list); + count++; + } + + if (!count) + return 0; + + bundle->cport_desc = kcalloc(count, sizeof(*bundle->cport_desc), + GFP_KERNEL); + if (!bundle->cport_desc) + goto exit; + + bundle->num_cports = count; + + i = 0; + list_for_each_entry_safe(desc, next, &list, links) { + desc_cport = desc->data; + memcpy(&bundle->cport_desc[i++], desc_cport, + sizeof(*desc_cport)); + + /* Release the cport descriptor */ + release_manifest_descriptor(desc); + } + + return count; +exit: + release_cport_descriptors(&list, bundle_id); + /* + * Free all cports for this bundle to avoid 'excess descriptors' + * warnings. + */ + release_cport_descriptors(&intf->manifest_descs, bundle_id); + + return 0; /* Error; count should also be 0 */ +} + +/* + * Find bundle descriptors in the manifest and set up their data + * structures. Returns the number of bundles set up for the + * given interface. + */ +static u32 gb_manifest_parse_bundles(struct gb_interface *intf) +{ + struct manifest_desc *desc; + struct gb_bundle *bundle; + struct gb_bundle *bundle_next; + u32 count = 0; + u8 bundle_id; + u8 class; + + while ((desc = get_next_bundle_desc(intf))) { + struct greybus_descriptor_bundle *desc_bundle; + + /* Found one. Set up its bundle structure*/ + desc_bundle = desc->data; + bundle_id = desc_bundle->id; + class = desc_bundle->class; + + /* Done with this bundle descriptor */ + release_manifest_descriptor(desc); + + /* Ignore any legacy control bundles */ + if (bundle_id == GB_CONTROL_BUNDLE_ID) { + dev_dbg(&intf->dev, "%s - ignoring control bundle\n", + __func__); + release_cport_descriptors(&intf->manifest_descs, + bundle_id); + continue; + } + + /* Nothing else should have its class set to control class */ + if (class == GREYBUS_CLASS_CONTROL) { + dev_err(&intf->dev, + "bundle %u cannot use control class\n", + bundle_id); + goto cleanup; + } + + bundle = gb_bundle_create(intf, bundle_id, class); + if (!bundle) + goto cleanup; + + /* + * Now go set up this bundle's functions and cports. + * + * A 'bundle' represents a device in greybus. It may require + * multiple cports for its functioning. If we fail to setup any + * cport of a bundle, we better reject the complete bundle as + * the device may not be able to function properly then. + * + * But, failing to setup a cport of bundle X doesn't mean that + * the device corresponding to bundle Y will not work properly. + * Bundles should be treated as separate independent devices. + * + * While parsing manifest for an interface, treat bundles as + * separate entities and don't reject entire interface and its + * bundles on failing to initialize a cport. But make sure the + * bundle which needs the cport, gets destroyed properly. + */ + if (!gb_manifest_parse_cports(bundle)) { + gb_bundle_destroy(bundle); + continue; + } + + count++; + } + + return count; +cleanup: + /* An error occurred; undo any changes we've made */ + list_for_each_entry_safe(bundle, bundle_next, &intf->bundles, links) { + gb_bundle_destroy(bundle); + count--; + } + return 0; /* Error; count should also be 0 */ +} + +static bool gb_manifest_parse_interface(struct gb_interface *intf, + struct manifest_desc *interface_desc) +{ + struct greybus_descriptor_interface *desc_intf = interface_desc->data; + struct gb_control *control = intf->control; + char *str; + + /* Handle the strings first--they can fail */ + str = gb_string_get(intf, desc_intf->vendor_stringid); + if (IS_ERR(str)) + return false; + control->vendor_string = str; + + str = gb_string_get(intf, desc_intf->product_stringid); + if (IS_ERR(str)) + goto out_free_vendor_string; + control->product_string = str; + + /* Assign feature flags communicated via manifest */ + intf->features = desc_intf->features; + + /* Release the interface descriptor, now that we're done with it */ + release_manifest_descriptor(interface_desc); + + /* An interface must have at least one bundle descriptor */ + if (!gb_manifest_parse_bundles(intf)) { + dev_err(&intf->dev, "manifest bundle descriptors not valid\n"); + goto out_err; + } + + return true; +out_err: + kfree(control->product_string); + control->product_string = NULL; +out_free_vendor_string: + kfree(control->vendor_string); + control->vendor_string = NULL; + + return false; +} + +/* + * Parse a buffer containing an interface manifest. + * + * If we find anything wrong with the content/format of the buffer + * we reject it. + * + * The first requirement is that the manifest's version is + * one we can parse. + * + * We make an initial pass through the buffer and identify all of + * the descriptors it contains, keeping track for each its type + * and the location size of its data in the buffer. + * + * Next we scan the descriptors, looking for an interface descriptor; + * there must be exactly one of those. When found, we record the + * information it contains, and then remove that descriptor (and any + * string descriptors it refers to) from further consideration. + * + * After that we look for the interface's bundles--there must be at + * least one of those. + * + * Returns true if parsing was successful, false otherwise. + */ +bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) +{ + struct greybus_manifest *manifest; + struct greybus_manifest_header *header; + struct greybus_descriptor *desc; + struct manifest_desc *descriptor; + struct manifest_desc *interface_desc = NULL; + u16 manifest_size; + u32 found = 0; + bool result; + + /* Manifest descriptor list should be empty here */ + if (WARN_ON(!list_empty(&intf->manifest_descs))) + return false; + + /* 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)); + return false; + } + + /* Make sure the size is right */ + manifest = data; + header = &manifest->header; + manifest_size = le16_to_cpu(header->size); + if (manifest_size != size) { + dev_err(&intf->dev, "manifest size mismatch (%zu != %u)\n", + 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); + return false; + } + + /* OK, find all the descriptors */ + desc = manifest->descriptors; + size -= sizeof(*header); + while (size) { + int desc_size; + + desc_size = identify_descriptor(intf, desc, size); + if (desc_size < 0) { + result = false; + goto out; + } + desc = (struct greybus_descriptor *)((char *)desc + desc_size); + size -= desc_size; + } + + /* There must be a single interface descriptor */ + list_for_each_entry(descriptor, &intf->manifest_descs, links) { + if (descriptor->type == GREYBUS_TYPE_INTERFACE) + if (!found++) + interface_desc = descriptor; + } + if (found != 1) { + dev_err(&intf->dev, "manifest must have 1 interface descriptor (%u found)\n", + found); + result = false; + goto out; + } + + /* Parse the manifest, starting with the interface descriptor */ + result = gb_manifest_parse_interface(intf, interface_desc); + + /* + * We really should have no remaining descriptors, but we + * don't know what newer format manifests might leave. + */ + if (result && !list_empty(&intf->manifest_descs)) + dev_info(&intf->dev, "excess descriptors in interface manifest\n"); +out: + release_manifest_descriptors(intf); + + return result; +} diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h new file mode 100644 index 000000000000..d96428407cd7 --- /dev/null +++ b/drivers/staging/greybus/manifest.h @@ -0,0 +1,16 @@ +/* + * Greybus manifest parsing + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __MANIFEST_H +#define __MANIFEST_H + +struct gb_interface; +bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size); + +#endif /* __MANIFEST_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c new file mode 100644 index 000000000000..69f67ddbd4a3 --- /dev/null +++ b/drivers/staging/greybus/module.c @@ -0,0 +1,238 @@ +/* + * Greybus Module code + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" +#include "greybus_trace.h" + + +static ssize_t eject_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct gb_module *module = to_gb_module(dev); + struct gb_interface *intf; + size_t i; + long val; + int ret; + + ret = kstrtol(buf, 0, &val); + if (ret) + return ret; + + if (!val) + return len; + + for (i = 0; i < module->num_interfaces; ++i) { + intf = module->interfaces[i]; + + mutex_lock(&intf->mutex); + /* Set flag to prevent concurrent activation. */ + intf->ejected = true; + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); + } + + /* Tell the SVC to eject the primary interface. */ + ret = gb_svc_intf_eject(module->hd->svc, module->module_id); + if (ret) + return ret; + + return len; +} +static DEVICE_ATTR_WO(eject); + +static ssize_t module_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_module *module = to_gb_module(dev); + + return sprintf(buf, "%u\n", module->module_id); +} +static DEVICE_ATTR_RO(module_id); + +static ssize_t num_interfaces_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_module *module = to_gb_module(dev); + + return sprintf(buf, "%zu\n", module->num_interfaces); +} +static DEVICE_ATTR_RO(num_interfaces); + +static struct attribute *module_attrs[] = { + &dev_attr_eject.attr, + &dev_attr_module_id.attr, + &dev_attr_num_interfaces.attr, + NULL, +}; +ATTRIBUTE_GROUPS(module); + +static void gb_module_release(struct device *dev) +{ + struct gb_module *module = to_gb_module(dev); + + trace_gb_module_release(module); + + kfree(module); +} + +struct device_type greybus_module_type = { + .name = "greybus_module", + .release = gb_module_release, +}; + +struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, + size_t num_interfaces) +{ + struct gb_interface *intf; + struct gb_module *module; + int i; + + module = kzalloc(sizeof(*module) + num_interfaces * sizeof(intf), + GFP_KERNEL); + if (!module) + return NULL; + + module->hd = hd; + module->module_id = module_id; + module->num_interfaces = num_interfaces; + + module->dev.parent = &hd->dev; + module->dev.bus = &greybus_bus_type; + module->dev.type = &greybus_module_type; + module->dev.groups = module_groups; + module->dev.dma_mask = hd->dev.dma_mask; + device_initialize(&module->dev); + dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id); + + trace_gb_module_create(module); + + for (i = 0; i < num_interfaces; ++i) { + intf = gb_interface_create(module, module_id + i); + if (!intf) { + dev_err(&module->dev, "failed to create interface %u\n", + module_id + i); + goto err_put_interfaces; + } + module->interfaces[i] = intf; + } + + return module; + +err_put_interfaces: + for (--i; i > 0; --i) + gb_interface_put(module->interfaces[i]); + + put_device(&module->dev); + + return NULL; +} + +/* + * Register and enable an interface after first attempting to activate it. + */ +static void gb_module_register_interface(struct gb_interface *intf) +{ + struct gb_module *module = intf->module; + u8 intf_id = intf->interface_id; + int ret; + + mutex_lock(&intf->mutex); + + ret = gb_interface_activate(intf); + if (ret) { + if (intf->type != GB_INTERFACE_TYPE_DUMMY) { + dev_err(&module->dev, + "failed to activate interface %u: %d\n", + intf_id, ret); + } + + gb_interface_add(intf); + goto err_unlock; + } + + ret = gb_interface_add(intf); + if (ret) + goto err_interface_deactivate; + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&module->dev, "failed to enable interface %u: %d\n", + intf_id, ret); + goto err_interface_deactivate; + } + + mutex_unlock(&intf->mutex); + + return; + +err_interface_deactivate: + gb_interface_deactivate(intf); +err_unlock: + mutex_unlock(&intf->mutex); +} + +static void gb_module_deregister_interface(struct gb_interface *intf) +{ + /* Mark as disconnected to prevent I/O during disable. */ + if (intf->module->disconnected) + intf->disconnected = true; + + mutex_lock(&intf->mutex); + intf->removed = true; + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); + + gb_interface_del(intf); +} + +/* Register a module and its interfaces. */ +int gb_module_add(struct gb_module *module) +{ + size_t i; + int ret; + + ret = device_add(&module->dev); + if (ret) { + dev_err(&module->dev, "failed to register module: %d\n", ret); + return ret; + } + + trace_gb_module_add(module); + + for (i = 0; i < module->num_interfaces; ++i) + gb_module_register_interface(module->interfaces[i]); + + return 0; +} + +/* Deregister a module and its interfaces. */ +void gb_module_del(struct gb_module *module) +{ + size_t i; + + for (i = 0; i < module->num_interfaces; ++i) + gb_module_deregister_interface(module->interfaces[i]); + + trace_gb_module_del(module); + + device_del(&module->dev); +} + +void gb_module_put(struct gb_module *module) +{ + size_t i; + + for (i = 0; i < module->num_interfaces; ++i) + gb_interface_put(module->interfaces[i]); + + put_device(&module->dev); +} diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h new file mode 100644 index 000000000000..88a97ce04243 --- /dev/null +++ b/drivers/staging/greybus/module.h @@ -0,0 +1,34 @@ +/* + * Greybus Module code + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __MODULE_H +#define __MODULE_H + +struct gb_module { + struct device dev; + struct gb_host_device *hd; + + struct list_head hd_node; + + u8 module_id; + size_t num_interfaces; + + bool disconnected; + + struct gb_interface *interfaces[0]; +}; +#define to_gb_module(d) container_of(d, struct gb_module, dev) + +struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, + size_t num_interfaces); +int gb_module_add(struct gb_module *module); +void gb_module_del(struct gb_module *module); +void gb_module_put(struct gb_module *module); + +#endif /* __MODULE_H */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c new file mode 100644 index 000000000000..0123109a1070 --- /dev/null +++ b/drivers/staging/greybus/operation.c @@ -0,0 +1,1239 @@ +/* + * Greybus operations + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "greybus_trace.h" + +static struct kmem_cache *gb_operation_cache; +static struct kmem_cache *gb_message_cache; + +/* Workqueue to handle Greybus operation completions. */ +static struct workqueue_struct *gb_operation_completion_wq; + +/* Wait queue for synchronous cancellations. */ +static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue); + +/* + * Protects updates to operation->errno. + */ +static DEFINE_SPINLOCK(gb_operations_lock); + +static int gb_operation_response_send(struct gb_operation *operation, + int errno); + +/* + * Increment operation active count and add to connection list unless the + * connection is going away. + * + * Caller holds operation reference. + */ +static int gb_operation_get_active(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + unsigned long flags; + + spin_lock_irqsave(&connection->lock, flags); + switch (connection->state) { + case GB_CONNECTION_STATE_ENABLED: + break; + case GB_CONNECTION_STATE_ENABLED_TX: + if (gb_operation_is_incoming(operation)) + goto err_unlock; + break; + case GB_CONNECTION_STATE_DISCONNECTING: + if (!gb_operation_is_core(operation)) + goto err_unlock; + break; + default: + goto err_unlock; + } + + if (operation->active++ == 0) + list_add_tail(&operation->links, &connection->operations); + + trace_gb_operation_get_active(operation); + + spin_unlock_irqrestore(&connection->lock, flags); + + return 0; + +err_unlock: + spin_unlock_irqrestore(&connection->lock, flags); + + return -ENOTCONN; +} + +/* Caller holds operation reference. */ +static void gb_operation_put_active(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + unsigned long flags; + + spin_lock_irqsave(&connection->lock, flags); + + trace_gb_operation_put_active(operation); + + if (--operation->active == 0) { + list_del(&operation->links); + if (atomic_read(&operation->waiters)) + wake_up(&gb_operation_cancellation_queue); + } + spin_unlock_irqrestore(&connection->lock, flags); +} + +static bool gb_operation_is_active(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + unsigned long flags; + bool ret; + + spin_lock_irqsave(&connection->lock, flags); + ret = operation->active; + spin_unlock_irqrestore(&connection->lock, flags); + + return ret; +} + +/* + * Set an operation's result. + * + * Initially an outgoing operation's errno value is -EBADR. + * If no error occurs before sending the request message the only + * valid value operation->errno can be set to is -EINPROGRESS, + * indicating the request has been (or rather is about to be) sent. + * At that point nobody should be looking at the result until the + * response arrives. + * + * The first time the result gets set after the request has been + * sent, that result "sticks." That is, if two concurrent threads + * race to set the result, the first one wins. The return value + * tells the caller whether its result was recorded; if not the + * caller has nothing more to do. + * + * The result value -EILSEQ is reserved to signal an implementation + * error; if it's ever observed, the code performing the request has + * done something fundamentally wrong. It is an error to try to set + * the result to -EBADR, and attempts to do so result in a warning, + * and -EILSEQ is used instead. Similarly, the only valid result + * value to set for an operation in initial state is -EINPROGRESS. + * Attempts to do otherwise will also record a (successful) -EILSEQ + * operation result. + */ +static bool gb_operation_result_set(struct gb_operation *operation, int result) +{ + unsigned long flags; + int prev; + + if (result == -EINPROGRESS) { + /* + * -EINPROGRESS is used to indicate the request is + * in flight. It should be the first result value + * set after the initial -EBADR. Issue a warning + * and record an implementation error if it's + * set at any other time. + */ + spin_lock_irqsave(&gb_operations_lock, flags); + prev = operation->errno; + if (prev == -EBADR) + operation->errno = result; + else + operation->errno = -EILSEQ; + spin_unlock_irqrestore(&gb_operations_lock, flags); + WARN_ON(prev != -EBADR); + + return true; + } + + /* + * The first result value set after a request has been sent + * will be the final result of the operation. Subsequent + * attempts to set the result are ignored. + * + * Note that -EBADR is a reserved "initial state" result + * value. Attempts to set this value result in a warning, + * and the result code is set to -EILSEQ instead. + */ + if (WARN_ON(result == -EBADR)) + result = -EILSEQ; /* Nobody should be setting -EBADR */ + + spin_lock_irqsave(&gb_operations_lock, flags); + prev = operation->errno; + if (prev == -EINPROGRESS) + operation->errno = result; /* First and final result */ + spin_unlock_irqrestore(&gb_operations_lock, flags); + + return prev == -EINPROGRESS; +} + +int gb_operation_result(struct gb_operation *operation) +{ + int result = operation->errno; + + WARN_ON(result == -EBADR); + WARN_ON(result == -EINPROGRESS); + + return result; +} +EXPORT_SYMBOL_GPL(gb_operation_result); + +/* + * Looks up an outgoing operation on a connection and returns a refcounted + * pointer if found, or NULL otherwise. + */ +static struct gb_operation * +gb_operation_find_outgoing(struct gb_connection *connection, u16 operation_id) +{ + struct gb_operation *operation; + unsigned long flags; + bool found = false; + + spin_lock_irqsave(&connection->lock, flags); + list_for_each_entry(operation, &connection->operations, links) + if (operation->id == operation_id && + !gb_operation_is_incoming(operation)) { + gb_operation_get(operation); + found = true; + break; + } + spin_unlock_irqrestore(&connection->lock, flags); + + return found ? operation : NULL; +} + +static int gb_message_send(struct gb_message *message, gfp_t gfp) +{ + struct gb_connection *connection = message->operation->connection; + + trace_gb_message_send(message); + return connection->hd->driver->message_send(connection->hd, + connection->hd_cport_id, + message, + gfp); +} + +/* + * Cancel a message we have passed to the host device layer to be sent. + */ +static void gb_message_cancel(struct gb_message *message) +{ + struct gb_host_device *hd = message->operation->connection->hd; + + hd->driver->message_cancel(message); +} + +static void gb_operation_request_handle(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + int status; + int ret; + + if (connection->handler) { + status = connection->handler(operation); + } else { + dev_err(&connection->hd->dev, + "%s: unexpected incoming request of type 0x%02x\n", + connection->name, operation->type); + + status = -EPROTONOSUPPORT; + } + + ret = gb_operation_response_send(operation, status); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to send response %d for type 0x%02x: %d\n", + connection->name, status, operation->type, ret); + return; + } +} + +/* + * Process operation work. + * + * For incoming requests, call the protocol request handler. The operation + * result should be -EINPROGRESS at this point. + * + * For outgoing requests, the operation result value should have + * been set before queueing this. The operation callback function + * allows the original requester to know the request has completed + * and its result is available. + */ +static void gb_operation_work(struct work_struct *work) +{ + struct gb_operation *operation; + + operation = container_of(work, struct gb_operation, work); + + if (gb_operation_is_incoming(operation)) + gb_operation_request_handle(operation); + else + operation->callback(operation); + + gb_operation_put_active(operation); + gb_operation_put(operation); +} + +static void gb_operation_message_init(struct gb_host_device *hd, + struct gb_message *message, u16 operation_id, + size_t payload_size, u8 type) +{ + struct gb_operation_msg_hdr *header; + + header = message->buffer; + + message->header = header; + message->payload = payload_size ? header + 1 : NULL; + message->payload_size = payload_size; + + /* + * The type supplied for incoming message buffers will be + * GB_REQUEST_TYPE_INVALID. Such buffers will be overwritten by + * arriving data so there's no need to initialize the message header. + */ + if (type != GB_REQUEST_TYPE_INVALID) { + u16 message_size = (u16)(sizeof(*header) + payload_size); + + /* + * For a request, the operation id gets filled in + * when the message is sent. For a response, it + * will be copied from the request by the caller. + * + * The result field in a request message must be + * zero. It will be set just prior to sending for + * a response. + */ + header->size = cpu_to_le16(message_size); + header->operation_id = 0; + header->type = type; + header->result = 0; + } +} + +/* + * Allocate a message to be used for an operation request or response. + * Both types of message contain a common header. The request message + * for an outgoing operation is outbound, as is the response message + * for an incoming operation. The message header for an outbound + * message is partially initialized here. + * + * The headers for inbound messages don't need to be initialized; + * they'll be filled in by arriving data. + * + * Our message buffers have the following layout: + * message header \_ these combined are + * message payload / the message size + */ +static struct gb_message * +gb_operation_message_alloc(struct gb_host_device *hd, u8 type, + size_t payload_size, gfp_t gfp_flags) +{ + struct gb_message *message; + struct gb_operation_msg_hdr *header; + size_t message_size = payload_size + sizeof(*header); + + if (message_size > hd->buffer_size_max) { + dev_warn(&hd->dev, "requested message size too big (%zu > %zu)\n", + message_size, hd->buffer_size_max); + return NULL; + } + + /* Allocate the message structure and buffer. */ + message = kmem_cache_zalloc(gb_message_cache, gfp_flags); + if (!message) + return NULL; + + message->buffer = kzalloc(message_size, gfp_flags); + if (!message->buffer) + goto err_free_message; + + /* Initialize the message. Operation id is filled in later. */ + gb_operation_message_init(hd, message, 0, payload_size, type); + + return message; + +err_free_message: + kmem_cache_free(gb_message_cache, message); + + return NULL; +} + +static void gb_operation_message_free(struct gb_message *message) +{ + kfree(message->buffer); + kmem_cache_free(gb_message_cache, message); +} + +/* + * Map an enum gb_operation_status value (which is represented in a + * message as a single byte) to an appropriate Linux negative errno. + */ +static int gb_operation_status_map(u8 status) +{ + switch (status) { + case GB_OP_SUCCESS: + return 0; + case GB_OP_INTERRUPTED: + return -EINTR; + case GB_OP_TIMEOUT: + return -ETIMEDOUT; + case GB_OP_NO_MEMORY: + return -ENOMEM; + case GB_OP_PROTOCOL_BAD: + return -EPROTONOSUPPORT; + case GB_OP_OVERFLOW: + return -EMSGSIZE; + case GB_OP_INVALID: + return -EINVAL; + case GB_OP_RETRY: + return -EAGAIN; + case GB_OP_NONEXISTENT: + return -ENODEV; + case GB_OP_MALFUNCTION: + return -EILSEQ; + case GB_OP_UNKNOWN_ERROR: + default: + return -EIO; + } +} + +/* + * Map a Linux errno value (from operation->errno) into the value + * that should represent it in a response message status sent + * over the wire. Returns an enum gb_operation_status value (which + * is represented in a message as a single byte). + */ +static u8 gb_operation_errno_map(int errno) +{ + switch (errno) { + case 0: + return GB_OP_SUCCESS; + case -EINTR: + return GB_OP_INTERRUPTED; + case -ETIMEDOUT: + return GB_OP_TIMEOUT; + case -ENOMEM: + return GB_OP_NO_MEMORY; + case -EPROTONOSUPPORT: + return GB_OP_PROTOCOL_BAD; + case -EMSGSIZE: + return GB_OP_OVERFLOW; /* Could be underflow too */ + case -EINVAL: + return GB_OP_INVALID; + case -EAGAIN: + return GB_OP_RETRY; + case -EILSEQ: + return GB_OP_MALFUNCTION; + case -ENODEV: + return GB_OP_NONEXISTENT; + case -EIO: + default: + return GB_OP_UNKNOWN_ERROR; + } +} + +bool gb_operation_response_alloc(struct gb_operation *operation, + size_t response_size, gfp_t gfp) +{ + struct gb_host_device *hd = operation->connection->hd; + struct gb_operation_msg_hdr *request_header; + struct gb_message *response; + u8 type; + + type = operation->type | GB_MESSAGE_TYPE_RESPONSE; + response = gb_operation_message_alloc(hd, type, response_size, gfp); + if (!response) + return false; + response->operation = operation; + + /* + * Size and type get initialized when the message is + * allocated. The errno will be set before sending. All + * that's left is the operation id, which we copy from the + * request message header (as-is, in little-endian order). + */ + request_header = operation->request->header; + response->header->operation_id = request_header->operation_id; + operation->response = response; + + return true; +} +EXPORT_SYMBOL_GPL(gb_operation_response_alloc); + +/* + * Create a Greybus operation to be sent over the given connection. + * The request buffer will be big enough for a payload of the given + * size. + * + * For outgoing requests, the request message's header will be + * initialized with the type of the request and the message size. + * Outgoing operations must also specify the response buffer size, + * which must be sufficient to hold all expected response data. The + * response message header will eventually be overwritten, so there's + * no need to initialize it here. + * + * Request messages for incoming operations can arrive in interrupt + * context, so they must be allocated with GFP_ATOMIC. In this case + * the request buffer will be immediately overwritten, so there is + * no need to initialize the message header. Responsibility for + * allocating a response buffer lies with the incoming request + * handler for a protocol. So we don't allocate that here. + * + * Returns a pointer to the new operation or a null pointer if an + * error occurs. + */ +static struct gb_operation * +gb_operation_create_common(struct gb_connection *connection, u8 type, + size_t request_size, size_t response_size, + unsigned long op_flags, gfp_t gfp_flags) +{ + struct gb_host_device *hd = connection->hd; + struct gb_operation *operation; + + operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); + if (!operation) + return NULL; + operation->connection = connection; + + operation->request = gb_operation_message_alloc(hd, type, request_size, + gfp_flags); + if (!operation->request) + goto err_cache; + operation->request->operation = operation; + + /* Allocate the response buffer for outgoing operations */ + if (!(op_flags & GB_OPERATION_FLAG_INCOMING)) { + if (!gb_operation_response_alloc(operation, response_size, + gfp_flags)) { + goto err_request; + } + } + + operation->flags = op_flags; + operation->type = type; + operation->errno = -EBADR; /* Initial value--means "never set" */ + + INIT_WORK(&operation->work, gb_operation_work); + init_completion(&operation->completion); + kref_init(&operation->kref); + atomic_set(&operation->waiters, 0); + + return operation; + +err_request: + gb_operation_message_free(operation->request); +err_cache: + kmem_cache_free(gb_operation_cache, operation); + + return NULL; +} + +/* + * Create a new operation associated with the given connection. The + * request and response sizes provided are the number of bytes + * required to hold the request/response payload only. Both of + * these are allowed to be 0. Note that 0x00 is reserved as an + * invalid operation type for all protocols, and this is enforced + * here. + */ +struct gb_operation * +gb_operation_create_flags(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp) +{ + struct gb_operation *operation; + + if (WARN_ON_ONCE(type == GB_REQUEST_TYPE_INVALID)) + return NULL; + if (WARN_ON_ONCE(type & GB_MESSAGE_TYPE_RESPONSE)) + type &= ~GB_MESSAGE_TYPE_RESPONSE; + + if (WARN_ON_ONCE(flags & ~GB_OPERATION_FLAG_USER_MASK)) + flags &= GB_OPERATION_FLAG_USER_MASK; + + operation = gb_operation_create_common(connection, type, + request_size, response_size, + flags, gfp); + if (operation) + trace_gb_operation_create(operation); + + return operation; +} +EXPORT_SYMBOL_GPL(gb_operation_create_flags); + +struct gb_operation * +gb_operation_create_core(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp) +{ + struct gb_operation *operation; + + flags |= GB_OPERATION_FLAG_CORE; + + operation = gb_operation_create_common(connection, type, + request_size, response_size, + flags, gfp); + if (operation) + trace_gb_operation_create_core(operation); + + return operation; +} +/* Do not export this function. */ + +size_t gb_operation_get_payload_size_max(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + + return hd->buffer_size_max - sizeof(struct gb_operation_msg_hdr); +} +EXPORT_SYMBOL_GPL(gb_operation_get_payload_size_max); + +static struct gb_operation * +gb_operation_create_incoming(struct gb_connection *connection, u16 id, + u8 type, void *data, size_t size) +{ + struct gb_operation *operation; + size_t request_size; + unsigned long flags = GB_OPERATION_FLAG_INCOMING; + + /* Caller has made sure we at least have a message header. */ + request_size = size - sizeof(struct gb_operation_msg_hdr); + + if (!id) + flags |= GB_OPERATION_FLAG_UNIDIRECTIONAL; + + operation = gb_operation_create_common(connection, type, + request_size, + GB_REQUEST_TYPE_INVALID, + flags, GFP_ATOMIC); + if (!operation) + return NULL; + + operation->id = id; + memcpy(operation->request->header, data, size); + trace_gb_operation_create_incoming(operation); + + return operation; +} + +/* + * Get an additional reference on an operation. + */ +void gb_operation_get(struct gb_operation *operation) +{ + kref_get(&operation->kref); +} +EXPORT_SYMBOL_GPL(gb_operation_get); + +/* + * Destroy a previously created operation. + */ +static void _gb_operation_destroy(struct kref *kref) +{ + struct gb_operation *operation; + + operation = container_of(kref, struct gb_operation, kref); + + trace_gb_operation_destroy(operation); + + if (operation->response) + gb_operation_message_free(operation->response); + gb_operation_message_free(operation->request); + + kmem_cache_free(gb_operation_cache, operation); +} + +/* + * Drop a reference on an operation, and destroy it when the last + * one is gone. + */ +void gb_operation_put(struct gb_operation *operation) +{ + if (WARN_ON(!operation)) + return; + + kref_put(&operation->kref, _gb_operation_destroy); +} +EXPORT_SYMBOL_GPL(gb_operation_put); + +/* Tell the requester we're done */ +static void gb_operation_sync_callback(struct gb_operation *operation) +{ + complete(&operation->completion); +} + +/** + * gb_operation_request_send() - send an operation request message + * @operation: the operation to initiate + * @callback: the operation completion callback + * @gfp: the memory flags to use for any allocations + * + * The caller has filled in any payload so the request message is ready to go. + * The callback function supplied will be called when the response message has + * arrived, a unidirectional request has been sent, or the operation is + * cancelled, indicating that the operation is complete. The callback function + * can fetch the result of the operation using gb_operation_result() if + * desired. + * + * Return: 0 if the request was successfully queued in the host-driver queues, + * or a negative errno. + */ +int gb_operation_request_send(struct gb_operation *operation, + gb_operation_callback callback, + gfp_t gfp) +{ + struct gb_connection *connection = operation->connection; + struct gb_operation_msg_hdr *header; + unsigned int cycle; + int ret; + + if (gb_connection_is_offloaded(connection)) + return -EBUSY; + + if (!callback) + return -EINVAL; + + /* + * Record the callback function, which is executed in + * non-atomic (workqueue) context when the final result + * of an operation has been set. + */ + operation->callback = callback; + + /* + * Assign the operation's id, and store it in the request header. + * Zero is a reserved operation id for unidirectional operations. + */ + if (gb_operation_is_unidirectional(operation)) { + operation->id = 0; + } else { + cycle = (unsigned int)atomic_inc_return(&connection->op_cycle); + operation->id = (u16)(cycle % U16_MAX + 1); + } + + header = operation->request->header; + header->operation_id = cpu_to_le16(operation->id); + + gb_operation_result_set(operation, -EINPROGRESS); + + /* + * Get an extra reference on the operation. It'll be dropped when the + * operation completes. + */ + gb_operation_get(operation); + ret = gb_operation_get_active(operation); + if (ret) + goto err_put; + + ret = gb_message_send(operation->request, gfp); + if (ret) + goto err_put_active; + + return 0; + +err_put_active: + gb_operation_put_active(operation); +err_put: + gb_operation_put(operation); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_operation_request_send); + +/* + * Send a synchronous operation. This function is expected to + * block, returning only when the response has arrived, (or when an + * error is detected. The return value is the result of the + * operation. + */ +int gb_operation_request_send_sync_timeout(struct gb_operation *operation, + unsigned int timeout) +{ + int ret; + unsigned long timeout_jiffies; + + ret = gb_operation_request_send(operation, gb_operation_sync_callback, + GFP_KERNEL); + if (ret) + return ret; + + if (timeout) + timeout_jiffies = msecs_to_jiffies(timeout); + else + timeout_jiffies = MAX_SCHEDULE_TIMEOUT; + + ret = wait_for_completion_interruptible_timeout(&operation->completion, + timeout_jiffies); + if (ret < 0) { + /* Cancel the operation if interrupted */ + gb_operation_cancel(operation, -ECANCELED); + } else if (ret == 0) { + /* Cancel the operation if op timed out */ + gb_operation_cancel(operation, -ETIMEDOUT); + } + + return gb_operation_result(operation); +} +EXPORT_SYMBOL_GPL(gb_operation_request_send_sync_timeout); + +/* + * Send a response for an incoming operation request. A non-zero + * errno indicates a failed operation. + * + * If there is any response payload, the incoming request handler is + * responsible for allocating the response message. Otherwise the + * it can simply supply the result errno; this function will + * allocate the response message if necessary. + */ +static int gb_operation_response_send(struct gb_operation *operation, + int errno) +{ + struct gb_connection *connection = operation->connection; + int ret; + + if (!operation->response && + !gb_operation_is_unidirectional(operation)) { + if (!gb_operation_response_alloc(operation, 0, GFP_KERNEL)) + return -ENOMEM; + } + + /* Record the result */ + if (!gb_operation_result_set(operation, errno)) { + dev_err(&connection->hd->dev, "request result already set\n"); + return -EIO; /* Shouldn't happen */ + } + + /* Sender of request does not care about response. */ + if (gb_operation_is_unidirectional(operation)) + return 0; + + /* Reference will be dropped when message has been sent. */ + gb_operation_get(operation); + ret = gb_operation_get_active(operation); + if (ret) + goto err_put; + + /* Fill in the response header and send it */ + operation->response->header->result = gb_operation_errno_map(errno); + + ret = gb_message_send(operation->response, GFP_KERNEL); + if (ret) + goto err_put_active; + + return 0; + +err_put_active: + gb_operation_put_active(operation); +err_put: + gb_operation_put(operation); + + return ret; +} + +/* + * This function is called when a message send request has completed. + */ +void greybus_message_sent(struct gb_host_device *hd, + struct gb_message *message, int status) +{ + struct gb_operation *operation = message->operation; + struct gb_connection *connection = operation->connection; + + /* + * If the message was a response, we just need to drop our + * reference to the operation. If an error occurred, report + * it. + * + * For requests, if there's no error and the operation in not + * unidirectional, there's nothing more to do until the response + * arrives. If an error occurred attempting to send it, or if the + * operation is unidrectional, record the result of the operation and + * schedule its completion. + */ + if (message == operation->response) { + if (status) { + dev_err(&connection->hd->dev, + "%s: error sending response 0x%02x: %d\n", + connection->name, operation->type, status); + } + + gb_operation_put_active(operation); + gb_operation_put(operation); + } else if (status || gb_operation_is_unidirectional(operation)) { + if (gb_operation_result_set(operation, status)) { + queue_work(gb_operation_completion_wq, + &operation->work); + } + } +} +EXPORT_SYMBOL_GPL(greybus_message_sent); + +/* + * We've received data on a connection, and it doesn't look like a + * response, so we assume it's a request. + * + * This is called in interrupt context, so just copy the incoming + * data into the request buffer and handle the rest via workqueue. + */ +static void gb_connection_recv_request(struct gb_connection *connection, + const struct gb_operation_msg_hdr *header, + void *data, size_t size) +{ + struct gb_operation *operation; + u16 operation_id; + u8 type; + int ret; + + operation_id = le16_to_cpu(header->operation_id); + type = header->type; + + operation = gb_operation_create_incoming(connection, operation_id, + type, data, size); + if (!operation) { + dev_err(&connection->hd->dev, + "%s: can't create incoming operation\n", + connection->name); + return; + } + + ret = gb_operation_get_active(operation); + if (ret) { + gb_operation_put(operation); + return; + } + trace_gb_message_recv_request(operation->request); + + /* + * The initial reference to the operation will be dropped when the + * request handler returns. + */ + if (gb_operation_result_set(operation, -EINPROGRESS)) + queue_work(connection->wq, &operation->work); +} + +/* + * We've received data that appears to be an operation response + * message. Look up the operation, and record that we've received + * its response. + * + * This is called in interrupt context, so just copy the incoming + * data into the response buffer and handle the rest via workqueue. + */ +static void gb_connection_recv_response(struct gb_connection *connection, + const struct gb_operation_msg_hdr *header, + void *data, size_t size) +{ + struct gb_operation *operation; + struct gb_message *message; + size_t message_size; + u16 operation_id; + int errno; + + operation_id = le16_to_cpu(header->operation_id); + + if (!operation_id) { + dev_err_ratelimited(&connection->hd->dev, + "%s: invalid response id 0 received\n", + connection->name); + return; + } + + operation = gb_operation_find_outgoing(connection, operation_id); + if (!operation) { + dev_err_ratelimited(&connection->hd->dev, + "%s: unexpected response id 0x%04x received\n", + connection->name, operation_id); + return; + } + + errno = gb_operation_status_map(header->result); + message = operation->response; + message_size = sizeof(*header) + message->payload_size; + if (!errno && size > message_size) { + dev_err_ratelimited(&connection->hd->dev, + "%s: malformed response 0x%02x received (%zu > %zu)\n", + connection->name, header->type, + size, message_size); + errno = -EMSGSIZE; + } else if (!errno && size < message_size) { + if (gb_operation_short_response_allowed(operation)) { + message->payload_size = size - sizeof(*header); + } else { + dev_err_ratelimited(&connection->hd->dev, + "%s: short response 0x%02x received (%zu < %zu)\n", + connection->name, header->type, + size, message_size); + errno = -EMSGSIZE; + } + } + + /* We must ignore the payload if a bad status is returned */ + if (errno) + size = sizeof(*header); + + /* The rest will be handled in work queue context */ + if (gb_operation_result_set(operation, errno)) { + memcpy(message->buffer, data, size); + + trace_gb_message_recv_response(message); + + queue_work(gb_operation_completion_wq, &operation->work); + } + + gb_operation_put(operation); +} + +/* + * Handle data arriving on a connection. As soon as we return the + * supplied data buffer will be reused (so unless we do something + * with, it's effectively dropped). + */ +void gb_connection_recv(struct gb_connection *connection, + void *data, size_t size) +{ + struct gb_operation_msg_hdr header; + struct device *dev = &connection->hd->dev; + size_t msg_size; + + if (connection->state == GB_CONNECTION_STATE_DISABLED || + gb_connection_is_offloaded(connection)) { + dev_warn_ratelimited(dev, "%s: dropping %zu received bytes\n", + connection->name, size); + return; + } + + if (size < sizeof(header)) { + dev_err_ratelimited(dev, "%s: short message received\n", + connection->name); + return; + } + + /* Use memcpy as data may be unaligned */ + memcpy(&header, data, sizeof(header)); + msg_size = le16_to_cpu(header.size); + if (size < msg_size) { + dev_err_ratelimited(dev, + "%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n", + connection->name, + le16_to_cpu(header.operation_id), + header.type, size, msg_size); + return; /* XXX Should still complete operation */ + } + + if (header.type & GB_MESSAGE_TYPE_RESPONSE) { + gb_connection_recv_response(connection, &header, data, + msg_size); + } else { + gb_connection_recv_request(connection, &header, data, + msg_size); + } +} + +/* + * Cancel an outgoing operation synchronously, and record the given error to + * indicate why. + */ +void gb_operation_cancel(struct gb_operation *operation, int errno) +{ + if (WARN_ON(gb_operation_is_incoming(operation))) + return; + + if (gb_operation_result_set(operation, errno)) { + gb_message_cancel(operation->request); + queue_work(gb_operation_completion_wq, &operation->work); + } + trace_gb_message_cancel_outgoing(operation->request); + + atomic_inc(&operation->waiters); + wait_event(gb_operation_cancellation_queue, + !gb_operation_is_active(operation)); + atomic_dec(&operation->waiters); +} +EXPORT_SYMBOL_GPL(gb_operation_cancel); + +/* + * Cancel an incoming operation synchronously. Called during connection tear + * down. + */ +void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) +{ + if (WARN_ON(!gb_operation_is_incoming(operation))) + return; + + if (!gb_operation_is_unidirectional(operation)) { + /* + * Make sure the request handler has submitted the response + * before cancelling it. + */ + flush_work(&operation->work); + if (!gb_operation_result_set(operation, errno)) + gb_message_cancel(operation->response); + } + trace_gb_message_cancel_incoming(operation->response); + + atomic_inc(&operation->waiters); + wait_event(gb_operation_cancellation_queue, + !gb_operation_is_active(operation)); + atomic_dec(&operation->waiters); +} + +/** + * gb_operation_sync_timeout() - implement a "simple" synchronous operation + * @connection: the Greybus connection to send this to + * @type: the type of operation to send + * @request: pointer to a memory buffer to copy the request from + * @request_size: size of @request + * @response: pointer to a memory buffer to copy the response to + * @response_size: the size of @response. + * @timeout: operation timeout in milliseconds + * + * This function implements a simple synchronous Greybus operation. It sends + * the provided operation request and waits (sleeps) until the corresponding + * operation response message has been successfully received, or an error + * occurs. @request and @response are buffers to hold the request and response + * data respectively, and if they are not NULL, their size must be specified in + * @request_size and @response_size. + * + * If a response payload is to come back, and @response is not NULL, + * @response_size number of bytes will be copied into @response if the operation + * is successful. + * + * If there is an error, the response buffer is left alone. + */ +int gb_operation_sync_timeout(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size, + unsigned int timeout) +{ + struct gb_operation *operation; + int ret; + + if ((response_size && !response) || + (request_size && !request)) + return -EINVAL; + + operation = gb_operation_create(connection, type, + request_size, response_size, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync_timeout(operation, timeout); + if (ret) { + dev_err(&connection->hd->dev, + "%s: synchronous operation id 0x%04x of type 0x%02x failed: %d\n", + connection->name, operation->id, type, ret); + } else { + if (response_size) { + memcpy(response, operation->response->payload, + response_size); + } + } + + gb_operation_put(operation); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_operation_sync_timeout); + +/** + * gb_operation_unidirectional_timeout() - initiate a unidirectional operation + * @connection: connection to use + * @type: type of operation to send + * @request: memory buffer to copy the request from + * @request_size: size of @request + * @timeout: send timeout in milliseconds + * + * Initiate a unidirectional operation by sending a request message and + * waiting for it to be acknowledged as sent by the host device. + * + * Note that successful send of a unidirectional operation does not imply that + * the request as actually reached the remote end of the connection. + */ +int gb_operation_unidirectional_timeout(struct gb_connection *connection, + int type, void *request, int request_size, + unsigned int timeout) +{ + struct gb_operation *operation; + int ret; + + if (request_size && !request) + return -EINVAL; + + operation = gb_operation_create_flags(connection, type, + request_size, 0, + GB_OPERATION_FLAG_UNIDIRECTIONAL, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync_timeout(operation, timeout); + if (ret) { + dev_err(&connection->hd->dev, + "%s: unidirectional operation of type 0x%02x failed: %d\n", + connection->name, type, ret); + } + + gb_operation_put(operation); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_operation_unidirectional_timeout); + +int __init gb_operation_init(void) +{ + gb_message_cache = kmem_cache_create("gb_message_cache", + sizeof(struct gb_message), 0, 0, NULL); + if (!gb_message_cache) + return -ENOMEM; + + gb_operation_cache = kmem_cache_create("gb_operation_cache", + sizeof(struct gb_operation), 0, 0, NULL); + if (!gb_operation_cache) + goto err_destroy_message_cache; + + gb_operation_completion_wq = alloc_workqueue("greybus_completion", + 0, 0); + if (!gb_operation_completion_wq) + goto err_destroy_operation_cache; + + return 0; + +err_destroy_operation_cache: + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; +err_destroy_message_cache: + kmem_cache_destroy(gb_message_cache); + gb_message_cache = NULL; + + return -ENOMEM; +} + +void gb_operation_exit(void) +{ + destroy_workqueue(gb_operation_completion_wq); + gb_operation_completion_wq = NULL; + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; + kmem_cache_destroy(gb_message_cache); + gb_message_cache = NULL; +} diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h new file mode 100644 index 000000000000..de09a2c7de54 --- /dev/null +++ b/drivers/staging/greybus/operation.h @@ -0,0 +1,210 @@ +/* + * Greybus operations + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __OPERATION_H +#define __OPERATION_H + +#include + +struct gb_operation; + +/* The default amount of time a request is given to complete */ +#define GB_OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ + +/* + * The top bit of the type in an operation message header indicates + * whether the message is a request (bit clear) or response (bit set) + */ +#define GB_MESSAGE_TYPE_RESPONSE ((u8)0x80) + +enum gb_operation_result { + GB_OP_SUCCESS = 0x00, + GB_OP_INTERRUPTED = 0x01, + GB_OP_TIMEOUT = 0x02, + GB_OP_NO_MEMORY = 0x03, + GB_OP_PROTOCOL_BAD = 0x04, + GB_OP_OVERFLOW = 0x05, + GB_OP_INVALID = 0x06, + GB_OP_RETRY = 0x07, + GB_OP_NONEXISTENT = 0x08, + GB_OP_UNKNOWN_ERROR = 0xfe, + GB_OP_MALFUNCTION = 0xff, +}; + +#define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) +#define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX + +/* + * Protocol code should only examine the payload and payload_size fields, and + * host-controller drivers may use the hcpriv field. All other fields are + * intended to be private to the operations core code. + */ +struct gb_message { + struct gb_operation *operation; + struct gb_operation_msg_hdr *header; + + void *payload; + size_t payload_size; + + void *buffer; + + void *hcpriv; +}; + +#define GB_OPERATION_FLAG_INCOMING BIT(0) +#define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) +#define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) +#define GB_OPERATION_FLAG_CORE BIT(3) + +#define GB_OPERATION_FLAG_USER_MASK (GB_OPERATION_FLAG_SHORT_RESPONSE | \ + GB_OPERATION_FLAG_UNIDIRECTIONAL) + +/* + * A Greybus operation is a remote procedure call performed over a + * connection between two UniPro interfaces. + * + * Every operation consists of a request message sent to the other + * end of the connection coupled with a reply message returned to + * the sender. Every operation has a type, whose interpretation is + * dependent on the protocol associated with the connection. + * + * Only four things in an operation structure are intended to be + * directly usable by protocol handlers: the operation's connection + * pointer; the operation type; the request message payload (and + * size); and the response message payload (and size). Note that a + * message with a 0-byte payload has a null message payload pointer. + * + * In addition, every operation has a result, which is an errno + * value. Protocol handlers access the operation result using + * gb_operation_result(). + */ +typedef void (*gb_operation_callback)(struct gb_operation *); +struct gb_operation { + struct gb_connection *connection; + struct gb_message *request; + struct gb_message *response; + + unsigned long flags; + u8 type; + u16 id; + int errno; /* Operation result */ + + struct work_struct work; + gb_operation_callback callback; + struct completion completion; + + struct kref kref; + atomic_t waiters; + + int active; + struct list_head links; /* connection->operations */ +}; + +static inline bool +gb_operation_is_incoming(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_INCOMING; +} + +static inline bool +gb_operation_is_unidirectional(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_UNIDIRECTIONAL; +} + +static inline bool +gb_operation_short_response_allowed(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_SHORT_RESPONSE; +} + +static inline bool gb_operation_is_core(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_CORE; +} + +void gb_connection_recv(struct gb_connection *connection, + void *data, size_t size); + +int gb_operation_result(struct gb_operation *operation); + +size_t gb_operation_get_payload_size_max(struct gb_connection *connection); +struct gb_operation * +gb_operation_create_flags(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp); + +static inline struct gb_operation * +gb_operation_create(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, gfp_t gfp) +{ + return gb_operation_create_flags(connection, type, request_size, + response_size, 0, gfp); +} + +struct gb_operation * +gb_operation_create_core(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp); + +void gb_operation_get(struct gb_operation *operation); +void gb_operation_put(struct gb_operation *operation); + +bool gb_operation_response_alloc(struct gb_operation *operation, + size_t response_size, gfp_t gfp); + +int gb_operation_request_send(struct gb_operation *operation, + gb_operation_callback callback, + gfp_t gfp); +int gb_operation_request_send_sync_timeout(struct gb_operation *operation, + unsigned int timeout); +static inline int +gb_operation_request_send_sync(struct gb_operation *operation) +{ + return gb_operation_request_send_sync_timeout(operation, + GB_OPERATION_TIMEOUT_DEFAULT); +} + +void gb_operation_cancel(struct gb_operation *operation, int errno); +void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); + +void greybus_message_sent(struct gb_host_device *hd, + struct gb_message *message, int status); + +int gb_operation_sync_timeout(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size, + unsigned int timeout); +int gb_operation_unidirectional_timeout(struct gb_connection *connection, + int type, void *request, int request_size, + unsigned int timeout); + +static inline int gb_operation_sync(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size) +{ + return gb_operation_sync_timeout(connection, type, + request, request_size, response, response_size, + GB_OPERATION_TIMEOUT_DEFAULT); +} + +static inline int gb_operation_unidirectional(struct gb_connection *connection, + int type, void *request, int request_size) +{ + return gb_operation_unidirectional_timeout(connection, type, + request, request_size, GB_OPERATION_TIMEOUT_DEFAULT); +} + +int gb_operation_init(void); +void gb_operation_exit(void); + +#endif /* !__OPERATION_H */ diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c new file mode 100644 index 000000000000..e85c988b7034 --- /dev/null +++ b/drivers/staging/greybus/power_supply.c @@ -0,0 +1,1141 @@ +/* + * Power Supply driver for a Greybus module. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include + +#include "greybus.h" + +#define PROP_MAX 32 + +struct gb_power_supply_prop { + enum power_supply_property prop; + u8 gb_prop; + int val; + int previous_val; + bool is_writeable; +}; + +struct gb_power_supply { + u8 id; + bool registered; + struct power_supply *psy; + struct power_supply_desc desc; + char name[64]; + struct gb_power_supplies *supplies; + struct delayed_work work; + char *manufacturer; + char *model_name; + char *serial_number; + u8 type; + u8 properties_count; + u8 properties_count_str; + unsigned long last_update; + u8 cache_invalid; + unsigned int update_interval; + bool changed; + struct gb_power_supply_prop *props; + enum power_supply_property *props_raw; + bool pm_acquired; + struct mutex supply_lock; +}; + +struct gb_power_supplies { + struct gb_connection *connection; + u8 supplies_count; + struct gb_power_supply *supply; + struct mutex supplies_lock; +}; + +#define to_gb_power_supply(x) power_supply_get_drvdata(x) + +/* + * General power supply properties that could be absent from various reasons, + * like kernel versions or vendor specific versions + */ +#ifndef POWER_SUPPLY_PROP_VOLTAGE_BOOT + #define POWER_SUPPLY_PROP_VOLTAGE_BOOT -1 +#endif +#ifndef POWER_SUPPLY_PROP_CURRENT_BOOT + #define POWER_SUPPLY_PROP_CURRENT_BOOT -1 +#endif +#ifndef POWER_SUPPLY_PROP_CALIBRATE + #define POWER_SUPPLY_PROP_CALIBRATE -1 +#endif + +/* cache time in milliseconds, if cache_time is set to 0 cache is disable */ +static unsigned int cache_time = 1000; +/* + * update interval initial and maximum value, between the two will + * back-off exponential + */ +static unsigned int update_interval_init = 1 * HZ; +static unsigned int update_interval_max = 30 * HZ; + +struct gb_power_supply_changes { + enum power_supply_property prop; + u32 tolerance_change; + void (*prop_changed)(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop); +}; + +static void gb_power_supply_state_change(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop); + +static const struct gb_power_supply_changes psy_props_changes[] = { + { .prop = GB_POWER_SUPPLY_PROP_STATUS, + .tolerance_change = 0, + .prop_changed = gb_power_supply_state_change, + }, + { .prop = GB_POWER_SUPPLY_PROP_TEMP, + .tolerance_change = 500, + .prop_changed = NULL, + }, + { .prop = GB_POWER_SUPPLY_PROP_ONLINE, + .tolerance_change = 0, + .prop_changed = NULL, + }, +}; + +static int get_psp_from_gb_prop(int gb_prop, enum power_supply_property *psp) +{ + int prop; + + switch (gb_prop) { + case GB_POWER_SUPPLY_PROP_STATUS: + prop = POWER_SUPPLY_PROP_STATUS; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_TYPE: + prop = POWER_SUPPLY_PROP_CHARGE_TYPE; + break; + case GB_POWER_SUPPLY_PROP_HEALTH: + prop = POWER_SUPPLY_PROP_HEALTH; + break; + case GB_POWER_SUPPLY_PROP_PRESENT: + prop = POWER_SUPPLY_PROP_PRESENT; + break; + case GB_POWER_SUPPLY_PROP_ONLINE: + prop = POWER_SUPPLY_PROP_ONLINE; + break; + case GB_POWER_SUPPLY_PROP_AUTHENTIC: + prop = POWER_SUPPLY_PROP_AUTHENTIC; + break; + case GB_POWER_SUPPLY_PROP_TECHNOLOGY: + prop = POWER_SUPPLY_PROP_TECHNOLOGY; + break; + case GB_POWER_SUPPLY_PROP_CYCLE_COUNT: + prop = POWER_SUPPLY_PROP_CYCLE_COUNT; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_MAX: + prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_MIN: + prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_NOW: + prop = POWER_SUPPLY_PROP_VOLTAGE_NOW; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_AVG: + prop = POWER_SUPPLY_PROP_VOLTAGE_AVG; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_OCV: + prop = POWER_SUPPLY_PROP_VOLTAGE_OCV; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT: + prop = POWER_SUPPLY_PROP_VOLTAGE_BOOT; + break; + case GB_POWER_SUPPLY_PROP_CURRENT_MAX: + prop = POWER_SUPPLY_PROP_CURRENT_MAX; + break; + case GB_POWER_SUPPLY_PROP_CURRENT_NOW: + prop = POWER_SUPPLY_PROP_CURRENT_NOW; + break; + case GB_POWER_SUPPLY_PROP_CURRENT_AVG: + prop = POWER_SUPPLY_PROP_CURRENT_AVG; + break; + case GB_POWER_SUPPLY_PROP_CURRENT_BOOT: + prop = POWER_SUPPLY_PROP_CURRENT_BOOT; + break; + case GB_POWER_SUPPLY_PROP_POWER_NOW: + prop = POWER_SUPPLY_PROP_POWER_NOW; + break; + case GB_POWER_SUPPLY_PROP_POWER_AVG: + prop = POWER_SUPPLY_PROP_POWER_AVG; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN: + prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_FULL: + prop = POWER_SUPPLY_PROP_CHARGE_FULL; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_EMPTY: + prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_NOW: + prop = POWER_SUPPLY_PROP_CHARGE_NOW; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_AVG: + prop = POWER_SUPPLY_PROP_CHARGE_AVG; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_COUNTER: + prop = POWER_SUPPLY_PROP_CHARGE_COUNTER; + break; + case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT; + break; + case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: + prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX; + break; + case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE; + break; + case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: + prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + prop = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: + prop = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX; + break; + case GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + prop = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN: + prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_FULL: + prop = POWER_SUPPLY_PROP_ENERGY_FULL; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_EMPTY: + prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_NOW: + prop = POWER_SUPPLY_PROP_ENERGY_NOW; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_AVG: + prop = POWER_SUPPLY_PROP_ENERGY_AVG; + break; + case GB_POWER_SUPPLY_PROP_CAPACITY: + prop = POWER_SUPPLY_PROP_CAPACITY; + break; + case GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: + prop = POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN; + break; + case GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX: + prop = POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX; + break; + case GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL: + prop = POWER_SUPPLY_PROP_CAPACITY_LEVEL; + break; + case GB_POWER_SUPPLY_PROP_TEMP: + prop = POWER_SUPPLY_PROP_TEMP; + break; + case GB_POWER_SUPPLY_PROP_TEMP_MAX: + prop = POWER_SUPPLY_PROP_TEMP_MAX; + break; + case GB_POWER_SUPPLY_PROP_TEMP_MIN: + prop = POWER_SUPPLY_PROP_TEMP_MIN; + break; + case GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN: + prop = POWER_SUPPLY_PROP_TEMP_ALERT_MIN; + break; + case GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX: + prop = POWER_SUPPLY_PROP_TEMP_ALERT_MAX; + break; + case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT: + prop = POWER_SUPPLY_PROP_TEMP_AMBIENT; + break; + case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN: + prop = POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN; + break; + case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX: + prop = POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX; + break; + case GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: + prop = POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW; + break; + case GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: + prop = POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG; + break; + case GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: + prop = POWER_SUPPLY_PROP_TIME_TO_FULL_NOW; + break; + case GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: + prop = POWER_SUPPLY_PROP_TIME_TO_FULL_AVG; + break; + case GB_POWER_SUPPLY_PROP_TYPE: + prop = POWER_SUPPLY_PROP_TYPE; + break; + case GB_POWER_SUPPLY_PROP_SCOPE: + prop = POWER_SUPPLY_PROP_SCOPE; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: + prop = POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT; + break; + case GB_POWER_SUPPLY_PROP_CALIBRATE: + prop = POWER_SUPPLY_PROP_CALIBRATE; + break; + default: + prop = -1; + break; + } + + if (prop < 0) + return prop; + + *psp = (enum power_supply_property)prop; + + return 0; +} + +static struct gb_connection *get_conn_from_psy(struct gb_power_supply *gbpsy) +{ + return gbpsy->supplies->connection; +} + +static struct gb_power_supply_prop *get_psy_prop(struct gb_power_supply *gbpsy, + enum power_supply_property psp) +{ + int i; + + for (i = 0; i < gbpsy->properties_count; i++) + if (gbpsy->props[i].prop == psp) + return &gbpsy->props[i]; + return NULL; +} + +static int is_psy_prop_writeable(struct gb_power_supply *gbpsy, + enum power_supply_property psp) +{ + struct gb_power_supply_prop *prop; + + prop = get_psy_prop(gbpsy, psp); + if (!prop) + return -ENOENT; + return prop->is_writeable ? 1 : 0; +} + +static int is_prop_valint(enum power_supply_property psp) +{ + return ((psp < POWER_SUPPLY_PROP_MODEL_NAME) ? 1 : 0); +} + +static void next_interval(struct gb_power_supply *gbpsy) +{ + if (gbpsy->update_interval == update_interval_max) + return; + + /* do some exponential back-off in the update interval */ + gbpsy->update_interval *= 2; + if (gbpsy->update_interval > update_interval_max) + gbpsy->update_interval = update_interval_max; +} + +static void __gb_power_supply_changed(struct gb_power_supply *gbpsy) +{ + power_supply_changed(gbpsy->psy); +} + +static void gb_power_supply_state_change(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + int ret; + + /* + * Check gbpsy->pm_acquired to make sure only one pair of 'get_sync' + * and 'put_autosuspend' runtime pm call for state property change. + */ + mutex_lock(&gbpsy->supply_lock); + + if ((prop->val == GB_POWER_SUPPLY_STATUS_CHARGING) && + !gbpsy->pm_acquired) { + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + dev_err(&connection->bundle->dev, + "Fail to set wake lock for charging state\n"); + else + gbpsy->pm_acquired = true; + } else { + if (gbpsy->pm_acquired) { + ret = gb_pm_runtime_put_autosuspend(connection->bundle); + if (ret) + dev_err(&connection->bundle->dev, + "Fail to set wake unlock for none charging\n"); + else + gbpsy->pm_acquired = false; + } + } + + mutex_unlock(&gbpsy->supply_lock); +} + +static void check_changed(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop) +{ + const struct gb_power_supply_changes *psyc; + int val = prop->val; + int prev_val = prop->previous_val; + bool changed = false; + int i; + + for (i = 0; i < ARRAY_SIZE(psy_props_changes); i++) { + psyc = &psy_props_changes[i]; + if (prop->prop == psyc->prop) { + if (!psyc->tolerance_change) + changed = true; + else if (val < prev_val && + prev_val - val > psyc->tolerance_change) + changed = true; + else if (val > prev_val && + val - prev_val > psyc->tolerance_change) + changed = true; + + if (changed && psyc->prop_changed) + psyc->prop_changed(gbpsy, prop); + + if (changed) + gbpsy->changed = true; + break; + } + } +} + +static int total_props(struct gb_power_supply *gbpsy) +{ + /* this return the intval plus the strval properties */ + return (gbpsy->properties_count + gbpsy->properties_count_str); +} + +static void prop_append(struct gb_power_supply *gbpsy, + enum power_supply_property prop) +{ + enum power_supply_property *new_props_raw; + + gbpsy->properties_count_str++; + new_props_raw = krealloc(gbpsy->props_raw, total_props(gbpsy) * + sizeof(enum power_supply_property), + GFP_KERNEL); + if (!new_props_raw) + return; + gbpsy->props_raw = new_props_raw; + gbpsy->props_raw[total_props(gbpsy) - 1] = prop; +} + +static int __gb_power_supply_set_name(char *init_name, char *name, size_t len) +{ + unsigned int i = 0; + int ret = 0; + struct power_supply *psy; + + if (!strlen(init_name)) + init_name = "gb_power_supply"; + strlcpy(name, init_name, len); + + while ((ret < len) && (psy = power_supply_get_by_name(name))) { + power_supply_put(psy); + + ret = snprintf(name, len, "%s_%u", init_name, ++i); + } + if (ret >= len) + return -ENOMEM; + return i; +} + +static void _gb_power_supply_append_props(struct gb_power_supply *gbpsy) +{ + if (strlen(gbpsy->manufacturer)) + prop_append(gbpsy, POWER_SUPPLY_PROP_MANUFACTURER); + if (strlen(gbpsy->model_name)) + prop_append(gbpsy, POWER_SUPPLY_PROP_MODEL_NAME); + if (strlen(gbpsy->serial_number)) + prop_append(gbpsy, POWER_SUPPLY_PROP_SERIAL_NUMBER); +} + +static int gb_power_supply_description_get(struct gb_power_supply *gbpsy) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct gb_power_supply_get_description_request req; + struct gb_power_supply_get_description_response resp; + int ret; + + req.psy_id = gbpsy->id; + + ret = gb_operation_sync(connection, + GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + gbpsy->manufacturer = kstrndup(resp.manufacturer, PROP_MAX, GFP_KERNEL); + if (!gbpsy->manufacturer) + return -ENOMEM; + gbpsy->model_name = kstrndup(resp.model, PROP_MAX, GFP_KERNEL); + if (!gbpsy->model_name) + return -ENOMEM; + gbpsy->serial_number = kstrndup(resp.serial_number, PROP_MAX, + GFP_KERNEL); + if (!gbpsy->serial_number) + return -ENOMEM; + + gbpsy->type = le16_to_cpu(resp.type); + gbpsy->properties_count = resp.properties_count; + + return 0; +} + +static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct gb_power_supply_get_property_descriptors_request *req; + struct gb_power_supply_get_property_descriptors_response *resp; + struct gb_operation *op; + u8 props_count = gbpsy->properties_count; + enum power_supply_property psp; + int ret; + int i, r = 0; + + if (props_count == 0) + return 0; + + op = gb_operation_create(connection, + GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS, + sizeof(req), sizeof(*resp) + props_count * + sizeof(struct gb_power_supply_props_desc), + GFP_KERNEL); + if (!op) + return -ENOMEM; + + req = op->request->payload; + req->psy_id = gbpsy->id; + + ret = gb_operation_request_send_sync(op); + if (ret < 0) + goto out_put_operation; + + resp = op->response->payload; + + /* validate received properties */ + for (i = 0; i < props_count; i++) { + ret = get_psp_from_gb_prop(resp->props[i].property, &psp); + if (ret < 0) { + dev_warn(&connection->bundle->dev, + "greybus property %u it is not supported by this kernel, dropped\n", + resp->props[i].property); + gbpsy->properties_count--; + } + } + + gbpsy->props = kcalloc(gbpsy->properties_count, sizeof(*gbpsy->props), + GFP_KERNEL); + if (!gbpsy->props) { + ret = -ENOMEM; + goto out_put_operation; + } + + gbpsy->props_raw = kcalloc(gbpsy->properties_count, + sizeof(*gbpsy->props_raw), GFP_KERNEL); + if (!gbpsy->props_raw) { + ret = -ENOMEM; + goto out_put_operation; + } + + /* Store available properties, skip the ones we do not support */ + for (i = 0; i < props_count; i++) { + ret = get_psp_from_gb_prop(resp->props[i].property, &psp); + if (ret < 0) { + r++; + continue; + } + gbpsy->props[i - r].prop = psp; + gbpsy->props[i - r].gb_prop = resp->props[i].property; + gbpsy->props_raw[i - r] = psp; + if (resp->props[i].is_writeable) + gbpsy->props[i - r].is_writeable = true; + } + + /* + * now append the properties that we already got information in the + * get_description operation. (char * ones) + */ + _gb_power_supply_append_props(gbpsy); + + ret = 0; +out_put_operation: + gb_operation_put(op); + + return ret; +} + +static int __gb_power_supply_property_update(struct gb_power_supply *gbpsy, + enum power_supply_property psp) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct gb_power_supply_prop *prop; + struct gb_power_supply_get_property_request req; + struct gb_power_supply_get_property_response resp; + int val; + int ret; + + prop = get_psy_prop(gbpsy, psp); + if (!prop) + return -EINVAL; + req.psy_id = gbpsy->id; + req.property = prop->gb_prop; + + ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_GET_PROPERTY, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + val = le32_to_cpu(resp.prop_val); + if (val == prop->val) + return 0; + + prop->previous_val = prop->val; + prop->val = val; + + check_changed(gbpsy, prop); + + return 0; +} + +static int __gb_power_supply_property_get(struct gb_power_supply *gbpsy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct gb_power_supply_prop *prop; + + prop = get_psy_prop(gbpsy, psp); + if (!prop) + return -EINVAL; + + val->intval = prop->val; + return 0; +} + +static int __gb_power_supply_property_strval_get(struct gb_power_supply *gbpsy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + switch (psp) { + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = gbpsy->model_name; + break; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = gbpsy->manufacturer; + break; + case POWER_SUPPLY_PROP_SERIAL_NUMBER: + val->strval = gbpsy->serial_number; + break; + default: + break; + } + + return 0; +} + +static int _gb_power_supply_property_get(struct gb_power_supply *gbpsy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + int ret; + + /* + * Properties of type const char *, were already fetched on + * get_description operation and should be cached in gb + */ + if (is_prop_valint(psp)) + ret = __gb_power_supply_property_get(gbpsy, psp, val); + else + ret = __gb_power_supply_property_strval_get(gbpsy, psp, val); + + if (ret < 0) + dev_err(&connection->bundle->dev, "get property %u\n", psp); + + return 0; +} + +static int is_cache_valid(struct gb_power_supply *gbpsy) +{ + /* check if cache is good enough or it has expired */ + if (gbpsy->cache_invalid) { + gbpsy->cache_invalid = 0; + return 0; + } + + if (gbpsy->last_update && + time_is_after_jiffies(gbpsy->last_update + + msecs_to_jiffies(cache_time))) + return 1; + + return 0; +} + +static int gb_power_supply_status_get(struct gb_power_supply *gbpsy) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + int ret = 0; + int i; + + if (is_cache_valid(gbpsy)) + return 0; + + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + return ret; + + for (i = 0; i < gbpsy->properties_count; i++) { + ret = __gb_power_supply_property_update(gbpsy, + gbpsy->props[i].prop); + if (ret < 0) + break; + } + + if (ret == 0) + gbpsy->last_update = jiffies; + + gb_pm_runtime_put_autosuspend(connection->bundle); + return ret; +} + +static void gb_power_supply_status_update(struct gb_power_supply *gbpsy) +{ + /* check if there a change that need to be reported */ + gb_power_supply_status_get(gbpsy); + + if (!gbpsy->changed) + return; + + gbpsy->update_interval = update_interval_init; + __gb_power_supply_changed(gbpsy); + gbpsy->changed = false; +} + +static void gb_power_supply_work(struct work_struct *work) +{ + struct gb_power_supply *gbpsy = container_of(work, + struct gb_power_supply, + work.work); + + /* + * if the poll interval is not set, disable polling, this is helpful + * specially at unregister time. + */ + if (!gbpsy->update_interval) + return; + + gb_power_supply_status_update(gbpsy); + next_interval(gbpsy); + schedule_delayed_work(&gbpsy->work, gbpsy->update_interval); +} + +static int get_property(struct power_supply *b, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct gb_power_supply *gbpsy = to_gb_power_supply(b); + + gb_power_supply_status_get(gbpsy); + + return _gb_power_supply_property_get(gbpsy, psp, val); +} + +static int gb_power_supply_property_set(struct gb_power_supply *gbpsy, + enum power_supply_property psp, + int val) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct gb_power_supply_prop *prop; + struct gb_power_supply_set_property_request req; + int ret; + + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + return ret; + + prop = get_psy_prop(gbpsy, psp); + if (!prop) { + ret = -EINVAL; + goto out; + } + + req.psy_id = gbpsy->id; + req.property = prop->gb_prop; + req.prop_val = cpu_to_le32((s32)val); + + ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_SET_PROPERTY, + &req, sizeof(req), NULL, 0); + if (ret < 0) + goto out; + + /* cache immediately the new value */ + prop->val = val; + +out: + gb_pm_runtime_put_autosuspend(connection->bundle); + return ret; +} + +static int set_property(struct power_supply *b, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct gb_power_supply *gbpsy = to_gb_power_supply(b); + + return gb_power_supply_property_set(gbpsy, psp, val->intval); +} + +static int property_is_writeable(struct power_supply *b, + enum power_supply_property psp) +{ + struct gb_power_supply *gbpsy = to_gb_power_supply(b); + + return is_psy_prop_writeable(gbpsy, psp); +} + +static int gb_power_supply_register(struct gb_power_supply *gbpsy) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct power_supply_config cfg = {}; + + cfg.drv_data = gbpsy; + + gbpsy->desc.name = gbpsy->name; + gbpsy->desc.type = gbpsy->type; + gbpsy->desc.properties = gbpsy->props_raw; + gbpsy->desc.num_properties = total_props(gbpsy); + gbpsy->desc.get_property = get_property; + gbpsy->desc.set_property = set_property; + gbpsy->desc.property_is_writeable = property_is_writeable; + + gbpsy->psy = power_supply_register(&connection->bundle->dev, + &gbpsy->desc, &cfg); + return PTR_ERR_OR_ZERO(gbpsy->psy); +} + +static void _gb_power_supply_free(struct gb_power_supply *gbpsy) +{ + kfree(gbpsy->serial_number); + kfree(gbpsy->model_name); + kfree(gbpsy->manufacturer); + kfree(gbpsy->props_raw); + kfree(gbpsy->props); +} + +static void _gb_power_supply_release(struct gb_power_supply *gbpsy) +{ + gbpsy->update_interval = 0; + + cancel_delayed_work_sync(&gbpsy->work); + + if (gbpsy->registered) + power_supply_unregister(gbpsy->psy); + + _gb_power_supply_free(gbpsy); +} + +static void _gb_power_supplies_release(struct gb_power_supplies *supplies) +{ + int i; + + if (!supplies->supply) + return; + + mutex_lock(&supplies->supplies_lock); + for (i = 0; i < supplies->supplies_count; i++) + _gb_power_supply_release(&supplies->supply[i]); + kfree(supplies->supply); + mutex_unlock(&supplies->supplies_lock); + kfree(supplies); +} + +static int gb_power_supplies_get_count(struct gb_power_supplies *supplies) +{ + struct gb_power_supply_get_supplies_response resp; + int ret; + + ret = gb_operation_sync(supplies->connection, + GB_POWER_SUPPLY_TYPE_GET_SUPPLIES, + NULL, 0, &resp, sizeof(resp)); + if (ret < 0) + return ret; + + if (!resp.supplies_count) + return -EINVAL; + + supplies->supplies_count = resp.supplies_count; + + return ret; +} + +static int gb_power_supply_config(struct gb_power_supplies *supplies, int id) +{ + struct gb_power_supply *gbpsy = &supplies->supply[id]; + int ret; + + gbpsy->supplies = supplies; + gbpsy->id = id; + + ret = gb_power_supply_description_get(gbpsy); + if (ret < 0) + return ret; + + return gb_power_supply_prop_descriptors_get(gbpsy); +} + +static int gb_power_supply_enable(struct gb_power_supply *gbpsy) +{ + int ret; + + /* guarantee that we have an unique name, before register */ + ret = __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name, + sizeof(gbpsy->name)); + if (ret < 0) + return ret; + + mutex_init(&gbpsy->supply_lock); + + ret = gb_power_supply_register(gbpsy); + if (ret < 0) + return ret; + + gbpsy->update_interval = update_interval_init; + INIT_DELAYED_WORK(&gbpsy->work, gb_power_supply_work); + schedule_delayed_work(&gbpsy->work, 0); + + /* everything went fine, mark it for release code to know */ + gbpsy->registered = true; + + return 0; +} + +static int gb_power_supplies_setup(struct gb_power_supplies *supplies) +{ + struct gb_connection *connection = supplies->connection; + int ret; + int i; + + mutex_lock(&supplies->supplies_lock); + + ret = gb_power_supplies_get_count(supplies); + if (ret < 0) + goto out; + + supplies->supply = kzalloc(supplies->supplies_count * + sizeof(struct gb_power_supply), + GFP_KERNEL); + + if (!supplies->supply) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < supplies->supplies_count; i++) { + ret = gb_power_supply_config(supplies, i); + if (ret < 0) { + dev_err(&connection->bundle->dev, + "Fail to configure supplies devices\n"); + goto out; + } + } +out: + mutex_unlock(&supplies->supplies_lock); + return ret; +} + +static int gb_power_supplies_register(struct gb_power_supplies *supplies) +{ + struct gb_connection *connection = supplies->connection; + int ret = 0; + int i; + + mutex_lock(&supplies->supplies_lock); + + for (i = 0; i < supplies->supplies_count; i++) { + ret = gb_power_supply_enable(&supplies->supply[i]); + if (ret < 0) { + dev_err(&connection->bundle->dev, + "Fail to enable supplies devices\n"); + break; + } + } + + mutex_unlock(&supplies->supplies_lock); + return ret; +} + +static int gb_supplies_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_power_supplies *supplies = gb_connection_get_data(connection); + struct gb_power_supply *gbpsy; + struct gb_message *request; + struct gb_power_supply_event_request *payload; + u8 psy_id; + u8 event; + int ret = 0; + + if (op->type != GB_POWER_SUPPLY_TYPE_EVENT) { + dev_err(&connection->bundle->dev, + "Unsupported unsolicited event: %u\n", op->type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size < sizeof(*payload)) { + dev_err(&connection->bundle->dev, + "Wrong event size received (%zu < %zu)\n", + request->payload_size, sizeof(*payload)); + return -EINVAL; + } + + payload = request->payload; + psy_id = payload->psy_id; + mutex_lock(&supplies->supplies_lock); + if (psy_id >= supplies->supplies_count || + !supplies->supply[psy_id].registered) { + dev_err(&connection->bundle->dev, + "Event received for unconfigured power_supply id: %d\n", + psy_id); + ret = -EINVAL; + goto out_unlock; + } + + event = payload->event; + /* + * we will only handle events after setup is done and before release is + * running. For that just check update_interval. + */ + gbpsy = &supplies->supply[psy_id]; + if (!gbpsy->update_interval) { + ret = -ESHUTDOWN; + goto out_unlock; + } + + if (event & GB_POWER_SUPPLY_UPDATE) { + /* + * we need to make sure we invalidate cache, if not no new + * values for the properties will be fetch and the all propose + * of this event is missed + */ + gbpsy->cache_invalid = 1; + gb_power_supply_status_update(gbpsy); + } + +out_unlock: + mutex_unlock(&supplies->supplies_lock); + return ret; +} + +static int gb_power_supply_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_power_supplies *supplies; + int ret; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_POWER_SUPPLY) + return -ENODEV; + + supplies = kzalloc(sizeof(*supplies), GFP_KERNEL); + if (!supplies) + return -ENOMEM; + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_supplies_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto out; + } + + supplies->connection = connection; + gb_connection_set_data(connection, supplies); + + mutex_init(&supplies->supplies_lock); + + greybus_set_drvdata(bundle, supplies); + + /* We aren't ready to receive an incoming request yet */ + ret = gb_connection_enable_tx(connection); + if (ret) + goto error_connection_destroy; + + ret = gb_power_supplies_setup(supplies); + if (ret < 0) + goto error_connection_disable; + + /* We are ready to receive an incoming request now, enable RX as well */ + ret = gb_connection_enable(connection); + if (ret) + goto error_connection_disable; + + ret = gb_power_supplies_register(supplies); + if (ret < 0) + goto error_connection_disable; + + gb_pm_runtime_put_autosuspend(bundle); + return 0; + +error_connection_disable: + gb_connection_disable(connection); +error_connection_destroy: + gb_connection_destroy(connection); +out: + _gb_power_supplies_release(supplies); + return ret; +} + +static void gb_power_supply_disconnect(struct gb_bundle *bundle) +{ + struct gb_power_supplies *supplies = greybus_get_drvdata(bundle); + + gb_connection_disable(supplies->connection); + gb_connection_destroy(supplies->connection); + + _gb_power_supplies_release(supplies); +} + +static const struct greybus_bundle_id gb_power_supply_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_power_supply_id_table); + +static struct greybus_driver gb_power_supply_driver = { + .name = "power_supply", + .probe = gb_power_supply_probe, + .disconnect = gb_power_supply_disconnect, + .id_table = gb_power_supply_id_table, +}; +module_greybus_driver(gb_power_supply_driver); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c new file mode 100644 index 000000000000..c4bf3298ba07 --- /dev/null +++ b/drivers/staging/greybus/pwm.c @@ -0,0 +1,338 @@ +/* + * PWM Greybus driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include + +#include "greybus.h" +#include "gbphy.h" + +struct gb_pwm_chip { + struct gb_connection *connection; + u8 pwm_max; /* max pwm number */ + + struct pwm_chip chip; + struct pwm_chip *pwm; +}; +#define pwm_chip_to_gb_pwm_chip(chip) \ + container_of(chip, struct gb_pwm_chip, chip) + + +static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) +{ + struct gb_pwm_count_response response; + int ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + pwmc->pwm_max = response.count; + return 0; +} + +static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_activate_request request; + struct gbphy_device *gbphy_dev; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE, + &request, sizeof(request), NULL, 0); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; +} + +static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_deactivate_request request; + struct gbphy_device *gbphy_dev; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE, + &request, sizeof(request), NULL, 0); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; +} + +static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, + u8 which, u32 duty, u32 period) +{ + struct gb_pwm_config_request request; + struct gbphy_device *gbphy_dev; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + request.duty = cpu_to_le32(duty); + request.period = cpu_to_le32(period); + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, + &request, sizeof(request), NULL, 0); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; +} + +static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, + u8 which, u8 polarity) +{ + struct gb_pwm_polarity_request request; + struct gbphy_device *gbphy_dev; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + request.polarity = polarity; + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY, + &request, sizeof(request), NULL, 0); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; +} + +static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_enable_request request; + struct gbphy_device *gbphy_dev; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE, + &request, sizeof(request), NULL, 0); + if (ret) + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; +} + +static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_disable_request request; + struct gbphy_device *gbphy_dev; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE, + &request, sizeof(request), NULL, 0); + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; +} + +static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_activate_operation(pwmc, pwm->hwpwm); +}; + +static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + if (pwm_is_enabled(pwm)) + dev_warn(chip->dev, "freeing PWM device without disabling\n"); + + gb_pwm_deactivate_operation(pwmc, pwm->hwpwm); +} + +static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns); +}; + +static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, + enum pwm_polarity polarity) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity); +}; + +static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_enable_operation(pwmc, pwm->hwpwm); +}; + +static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + gb_pwm_disable_operation(pwmc, pwm->hwpwm); +}; + +static const struct pwm_ops gb_pwm_ops = { + .request = gb_pwm_request, + .free = gb_pwm_free, + .config = gb_pwm_config, + .set_polarity = gb_pwm_set_polarity, + .enable = gb_pwm_enable, + .disable = gb_pwm_disable, + .owner = THIS_MODULE, +}; + +static int gb_pwm_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) +{ + struct gb_connection *connection; + struct gb_pwm_chip *pwmc; + struct pwm_chip *pwm; + int ret; + + pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL); + if (!pwmc) + return -ENOMEM; + + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), + NULL); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_pwmc_free; + } + + pwmc->connection = connection; + gb_connection_set_data(connection, pwmc); + gb_gbphy_set_data(gbphy_dev, pwmc); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + /* Query number of pwms present */ + ret = gb_pwm_count_operation(pwmc); + if (ret) + goto exit_connection_disable; + + pwm = &pwmc->chip; + + pwm->dev = &gbphy_dev->dev; + pwm->ops = &gb_pwm_ops; + pwm->base = -1; /* Allocate base dynamically */ + pwm->npwm = pwmc->pwm_max + 1; + pwm->can_sleep = true; /* FIXME */ + + ret = pwmchip_add(pwm); + if (ret) { + dev_err(&gbphy_dev->dev, + "failed to register PWM: %d\n", ret); + goto exit_connection_disable; + } + + gbphy_runtime_put_autosuspend(gbphy_dev); + return 0; + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_pwmc_free: + kfree(pwmc); + return ret; +} + +static void gb_pwm_remove(struct gbphy_device *gbphy_dev) +{ + struct gb_pwm_chip *pwmc = gb_gbphy_get_data(gbphy_dev); + struct gb_connection *connection = pwmc->connection; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); + + pwmchip_remove(&pwmc->chip); + gb_connection_disable(connection); + gb_connection_destroy(connection); + kfree(pwmc); +} + +static const struct gbphy_device_id gb_pwm_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_PWM) }, + { }, +}; +MODULE_DEVICE_TABLE(gbphy, gb_pwm_id_table); + +static struct gbphy_driver pwm_driver = { + .name = "pwm", + .probe = gb_pwm_probe, + .remove = gb_pwm_remove, + .id_table = gb_pwm_id_table, +}; + +module_gbphy_driver(pwm_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c new file mode 100644 index 000000000000..729d25811568 --- /dev/null +++ b/drivers/staging/greybus/raw.c @@ -0,0 +1,381 @@ +/* + * Greybus driver for the Raw protocol + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + +struct gb_raw { + struct gb_connection *connection; + + struct list_head list; + int list_data; + struct mutex list_lock; + dev_t dev; + struct cdev cdev; + struct device *device; +}; + +struct raw_data { + struct list_head entry; + u32 len; + u8 data[0]; +}; + +static struct class *raw_class; +static int raw_major; +static const struct file_operations raw_fops; +static DEFINE_IDA(minors); + +/* Number of minor devices this driver supports */ +#define NUM_MINORS 256 + +/* Maximum size of any one send data buffer we support */ +#define MAX_PACKET_SIZE (PAGE_SIZE * 2) + +/* + * Maximum size of the data in the receive buffer we allow before we start to + * drop messages on the floor + */ +#define MAX_DATA_SIZE (MAX_PACKET_SIZE * 8) + +/* + * Add the raw data message to the list of received messages. + */ +static int receive_data(struct gb_raw *raw, u32 len, u8 *data) +{ + struct raw_data *raw_data; + struct device *dev = &raw->connection->bundle->dev; + int retval = 0; + + if (len > MAX_PACKET_SIZE) { + dev_err(dev, "Too big of a data packet, rejected\n"); + return -EINVAL; + } + + mutex_lock(&raw->list_lock); + if ((raw->list_data + len) > MAX_DATA_SIZE) { + dev_err(dev, "Too much data in receive buffer, now dropping packets\n"); + retval = -EINVAL; + goto exit; + } + + raw_data = kmalloc(sizeof(*raw_data) + len, GFP_KERNEL); + if (!raw_data) { + retval = -ENOMEM; + goto exit; + } + + raw->list_data += len; + raw_data->len = len; + memcpy(&raw_data->data[0], data, len); + + list_add_tail(&raw_data->entry, &raw->list); +exit: + mutex_unlock(&raw->list_lock); + return retval; +} + +static int gb_raw_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct device *dev = &connection->bundle->dev; + struct gb_raw *raw = greybus_get_drvdata(connection->bundle); + struct gb_raw_send_request *receive; + u32 len; + + if (op->type != GB_RAW_TYPE_SEND) { + dev_err(dev, "unknown request type 0x%02x\n", op->type); + return -EINVAL; + } + + /* Verify size of payload */ + if (op->request->payload_size < sizeof(*receive)) { + dev_err(dev, "raw receive request too small (%zu < %zu)\n", + op->request->payload_size, sizeof(*receive)); + return -EINVAL; + } + receive = op->request->payload; + len = le32_to_cpu(receive->len); + if (len != (int)(op->request->payload_size - sizeof(__le32))) { + dev_err(dev, "raw receive request wrong size %d vs %d\n", len, + (int)(op->request->payload_size - sizeof(__le32))); + return -EINVAL; + } + if (len == 0) { + dev_err(dev, "raw receive request of 0 bytes?\n"); + return -EINVAL; + } + + return receive_data(raw, len, receive->data); +} + +static int gb_raw_send(struct gb_raw *raw, u32 len, const char __user *data) +{ + struct gb_connection *connection = raw->connection; + struct gb_raw_send_request *request; + int retval; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + if (copy_from_user(&request->data[0], data, len)) { + kfree(request); + return -EFAULT; + } + + request->len = cpu_to_le32(len); + + retval = gb_operation_sync(connection, GB_RAW_TYPE_SEND, + request, len + sizeof(*request), + NULL, 0); + + kfree(request); + return retval; +} + +static int gb_raw_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_raw *raw; + int retval; + int minor; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_RAW) + return -ENODEV; + + raw = kzalloc(sizeof(*raw), GFP_KERNEL); + if (!raw) + return -ENOMEM; + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_raw_request_handler); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto error_free; + } + + INIT_LIST_HEAD(&raw->list); + mutex_init(&raw->list_lock); + + raw->connection = connection; + greybus_set_drvdata(bundle, raw); + + minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); + if (minor < 0) { + retval = minor; + goto error_connection_destroy; + } + + raw->dev = MKDEV(raw_major, minor); + cdev_init(&raw->cdev, &raw_fops); + + retval = gb_connection_enable(connection); + if (retval) + goto error_remove_ida; + + retval = cdev_add(&raw->cdev, raw->dev, 1); + if (retval) + goto error_connection_disable; + + raw->device = device_create(raw_class, &connection->bundle->dev, + raw->dev, raw, "gb!raw%d", minor); + if (IS_ERR(raw->device)) { + retval = PTR_ERR(raw->device); + goto error_del_cdev; + } + + return 0; + +error_del_cdev: + cdev_del(&raw->cdev); + +error_connection_disable: + gb_connection_disable(connection); + +error_remove_ida: + ida_simple_remove(&minors, minor); + +error_connection_destroy: + gb_connection_destroy(connection); + +error_free: + kfree(raw); + return retval; +} + +static void gb_raw_disconnect(struct gb_bundle *bundle) +{ + struct gb_raw *raw = greybus_get_drvdata(bundle); + struct gb_connection *connection = raw->connection; + struct raw_data *raw_data; + struct raw_data *temp; + + // FIXME - handle removing a connection when the char device node is open. + device_destroy(raw_class, raw->dev); + cdev_del(&raw->cdev); + gb_connection_disable(connection); + ida_simple_remove(&minors, MINOR(raw->dev)); + gb_connection_destroy(connection); + + mutex_lock(&raw->list_lock); + list_for_each_entry_safe(raw_data, temp, &raw->list, entry) { + list_del(&raw_data->entry); + kfree(raw_data); + } + mutex_unlock(&raw->list_lock); + + kfree(raw); +} + +/* + * Character device node interfaces. + * + * Note, we are using read/write to only allow a single read/write per message. + * This means for read(), you have to provide a big enough buffer for the full + * message to be copied into. If the buffer isn't big enough, the read() will + * fail with -ENOSPC. + */ + +static int raw_open(struct inode *inode, struct file *file) +{ + struct cdev *cdev = inode->i_cdev; + struct gb_raw *raw = container_of(cdev, struct gb_raw, cdev); + + file->private_data = raw; + return 0; +} + +static ssize_t raw_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct gb_raw *raw = file->private_data; + int retval; + + if (!count) + return 0; + + if (count > MAX_PACKET_SIZE) + return -E2BIG; + + retval = gb_raw_send(raw, count, buf); + if (retval) + return retval; + + return count; +} + +static ssize_t raw_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct gb_raw *raw = file->private_data; + int retval = 0; + struct raw_data *raw_data; + + mutex_lock(&raw->list_lock); + if (list_empty(&raw->list)) + goto exit; + + raw_data = list_first_entry(&raw->list, struct raw_data, entry); + if (raw_data->len > count) { + retval = -ENOSPC; + goto exit; + } + + if (copy_to_user(buf, &raw_data->data[0], raw_data->len)) { + retval = -EFAULT; + goto exit; + } + + list_del(&raw_data->entry); + raw->list_data -= raw_data->len; + retval = raw_data->len; + kfree(raw_data); + +exit: + mutex_unlock(&raw->list_lock); + return retval; +} + +static const struct file_operations raw_fops = { + .owner = THIS_MODULE, + .write = raw_write, + .read = raw_read, + .open = raw_open, + .llseek = noop_llseek, +}; + +static const struct greybus_bundle_id gb_raw_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_raw_id_table); + +static struct greybus_driver gb_raw_driver = { + .name = "raw", + .probe = gb_raw_probe, + .disconnect = gb_raw_disconnect, + .id_table = gb_raw_id_table, +}; + +static int raw_init(void) +{ + dev_t dev; + int retval; + + raw_class = class_create(THIS_MODULE, "gb_raw"); + if (IS_ERR(raw_class)) { + retval = PTR_ERR(raw_class); + goto error_class; + } + + retval = alloc_chrdev_region(&dev, 0, NUM_MINORS, "gb_raw"); + if (retval < 0) + goto error_chrdev; + + raw_major = MAJOR(dev); + + retval = greybus_register(&gb_raw_driver); + if (retval) + goto error_gb; + + return 0; + +error_gb: + unregister_chrdev_region(dev, NUM_MINORS); +error_chrdev: + class_destroy(raw_class); +error_class: + return retval; +} +module_init(raw_init); + +static void __exit raw_exit(void) +{ + greybus_deregister(&gb_raw_driver); + unregister_chrdev_region(MKDEV(raw_major, 0), NUM_MINORS); + class_destroy(raw_class); + ida_destroy(&minors); +} +module_exit(raw_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c new file mode 100644 index 000000000000..5649ef1e379d --- /dev/null +++ b/drivers/staging/greybus/sdio.c @@ -0,0 +1,884 @@ +/* + * SD/MMC Greybus driver. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "gbphy.h" + +struct gb_sdio_host { + struct gb_connection *connection; + struct gbphy_device *gbphy_dev; + struct mmc_host *mmc; + struct mmc_request *mrq; + struct mutex lock; /* lock for this host */ + size_t data_max; + spinlock_t xfer; /* lock to cancel ongoing transfer */ + bool xfer_stop; + struct workqueue_struct *mrq_workqueue; + struct work_struct mrqwork; + u8 queued_events; + bool removed; + bool card_present; + bool read_only; +}; + + +#define GB_SDIO_RSP_R1_R5_R6_R7 (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ + GB_SDIO_RSP_OPCODE) +#define GB_SDIO_RSP_R3_R4 (GB_SDIO_RSP_PRESENT) +#define GB_SDIO_RSP_R2 (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ + GB_SDIO_RSP_136) +#define GB_SDIO_RSP_R1B (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ + GB_SDIO_RSP_OPCODE | GB_SDIO_RSP_BUSY) + +/* kernel vdd starts at 0x80 and we need to translate to greybus ones 0x01 */ +#define GB_SDIO_VDD_SHIFT 8 + +#ifndef MMC_CAP2_CORE_RUNTIME_PM +#define MMC_CAP2_CORE_RUNTIME_PM 0 +#endif + +static inline bool single_op(struct mmc_command *cmd) +{ + uint32_t opcode = cmd->opcode; + + return opcode == MMC_WRITE_BLOCK || + opcode == MMC_READ_SINGLE_BLOCK; +} + +static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) +{ + u32 caps = 0; + u32 caps2 = 0; + + caps = ((r & GB_SDIO_CAP_NONREMOVABLE) ? MMC_CAP_NONREMOVABLE : 0) | + ((r & GB_SDIO_CAP_4_BIT_DATA) ? MMC_CAP_4_BIT_DATA : 0) | + ((r & GB_SDIO_CAP_8_BIT_DATA) ? MMC_CAP_8_BIT_DATA : 0) | + ((r & GB_SDIO_CAP_MMC_HS) ? MMC_CAP_MMC_HIGHSPEED : 0) | + ((r & GB_SDIO_CAP_SD_HS) ? MMC_CAP_SD_HIGHSPEED : 0) | + ((r & GB_SDIO_CAP_ERASE) ? MMC_CAP_ERASE : 0) | + ((r & GB_SDIO_CAP_1_2V_DDR) ? MMC_CAP_1_2V_DDR : 0) | + ((r & GB_SDIO_CAP_1_8V_DDR) ? MMC_CAP_1_8V_DDR : 0) | + ((r & GB_SDIO_CAP_POWER_OFF_CARD) ? MMC_CAP_POWER_OFF_CARD : 0) | + ((r & GB_SDIO_CAP_UHS_SDR12) ? MMC_CAP_UHS_SDR12 : 0) | + ((r & GB_SDIO_CAP_UHS_SDR25) ? MMC_CAP_UHS_SDR25 : 0) | + ((r & GB_SDIO_CAP_UHS_SDR50) ? MMC_CAP_UHS_SDR50 : 0) | + ((r & GB_SDIO_CAP_UHS_SDR104) ? MMC_CAP_UHS_SDR104 : 0) | + ((r & GB_SDIO_CAP_UHS_DDR50) ? MMC_CAP_UHS_DDR50 : 0) | + ((r & GB_SDIO_CAP_DRIVER_TYPE_A) ? MMC_CAP_DRIVER_TYPE_A : 0) | + ((r & GB_SDIO_CAP_DRIVER_TYPE_C) ? MMC_CAP_DRIVER_TYPE_C : 0) | + ((r & GB_SDIO_CAP_DRIVER_TYPE_D) ? MMC_CAP_DRIVER_TYPE_D : 0); + + caps2 = ((r & GB_SDIO_CAP_HS200_1_2V) ? MMC_CAP2_HS200_1_2V_SDR : 0) | + ((r & GB_SDIO_CAP_HS400_1_2V) ? MMC_CAP2_HS400_1_2V : 0) | + ((r & GB_SDIO_CAP_HS400_1_8V) ? MMC_CAP2_HS400_1_8V : 0) | + ((r & GB_SDIO_CAP_HS200_1_8V) ? MMC_CAP2_HS200_1_8V_SDR : 0); + + host->mmc->caps = caps; + host->mmc->caps2 = caps2 | MMC_CAP2_CORE_RUNTIME_PM; + + if (caps & MMC_CAP_NONREMOVABLE) + host->card_present = true; +} + +static u32 _gb_sdio_get_host_ocr(u32 ocr) +{ + return (((ocr & GB_SDIO_VDD_165_195) ? MMC_VDD_165_195 : 0) | + ((ocr & GB_SDIO_VDD_20_21) ? MMC_VDD_20_21 : 0) | + ((ocr & GB_SDIO_VDD_21_22) ? MMC_VDD_21_22 : 0) | + ((ocr & GB_SDIO_VDD_22_23) ? MMC_VDD_22_23 : 0) | + ((ocr & GB_SDIO_VDD_23_24) ? MMC_VDD_23_24 : 0) | + ((ocr & GB_SDIO_VDD_24_25) ? MMC_VDD_24_25 : 0) | + ((ocr & GB_SDIO_VDD_25_26) ? MMC_VDD_25_26 : 0) | + ((ocr & GB_SDIO_VDD_26_27) ? MMC_VDD_26_27 : 0) | + ((ocr & GB_SDIO_VDD_27_28) ? MMC_VDD_27_28 : 0) | + ((ocr & GB_SDIO_VDD_28_29) ? MMC_VDD_28_29 : 0) | + ((ocr & GB_SDIO_VDD_29_30) ? MMC_VDD_29_30 : 0) | + ((ocr & GB_SDIO_VDD_30_31) ? MMC_VDD_30_31 : 0) | + ((ocr & GB_SDIO_VDD_31_32) ? MMC_VDD_31_32 : 0) | + ((ocr & GB_SDIO_VDD_32_33) ? MMC_VDD_32_33 : 0) | + ((ocr & GB_SDIO_VDD_33_34) ? MMC_VDD_33_34 : 0) | + ((ocr & GB_SDIO_VDD_34_35) ? MMC_VDD_34_35 : 0) | + ((ocr & GB_SDIO_VDD_35_36) ? MMC_VDD_35_36 : 0) + ); +} + +static int gb_sdio_get_caps(struct gb_sdio_host *host) +{ + struct gb_sdio_get_caps_response response; + struct mmc_host *mmc = host->mmc; + u16 data_max; + u32 blksz; + u32 ocr; + u32 r; + int ret; + + ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_GET_CAPABILITIES, + NULL, 0, &response, sizeof(response)); + if (ret < 0) + return ret; + r = le32_to_cpu(response.caps); + + _gb_sdio_set_host_caps(host, r); + + /* get the max block size that could fit our payload */ + data_max = gb_operation_get_payload_size_max(host->connection); + data_max = min(data_max - sizeof(struct gb_sdio_transfer_request), + data_max - sizeof(struct gb_sdio_transfer_response)); + + blksz = min_t(u16, le16_to_cpu(response.max_blk_size), data_max); + blksz = max_t(u32, 512, blksz); + + mmc->max_blk_size = rounddown_pow_of_two(blksz); + mmc->max_blk_count = le16_to_cpu(response.max_blk_count); + host->data_max = data_max; + + /* get ocr supported values */ + ocr = _gb_sdio_get_host_ocr(le32_to_cpu(response.ocr)); + mmc->ocr_avail = ocr; + mmc->ocr_avail_sdio = mmc->ocr_avail; + mmc->ocr_avail_sd = mmc->ocr_avail; + mmc->ocr_avail_mmc = mmc->ocr_avail; + + /* get frequency range values */ + mmc->f_min = le32_to_cpu(response.f_min); + mmc->f_max = le32_to_cpu(response.f_max); + + return 0; +} + +static void _gb_queue_event(struct gb_sdio_host *host, u8 event) +{ + if (event & GB_SDIO_CARD_INSERTED) + host->queued_events &= ~GB_SDIO_CARD_REMOVED; + else if (event & GB_SDIO_CARD_REMOVED) + host->queued_events &= ~GB_SDIO_CARD_INSERTED; + + host->queued_events |= event; +} + +static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event) +{ + u8 state_changed = 0; + + if (event & GB_SDIO_CARD_INSERTED) { + if (host->mmc->caps & MMC_CAP_NONREMOVABLE) + return 0; + if (host->card_present) + return 0; + host->card_present = true; + state_changed = 1; + } + + if (event & GB_SDIO_CARD_REMOVED) { + if (host->mmc->caps & MMC_CAP_NONREMOVABLE) + return 0; + if (!(host->card_present)) + return 0; + host->card_present = false; + state_changed = 1; + } + + if (event & GB_SDIO_WP) { + host->read_only = true; + } + + if (state_changed) { + dev_info(mmc_dev(host->mmc), "card %s now event\n", + (host->card_present ? "inserted" : "removed")); + mmc_detect_change(host->mmc, 0); + } + + return 0; +} + +static int gb_sdio_request_handler(struct gb_operation *op) +{ + struct gb_sdio_host *host = gb_connection_get_data(op->connection); + struct gb_message *request; + struct gb_sdio_event_request *payload; + u8 type = op->type; + int ret = 0; + u8 event; + + if (type != GB_SDIO_TYPE_EVENT) { + dev_err(mmc_dev(host->mmc), + "unsupported unsolicited event: %u\n", type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size < sizeof(*payload)) { + dev_err(mmc_dev(host->mmc), "wrong event size received (%zu < %zu)\n", + request->payload_size, sizeof(*payload)); + return -EINVAL; + } + + payload = request->payload; + event = payload->event; + + if (host->removed) + _gb_queue_event(host, event); + else + ret = _gb_sdio_process_events(host, event); + + return ret; +} + +static int gb_sdio_set_ios(struct gb_sdio_host *host, + struct gb_sdio_set_ios_request *request) +{ + int ret; + + ret = gbphy_runtime_get_sync(host->gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_SET_IOS, request, + sizeof(*request), NULL, 0); + + gbphy_runtime_put_autosuspend(host->gbphy_dev); + + return ret; +} + +static int _gb_sdio_send(struct gb_sdio_host *host, struct mmc_data *data, + size_t len, u16 nblocks, off_t skip) +{ + struct gb_sdio_transfer_request *request; + struct gb_sdio_transfer_response *response; + struct gb_operation *operation; + struct scatterlist *sg = data->sg; + unsigned int sg_len = data->sg_len; + size_t copied; + u16 send_blksz; + u16 send_blocks; + int ret; + + WARN_ON(len > host->data_max); + + operation = gb_operation_create(host->connection, GB_SDIO_TYPE_TRANSFER, + len + sizeof(*request), + sizeof(*response), GFP_KERNEL); + if (!operation) + return -ENOMEM; + + request = operation->request->payload; + request->data_flags = (data->flags >> 8); + request->data_blocks = cpu_to_le16(nblocks); + request->data_blksz = cpu_to_le16(data->blksz); + + copied = sg_pcopy_to_buffer(sg, sg_len, &request->data[0], len, skip); + + if (copied != len) { + ret = -EINVAL; + goto err_put_operation; + } + + ret = gb_operation_request_send_sync(operation); + if (ret < 0) + goto err_put_operation; + + response = operation->response->payload; + + send_blocks = le16_to_cpu(response->data_blocks); + send_blksz = le16_to_cpu(response->data_blksz); + + if (len != send_blksz * send_blocks) { + dev_err(mmc_dev(host->mmc), "send: size received: %zu != %d\n", + len, send_blksz * send_blocks); + ret = -EINVAL; + } + +err_put_operation: + gb_operation_put(operation); + + return ret; +} + +static int _gb_sdio_recv(struct gb_sdio_host *host, struct mmc_data *data, + size_t len, u16 nblocks, off_t skip) +{ + struct gb_sdio_transfer_request *request; + struct gb_sdio_transfer_response *response; + struct gb_operation *operation; + struct scatterlist *sg = data->sg; + unsigned int sg_len = data->sg_len; + size_t copied; + u16 recv_blksz; + u16 recv_blocks; + int ret; + + WARN_ON(len > host->data_max); + + operation = gb_operation_create(host->connection, GB_SDIO_TYPE_TRANSFER, + sizeof(*request), + len + sizeof(*response), GFP_KERNEL); + if (!operation) + return -ENOMEM; + + request = operation->request->payload; + request->data_flags = (data->flags >> 8); + request->data_blocks = cpu_to_le16(nblocks); + request->data_blksz = cpu_to_le16(data->blksz); + + ret = gb_operation_request_send_sync(operation); + if (ret < 0) + goto err_put_operation; + + response = operation->response->payload; + recv_blocks = le16_to_cpu(response->data_blocks); + recv_blksz = le16_to_cpu(response->data_blksz); + + if (len != recv_blksz * recv_blocks) { + dev_err(mmc_dev(host->mmc), "recv: size received: %d != %zu\n", + recv_blksz * recv_blocks, len); + ret = -EINVAL; + goto err_put_operation; + } + + copied = sg_pcopy_from_buffer(sg, sg_len, &response->data[0], len, + skip); + if (copied != len) + ret = -EINVAL; + +err_put_operation: + gb_operation_put(operation); + + return ret; +} + +static int gb_sdio_transfer(struct gb_sdio_host *host, struct mmc_data *data) +{ + size_t left, len; + off_t skip = 0; + int ret = 0; + u16 nblocks; + + if (single_op(data->mrq->cmd) && data->blocks > 1) { + ret = -ETIMEDOUT; + goto out; + } + + left = data->blksz * data->blocks; + + while (left) { + /* check is a stop transmission is pending */ + spin_lock(&host->xfer); + if (host->xfer_stop) { + host->xfer_stop = false; + spin_unlock(&host->xfer); + ret = -EINTR; + goto out; + } + spin_unlock(&host->xfer); + len = min(left, host->data_max); + nblocks = len / data->blksz; + len = nblocks * data->blksz; + + if (data->flags & MMC_DATA_READ) { + ret = _gb_sdio_recv(host, data, len, nblocks, skip); + if (ret < 0) + goto out; + } else { + ret = _gb_sdio_send(host, data, len, nblocks, skip); + if (ret < 0) + goto out; + } + data->bytes_xfered += len; + left -= len; + skip += len; + } + +out: + data->error = ret; + return ret; +} + +static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) +{ + struct gb_sdio_command_request request = {0}; + struct gb_sdio_command_response response; + struct mmc_data *data = host->mrq->data; + u8 cmd_flags; + u8 cmd_type; + int i; + int ret; + + switch (mmc_resp_type(cmd)) { + case MMC_RSP_NONE: + cmd_flags = GB_SDIO_RSP_NONE; + break; + case MMC_RSP_R1: + cmd_flags = GB_SDIO_RSP_R1_R5_R6_R7; + break; + case MMC_RSP_R1B: + cmd_flags = GB_SDIO_RSP_R1B; + break; + case MMC_RSP_R2: + cmd_flags = GB_SDIO_RSP_R2; + break; + case MMC_RSP_R3: + cmd_flags = GB_SDIO_RSP_R3_R4; + break; + default: + dev_err(mmc_dev(host->mmc), "cmd flag invalid 0x%04x\n", + mmc_resp_type(cmd)); + ret = -EINVAL; + goto out; + } + + switch (mmc_cmd_type(cmd)) { + case MMC_CMD_BC: + cmd_type = GB_SDIO_CMD_BC; + break; + case MMC_CMD_BCR: + cmd_type = GB_SDIO_CMD_BCR; + break; + case MMC_CMD_AC: + cmd_type = GB_SDIO_CMD_AC; + break; + case MMC_CMD_ADTC: + cmd_type = GB_SDIO_CMD_ADTC; + break; + default: + dev_err(mmc_dev(host->mmc), "cmd type invalid 0x%04x\n", + mmc_cmd_type(cmd)); + ret = -EINVAL; + goto out; + } + + request.cmd = cmd->opcode; + request.cmd_flags = cmd_flags; + request.cmd_type = cmd_type; + request.cmd_arg = cpu_to_le32(cmd->arg); + /* some controllers need to know at command time data details */ + if (data) { + request.data_blocks = cpu_to_le16(data->blocks); + request.data_blksz = cpu_to_le16(data->blksz); + } + + ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_COMMAND, + &request, sizeof(request), &response, + sizeof(response)); + if (ret < 0) + goto out; + + /* no response expected */ + if (cmd_flags == GB_SDIO_RSP_NONE) + goto out; + + /* long response expected */ + if (cmd_flags & GB_SDIO_RSP_R2) + for (i = 0; i < 4; i++) + cmd->resp[i] = le32_to_cpu(response.resp[i]); + else + cmd->resp[0] = le32_to_cpu(response.resp[0]); + +out: + cmd->error = ret; + return ret; +} + +static void gb_sdio_mrq_work(struct work_struct *work) +{ + struct gb_sdio_host *host; + struct mmc_request *mrq; + int ret; + + host = container_of(work, struct gb_sdio_host, mrqwork); + + ret = gbphy_runtime_get_sync(host->gbphy_dev); + if (ret) + return; + + mutex_lock(&host->lock); + mrq = host->mrq; + if (!mrq) { + mutex_unlock(&host->lock); + gbphy_runtime_put_autosuspend(host->gbphy_dev); + dev_err(mmc_dev(host->mmc), "mmc request is NULL"); + return; + } + + if (host->removed) { + mrq->cmd->error = -ESHUTDOWN; + goto done; + } + + if (mrq->sbc) { + ret = gb_sdio_command(host, mrq->sbc); + if (ret < 0) + goto done; + } + + ret = gb_sdio_command(host, mrq->cmd); + if (ret < 0) + goto done; + + if (mrq->data) { + ret = gb_sdio_transfer(host, mrq->data); + if (ret < 0) + goto done; + } + + if (mrq->stop) { + ret = gb_sdio_command(host, mrq->stop); + if (ret < 0) + goto done; + } + +done: + host->mrq = NULL; + mutex_unlock(&host->lock); + mmc_request_done(host->mmc, mrq); + gbphy_runtime_put_autosuspend(host->gbphy_dev); +} + +static void gb_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct gb_sdio_host *host = mmc_priv(mmc); + struct mmc_command *cmd = mrq->cmd; + + /* Check if it is a cancel to ongoing transfer */ + if (cmd->opcode == MMC_STOP_TRANSMISSION) { + spin_lock(&host->xfer); + host->xfer_stop = true; + spin_unlock(&host->xfer); + } + + mutex_lock(&host->lock); + + WARN_ON(host->mrq); + host->mrq = mrq; + + if (host->removed) { + mrq->cmd->error = -ESHUTDOWN; + goto out; + } + if (!host->card_present) { + mrq->cmd->error = -ENOMEDIUM; + goto out; + } + + queue_work(host->mrq_workqueue, &host->mrqwork); + + mutex_unlock(&host->lock); + return; + +out: + host->mrq = NULL; + mutex_unlock(&host->lock); + mmc_request_done(mmc, mrq); +} + +static void gb_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct gb_sdio_host *host = mmc_priv(mmc); + struct gb_sdio_set_ios_request request; + int ret; + u8 power_mode; + u8 bus_width; + u8 timing; + u8 signal_voltage; + u8 drv_type; + u32 vdd = 0; + + mutex_lock(&host->lock); + request.clock = cpu_to_le32(ios->clock); + + if (ios->vdd) + vdd = 1 << (ios->vdd - GB_SDIO_VDD_SHIFT); + request.vdd = cpu_to_le32(vdd); + + request.bus_mode = (ios->bus_mode == MMC_BUSMODE_OPENDRAIN ? + GB_SDIO_BUSMODE_OPENDRAIN : + GB_SDIO_BUSMODE_PUSHPULL); + + switch (ios->power_mode) { + case MMC_POWER_OFF: + default: + power_mode = GB_SDIO_POWER_OFF; + break; + case MMC_POWER_UP: + power_mode = GB_SDIO_POWER_UP; + break; + case MMC_POWER_ON: + power_mode = GB_SDIO_POWER_ON; + break; + case MMC_POWER_UNDEFINED: + power_mode = GB_SDIO_POWER_UNDEFINED; + break; + } + request.power_mode = power_mode; + + switch (ios->bus_width) { + case MMC_BUS_WIDTH_1: + bus_width = GB_SDIO_BUS_WIDTH_1; + break; + case MMC_BUS_WIDTH_4: + default: + bus_width = GB_SDIO_BUS_WIDTH_4; + break; + case MMC_BUS_WIDTH_8: + bus_width = GB_SDIO_BUS_WIDTH_8; + break; + } + request.bus_width = bus_width; + + switch (ios->timing) { + case MMC_TIMING_LEGACY: + default: + timing = GB_SDIO_TIMING_LEGACY; + break; + case MMC_TIMING_MMC_HS: + timing = GB_SDIO_TIMING_MMC_HS; + break; + case MMC_TIMING_SD_HS: + timing = GB_SDIO_TIMING_SD_HS; + break; + case MMC_TIMING_UHS_SDR12: + timing = GB_SDIO_TIMING_UHS_SDR12; + break; + case MMC_TIMING_UHS_SDR25: + timing = GB_SDIO_TIMING_UHS_SDR25; + break; + case MMC_TIMING_UHS_SDR50: + timing = GB_SDIO_TIMING_UHS_SDR50; + break; + case MMC_TIMING_UHS_SDR104: + timing = GB_SDIO_TIMING_UHS_SDR104; + break; + case MMC_TIMING_UHS_DDR50: + timing = GB_SDIO_TIMING_UHS_DDR50; + break; + case MMC_TIMING_MMC_DDR52: + timing = GB_SDIO_TIMING_MMC_DDR52; + break; + case MMC_TIMING_MMC_HS200: + timing = GB_SDIO_TIMING_MMC_HS200; + break; + case MMC_TIMING_MMC_HS400: + timing = GB_SDIO_TIMING_MMC_HS400; + break; + } + request.timing = timing; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: + signal_voltage = GB_SDIO_SIGNAL_VOLTAGE_330; + break; + case MMC_SIGNAL_VOLTAGE_180: + default: + signal_voltage = GB_SDIO_SIGNAL_VOLTAGE_180; + break; + case MMC_SIGNAL_VOLTAGE_120: + signal_voltage = GB_SDIO_SIGNAL_VOLTAGE_120; + break; + } + request.signal_voltage = signal_voltage; + + switch (ios->drv_type) { + case MMC_SET_DRIVER_TYPE_A: + drv_type = GB_SDIO_SET_DRIVER_TYPE_A; + break; + case MMC_SET_DRIVER_TYPE_C: + drv_type = GB_SDIO_SET_DRIVER_TYPE_C; + break; + case MMC_SET_DRIVER_TYPE_D: + drv_type = GB_SDIO_SET_DRIVER_TYPE_D; + break; + case MMC_SET_DRIVER_TYPE_B: + default: + drv_type = GB_SDIO_SET_DRIVER_TYPE_B; + break; + } + request.drv_type = drv_type; + + ret = gb_sdio_set_ios(host, &request); + if (ret < 0) + goto out; + + memcpy(&mmc->ios, ios, sizeof(mmc->ios)); + +out: + mutex_unlock(&host->lock); +} + +static int gb_mmc_get_ro(struct mmc_host *mmc) +{ + struct gb_sdio_host *host = mmc_priv(mmc); + + mutex_lock(&host->lock); + if (host->removed) { + mutex_unlock(&host->lock); + return -ESHUTDOWN; + } + mutex_unlock(&host->lock); + + return host->read_only; +} + +static int gb_mmc_get_cd(struct mmc_host *mmc) +{ + struct gb_sdio_host *host = mmc_priv(mmc); + + mutex_lock(&host->lock); + if (host->removed) { + mutex_unlock(&host->lock); + return -ESHUTDOWN; + } + mutex_unlock(&host->lock); + + return host->card_present; +} + +static int gb_mmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) +{ + return 0; +} + +static const struct mmc_host_ops gb_sdio_ops = { + .request = gb_mmc_request, + .set_ios = gb_mmc_set_ios, + .get_ro = gb_mmc_get_ro, + .get_cd = gb_mmc_get_cd, + .start_signal_voltage_switch = gb_mmc_switch_voltage, +}; + +static int gb_sdio_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) +{ + struct gb_connection *connection; + struct mmc_host *mmc; + struct gb_sdio_host *host; + int ret = 0; + + mmc = mmc_alloc_host(sizeof(*host), &gbphy_dev->dev); + if (!mmc) + return -ENOMEM; + + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), + gb_sdio_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_mmc_free; + } + + host = mmc_priv(mmc); + host->mmc = mmc; + host->removed = true; + + host->connection = connection; + gb_connection_set_data(connection, host); + host->gbphy_dev = gbphy_dev; + gb_gbphy_set_data(gbphy_dev, host); + + ret = gb_connection_enable_tx(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_sdio_get_caps(host); + if (ret < 0) + goto exit_connection_disable; + + mmc->ops = &gb_sdio_ops; + + mmc->max_segs = host->mmc->max_blk_count; + + /* for now we make a map 1:1 between max request and segment size */ + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_req_size; + + mutex_init(&host->lock); + spin_lock_init(&host->xfer); + host->mrq_workqueue = alloc_workqueue("mmc-%s", 0, 1, + dev_name(&gbphy_dev->dev)); + if (!host->mrq_workqueue) { + ret = -ENOMEM; + goto exit_connection_disable; + } + INIT_WORK(&host->mrqwork, gb_sdio_mrq_work); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_wq_destroy; + + ret = mmc_add_host(mmc); + if (ret < 0) + goto exit_wq_destroy; + host->removed = false; + ret = _gb_sdio_process_events(host, host->queued_events); + host->queued_events = 0; + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; + +exit_wq_destroy: + destroy_workqueue(host->mrq_workqueue); +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_mmc_free: + mmc_free_host(mmc); + + return ret; +} + +static void gb_sdio_remove(struct gbphy_device *gbphy_dev) +{ + struct gb_sdio_host *host = gb_gbphy_get_data(gbphy_dev); + struct gb_connection *connection = host->connection; + struct mmc_host *mmc; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); + + mutex_lock(&host->lock); + host->removed = true; + mmc = host->mmc; + gb_connection_set_data(connection, NULL); + mutex_unlock(&host->lock); + + flush_workqueue(host->mrq_workqueue); + destroy_workqueue(host->mrq_workqueue); + gb_connection_disable_rx(connection); + mmc_remove_host(mmc); + gb_connection_disable(connection); + gb_connection_destroy(connection); + mmc_free_host(mmc); +} + +static const struct gbphy_device_id gb_sdio_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_SDIO) }, + { }, +}; +MODULE_DEVICE_TABLE(gbphy, gb_sdio_id_table); + +static struct gbphy_driver sdio_driver = { + .name = "sdio", + .probe = gb_sdio_probe, + .remove = gb_sdio_remove, + .id_table = gb_sdio_id_table, +}; + +module_gbphy_driver(sdio_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c new file mode 100644 index 000000000000..c893552b5c0b --- /dev/null +++ b/drivers/staging/greybus/spi.c @@ -0,0 +1,79 @@ +/* + * SPI bridge PHY driver. + * + * Copyright 2014-2016 Google Inc. + * Copyright 2014-2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include + +#include "greybus.h" +#include "gbphy.h" +#include "spilib.h" + +static struct spilib_ops *spilib_ops; + +static int gb_spi_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) +{ + struct gb_connection *connection; + int ret; + + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), + NULL); + if (IS_ERR(connection)) + return PTR_ERR(connection); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_spilib_master_init(connection, &gbphy_dev->dev, spilib_ops); + if (ret) + goto exit_connection_disable; + + gb_gbphy_set_data(gbphy_dev, connection); + + gbphy_runtime_put_autosuspend(gbphy_dev); + return 0; + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); + + return ret; +} + +static void gb_spi_remove(struct gbphy_device *gbphy_dev) +{ + struct gb_connection *connection = gb_gbphy_get_data(gbphy_dev); + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); + + gb_spilib_master_exit(connection); + gb_connection_disable(connection); + gb_connection_destroy(connection); +} + +static const struct gbphy_device_id gb_spi_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, + { }, +}; +MODULE_DEVICE_TABLE(gbphy, gb_spi_id_table); + +static struct gbphy_driver spi_driver = { + .name = "spi", + .probe = gb_spi_probe, + .remove = gb_spi_remove, + .id_table = gb_spi_id_table, +}; + +module_gbphy_driver(spi_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c new file mode 100644 index 000000000000..e97b19148497 --- /dev/null +++ b/drivers/staging/greybus/spilib.c @@ -0,0 +1,565 @@ +/* + * Greybus SPI library + * + * Copyright 2014-2016 Google Inc. + * Copyright 2014-2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "spilib.h" + +struct gb_spilib { + struct gb_connection *connection; + struct device *parent; + struct spi_transfer *first_xfer; + struct spi_transfer *last_xfer; + struct spilib_ops *ops; + u32 rx_xfer_offset; + u32 tx_xfer_offset; + u32 last_xfer_size; + unsigned int op_timeout; + u16 mode; + u16 flags; + u32 bits_per_word_mask; + u8 num_chipselect; + u32 min_speed_hz; + u32 max_speed_hz; +}; + +#define GB_SPI_STATE_MSG_DONE ((void *)0) +#define GB_SPI_STATE_MSG_IDLE ((void *)1) +#define GB_SPI_STATE_MSG_RUNNING ((void *)2) +#define GB_SPI_STATE_OP_READY ((void *)3) +#define GB_SPI_STATE_OP_DONE ((void *)4) +#define GB_SPI_STATE_MSG_ERROR ((void *)-1) + +#define XFER_TIMEOUT_TOLERANCE 200 + +static struct spi_master *get_master_from_spi(struct gb_spilib *spi) +{ + return gb_connection_get_data(spi->connection); +} + +static int tx_header_fit_operation(u32 tx_size, u32 count, size_t data_max) +{ + size_t headers_size; + + data_max -= sizeof(struct gb_spi_transfer_request); + headers_size = (count + 1) * sizeof(struct gb_spi_transfer); + + return tx_size + headers_size > data_max ? 0 : 1; +} + +static size_t calc_rx_xfer_size(u32 rx_size, u32 *tx_xfer_size, u32 len, + size_t data_max) +{ + size_t rx_xfer_size; + + data_max -= sizeof(struct gb_spi_transfer_response); + + if (rx_size + len > data_max) + rx_xfer_size = data_max - rx_size; + else + rx_xfer_size = len; + + /* if this is a write_read, for symmetry read the same as write */ + if (*tx_xfer_size && rx_xfer_size > *tx_xfer_size) + rx_xfer_size = *tx_xfer_size; + if (*tx_xfer_size && rx_xfer_size < *tx_xfer_size) + *tx_xfer_size = rx_xfer_size; + + return rx_xfer_size; +} + +static size_t calc_tx_xfer_size(u32 tx_size, u32 count, size_t len, + size_t data_max) +{ + size_t headers_size; + + data_max -= sizeof(struct gb_spi_transfer_request); + headers_size = (count + 1) * sizeof(struct gb_spi_transfer); + + if (tx_size + headers_size + len > data_max) + return data_max - (tx_size + sizeof(struct gb_spi_transfer)); + + return len; +} + +static void clean_xfer_state(struct gb_spilib *spi) +{ + spi->first_xfer = NULL; + spi->last_xfer = NULL; + spi->rx_xfer_offset = 0; + spi->tx_xfer_offset = 0; + spi->last_xfer_size = 0; + spi->op_timeout = 0; +} + +static bool is_last_xfer_done(struct gb_spilib *spi) +{ + struct spi_transfer *last_xfer = spi->last_xfer; + + if ((spi->tx_xfer_offset + spi->last_xfer_size == last_xfer->len) || + (spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) + return true; + + return false; +} + +static int setup_next_xfer(struct gb_spilib *spi, struct spi_message *msg) +{ + struct spi_transfer *last_xfer = spi->last_xfer; + + if (msg->state != GB_SPI_STATE_OP_DONE) + return 0; + + /* + * if we transferred all content of the last transfer, reset values and + * check if this was the last transfer in the message + */ + if (is_last_xfer_done(spi)) { + spi->tx_xfer_offset = 0; + spi->rx_xfer_offset = 0; + spi->op_timeout = 0; + if (last_xfer == list_last_entry(&msg->transfers, + struct spi_transfer, + transfer_list)) + msg->state = GB_SPI_STATE_MSG_DONE; + else + spi->first_xfer = list_next_entry(last_xfer, + transfer_list); + return 0; + } + + spi->first_xfer = last_xfer; + if (last_xfer->tx_buf) + spi->tx_xfer_offset += spi->last_xfer_size; + + if (last_xfer->rx_buf) + spi->rx_xfer_offset += spi->last_xfer_size; + + return 0; +} + +static struct spi_transfer *get_next_xfer(struct spi_transfer *xfer, + struct spi_message *msg) +{ + if (xfer == list_last_entry(&msg->transfers, struct spi_transfer, + transfer_list)) + return NULL; + + return list_next_entry(xfer, transfer_list); +} + +/* Routines to transfer data */ +static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi, + struct gb_connection *connection, struct spi_message *msg) +{ + struct gb_spi_transfer_request *request; + struct spi_device *dev = msg->spi; + struct spi_transfer *xfer; + struct gb_spi_transfer *gb_xfer; + struct gb_operation *operation; + u32 tx_size = 0, rx_size = 0, count = 0, xfer_len = 0, request_size; + u32 tx_xfer_size = 0, rx_xfer_size = 0, len; + u32 total_len = 0; + unsigned int xfer_timeout; + size_t data_max; + void *tx_data; + + data_max = gb_operation_get_payload_size_max(connection); + xfer = spi->first_xfer; + + /* Find number of transfers queued and tx/rx length in the message */ + + while (msg->state != GB_SPI_STATE_OP_READY) { + msg->state = GB_SPI_STATE_MSG_RUNNING; + spi->last_xfer = xfer; + + if (!xfer->tx_buf && !xfer->rx_buf) { + dev_err(spi->parent, + "bufferless transfer, length %u\n", xfer->len); + msg->state = GB_SPI_STATE_MSG_ERROR; + return NULL; + } + + tx_xfer_size = 0; + rx_xfer_size = 0; + + if (xfer->tx_buf) { + len = xfer->len - spi->tx_xfer_offset; + if (!tx_header_fit_operation(tx_size, count, data_max)) + break; + tx_xfer_size = calc_tx_xfer_size(tx_size, count, + len, data_max); + spi->last_xfer_size = tx_xfer_size; + } + + if (xfer->rx_buf) { + len = xfer->len - spi->rx_xfer_offset; + rx_xfer_size = calc_rx_xfer_size(rx_size, &tx_xfer_size, + len, data_max); + spi->last_xfer_size = rx_xfer_size; + } + + tx_size += tx_xfer_size; + rx_size += rx_xfer_size; + + total_len += spi->last_xfer_size; + count++; + + xfer = get_next_xfer(xfer, msg); + if (!xfer || total_len >= data_max) + msg->state = GB_SPI_STATE_OP_READY; + } + + /* + * In addition to space for all message descriptors we need + * to have enough to hold all tx data. + */ + request_size = sizeof(*request); + request_size += count * sizeof(*gb_xfer); + request_size += tx_size; + + /* Response consists only of incoming data */ + operation = gb_operation_create(connection, GB_SPI_TYPE_TRANSFER, + request_size, rx_size, GFP_KERNEL); + if (!operation) + return NULL; + + request = operation->request->payload; + request->count = cpu_to_le16(count); + request->mode = dev->mode; + request->chip_select = dev->chip_select; + + gb_xfer = &request->transfers[0]; + tx_data = gb_xfer + count; /* place tx data after last gb_xfer */ + + /* Fill in the transfers array */ + xfer = spi->first_xfer; + while (msg->state != GB_SPI_STATE_OP_DONE) { + if (xfer == spi->last_xfer) + xfer_len = spi->last_xfer_size; + else + xfer_len = xfer->len; + + /* make sure we do not timeout in a slow transfer */ + xfer_timeout = xfer_len * 8 * MSEC_PER_SEC / xfer->speed_hz; + xfer_timeout += GB_OPERATION_TIMEOUT_DEFAULT; + + if (xfer_timeout > spi->op_timeout) + spi->op_timeout = xfer_timeout; + + gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz); + gb_xfer->len = cpu_to_le32(xfer_len); + gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); + gb_xfer->cs_change = xfer->cs_change; + gb_xfer->bits_per_word = xfer->bits_per_word; + + /* Copy tx data */ + if (xfer->tx_buf) { + gb_xfer->xfer_flags |= GB_SPI_XFER_WRITE; + memcpy(tx_data, xfer->tx_buf + spi->tx_xfer_offset, + xfer_len); + tx_data += xfer_len; + } + + if (xfer->rx_buf) + gb_xfer->xfer_flags |= GB_SPI_XFER_READ; + + if (xfer == spi->last_xfer) { + if (!is_last_xfer_done(spi)) + gb_xfer->xfer_flags |= GB_SPI_XFER_INPROGRESS; + msg->state = GB_SPI_STATE_OP_DONE; + continue; + } + + gb_xfer++; + xfer = get_next_xfer(xfer, msg); + } + + msg->actual_length += total_len; + + return operation; +} + +static void gb_spi_decode_response(struct gb_spilib *spi, + struct spi_message *msg, + struct gb_spi_transfer_response *response) +{ + struct spi_transfer *xfer = spi->first_xfer; + void *rx_data = response->data; + u32 xfer_len; + + while (xfer) { + /* Copy rx data */ + if (xfer->rx_buf) { + if (xfer == spi->first_xfer) + xfer_len = xfer->len - spi->rx_xfer_offset; + else if (xfer == spi->last_xfer) + xfer_len = spi->last_xfer_size; + else + xfer_len = xfer->len; + + memcpy(xfer->rx_buf + spi->rx_xfer_offset, rx_data, + xfer_len); + rx_data += xfer_len; + } + + if (xfer == spi->last_xfer) + break; + + xfer = list_next_entry(xfer, transfer_list); + } +} + +static int gb_spi_transfer_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct gb_spilib *spi = spi_master_get_devdata(master); + struct gb_connection *connection = spi->connection; + struct gb_spi_transfer_response *response; + struct gb_operation *operation; + int ret = 0; + + spi->first_xfer = list_first_entry_or_null(&msg->transfers, + struct spi_transfer, + transfer_list); + if (!spi->first_xfer) { + ret = -ENOMEM; + goto out; + } + + msg->state = GB_SPI_STATE_MSG_IDLE; + + while (msg->state != GB_SPI_STATE_MSG_DONE && + msg->state != GB_SPI_STATE_MSG_ERROR) { + operation = gb_spi_operation_create(spi, connection, msg); + if (!operation) { + msg->state = GB_SPI_STATE_MSG_ERROR; + ret = -EINVAL; + continue; + } + + ret = gb_operation_request_send_sync_timeout(operation, + spi->op_timeout); + if (!ret) { + response = operation->response->payload; + if (response) + gb_spi_decode_response(spi, msg, response); + } else { + dev_err(spi->parent, + "transfer operation failed: %d\n", ret); + msg->state = GB_SPI_STATE_MSG_ERROR; + } + + gb_operation_put(operation); + setup_next_xfer(spi, msg); + } + +out: + msg->status = ret; + clean_xfer_state(spi); + spi_finalize_current_message(master); + + return ret; +} + +static int gb_spi_prepare_transfer_hardware(struct spi_master *master) +{ + struct gb_spilib *spi = spi_master_get_devdata(master); + + return spi->ops->prepare_transfer_hardware(spi->parent); +} + +static int gb_spi_unprepare_transfer_hardware(struct spi_master *master) +{ + struct gb_spilib *spi = spi_master_get_devdata(master); + + spi->ops->unprepare_transfer_hardware(spi->parent); + + return 0; +} + +static int gb_spi_setup(struct spi_device *spi) +{ + /* Nothing to do for now */ + return 0; +} + +static void gb_spi_cleanup(struct spi_device *spi) +{ + /* Nothing to do for now */ +} + +/* Routines to get controller information */ + +/* + * Map Greybus spi mode bits/flags/bpw into Linux ones. + * All bits are same for now and so these macro's return same values. + */ +#define gb_spi_mode_map(mode) mode +#define gb_spi_flags_map(flags) flags + +static int gb_spi_get_master_config(struct gb_spilib *spi) +{ + struct gb_spi_master_config_response response; + u16 mode, flags; + int ret; + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_MASTER_CONFIG, + NULL, 0, &response, sizeof(response)); + if (ret < 0) + return ret; + + mode = le16_to_cpu(response.mode); + spi->mode = gb_spi_mode_map(mode); + + flags = le16_to_cpu(response.flags); + spi->flags = gb_spi_flags_map(flags); + + spi->bits_per_word_mask = le32_to_cpu(response.bits_per_word_mask); + spi->num_chipselect = response.num_chipselect; + + spi->min_speed_hz = le32_to_cpu(response.min_speed_hz); + spi->max_speed_hz = le32_to_cpu(response.max_speed_hz); + + return 0; +} + +static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs) +{ + struct spi_master *master = get_master_from_spi(spi); + struct gb_spi_device_config_request request; + struct gb_spi_device_config_response response; + struct spi_board_info spi_board = { {0} }; + struct spi_device *spidev; + int ret; + u8 dev_type; + + request.chip_select = cs; + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_DEVICE_CONFIG, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + + dev_type = response.device_type; + + if (dev_type == GB_SPI_SPI_DEV) + strlcpy(spi_board.modalias, "spidev", + sizeof(spi_board.modalias)); + else if (dev_type == GB_SPI_SPI_NOR) + strlcpy(spi_board.modalias, "spi-nor", + sizeof(spi_board.modalias)); + else if (dev_type == GB_SPI_SPI_MODALIAS) + memcpy(spi_board.modalias, response.name, + sizeof(spi_board.modalias)); + else + return -EINVAL; + + spi_board.mode = le16_to_cpu(response.mode); + spi_board.bus_num = master->bus_num; + spi_board.chip_select = cs; + spi_board.max_speed_hz = le32_to_cpu(response.max_speed_hz); + + spidev = spi_new_device(master, &spi_board); + if (!spidev) + return -EINVAL; + + return 0; +} + +int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, + struct spilib_ops *ops) +{ + struct gb_spilib *spi; + struct spi_master *master; + int ret; + u8 i; + + /* Allocate master with space for data */ + master = spi_alloc_master(dev, sizeof(*spi)); + if (!master) { + dev_err(dev, "cannot alloc SPI master\n"); + return -ENOMEM; + } + + spi = spi_master_get_devdata(master); + spi->connection = connection; + gb_connection_set_data(connection, master); + spi->parent = dev; + spi->ops = ops; + + /* get master configuration */ + ret = gb_spi_get_master_config(spi); + if (ret) + goto exit_spi_put; + + master->bus_num = -1; /* Allow spi-core to allocate it dynamically */ + master->num_chipselect = spi->num_chipselect; + master->mode_bits = spi->mode; + master->flags = spi->flags; + master->bits_per_word_mask = spi->bits_per_word_mask; + + /* Attach methods */ + master->cleanup = gb_spi_cleanup; + master->setup = gb_spi_setup; + master->transfer_one_message = gb_spi_transfer_one_message; + + if (ops && ops->prepare_transfer_hardware) { + master->prepare_transfer_hardware = + gb_spi_prepare_transfer_hardware; + } + + if (ops && ops->unprepare_transfer_hardware) { + master->unprepare_transfer_hardware = + gb_spi_unprepare_transfer_hardware; + } + + master->auto_runtime_pm = true; + + ret = spi_register_master(master); + if (ret < 0) + goto exit_spi_put; + + /* now, fetch the devices configuration */ + for (i = 0; i < spi->num_chipselect; i++) { + ret = gb_spi_setup_device(spi, i); + if (ret < 0) { + dev_err(dev, "failed to allocate spi device %d: %d\n", + i, ret); + goto exit_spi_unregister; + } + } + + return 0; + +exit_spi_unregister: + spi_unregister_master(master); +exit_spi_put: + spi_master_put(master); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_spilib_master_init); + +void gb_spilib_master_exit(struct gb_connection *connection) +{ + struct spi_master *master = gb_connection_get_data(connection); + + spi_unregister_master(master); + spi_master_put(master); +} +EXPORT_SYMBOL_GPL(gb_spilib_master_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spilib.h b/drivers/staging/greybus/spilib.h new file mode 100644 index 000000000000..566d0dde7f79 --- /dev/null +++ b/drivers/staging/greybus/spilib.h @@ -0,0 +1,24 @@ +/* + * Greybus SPI library header + * + * copyright 2016 google inc. + * copyright 2016 linaro ltd. + * + * released under the gplv2 only. + */ + +#ifndef __SPILIB_H +#define __SPILIB_H + +struct device; +struct gb_connection; + +struct spilib_ops { + int (*prepare_transfer_hardware)(struct device *dev); + void (*unprepare_transfer_hardware)(struct device *dev); +}; + +int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, struct spilib_ops *ops); +void gb_spilib_master_exit(struct gb_connection *connection); + +#endif /* __SPILIB_H */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c new file mode 100644 index 000000000000..550055ec27a5 --- /dev/null +++ b/drivers/staging/greybus/svc.c @@ -0,0 +1,1486 @@ +/* + * SVC Greybus driver. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include + +#include "greybus.h" + +#define SVC_INTF_EJECT_TIMEOUT 9000 +#define SVC_INTF_ACTIVATE_TIMEOUT 6000 +#define SVC_INTF_RESUME_TIMEOUT 3000 + +struct gb_svc_deferred_request { + struct work_struct work; + struct gb_operation *operation; +}; + + +static int gb_svc_queue_deferred_request(struct gb_operation *operation); + +static ssize_t endo_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "0x%04x\n", svc->endo_id); +} +static DEVICE_ATTR_RO(endo_id); + +static ssize_t ap_intf_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "%u\n", svc->ap_intf_id); +} +static DEVICE_ATTR_RO(ap_intf_id); + +// FIXME +// This is a hack, we need to do this "right" and clean the interface up +// properly, not just forcibly yank the thing out of the system and hope for the +// best. But for now, people want their modules to come out without having to +// throw the thing to the ground or get out a screwdriver. +static ssize_t intf_eject_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + unsigned short intf_id; + int ret; + + ret = kstrtou16(buf, 10, &intf_id); + if (ret < 0) + return ret; + + dev_warn(dev, "Forcibly trying to eject interface %d\n", intf_id); + + ret = gb_svc_intf_eject(svc, intf_id); + if (ret < 0) + return ret; + + return len; +} +static DEVICE_ATTR_WO(intf_eject); + +static ssize_t watchdog_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "%s\n", + gb_svc_watchdog_enabled(svc) ? "enabled" : "disabled"); +} + +static ssize_t watchdog_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + int retval; + bool user_request; + + retval = strtobool(buf, &user_request); + if (retval) + return retval; + + if (user_request) + retval = gb_svc_watchdog_enable(svc); + else + retval = gb_svc_watchdog_disable(svc); + if (retval) + return retval; + return len; +} +static DEVICE_ATTR_RW(watchdog); + +static ssize_t watchdog_action_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) + return sprintf(buf, "panic\n"); + else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) + return sprintf(buf, "reset\n"); + + return -EINVAL; +} + +static ssize_t watchdog_action_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + + if (sysfs_streq(buf, "panic")) + svc->action = GB_SVC_WATCHDOG_BITE_PANIC_KERNEL; + else if (sysfs_streq(buf, "reset")) + svc->action = GB_SVC_WATCHDOG_BITE_RESET_UNIPRO; + else + return -EINVAL; + + return len; +} +static DEVICE_ATTR_RW(watchdog_action); + +static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value) +{ + struct gb_svc_pwrmon_rail_count_get_response response; + int ret; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get rail count: %d\n", ret); + return ret; + } + + *value = response.rail_count; + + return 0; +} + +static int gb_svc_pwrmon_rail_names_get(struct gb_svc *svc, + struct gb_svc_pwrmon_rail_names_get_response *response, + size_t bufsize) +{ + int ret; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET, NULL, 0, + response, bufsize); + if (ret) { + dev_err(&svc->dev, "failed to get rail names: %d\n", ret); + return ret; + } + + if (response->status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, + "SVC error while getting rail names: %u\n", + response->status); + return -EREMOTEIO; + } + + return 0; +} + +static int gb_svc_pwrmon_sample_get(struct gb_svc *svc, u8 rail_id, + u8 measurement_type, u32 *value) +{ + struct gb_svc_pwrmon_sample_get_request request; + struct gb_svc_pwrmon_sample_get_response response; + int ret; + + request.rail_id = rail_id; + request.measurement_type = measurement_type; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_PWRMON_SAMPLE_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get rail sample: %d\n", ret); + return ret; + } + + if (response.result) { + dev_err(&svc->dev, + "UniPro error while getting rail power sample (%d %d): %d\n", + rail_id, measurement_type, response.result); + switch (response.result) { + case GB_SVC_PWRMON_GET_SAMPLE_INVAL: + return -EINVAL; + case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: + return -ENOMSG; + default: + return -EREMOTEIO; + } + } + + *value = le32_to_cpu(response.measurement); + + return 0; +} + +int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, + u8 measurement_type, u32 *value) +{ + struct gb_svc_pwrmon_intf_sample_get_request request; + struct gb_svc_pwrmon_intf_sample_get_response response; + int ret; + + request.intf_id = intf_id; + request.measurement_type = measurement_type; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get intf sample: %d\n", ret); + return ret; + } + + if (response.result) { + dev_err(&svc->dev, + "UniPro error while getting intf power sample (%d %d): %d\n", + intf_id, measurement_type, response.result); + switch (response.result) { + case GB_SVC_PWRMON_GET_SAMPLE_INVAL: + return -EINVAL; + case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: + return -ENOMSG; + default: + return -EREMOTEIO; + } + } + + *value = le32_to_cpu(response.measurement); + + return 0; +} + +static struct attribute *svc_attrs[] = { + &dev_attr_endo_id.attr, + &dev_attr_ap_intf_id.attr, + &dev_attr_intf_eject.attr, + &dev_attr_watchdog.attr, + &dev_attr_watchdog_action.attr, + NULL, +}; +ATTRIBUTE_GROUPS(svc); + +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) +{ + struct gb_svc_intf_device_id_request request; + + request.intf_id = intf_id; + request.device_id = device_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_DEVICE_ID, + &request, sizeof(request), NULL, 0); +} + +int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_eject_request request; + int ret; + + request.intf_id = intf_id; + + /* + * The pulse width for module release in svc is long so we need to + * increase the timeout so the operation will not return to soon. + */ + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_EJECT, &request, + sizeof(request), NULL, 0, + SVC_INTF_EJECT_TIMEOUT); + if (ret) { + dev_err(&svc->dev, "failed to eject interface %u\n", intf_id); + return ret; + } + + return 0; +} + +int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + struct gb_svc_intf_vsys_request request; + struct gb_svc_intf_vsys_response response; + int type, ret; + + request.intf_id = intf_id; + + if (enable) + type = GB_SVC_TYPE_INTF_VSYS_ENABLE; + else + type = GB_SVC_TYPE_INTF_VSYS_DISABLE; + + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_VSYS_OK) + return -EREMOTEIO; + return 0; +} + +int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + struct gb_svc_intf_refclk_request request; + struct gb_svc_intf_refclk_response response; + int type, ret; + + request.intf_id = intf_id; + + if (enable) + type = GB_SVC_TYPE_INTF_REFCLK_ENABLE; + else + type = GB_SVC_TYPE_INTF_REFCLK_DISABLE; + + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_REFCLK_OK) + return -EREMOTEIO; + return 0; +} + +int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + struct gb_svc_intf_unipro_request request; + struct gb_svc_intf_unipro_response response; + int type, ret; + + request.intf_id = intf_id; + + if (enable) + type = GB_SVC_TYPE_INTF_UNIPRO_ENABLE; + else + type = GB_SVC_TYPE_INTF_UNIPRO_DISABLE; + + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_UNIPRO_OK) + return -EREMOTEIO; + return 0; +} + +int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type) +{ + struct gb_svc_intf_activate_request request; + struct gb_svc_intf_activate_response response; + int ret; + + request.intf_id = intf_id; + + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_ACTIVATE, + &request, sizeof(request), + &response, sizeof(response), + SVC_INTF_ACTIVATE_TIMEOUT); + if (ret < 0) + return ret; + if (response.status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, "failed to activate interface %u: %u\n", + intf_id, response.status); + return -EREMOTEIO; + } + + *intf_type = response.intf_type; + + return 0; +} + +int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_resume_request request; + struct gb_svc_intf_resume_response response; + int ret; + + request.intf_id = intf_id; + + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_RESUME, + &request, sizeof(request), + &response, sizeof(response), + SVC_INTF_RESUME_TIMEOUT); + if (ret < 0) { + dev_err(&svc->dev, "failed to send interface resume %u: %d\n", + intf_id, ret); + return ret; + } + + if (response.status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, "failed to resume interface %u: %u\n", + intf_id, response.status); + return -EREMOTEIO; + } + + return 0; +} + +int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 *value) +{ + struct gb_svc_dme_peer_get_request request; + struct gb_svc_dme_peer_get_response response; + u16 result; + int ret; + + request.intf_id = intf_id; + request.attr = cpu_to_le16(attr); + request.selector = cpu_to_le16(selector); + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_DME_PEER_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get DME attribute (%u 0x%04x %u): %d\n", + intf_id, attr, selector, ret); + return ret; + } + + result = le16_to_cpu(response.result_code); + if (result) { + dev_err(&svc->dev, "UniPro error while getting DME attribute (%u 0x%04x %u): %u\n", + intf_id, attr, selector, result); + return -EREMOTEIO; + } + + if (value) + *value = le32_to_cpu(response.attr_value); + + return 0; +} + +int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 value) +{ + struct gb_svc_dme_peer_set_request request; + struct gb_svc_dme_peer_set_response response; + u16 result; + int ret; + + request.intf_id = intf_id; + request.attr = cpu_to_le16(attr); + request.selector = cpu_to_le16(selector); + request.value = cpu_to_le32(value); + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_DME_PEER_SET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to set DME attribute (%u 0x%04x %u %u): %d\n", + intf_id, attr, selector, value, ret); + return ret; + } + + result = le16_to_cpu(response.result_code); + if (result) { + dev_err(&svc->dev, "UniPro error while setting DME attribute (%u 0x%04x %u %u): %u\n", + intf_id, attr, selector, value, result); + return -EREMOTEIO; + } + + return 0; +} + +int gb_svc_connection_create(struct gb_svc *svc, + u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id, + u8 cport_flags) +{ + struct gb_svc_conn_create_request request; + + request.intf1_id = intf1_id; + request.cport1_id = cpu_to_le16(cport1_id); + request.intf2_id = intf2_id; + request.cport2_id = cpu_to_le16(cport2_id); + request.tc = 0; /* TC0 */ + request.flags = cport_flags; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, + &request, sizeof(request), NULL, 0); +} + +void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) +{ + struct gb_svc_conn_destroy_request request; + struct gb_connection *connection = svc->connection; + int ret; + + request.intf1_id = intf1_id; + request.cport1_id = cpu_to_le16(cport1_id); + request.intf2_id = intf2_id; + request.cport2_id = cpu_to_le16(cport2_id); + + ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, + &request, sizeof(request), NULL, 0); + if (ret) { + dev_err(&svc->dev, "failed to destroy connection (%u:%u %u:%u): %d\n", + intf1_id, cport1_id, intf2_id, cport2_id, ret); + } +} + +int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, + u32 strobe_delay, u32 refclk) +{ + struct gb_connection *connection = svc->connection; + struct gb_svc_timesync_enable_request request; + + request.count = count; + request.frame_time = cpu_to_le64(frame_time); + request.strobe_delay = cpu_to_le32(strobe_delay); + request.refclk = cpu_to_le32(refclk); + return gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_ENABLE, + &request, sizeof(request), NULL, 0); +} + +int gb_svc_timesync_disable(struct gb_svc *svc) +{ + struct gb_connection *connection = svc->connection; + + return gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_DISABLE, + NULL, 0, NULL, 0); +} + +int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time) +{ + struct gb_connection *connection = svc->connection; + struct gb_svc_timesync_authoritative_response response; + int ret, i; + + ret = gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_AUTHORITATIVE, NULL, 0, + &response, sizeof(response)); + if (ret < 0) + return ret; + + for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) + frame_time[i] = le64_to_cpu(response.frame_time[i]); + return 0; +} + +int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time) +{ + struct gb_connection *connection = svc->connection; + struct gb_svc_timesync_ping_response response; + int ret; + + ret = gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_PING, + NULL, 0, + &response, sizeof(response)); + if (ret < 0) + return ret; + + *frame_time = le64_to_cpu(response.frame_time); + return 0; +} + +int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask) +{ + struct gb_connection *connection = svc->connection; + struct gb_svc_timesync_wake_pins_acquire_request request; + + request.strobe_mask = cpu_to_le32(strobe_mask); + return gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE, + &request, sizeof(request), + NULL, 0); +} + +int gb_svc_timesync_wake_pins_release(struct gb_svc *svc) +{ + struct gb_connection *connection = svc->connection; + + return gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE, + NULL, 0, NULL, 0); +} + +/* Creates bi-directional routes between the devices */ +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id) +{ + struct gb_svc_route_create_request request; + + request.intf1_id = intf1_id; + request.dev1_id = dev1_id; + request.intf2_id = intf2_id; + request.dev2_id = dev2_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE, + &request, sizeof(request), NULL, 0); +} + +/* Destroys bi-directional routes between the devices */ +void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) +{ + struct gb_svc_route_destroy_request request; + int ret; + + request.intf1_id = intf1_id; + request.intf2_id = intf2_id; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_DESTROY, + &request, sizeof(request), NULL, 0); + if (ret) { + dev_err(&svc->dev, "failed to destroy route (%u %u): %d\n", + intf1_id, intf2_id, ret); + } +} + +int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, + u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, + u8 rx_mode, u8 rx_gear, u8 rx_nlanes, + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote) +{ + struct gb_svc_intf_set_pwrm_request request; + struct gb_svc_intf_set_pwrm_response response; + int ret; + u16 result_code; + + memset(&request, 0, sizeof(request)); + + request.intf_id = intf_id; + request.hs_series = hs_series; + request.tx_mode = tx_mode; + request.tx_gear = tx_gear; + request.tx_nlanes = tx_nlanes; + request.tx_amplitude = tx_amplitude; + request.tx_hs_equalizer = tx_hs_equalizer; + request.rx_mode = rx_mode; + request.rx_gear = rx_gear; + request.rx_nlanes = rx_nlanes; + request.flags = flags; + request.quirks = cpu_to_le32(quirks); + if (local) + request.local_l2timerdata = *local; + if (remote) + request.remote_l2timerdata = *remote; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + + result_code = response.result_code; + if (result_code != GB_SVC_SETPWRM_PWR_LOCAL) { + dev_err(&svc->dev, "set power mode = %d\n", result_code); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); + +int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_set_pwrm_request request; + struct gb_svc_intf_set_pwrm_response response; + int ret; + u16 result_code; + + memset(&request, 0, sizeof(request)); + + request.intf_id = intf_id; + request.hs_series = GB_SVC_UNIPRO_HS_SERIES_A; + request.tx_mode = GB_SVC_UNIPRO_HIBERNATE_MODE; + request.rx_mode = GB_SVC_UNIPRO_HIBERNATE_MODE; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) { + dev_err(&svc->dev, + "failed to send set power mode operation to interface %u: %d\n", + intf_id, ret); + return ret; + } + + result_code = response.result_code; + if (result_code != GB_SVC_SETPWRM_PWR_OK) { + dev_err(&svc->dev, + "failed to hibernate the link for interface %u: %u\n", + intf_id, result_code); + return -EIO; + } + + return 0; +} + +int gb_svc_ping(struct gb_svc *svc) +{ + return gb_operation_sync_timeout(svc->connection, GB_SVC_TYPE_PING, + NULL, 0, NULL, 0, + GB_OPERATION_TIMEOUT_DEFAULT * 2); +} + +static int gb_svc_version_request(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_svc_version_request *request; + struct gb_svc_version_response *response; + + if (op->request->payload_size < sizeof(*request)) { + dev_err(&svc->dev, "short version request (%zu < %zu)\n", + op->request->payload_size, + sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + if (request->major > GB_SVC_VERSION_MAJOR) { + dev_warn(&svc->dev, "unsupported major version (%u > %u)\n", + request->major, GB_SVC_VERSION_MAJOR); + return -ENOTSUPP; + } + + svc->protocol_major = request->major; + svc->protocol_minor = request->minor; + + if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) + return -ENOMEM; + + response = op->response->payload; + response->major = svc->protocol_major; + response->minor = svc->protocol_minor; + + return 0; +} + +static ssize_t pwr_debugfs_voltage_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = file->f_inode->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_VOL, &value); + if (ret) { + dev_err(&svc->dev, + "failed to get voltage sample %u: %d\n", + pwrmon_rails->id, ret); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static ssize_t pwr_debugfs_current_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = file->f_inode->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_CURR, &value); + if (ret) { + dev_err(&svc->dev, + "failed to get current sample %u: %d\n", + pwrmon_rails->id, ret); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static ssize_t pwr_debugfs_power_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = file->f_inode->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_PWR, &value); + if (ret) { + dev_err(&svc->dev, "failed to get power sample %u: %d\n", + pwrmon_rails->id, ret); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static const struct file_operations pwrmon_debugfs_voltage_fops = { + .read = pwr_debugfs_voltage_read, +}; + +static const struct file_operations pwrmon_debugfs_current_fops = { + .read = pwr_debugfs_current_read, +}; + +static const struct file_operations pwrmon_debugfs_power_fops = { + .read = pwr_debugfs_power_read, +}; + +static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc) +{ + int i; + size_t bufsize; + struct dentry *dent; + struct gb_svc_pwrmon_rail_names_get_response *rail_names; + u8 rail_count; + + dent = debugfs_create_dir("pwrmon", svc->debugfs_dentry); + if (IS_ERR_OR_NULL(dent)) + return; + + if (gb_svc_pwrmon_rail_count_get(svc, &rail_count)) + goto err_pwrmon_debugfs; + + if (!rail_count || rail_count > GB_SVC_PWRMON_MAX_RAIL_COUNT) + goto err_pwrmon_debugfs; + + bufsize = sizeof(*rail_names) + + GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * rail_count; + + rail_names = kzalloc(bufsize, GFP_KERNEL); + if (!rail_names) + goto err_pwrmon_debugfs; + + svc->pwrmon_rails = kcalloc(rail_count, sizeof(*svc->pwrmon_rails), + GFP_KERNEL); + if (!svc->pwrmon_rails) + goto err_pwrmon_debugfs_free; + + if (gb_svc_pwrmon_rail_names_get(svc, rail_names, bufsize)) + goto err_pwrmon_debugfs_free; + + for (i = 0; i < rail_count; i++) { + struct dentry *dir; + struct svc_debugfs_pwrmon_rail *rail = &svc->pwrmon_rails[i]; + char fname[GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; + + snprintf(fname, sizeof(fname), "%s", + (char *)&rail_names->name[i]); + + rail->id = i; + rail->svc = svc; + + dir = debugfs_create_dir(fname, dent); + debugfs_create_file("voltage_now", S_IRUGO, dir, rail, + &pwrmon_debugfs_voltage_fops); + debugfs_create_file("current_now", S_IRUGO, dir, rail, + &pwrmon_debugfs_current_fops); + debugfs_create_file("power_now", S_IRUGO, dir, rail, + &pwrmon_debugfs_power_fops); + } + + kfree(rail_names); + return; + +err_pwrmon_debugfs_free: + kfree(rail_names); + kfree(svc->pwrmon_rails); + svc->pwrmon_rails = NULL; + +err_pwrmon_debugfs: + debugfs_remove(dent); +} + +static void gb_svc_debugfs_init(struct gb_svc *svc) +{ + svc->debugfs_dentry = debugfs_create_dir(dev_name(&svc->dev), + gb_debugfs_get()); + gb_svc_pwrmon_debugfs_init(svc); +} + +static void gb_svc_debugfs_exit(struct gb_svc *svc) +{ + debugfs_remove_recursive(svc->debugfs_dentry); + kfree(svc->pwrmon_rails); + svc->pwrmon_rails = NULL; +} + +static int gb_svc_hello(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_svc_hello_request *hello_request; + int ret; + + if (op->request->payload_size < sizeof(*hello_request)) { + dev_warn(&svc->dev, "short hello request (%zu < %zu)\n", + op->request->payload_size, + sizeof(*hello_request)); + return -EINVAL; + } + + hello_request = op->request->payload; + svc->endo_id = le16_to_cpu(hello_request->endo_id); + svc->ap_intf_id = hello_request->interface_id; + + ret = device_add(&svc->dev); + if (ret) { + dev_err(&svc->dev, "failed to register svc device: %d\n", ret); + return ret; + } + + ret = gb_svc_watchdog_create(svc); + if (ret) { + dev_err(&svc->dev, "failed to create watchdog: %d\n", ret); + goto err_unregister_device; + } + + gb_svc_debugfs_init(svc); + + ret = gb_timesync_svc_add(svc); + if (ret) { + dev_err(&svc->dev, "failed to add SVC to timesync: %d\n", ret); + gb_svc_debugfs_exit(svc); + goto err_unregister_device; + } + + return gb_svc_queue_deferred_request(op); + +err_unregister_device: + gb_svc_watchdog_destroy(svc); + device_del(&svc->dev); + return ret; +} + +static struct gb_interface *gb_svc_interface_lookup(struct gb_svc *svc, + u8 intf_id) +{ + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + size_t num_interfaces; + u8 module_id; + + list_for_each_entry(module, &hd->modules, hd_node) { + module_id = module->module_id; + num_interfaces = module->num_interfaces; + + if (intf_id >= module_id && + intf_id < module_id + num_interfaces) { + return module->interfaces[intf_id - module_id]; + } + } + + return NULL; +} + +static struct gb_module *gb_svc_module_lookup(struct gb_svc *svc, u8 module_id) +{ + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + + list_for_each_entry(module, &hd->modules, hd_node) { + if (module->module_id == module_id) + return module; + } + + return NULL; +} + +static void gb_svc_process_hello_deferred(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + int ret; + + /* + * XXX This is a hack/work-around to reconfigure the APBridgeA-Switch + * link to PWM G2, 1 Lane, Slow Auto, so that it has sufficient + * bandwidth for 3 audio streams plus boot-over-UniPro of a hot-plugged + * module. + * + * The code should be removed once SW-2217, Heuristic for UniPro + * Power Mode Changes is resolved. + */ + ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 2, 1, + GB_SVC_SMALL_AMPLITUDE, GB_SVC_NO_DE_EMPHASIS, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 2, 1, + 0, 0, + NULL, NULL); + + if (ret) + dev_warn(&svc->dev, + "power mode change failed on AP to switch link: %d\n", + ret); +} + +static void gb_svc_process_module_inserted(struct gb_operation *operation) +{ + struct gb_svc_module_inserted_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + size_t num_interfaces; + u8 module_id; + u16 flags; + int ret; + + /* The request message size has already been verified. */ + request = operation->request->payload; + module_id = request->primary_intf_id; + num_interfaces = request->intf_count; + flags = le16_to_cpu(request->flags); + + dev_dbg(&svc->dev, "%s - id = %u, num_interfaces = %zu, flags = 0x%04x\n", + __func__, module_id, num_interfaces, flags); + + if (flags & GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY) { + dev_warn(&svc->dev, "no primary interface detected on module %u\n", + module_id); + } + + module = gb_svc_module_lookup(svc, module_id); + if (module) { + dev_warn(&svc->dev, "unexpected module-inserted event %u\n", + module_id); + return; + } + + module = gb_module_create(hd, module_id, num_interfaces); + if (!module) { + dev_err(&svc->dev, "failed to create module\n"); + return; + } + + ret = gb_module_add(module); + if (ret) { + gb_module_put(module); + return; + } + + list_add(&module->hd_node, &hd->modules); +} + +static void gb_svc_process_module_removed(struct gb_operation *operation) +{ + struct gb_svc_module_removed_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_module *module; + u8 module_id; + + /* The request message size has already been verified. */ + request = operation->request->payload; + module_id = request->primary_intf_id; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, module_id); + + module = gb_svc_module_lookup(svc, module_id); + if (!module) { + dev_warn(&svc->dev, "unexpected module-removed event %u\n", + module_id); + return; + } + + module->disconnected = true; + + gb_module_del(module); + list_del(&module->hd_node); + gb_module_put(module); +} + +static void gb_svc_process_intf_oops(struct gb_operation *operation) +{ + struct gb_svc_intf_oops_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_interface *intf; + u8 intf_id; + u8 reason; + + /* The request message size has already been verified. */ + request = operation->request->payload; + intf_id = request->intf_id; + reason = request->reason; + + intf = gb_svc_interface_lookup(svc, intf_id); + if (!intf) { + dev_warn(&svc->dev, "unexpected interface-oops event %u\n", + intf_id); + return; + } + + dev_info(&svc->dev, "Deactivating interface %u, interface oops reason = %u\n", + intf_id, reason); + + mutex_lock(&intf->mutex); + intf->disconnected = true; + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); +} + +static void gb_svc_process_intf_mailbox_event(struct gb_operation *operation) +{ + struct gb_svc_intf_mailbox_event_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_interface *intf; + u8 intf_id; + u16 result_code; + u32 mailbox; + + /* The request message size has already been verified. */ + request = operation->request->payload; + intf_id = request->intf_id; + result_code = le16_to_cpu(request->result_code); + mailbox = le32_to_cpu(request->mailbox); + + dev_dbg(&svc->dev, "%s - id = %u, result = 0x%04x, mailbox = 0x%08x\n", + __func__, intf_id, result_code, mailbox); + + intf = gb_svc_interface_lookup(svc, intf_id); + if (!intf) { + dev_warn(&svc->dev, "unexpected mailbox event %u\n", intf_id); + return; + } + + gb_interface_mailbox_event(intf, result_code, mailbox); +} + +static void gb_svc_process_deferred_request(struct work_struct *work) +{ + struct gb_svc_deferred_request *dr; + struct gb_operation *operation; + struct gb_svc *svc; + u8 type; + + dr = container_of(work, struct gb_svc_deferred_request, work); + operation = dr->operation; + svc = gb_connection_get_data(operation->connection); + type = operation->request->header->type; + + switch (type) { + case GB_SVC_TYPE_SVC_HELLO: + gb_svc_process_hello_deferred(operation); + break; + case GB_SVC_TYPE_MODULE_INSERTED: + gb_svc_process_module_inserted(operation); + break; + case GB_SVC_TYPE_MODULE_REMOVED: + gb_svc_process_module_removed(operation); + break; + case GB_SVC_TYPE_INTF_MAILBOX_EVENT: + gb_svc_process_intf_mailbox_event(operation); + break; + case GB_SVC_TYPE_INTF_OOPS: + gb_svc_process_intf_oops(operation); + break; + default: + dev_err(&svc->dev, "bad deferred request type: 0x%02x\n", type); + } + + gb_operation_put(operation); + kfree(dr); +} + +static int gb_svc_queue_deferred_request(struct gb_operation *operation) +{ + struct gb_svc *svc = gb_connection_get_data(operation->connection); + struct gb_svc_deferred_request *dr; + + dr = kmalloc(sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + gb_operation_get(operation); + + dr->operation = operation; + INIT_WORK(&dr->work, gb_svc_process_deferred_request); + + queue_work(svc->wq, &dr->work); + + return 0; +} + +static int gb_svc_intf_reset_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_message *request = op->request; + struct gb_svc_intf_reset_request *reset; + u8 intf_id; + + if (request->payload_size < sizeof(*reset)) { + dev_warn(&svc->dev, "short reset request received (%zu < %zu)\n", + request->payload_size, sizeof(*reset)); + return -EINVAL; + } + reset = request->payload; + + intf_id = reset->intf_id; + + /* FIXME Reset the interface here */ + + return 0; +} + +static int gb_svc_module_inserted_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_module_inserted_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short module-inserted request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, + request->primary_intf_id); + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_module_removed_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_module_removed_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short module-removed request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, + request->primary_intf_id); + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_intf_oops_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_intf_oops_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short intf-oops request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_intf_mailbox_event_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_intf_mailbox_event_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short mailbox request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + u8 type = op->type; + int ret = 0; + + /* + * SVC requests need to follow a specific order (at least initially) and + * below code takes care of enforcing that. The expected order is: + * - PROTOCOL_VERSION + * - SVC_HELLO + * - Any other request, but the earlier two. + * + * Incoming requests are guaranteed to be serialized and so we don't + * need to protect 'state' for any races. + */ + switch (type) { + case GB_SVC_TYPE_PROTOCOL_VERSION: + if (svc->state != GB_SVC_STATE_RESET) + ret = -EINVAL; + break; + case GB_SVC_TYPE_SVC_HELLO: + if (svc->state != GB_SVC_STATE_PROTOCOL_VERSION) + ret = -EINVAL; + break; + default: + if (svc->state != GB_SVC_STATE_SVC_HELLO) + ret = -EINVAL; + break; + } + + if (ret) { + dev_warn(&svc->dev, "unexpected request 0x%02x received (state %u)\n", + type, svc->state); + return ret; + } + + switch (type) { + case GB_SVC_TYPE_PROTOCOL_VERSION: + ret = gb_svc_version_request(op); + if (!ret) + svc->state = GB_SVC_STATE_PROTOCOL_VERSION; + return ret; + case GB_SVC_TYPE_SVC_HELLO: + ret = gb_svc_hello(op); + if (!ret) + svc->state = GB_SVC_STATE_SVC_HELLO; + return ret; + case GB_SVC_TYPE_INTF_RESET: + return gb_svc_intf_reset_recv(op); + case GB_SVC_TYPE_MODULE_INSERTED: + return gb_svc_module_inserted_recv(op); + case GB_SVC_TYPE_MODULE_REMOVED: + return gb_svc_module_removed_recv(op); + case GB_SVC_TYPE_INTF_MAILBOX_EVENT: + return gb_svc_intf_mailbox_event_recv(op); + case GB_SVC_TYPE_INTF_OOPS: + return gb_svc_intf_oops_recv(op); + default: + dev_warn(&svc->dev, "unsupported request 0x%02x\n", type); + return -EINVAL; + } +} + +static void gb_svc_release(struct device *dev) +{ + struct gb_svc *svc = to_gb_svc(dev); + + if (svc->connection) + gb_connection_destroy(svc->connection); + ida_destroy(&svc->device_id_map); + destroy_workqueue(svc->wq); + kfree(svc); +} + +struct device_type greybus_svc_type = { + .name = "greybus_svc", + .release = gb_svc_release, +}; + +struct gb_svc *gb_svc_create(struct gb_host_device *hd) +{ + struct gb_svc *svc; + + svc = kzalloc(sizeof(*svc), GFP_KERNEL); + if (!svc) + return NULL; + + svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev)); + if (!svc->wq) { + kfree(svc); + return NULL; + } + + svc->dev.parent = &hd->dev; + svc->dev.bus = &greybus_bus_type; + svc->dev.type = &greybus_svc_type; + svc->dev.groups = svc_groups; + svc->dev.dma_mask = svc->dev.parent->dma_mask; + device_initialize(&svc->dev); + + dev_set_name(&svc->dev, "%d-svc", hd->bus_id); + + ida_init(&svc->device_id_map); + svc->state = GB_SVC_STATE_RESET; + svc->hd = hd; + + svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, + gb_svc_request_handler); + if (IS_ERR(svc->connection)) { + dev_err(&svc->dev, "failed to create connection: %ld\n", + PTR_ERR(svc->connection)); + goto err_put_device; + } + + gb_connection_set_data(svc->connection, svc); + + return svc; + +err_put_device: + put_device(&svc->dev); + return NULL; +} + +int gb_svc_add(struct gb_svc *svc) +{ + int ret; + + /* + * The SVC protocol is currently driven by the SVC, so the SVC device + * is added from the connection request handler when enough + * information has been received. + */ + ret = gb_connection_enable(svc->connection); + if (ret) + return ret; + + return 0; +} + +static void gb_svc_remove_modules(struct gb_svc *svc) +{ + struct gb_host_device *hd = svc->hd; + struct gb_module *module, *tmp; + + list_for_each_entry_safe(module, tmp, &hd->modules, hd_node) { + gb_module_del(module); + list_del(&module->hd_node); + gb_module_put(module); + } +} + +void gb_svc_del(struct gb_svc *svc) +{ + gb_connection_disable_rx(svc->connection); + + /* + * The SVC device may have been registered from the request handler. + */ + if (device_is_registered(&svc->dev)) { + gb_timesync_svc_remove(svc); + gb_svc_debugfs_exit(svc); + gb_svc_watchdog_destroy(svc); + device_del(&svc->dev); + } + + flush_workqueue(svc->wq); + + gb_svc_remove_modules(svc); + + gb_connection_disable(svc->connection); +} + +void gb_svc_put(struct gb_svc *svc) +{ + put_device(&svc->dev); +} diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h new file mode 100644 index 000000000000..d1d7ef967385 --- /dev/null +++ b/drivers/staging/greybus/svc.h @@ -0,0 +1,109 @@ +/* + * Greybus SVC code + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __SVC_H +#define __SVC_H + +#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) + +enum gb_svc_state { + GB_SVC_STATE_RESET, + GB_SVC_STATE_PROTOCOL_VERSION, + GB_SVC_STATE_SVC_HELLO, +}; + +enum gb_svc_watchdog_bite { + GB_SVC_WATCHDOG_BITE_RESET_UNIPRO = 0, + GB_SVC_WATCHDOG_BITE_PANIC_KERNEL, +}; + +struct gb_svc_watchdog; + +struct svc_debugfs_pwrmon_rail { + u8 id; + struct gb_svc *svc; +}; + +struct gb_svc { + struct device dev; + + struct gb_host_device *hd; + struct gb_connection *connection; + enum gb_svc_state state; + struct ida device_id_map; + struct workqueue_struct *wq; + + u16 endo_id; + u8 ap_intf_id; + + u8 protocol_major; + u8 protocol_minor; + + struct gb_svc_watchdog *watchdog; + enum gb_svc_watchdog_bite action; + + struct dentry *debugfs_dentry; + struct svc_debugfs_pwrmon_rail *pwrmon_rails; +}; +#define to_gb_svc(d) container_of(d, struct gb_svc, dev) + +struct gb_svc *gb_svc_create(struct gb_host_device *hd); +int gb_svc_add(struct gb_svc *svc); +void gb_svc_del(struct gb_svc *svc); +void gb_svc_put(struct gb_svc *svc); + +int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, + u8 measurement_type, u32 *value); +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id); +void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id); +int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id, u8 cport_flags); +void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id); +int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); +int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type); +int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id); + +int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 *value); +int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 value); +int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, + u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, + u8 rx_mode, u8 rx_gear, u8 rx_nlanes, + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote); +int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id); +int gb_svc_ping(struct gb_svc *svc); +int gb_svc_watchdog_create(struct gb_svc *svc); +void gb_svc_watchdog_destroy(struct gb_svc *svc); +bool gb_svc_watchdog_enabled(struct gb_svc *svc); +int gb_svc_watchdog_enable(struct gb_svc *svc); +int gb_svc_watchdog_disable(struct gb_svc *svc); +int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, + u32 strobe_delay, u32 refclk); +int gb_svc_timesync_disable(struct gb_svc *svc); +int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time); +int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time); +int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask); +int gb_svc_timesync_wake_pins_release(struct gb_svc *svc); + +int gb_svc_protocol_init(void); +void gb_svc_protocol_exit(void); + +#endif /* __SVC_H */ diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c new file mode 100644 index 000000000000..3729460fb954 --- /dev/null +++ b/drivers/staging/greybus/svc_watchdog.c @@ -0,0 +1,198 @@ +/* + * SVC Greybus "watchdog" driver. + * + * Copyright 2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include "greybus.h" + +#define SVC_WATCHDOG_PERIOD (2*HZ) + +struct gb_svc_watchdog { + struct delayed_work work; + struct gb_svc *svc; + bool enabled; + struct notifier_block pm_notifier; +}; + +static struct delayed_work reset_work; + +static int svc_watchdog_pm_notifier(struct notifier_block *notifier, + unsigned long pm_event, void *unused) +{ + struct gb_svc_watchdog *watchdog = + container_of(notifier, struct gb_svc_watchdog, pm_notifier); + + switch (pm_event) { + case PM_SUSPEND_PREPARE: + gb_svc_watchdog_disable(watchdog->svc); + break; + case PM_POST_SUSPEND: + gb_svc_watchdog_enable(watchdog->svc); + break; + default: + break; + } + + return NOTIFY_DONE; +} + +static void greybus_reset(struct work_struct *work) +{ + static char start_path[256] = "/system/bin/start"; + static char *envp[] = { + "HOME=/", + "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", + NULL, + }; + static char *argv[] = { + start_path, + "unipro_reset", + NULL, + }; + + printk(KERN_ERR "svc_watchdog: calling \"%s %s\" to reset greybus network!\n", + argv[0], argv[1]); + call_usermodehelper(start_path, argv, envp, UMH_WAIT_EXEC); +} + +static void do_work(struct work_struct *work) +{ + struct gb_svc_watchdog *watchdog; + struct gb_svc *svc; + int retval; + + watchdog = container_of(work, struct gb_svc_watchdog, work.work); + svc = watchdog->svc; + + dev_dbg(&svc->dev, "%s: ping.\n", __func__); + retval = gb_svc_ping(svc); + if (retval) { + /* + * Something went really wrong, let's warn userspace and then + * pull the plug and reset the whole greybus network. + * We need to do this outside of this workqueue as we will be + * tearing down the svc device itself. So queue up + * yet-another-callback to do that. + */ + dev_err(&svc->dev, + "SVC ping has returned %d, something is wrong!!!\n", + retval); + + if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) { + panic("SVC is not responding\n"); + } else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) { + dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); + + INIT_DELAYED_WORK(&reset_work, greybus_reset); + schedule_delayed_work(&reset_work, HZ / 2); + + /* + * Disable ourselves, we don't want to trip again unless + * userspace wants us to. + */ + watchdog->enabled = false; + } + } + + /* resubmit our work to happen again, if we are still "alive" */ + if (watchdog->enabled) + schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); +} + +int gb_svc_watchdog_create(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + int retval; + + if (svc->watchdog) + return 0; + + watchdog = kmalloc(sizeof(*watchdog), GFP_KERNEL); + if (!watchdog) + return -ENOMEM; + + watchdog->enabled = false; + watchdog->svc = svc; + INIT_DELAYED_WORK(&watchdog->work, do_work); + svc->watchdog = watchdog; + + watchdog->pm_notifier.notifier_call = svc_watchdog_pm_notifier; + retval = register_pm_notifier(&watchdog->pm_notifier); + if (retval) { + dev_err(&svc->dev, "error registering pm notifier(%d)\n", + retval); + goto svc_watchdog_create_err; + } + + retval = gb_svc_watchdog_enable(svc); + if (retval) { + dev_err(&svc->dev, "error enabling watchdog (%d)\n", retval); + unregister_pm_notifier(&watchdog->pm_notifier); + goto svc_watchdog_create_err; + } + return retval; + +svc_watchdog_create_err: + svc->watchdog = NULL; + kfree(watchdog); + + return retval; +} + +void gb_svc_watchdog_destroy(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog = svc->watchdog; + + if (!watchdog) + return; + + unregister_pm_notifier(&watchdog->pm_notifier); + gb_svc_watchdog_disable(svc); + svc->watchdog = NULL; + kfree(watchdog); +} + +bool gb_svc_watchdog_enabled(struct gb_svc *svc) +{ + if (!svc || !svc->watchdog) + return false; + return svc->watchdog->enabled; +} + +int gb_svc_watchdog_enable(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + + if (!svc->watchdog) + return -ENODEV; + + watchdog = svc->watchdog; + if (watchdog->enabled) + return 0; + + watchdog->enabled = true; + schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); + return 0; +} + +int gb_svc_watchdog_disable(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + + if (!svc->watchdog) + return -ENODEV; + + watchdog = svc->watchdog; + if (!watchdog->enabled) + return 0; + + watchdog->enabled = false; + cancel_delayed_work_sync(&watchdog->work); + return 0; +} diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c new file mode 100644 index 000000000000..2e68af7dea6d --- /dev/null +++ b/drivers/staging/greybus/timesync.c @@ -0,0 +1,1357 @@ +/* + * TimeSync API driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include "greybus.h" +#include "timesync.h" +#include "greybus_trace.h" + +/* + * Minimum inter-strobe value of one millisecond is chosen because it + * just-about fits the common definition of a jiffy. + * + * Maximum value OTOH is constrained by the number of bits the SVC can fit + * into a 16 bit up-counter. The SVC configures the timer in microseconds + * so the maximum allowable value is 65535 microseconds. We clip that value + * to 10000 microseconds for the sake of using nice round base 10 numbers + * and since right-now there's no imaginable use-case requiring anything + * other than a one millisecond inter-strobe time, let alone something + * higher than ten milliseconds. + */ +#define GB_TIMESYNC_STROBE_DELAY_US 1000 +#define GB_TIMESYNC_DEFAULT_OFFSET_US 1000 + +/* Work queue timers long, short and SVC strobe timeout */ +#define GB_TIMESYNC_DELAYED_WORK_LONG msecs_to_jiffies(10) +#define GB_TIMESYNC_DELAYED_WORK_SHORT msecs_to_jiffies(1) +#define GB_TIMESYNC_MAX_WAIT_SVC msecs_to_jiffies(5000) +#define GB_TIMESYNC_KTIME_UPDATE msecs_to_jiffies(1000) +#define GB_TIMESYNC_MAX_KTIME_CONVERSION 15 + +/* Maximum number of times we'll retry a failed synchronous sync */ +#define GB_TIMESYNC_MAX_RETRIES 5 + +/* Reported nanoseconds/femtoseconds per clock */ +static u64 gb_timesync_ns_per_clock; +static u64 gb_timesync_fs_per_clock; + +/* Maximum difference we will accept converting FrameTime to ktime */ +static u32 gb_timesync_max_ktime_diff; + +/* Reported clock rate */ +static unsigned long gb_timesync_clock_rate; + +/* Workqueue */ +static void gb_timesync_worker(struct work_struct *work); + +/* List of SVCs with one FrameTime per SVC */ +static LIST_HEAD(gb_timesync_svc_list); + +/* Synchronize parallel contexts accessing a valid timesync_svc pointer */ +static DEFINE_MUTEX(gb_timesync_svc_list_mutex); + +/* Structure to convert from FrameTime to timespec/ktime */ +struct gb_timesync_frame_time_data { + u64 frame_time; + struct timespec ts; +}; + +struct gb_timesync_svc { + struct list_head list; + struct list_head interface_list; + struct gb_svc *svc; + struct gb_timesync_host_device *timesync_hd; + + spinlock_t spinlock; /* Per SVC spinlock to sync with ISR */ + struct mutex mutex; /* Per SVC mutex for regular synchronization */ + + struct dentry *frame_time_dentry; + struct dentry *frame_ktime_dentry; + struct workqueue_struct *work_queue; + wait_queue_head_t wait_queue; + struct delayed_work delayed_work; + struct timer_list ktime_timer; + + /* The current local FrameTime */ + u64 frame_time_offset; + struct gb_timesync_frame_time_data strobe_data[GB_TIMESYNC_MAX_STROBES]; + struct gb_timesync_frame_time_data ktime_data; + + /* The SVC FrameTime and relative AP FrameTime @ last TIMESYNC_PING */ + u64 svc_ping_frame_time; + u64 ap_ping_frame_time; + + /* Transitory settings */ + u32 strobe_mask; + bool offset_down; + bool print_ping; + bool capture_ping; + int strobe; + + /* Current state */ + int state; +}; + +struct gb_timesync_host_device { + struct list_head list; + struct gb_host_device *hd; + u64 ping_frame_time; +}; + +struct gb_timesync_interface { + struct list_head list; + struct gb_interface *interface; + u64 ping_frame_time; +}; + +enum gb_timesync_state { + GB_TIMESYNC_STATE_INVALID = 0, + GB_TIMESYNC_STATE_INACTIVE = 1, + GB_TIMESYNC_STATE_INIT = 2, + GB_TIMESYNC_STATE_WAIT_SVC = 3, + GB_TIMESYNC_STATE_AUTHORITATIVE = 4, + GB_TIMESYNC_STATE_PING = 5, + GB_TIMESYNC_STATE_ACTIVE = 6, +}; + +static void gb_timesync_ktime_timer_fn(unsigned long data); + +static u64 gb_timesync_adjust_count(struct gb_timesync_svc *timesync_svc, + u64 counts) +{ + if (timesync_svc->offset_down) + return counts - timesync_svc->frame_time_offset; + else + return counts + timesync_svc->frame_time_offset; +} + +/* + * This function provides the authoritative FrameTime to a calling function. It + * is designed to be lockless and should remain that way the caller is assumed + * to be state-aware. + */ +static u64 __gb_timesync_get_frame_time(struct gb_timesync_svc *timesync_svc) +{ + u64 clocks = gb_timesync_platform_get_counter(); + + return gb_timesync_adjust_count(timesync_svc, clocks); +} + +static void gb_timesync_schedule_svc_timeout(struct gb_timesync_svc + *timesync_svc) +{ + queue_delayed_work(timesync_svc->work_queue, + ×ync_svc->delayed_work, + GB_TIMESYNC_MAX_WAIT_SVC); +} + +static void gb_timesync_set_state(struct gb_timesync_svc *timesync_svc, + int state) +{ + switch (state) { + case GB_TIMESYNC_STATE_INVALID: + timesync_svc->state = state; + wake_up(×ync_svc->wait_queue); + break; + case GB_TIMESYNC_STATE_INACTIVE: + timesync_svc->state = state; + wake_up(×ync_svc->wait_queue); + break; + case GB_TIMESYNC_STATE_INIT: + if (timesync_svc->state != GB_TIMESYNC_STATE_INVALID) { + timesync_svc->strobe = 0; + timesync_svc->frame_time_offset = 0; + timesync_svc->state = state; + cancel_delayed_work(×ync_svc->delayed_work); + queue_delayed_work(timesync_svc->work_queue, + ×ync_svc->delayed_work, + GB_TIMESYNC_DELAYED_WORK_LONG); + } + break; + case GB_TIMESYNC_STATE_WAIT_SVC: + if (timesync_svc->state == GB_TIMESYNC_STATE_INIT) + timesync_svc->state = state; + break; + case GB_TIMESYNC_STATE_AUTHORITATIVE: + if (timesync_svc->state == GB_TIMESYNC_STATE_WAIT_SVC) { + timesync_svc->state = state; + cancel_delayed_work(×ync_svc->delayed_work); + queue_delayed_work(timesync_svc->work_queue, + ×ync_svc->delayed_work, 0); + } + break; + case GB_TIMESYNC_STATE_PING: + if (timesync_svc->state == GB_TIMESYNC_STATE_ACTIVE) { + timesync_svc->state = state; + queue_delayed_work(timesync_svc->work_queue, + ×ync_svc->delayed_work, + GB_TIMESYNC_DELAYED_WORK_SHORT); + } + break; + case GB_TIMESYNC_STATE_ACTIVE: + if (timesync_svc->state == GB_TIMESYNC_STATE_AUTHORITATIVE || + timesync_svc->state == GB_TIMESYNC_STATE_PING) { + timesync_svc->state = state; + wake_up(×ync_svc->wait_queue); + } + break; + } + + if (WARN_ON(timesync_svc->state != state)) { + pr_err("Invalid state transition %d=>%d\n", + timesync_svc->state, state); + } +} + +static void gb_timesync_set_state_atomic(struct gb_timesync_svc *timesync_svc, + int state) +{ + unsigned long flags; + + spin_lock_irqsave(×ync_svc->spinlock, flags); + gb_timesync_set_state(timesync_svc, state); + spin_unlock_irqrestore(×ync_svc->spinlock, flags); +} + +static u64 gb_timesync_diff(u64 x, u64 y) +{ + if (x > y) + return x - y; + else + return y - x; +} + +static void gb_timesync_adjust_to_svc(struct gb_timesync_svc *svc, + u64 svc_frame_time, u64 ap_frame_time) +{ + if (svc_frame_time > ap_frame_time) { + svc->frame_time_offset = svc_frame_time - ap_frame_time; + svc->offset_down = false; + } else { + svc->frame_time_offset = ap_frame_time - svc_frame_time; + svc->offset_down = true; + } +} + +/* + * Associate a FrameTime with a ktime timestamp represented as struct timespec + * Requires the calling context to hold timesync_svc->mutex + */ +static void gb_timesync_store_ktime(struct gb_timesync_svc *timesync_svc, + struct timespec ts, u64 frame_time) +{ + timesync_svc->ktime_data.ts = ts; + timesync_svc->ktime_data.frame_time = frame_time; +} + +/* + * Find the two pulses that best-match our expected inter-strobe gap and + * then calculate the difference between the SVC time at the second pulse + * to the local time at the second pulse. + */ +static void gb_timesync_collate_frame_time(struct gb_timesync_svc *timesync_svc, + u64 *frame_time) +{ + int i = 0; + u64 delta, ap_frame_time; + u64 strobe_delay_ns = GB_TIMESYNC_STROBE_DELAY_US * NSEC_PER_USEC; + u64 least = 0; + + for (i = 1; i < GB_TIMESYNC_MAX_STROBES; i++) { + delta = timesync_svc->strobe_data[i].frame_time - + timesync_svc->strobe_data[i - 1].frame_time; + delta *= gb_timesync_ns_per_clock; + delta = gb_timesync_diff(delta, strobe_delay_ns); + + if (!least || delta < least) { + least = delta; + gb_timesync_adjust_to_svc(timesync_svc, frame_time[i], + timesync_svc->strobe_data[i].frame_time); + + ap_frame_time = timesync_svc->strobe_data[i].frame_time; + ap_frame_time = gb_timesync_adjust_count(timesync_svc, + ap_frame_time); + gb_timesync_store_ktime(timesync_svc, + timesync_svc->strobe_data[i].ts, + ap_frame_time); + + pr_debug("adjust %s local %llu svc %llu delta %llu\n", + timesync_svc->offset_down ? "down" : "up", + timesync_svc->strobe_data[i].frame_time, + frame_time[i], delta); + } + } +} + +static void gb_timesync_teardown(struct gb_timesync_svc *timesync_svc) +{ + struct gb_timesync_interface *timesync_interface; + struct gb_svc *svc = timesync_svc->svc; + struct gb_interface *interface; + struct gb_host_device *hd; + int ret; + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + interface = timesync_interface->interface; + ret = gb_interface_timesync_disable(interface); + if (ret) { + dev_err(&interface->dev, + "interface timesync_disable %d\n", ret); + } + } + + hd = timesync_svc->timesync_hd->hd; + ret = hd->driver->timesync_disable(hd); + if (ret < 0) { + dev_err(&hd->dev, "host timesync_disable %d\n", + ret); + } + + gb_svc_timesync_wake_pins_release(svc); + gb_svc_timesync_disable(svc); + gb_timesync_platform_unlock_bus(); + + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INACTIVE); +} + +static void gb_timesync_platform_lock_bus_fail(struct gb_timesync_svc + *timesync_svc, int ret) +{ + if (ret == -EAGAIN) { + gb_timesync_set_state(timesync_svc, timesync_svc->state); + } else { + pr_err("Failed to lock timesync bus %d\n", ret); + gb_timesync_set_state(timesync_svc, GB_TIMESYNC_STATE_INACTIVE); + } +} + +static void gb_timesync_enable(struct gb_timesync_svc *timesync_svc) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_interface *interface; + u64 init_frame_time; + unsigned long clock_rate = gb_timesync_clock_rate; + int ret; + + /* + * Get access to the wake pins in the AP and SVC + * Release these pins either in gb_timesync_teardown() or in + * gb_timesync_authoritative() + */ + ret = gb_timesync_platform_lock_bus(timesync_svc); + if (ret < 0) { + gb_timesync_platform_lock_bus_fail(timesync_svc, ret); + return; + } + ret = gb_svc_timesync_wake_pins_acquire(svc, timesync_svc->strobe_mask); + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_wake_pins_acquire %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + + /* Choose an initial time in the future */ + init_frame_time = __gb_timesync_get_frame_time(timesync_svc) + 100000UL; + + /* Send enable command to all relevant participants */ + list_for_each_entry(timesync_interface, ×ync_svc->interface_list, + list) { + interface = timesync_interface->interface; + ret = gb_interface_timesync_enable(interface, + GB_TIMESYNC_MAX_STROBES, + init_frame_time, + GB_TIMESYNC_STROBE_DELAY_US, + clock_rate); + if (ret) { + dev_err(&interface->dev, + "interface timesync_enable %d\n", ret); + } + } + + hd = timesync_svc->timesync_hd->hd; + ret = hd->driver->timesync_enable(hd, GB_TIMESYNC_MAX_STROBES, + init_frame_time, + GB_TIMESYNC_STROBE_DELAY_US, + clock_rate); + if (ret < 0) { + dev_err(&hd->dev, "host timesync_enable %d\n", + ret); + } + + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_WAIT_SVC); + ret = gb_svc_timesync_enable(svc, GB_TIMESYNC_MAX_STROBES, + init_frame_time, + GB_TIMESYNC_STROBE_DELAY_US, + clock_rate); + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_enable %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + + /* Schedule a timeout waiting for SVC to complete strobing */ + gb_timesync_schedule_svc_timeout(timesync_svc); +} + +static void gb_timesync_authoritative(struct gb_timesync_svc *timesync_svc) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_interface *interface; + u64 svc_frame_time[GB_TIMESYNC_MAX_STROBES]; + int ret; + + /* Get authoritative time from SVC and adjust local clock */ + ret = gb_svc_timesync_authoritative(svc, svc_frame_time); + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_authoritative %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + gb_timesync_collate_frame_time(timesync_svc, svc_frame_time); + + /* Transmit authoritative time to downstream slaves */ + hd = timesync_svc->timesync_hd->hd; + ret = hd->driver->timesync_authoritative(hd, svc_frame_time); + if (ret < 0) + dev_err(&hd->dev, "host timesync_authoritative %d\n", ret); + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + interface = timesync_interface->interface; + ret = gb_interface_timesync_authoritative( + interface, + svc_frame_time); + if (ret) { + dev_err(&interface->dev, + "interface timesync_authoritative %d\n", ret); + } + } + + /* Release wake pins */ + gb_svc_timesync_wake_pins_release(svc); + gb_timesync_platform_unlock_bus(); + + /* Transition to state ACTIVE */ + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_ACTIVE); + + /* Schedule a ping to verify the synchronized system time */ + timesync_svc->print_ping = true; + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_PING); +} + +static int __gb_timesync_get_status(struct gb_timesync_svc *timesync_svc) +{ + int ret = -EINVAL; + + switch (timesync_svc->state) { + case GB_TIMESYNC_STATE_INVALID: + case GB_TIMESYNC_STATE_INACTIVE: + ret = -ENODEV; + break; + case GB_TIMESYNC_STATE_INIT: + case GB_TIMESYNC_STATE_WAIT_SVC: + case GB_TIMESYNC_STATE_AUTHORITATIVE: + ret = -EAGAIN; + break; + case GB_TIMESYNC_STATE_PING: + case GB_TIMESYNC_STATE_ACTIVE: + ret = 0; + break; + } + return ret; +} + +/* + * This routine takes a FrameTime and derives the difference with-respect + * to a reference FrameTime/ktime pair. It then returns the calculated + * ktime based on the difference between the supplied FrameTime and + * the reference FrameTime. + * + * The time difference is calculated to six decimal places. Taking 19.2MHz + * as an example this means we have 52.083333~ nanoseconds per clock or + * 52083333~ femtoseconds per clock. + * + * Naively taking the count difference and converting to + * seconds/nanoseconds would quickly see the 0.0833 component produce + * noticeable errors. For example a time difference of one second would + * loose 19200000 * 0.08333x nanoseconds or 1.59 seconds. + * + * In contrast calculating in femtoseconds the same example of 19200000 * + * 0.000000083333x nanoseconds per count of error is just 1.59 nanoseconds! + * + * Continuing the example of 19.2 MHz we cap the maximum error difference + * at a worst-case 0.3 microseconds over a potential calculation window of + * abount 15 seconds, meaning you can convert a FrameTime that is <= 15 + * seconds older/younger than the reference time with a maximum error of + * 0.2385 useconds. Note 19.2MHz is an example frequency not a requirement. + */ +static int gb_timesync_to_timespec(struct gb_timesync_svc *timesync_svc, + u64 frame_time, struct timespec *ts) +{ + unsigned long flags; + u64 delta_fs, counts, sec, nsec; + bool add; + int ret = 0; + + memset(ts, 0x00, sizeof(*ts)); + mutex_lock(×ync_svc->mutex); + spin_lock_irqsave(×ync_svc->spinlock, flags); + + ret = __gb_timesync_get_status(timesync_svc); + if (ret) + goto done; + + /* Support calculating ktime upwards or downwards from the reference */ + if (frame_time < timesync_svc->ktime_data.frame_time) { + add = false; + counts = timesync_svc->ktime_data.frame_time - frame_time; + } else { + add = true; + counts = frame_time - timesync_svc->ktime_data.frame_time; + } + + /* Enforce the .23 of a usecond boundary @ 19.2MHz */ + if (counts > gb_timesync_max_ktime_diff) { + ret = -EINVAL; + goto done; + } + + /* Determine the time difference in femtoseconds */ + delta_fs = counts * gb_timesync_fs_per_clock; + + /* Convert to seconds */ + sec = delta_fs; + do_div(sec, NSEC_PER_SEC); + do_div(sec, 1000000UL); + + /* Get the nanosecond remainder */ + nsec = do_div(delta_fs, sec); + do_div(nsec, 1000000UL); + + if (add) { + /* Add the calculated offset - overflow nanoseconds upwards */ + ts->tv_sec = timesync_svc->ktime_data.ts.tv_sec + sec; + ts->tv_nsec = timesync_svc->ktime_data.ts.tv_nsec + nsec; + if (ts->tv_nsec >= NSEC_PER_SEC) { + ts->tv_sec++; + ts->tv_nsec -= NSEC_PER_SEC; + } + } else { + /* Subtract the difference over/underflow as necessary */ + if (nsec > timesync_svc->ktime_data.ts.tv_nsec) { + sec++; + nsec = nsec + timesync_svc->ktime_data.ts.tv_nsec; + nsec = do_div(nsec, NSEC_PER_SEC); + } else { + nsec = timesync_svc->ktime_data.ts.tv_nsec - nsec; + } + /* Cannot return a negative second value */ + if (sec > timesync_svc->ktime_data.ts.tv_sec) { + ret = -EINVAL; + goto done; + } + ts->tv_sec = timesync_svc->ktime_data.ts.tv_sec - sec; + ts->tv_nsec = nsec; + } +done: + spin_unlock_irqrestore(×ync_svc->spinlock, flags); + mutex_unlock(×ync_svc->mutex); + return ret; +} + +static size_t gb_timesync_log_frame_time(struct gb_timesync_svc *timesync_svc, + char *buf, size_t buflen) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_interface *interface; + unsigned int len; + size_t off; + + /* AP/SVC */ + off = snprintf(buf, buflen, "%s frametime: ap=%llu %s=%llu ", + greybus_bus_type.name, + timesync_svc->ap_ping_frame_time, dev_name(&svc->dev), + timesync_svc->svc_ping_frame_time); + len = buflen - off; + + /* APB/GPB */ + if (len < buflen) { + hd = timesync_svc->timesync_hd->hd; + off += snprintf(&buf[off], len, "%s=%llu ", dev_name(&hd->dev), + timesync_svc->timesync_hd->ping_frame_time); + len = buflen - off; + } + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + if (len < buflen) { + interface = timesync_interface->interface; + off += snprintf(&buf[off], len, "%s=%llu ", + dev_name(&interface->dev), + timesync_interface->ping_frame_time); + len = buflen - off; + } + } + if (len < buflen) + off += snprintf(&buf[off], len, "\n"); + return off; +} + +static size_t gb_timesync_log_frame_ktime(struct gb_timesync_svc *timesync_svc, + char *buf, size_t buflen) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_interface *interface; + struct timespec ts; + unsigned int len; + size_t off; + + /* AP */ + gb_timesync_to_timespec(timesync_svc, timesync_svc->ap_ping_frame_time, + &ts); + off = snprintf(buf, buflen, "%s frametime: ap=%lu.%lu ", + greybus_bus_type.name, ts.tv_sec, ts.tv_nsec); + len = buflen - off; + if (len >= buflen) + goto done; + + /* SVC */ + gb_timesync_to_timespec(timesync_svc, timesync_svc->svc_ping_frame_time, + &ts); + off += snprintf(&buf[off], len, "%s=%lu.%lu ", dev_name(&svc->dev), + ts.tv_sec, ts.tv_nsec); + len = buflen - off; + if (len >= buflen) + goto done; + + /* APB/GPB */ + hd = timesync_svc->timesync_hd->hd; + gb_timesync_to_timespec(timesync_svc, + timesync_svc->timesync_hd->ping_frame_time, + &ts); + off += snprintf(&buf[off], len, "%s=%lu.%lu ", + dev_name(&hd->dev), + ts.tv_sec, ts.tv_nsec); + len = buflen - off; + if (len >= buflen) + goto done; + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + interface = timesync_interface->interface; + gb_timesync_to_timespec(timesync_svc, + timesync_interface->ping_frame_time, + &ts); + off += snprintf(&buf[off], len, "%s=%lu.%lu ", + dev_name(&interface->dev), + ts.tv_sec, ts.tv_nsec); + len = buflen - off; + if (len >= buflen) + goto done; + } + off += snprintf(&buf[off], len, "\n"); +done: + return off; +} + +/* + * Send an SVC initiated wake 'ping' to each TimeSync participant. + * Get the FrameTime from each participant associated with the wake + * ping. + */ +static void gb_timesync_ping(struct gb_timesync_svc *timesync_svc) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_control *control; + u64 *ping_frame_time; + int ret; + + /* Get access to the wake pins in the AP and SVC */ + ret = gb_timesync_platform_lock_bus(timesync_svc); + if (ret < 0) { + gb_timesync_platform_lock_bus_fail(timesync_svc, ret); + return; + } + ret = gb_svc_timesync_wake_pins_acquire(svc, timesync_svc->strobe_mask); + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_wake_pins_acquire %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + + /* Have SVC generate a timesync ping */ + timesync_svc->capture_ping = true; + timesync_svc->svc_ping_frame_time = 0; + ret = gb_svc_timesync_ping(svc, ×ync_svc->svc_ping_frame_time); + timesync_svc->capture_ping = false; + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_ping %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + + /* Get the ping FrameTime from each APB/GPB */ + hd = timesync_svc->timesync_hd->hd; + timesync_svc->timesync_hd->ping_frame_time = 0; + ret = hd->driver->timesync_get_last_event(hd, + ×ync_svc->timesync_hd->ping_frame_time); + if (ret) + dev_err(&hd->dev, "host timesync_get_last_event %d\n", ret); + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + control = timesync_interface->interface->control; + timesync_interface->ping_frame_time = 0; + ping_frame_time = ×ync_interface->ping_frame_time; + ret = gb_control_timesync_get_last_event(control, + ping_frame_time); + if (ret) { + dev_err(×ync_interface->interface->dev, + "gb_control_timesync_get_last_event %d\n", ret); + } + } + + /* Ping success - move to timesync active */ + gb_svc_timesync_wake_pins_release(svc); + gb_timesync_platform_unlock_bus(); + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_ACTIVE); +} + +static void gb_timesync_log_ping_time(struct gb_timesync_svc *timesync_svc) +{ + char *buf; + + if (!timesync_svc->print_ping) + return; + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (buf) { + gb_timesync_log_frame_time(timesync_svc, buf, PAGE_SIZE); + dev_dbg(×ync_svc->svc->dev, "%s", buf); + kfree(buf); + } +} + +/* + * Perform the actual work of scheduled TimeSync logic. + */ +static void gb_timesync_worker(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct gb_timesync_svc *timesync_svc = + container_of(delayed_work, struct gb_timesync_svc, delayed_work); + + mutex_lock(×ync_svc->mutex); + + switch (timesync_svc->state) { + case GB_TIMESYNC_STATE_INIT: + gb_timesync_enable(timesync_svc); + break; + + case GB_TIMESYNC_STATE_WAIT_SVC: + dev_err(×ync_svc->svc->dev, + "timeout SVC strobe completion %d/%d\n", + timesync_svc->strobe, GB_TIMESYNC_MAX_STROBES); + gb_timesync_teardown(timesync_svc); + break; + + case GB_TIMESYNC_STATE_AUTHORITATIVE: + gb_timesync_authoritative(timesync_svc); + break; + + case GB_TIMESYNC_STATE_PING: + gb_timesync_ping(timesync_svc); + gb_timesync_log_ping_time(timesync_svc); + break; + + default: + pr_err("Invalid state %d for delayed work\n", + timesync_svc->state); + break; + } + + mutex_unlock(×ync_svc->mutex); +} + +/* + * Schedule a new TimeSync INIT or PING operation serialized w/r to + * gb_timesync_worker(). + */ +static int gb_timesync_schedule(struct gb_timesync_svc *timesync_svc, int state) +{ + int ret = 0; + + if (state != GB_TIMESYNC_STATE_INIT && state != GB_TIMESYNC_STATE_PING) + return -EINVAL; + + mutex_lock(×ync_svc->mutex); + if (timesync_svc->state != GB_TIMESYNC_STATE_INVALID) { + gb_timesync_set_state_atomic(timesync_svc, state); + } else { + ret = -ENODEV; + } + mutex_unlock(×ync_svc->mutex); + return ret; +} + +static int __gb_timesync_schedule_synchronous( + struct gb_timesync_svc *timesync_svc, int state) +{ + unsigned long flags; + int ret; + + ret = gb_timesync_schedule(timesync_svc, state); + if (ret) + return ret; + + ret = wait_event_interruptible(timesync_svc->wait_queue, + (timesync_svc->state == GB_TIMESYNC_STATE_ACTIVE || + timesync_svc->state == GB_TIMESYNC_STATE_INACTIVE || + timesync_svc->state == GB_TIMESYNC_STATE_INVALID)); + if (ret) + return ret; + + mutex_lock(×ync_svc->mutex); + spin_lock_irqsave(×ync_svc->spinlock, flags); + + ret = __gb_timesync_get_status(timesync_svc); + + spin_unlock_irqrestore(×ync_svc->spinlock, flags); + mutex_unlock(×ync_svc->mutex); + + return ret; +} + +static struct gb_timesync_svc *gb_timesync_find_timesync_svc( + struct gb_host_device *hd) +{ + struct gb_timesync_svc *timesync_svc; + + list_for_each_entry(timesync_svc, &gb_timesync_svc_list, list) { + if (timesync_svc->svc == hd->svc) + return timesync_svc; + } + return NULL; +} + +static struct gb_timesync_interface *gb_timesync_find_timesync_interface( + struct gb_timesync_svc *timesync_svc, + struct gb_interface *interface) +{ + struct gb_timesync_interface *timesync_interface; + + list_for_each_entry(timesync_interface, ×ync_svc->interface_list, list) { + if (timesync_interface->interface == interface) + return timesync_interface; + } + return NULL; +} + +int gb_timesync_schedule_synchronous(struct gb_interface *interface) +{ + int ret; + struct gb_timesync_svc *timesync_svc; + int retries; + + if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) + return 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + for (retries = 0; retries < GB_TIMESYNC_MAX_RETRIES; retries++) { + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } + + ret = __gb_timesync_schedule_synchronous(timesync_svc, + GB_TIMESYNC_STATE_INIT); + if (!ret) + break; + } + if (ret && retries == GB_TIMESYNC_MAX_RETRIES) + ret = -ETIMEDOUT; +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_schedule_synchronous); + +void gb_timesync_schedule_asynchronous(struct gb_interface *interface) +{ + struct gb_timesync_svc *timesync_svc; + + if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) + return; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) + goto done; + + gb_timesync_schedule(timesync_svc, GB_TIMESYNC_STATE_INIT); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return; +} +EXPORT_SYMBOL_GPL(gb_timesync_schedule_asynchronous); + +static ssize_t gb_timesync_ping_read(struct file *file, char __user *ubuf, + size_t len, loff_t *offset, bool ktime) +{ + struct gb_timesync_svc *timesync_svc = file->f_inode->i_private; + char *buf; + ssize_t ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + mutex_lock(×ync_svc->mutex); + if (list_empty(×ync_svc->interface_list)) + ret = -ENODEV; + timesync_svc->print_ping = false; + mutex_unlock(×ync_svc->mutex); + if (ret) + goto done; + + ret = __gb_timesync_schedule_synchronous(timesync_svc, + GB_TIMESYNC_STATE_PING); + if (ret) + goto done; + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto done; + } + + if (ktime) + ret = gb_timesync_log_frame_ktime(timesync_svc, buf, PAGE_SIZE); + else + ret = gb_timesync_log_frame_time(timesync_svc, buf, PAGE_SIZE); + if (ret > 0) + ret = simple_read_from_buffer(ubuf, len, offset, buf, ret); + kfree(buf); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} + +static ssize_t gb_timesync_ping_read_frame_time(struct file *file, + char __user *buf, + size_t len, loff_t *offset) +{ + return gb_timesync_ping_read(file, buf, len, offset, false); +} + +static ssize_t gb_timesync_ping_read_frame_ktime(struct file *file, + char __user *buf, + size_t len, loff_t *offset) +{ + return gb_timesync_ping_read(file, buf, len, offset, true); +} + +static const struct file_operations gb_timesync_debugfs_frame_time_ops = { + .read = gb_timesync_ping_read_frame_time, +}; + +static const struct file_operations gb_timesync_debugfs_frame_ktime_ops = { + .read = gb_timesync_ping_read_frame_ktime, +}; + +static int gb_timesync_hd_add(struct gb_timesync_svc *timesync_svc, + struct gb_host_device *hd) +{ + struct gb_timesync_host_device *timesync_hd; + + timesync_hd = kzalloc(sizeof(*timesync_hd), GFP_KERNEL); + if (!timesync_hd) + return -ENOMEM; + + WARN_ON(timesync_svc->timesync_hd); + timesync_hd->hd = hd; + timesync_svc->timesync_hd = timesync_hd; + + return 0; +} + +static void gb_timesync_hd_remove(struct gb_timesync_svc *timesync_svc, + struct gb_host_device *hd) +{ + if (timesync_svc->timesync_hd->hd == hd) { + kfree(timesync_svc->timesync_hd); + timesync_svc->timesync_hd = NULL; + return; + } + WARN_ON(1); +} + +int gb_timesync_svc_add(struct gb_svc *svc) +{ + struct gb_timesync_svc *timesync_svc; + int ret; + + timesync_svc = kzalloc(sizeof(*timesync_svc), GFP_KERNEL); + if (!timesync_svc) + return -ENOMEM; + + timesync_svc->work_queue = + create_singlethread_workqueue("gb-timesync-work_queue"); + + if (!timesync_svc->work_queue) { + kfree(timesync_svc); + return -ENOMEM; + } + + mutex_lock(&gb_timesync_svc_list_mutex); + INIT_LIST_HEAD(×ync_svc->interface_list); + INIT_DELAYED_WORK(×ync_svc->delayed_work, gb_timesync_worker); + mutex_init(×ync_svc->mutex); + spin_lock_init(×ync_svc->spinlock); + init_waitqueue_head(×ync_svc->wait_queue); + + timesync_svc->svc = svc; + timesync_svc->frame_time_offset = 0; + timesync_svc->capture_ping = false; + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INACTIVE); + + timesync_svc->frame_time_dentry = + debugfs_create_file("frame-time", S_IRUGO, svc->debugfs_dentry, + timesync_svc, + &gb_timesync_debugfs_frame_time_ops); + timesync_svc->frame_ktime_dentry = + debugfs_create_file("frame-ktime", S_IRUGO, svc->debugfs_dentry, + timesync_svc, + &gb_timesync_debugfs_frame_ktime_ops); + + list_add(×ync_svc->list, &gb_timesync_svc_list); + ret = gb_timesync_hd_add(timesync_svc, svc->hd); + if (ret) { + list_del(×ync_svc->list); + debugfs_remove(timesync_svc->frame_ktime_dentry); + debugfs_remove(timesync_svc->frame_time_dentry); + destroy_workqueue(timesync_svc->work_queue); + kfree(timesync_svc); + goto done; + } + + init_timer(×ync_svc->ktime_timer); + timesync_svc->ktime_timer.function = gb_timesync_ktime_timer_fn; + timesync_svc->ktime_timer.expires = jiffies + GB_TIMESYNC_KTIME_UPDATE; + timesync_svc->ktime_timer.data = (unsigned long)timesync_svc; + add_timer(×ync_svc->ktime_timer); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_svc_add); + +void gb_timesync_svc_remove(struct gb_svc *svc) +{ + struct gb_timesync_svc *timesync_svc; + struct gb_timesync_interface *timesync_interface; + struct gb_timesync_interface *next; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(svc->hd); + if (!timesync_svc) + goto done; + + cancel_delayed_work_sync(×ync_svc->delayed_work); + + mutex_lock(×ync_svc->mutex); + + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INVALID); + del_timer_sync(×ync_svc->ktime_timer); + gb_timesync_teardown(timesync_svc); + + gb_timesync_hd_remove(timesync_svc, svc->hd); + list_for_each_entry_safe(timesync_interface, next, + ×ync_svc->interface_list, list) { + list_del(×ync_interface->list); + kfree(timesync_interface); + } + debugfs_remove(timesync_svc->frame_ktime_dentry); + debugfs_remove(timesync_svc->frame_time_dentry); + destroy_workqueue(timesync_svc->work_queue); + list_del(×ync_svc->list); + + mutex_unlock(×ync_svc->mutex); + + kfree(timesync_svc); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); +} +EXPORT_SYMBOL_GPL(gb_timesync_svc_remove); + +/* + * Add a Greybus Interface to the set of TimeSync Interfaces. + */ +int gb_timesync_interface_add(struct gb_interface *interface) +{ + struct gb_timesync_svc *timesync_svc; + struct gb_timesync_interface *timesync_interface; + int ret = 0; + + if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) + return 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } + + timesync_interface = kzalloc(sizeof(*timesync_interface), GFP_KERNEL); + if (!timesync_interface) { + ret = -ENOMEM; + goto done; + } + + mutex_lock(×ync_svc->mutex); + timesync_interface->interface = interface; + list_add(×ync_interface->list, ×ync_svc->interface_list); + timesync_svc->strobe_mask |= 1 << interface->interface_id; + mutex_unlock(×ync_svc->mutex); + +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_interface_add); + +/* + * Remove a Greybus Interface from the set of TimeSync Interfaces. + */ +void gb_timesync_interface_remove(struct gb_interface *interface) +{ + struct gb_timesync_svc *timesync_svc; + struct gb_timesync_interface *timesync_interface; + + if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) + return; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) + goto done; + + timesync_interface = gb_timesync_find_timesync_interface(timesync_svc, + interface); + if (!timesync_interface) + goto done; + + mutex_lock(×ync_svc->mutex); + timesync_svc->strobe_mask &= ~(1 << interface->interface_id); + list_del(×ync_interface->list); + kfree(timesync_interface); + mutex_unlock(×ync_svc->mutex); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); +} +EXPORT_SYMBOL_GPL(gb_timesync_interface_remove); + +/* + * Give the authoritative FrameTime to the calling function. Returns zero if we + * are not in GB_TIMESYNC_STATE_ACTIVE. + */ +static u64 gb_timesync_get_frame_time(struct gb_timesync_svc *timesync_svc) +{ + unsigned long flags; + u64 ret; + + spin_lock_irqsave(×ync_svc->spinlock, flags); + if (timesync_svc->state == GB_TIMESYNC_STATE_ACTIVE) + ret = __gb_timesync_get_frame_time(timesync_svc); + else + ret = 0; + spin_unlock_irqrestore(×ync_svc->spinlock, flags); + return ret; +} + +u64 gb_timesync_get_frame_time_by_interface(struct gb_interface *interface) +{ + struct gb_timesync_svc *timesync_svc; + u64 ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) + goto done; + + ret = gb_timesync_get_frame_time(timesync_svc); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_get_frame_time_by_interface); + +u64 gb_timesync_get_frame_time_by_svc(struct gb_svc *svc) +{ + struct gb_timesync_svc *timesync_svc; + u64 ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(svc->hd); + if (!timesync_svc) + goto done; + + ret = gb_timesync_get_frame_time(timesync_svc); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_get_frame_time_by_svc); + +/* Incrementally updates the conversion base from FrameTime to ktime */ +static void gb_timesync_ktime_timer_fn(unsigned long data) +{ + struct gb_timesync_svc *timesync_svc = + (struct gb_timesync_svc *)data; + unsigned long flags; + u64 frame_time; + struct timespec ts; + + spin_lock_irqsave(×ync_svc->spinlock, flags); + + if (timesync_svc->state != GB_TIMESYNC_STATE_ACTIVE) + goto done; + + ktime_get_ts(&ts); + frame_time = __gb_timesync_get_frame_time(timesync_svc); + gb_timesync_store_ktime(timesync_svc, ts, frame_time); + +done: + spin_unlock_irqrestore(×ync_svc->spinlock, flags); + mod_timer(×ync_svc->ktime_timer, + jiffies + GB_TIMESYNC_KTIME_UPDATE); +} + +int gb_timesync_to_timespec_by_svc(struct gb_svc *svc, u64 frame_time, + struct timespec *ts) +{ + struct gb_timesync_svc *timesync_svc; + int ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(svc->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } + ret = gb_timesync_to_timespec(timesync_svc, frame_time, ts); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_to_timespec_by_svc); + +int gb_timesync_to_timespec_by_interface(struct gb_interface *interface, + u64 frame_time, struct timespec *ts) +{ + struct gb_timesync_svc *timesync_svc; + int ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } + + ret = gb_timesync_to_timespec(timesync_svc, frame_time, ts); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_to_timespec_by_interface); + +void gb_timesync_irq(struct gb_timesync_svc *timesync_svc) +{ + unsigned long flags; + u64 strobe_time; + bool strobe_is_ping = true; + struct timespec ts; + + ktime_get_ts(&ts); + strobe_time = __gb_timesync_get_frame_time(timesync_svc); + + spin_lock_irqsave(×ync_svc->spinlock, flags); + + if (timesync_svc->state == GB_TIMESYNC_STATE_PING) { + if (!timesync_svc->capture_ping) + goto done_nolog; + timesync_svc->ap_ping_frame_time = strobe_time; + goto done_log; + } else if (timesync_svc->state != GB_TIMESYNC_STATE_WAIT_SVC) { + goto done_nolog; + } + + timesync_svc->strobe_data[timesync_svc->strobe].frame_time = strobe_time; + timesync_svc->strobe_data[timesync_svc->strobe].ts = ts; + + if (++timesync_svc->strobe == GB_TIMESYNC_MAX_STROBES) { + gb_timesync_set_state(timesync_svc, + GB_TIMESYNC_STATE_AUTHORITATIVE); + } + strobe_is_ping = false; +done_log: + trace_gb_timesync_irq(strobe_is_ping, timesync_svc->strobe, + GB_TIMESYNC_MAX_STROBES, strobe_time); +done_nolog: + spin_unlock_irqrestore(×ync_svc->spinlock, flags); +} +EXPORT_SYMBOL(gb_timesync_irq); + +int __init gb_timesync_init(void) +{ + int ret = 0; + + ret = gb_timesync_platform_init(); + if (ret) { + pr_err("timesync platform init fail!\n"); + return ret; + } + + gb_timesync_clock_rate = gb_timesync_platform_get_clock_rate(); + + /* Calculate nanoseconds and femtoseconds per clock */ + gb_timesync_fs_per_clock = FSEC_PER_SEC; + do_div(gb_timesync_fs_per_clock, gb_timesync_clock_rate); + gb_timesync_ns_per_clock = NSEC_PER_SEC; + do_div(gb_timesync_ns_per_clock, gb_timesync_clock_rate); + + /* Calculate the maximum number of clocks we will convert to ktime */ + gb_timesync_max_ktime_diff = + GB_TIMESYNC_MAX_KTIME_CONVERSION * gb_timesync_clock_rate; + + pr_info("Time-Sync @ %lu Hz max ktime conversion +/- %d seconds\n", + gb_timesync_clock_rate, GB_TIMESYNC_MAX_KTIME_CONVERSION); + return 0; +} + +void gb_timesync_exit(void) +{ + gb_timesync_platform_exit(); +} diff --git a/drivers/staging/greybus/timesync.h b/drivers/staging/greybus/timesync.h new file mode 100644 index 000000000000..72fc9a35a002 --- /dev/null +++ b/drivers/staging/greybus/timesync.h @@ -0,0 +1,45 @@ +/* + * TimeSync API driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __TIMESYNC_H +#define __TIMESYNC_H + +struct gb_svc; +struct gb_interface; +struct gb_timesync_svc; + +/* Platform */ +u64 gb_timesync_platform_get_counter(void); +u32 gb_timesync_platform_get_clock_rate(void); +int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata); +void gb_timesync_platform_unlock_bus(void); + +int gb_timesync_platform_init(void); +void gb_timesync_platform_exit(void); + +/* Core API */ +int gb_timesync_interface_add(struct gb_interface *interface); +void gb_timesync_interface_remove(struct gb_interface *interface); +int gb_timesync_svc_add(struct gb_svc *svc); +void gb_timesync_svc_remove(struct gb_svc *svc); + +u64 gb_timesync_get_frame_time_by_interface(struct gb_interface *interface); +u64 gb_timesync_get_frame_time_by_svc(struct gb_svc *svc); +int gb_timesync_to_timespec_by_svc(struct gb_svc *svc, u64 frame_time, + struct timespec *ts); +int gb_timesync_to_timespec_by_interface(struct gb_interface *interface, + u64 frame_time, struct timespec *ts); + +int gb_timesync_schedule_synchronous(struct gb_interface *intf); +void gb_timesync_schedule_asynchronous(struct gb_interface *intf); +void gb_timesync_irq(struct gb_timesync_svc *timesync_svc); +int gb_timesync_init(void); +void gb_timesync_exit(void); + +#endif /* __TIMESYNC_H */ diff --git a/drivers/staging/greybus/timesync_platform.c b/drivers/staging/greybus/timesync_platform.c new file mode 100644 index 000000000000..113f3d6c4b3a --- /dev/null +++ b/drivers/staging/greybus/timesync_platform.c @@ -0,0 +1,82 @@ +/* + * TimeSync API driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + * + * This code reads directly from an ARMv7 memory-mapped timer that lives in + * MMIO space. Since this counter lives inside of MMIO space its shared between + * cores and that means we don't have to worry about issues like TSC on x86 + * where each time-stamp-counter (TSC) is local to a particular core. + * + * Register-level access code is based on + * drivers/clocksource/arm_arch_timer.c + */ +#include +#include + +#include "greybus.h" +#include "arche_platform.h" + +#define DEFAULT_FRAMETIME_CLOCK_HZ 19200000 + +static u32 gb_timesync_clock_frequency; +int (*arche_platform_change_state_cb)(enum arche_platform_state state, + struct gb_timesync_svc *pdata); +EXPORT_SYMBOL_GPL(arche_platform_change_state_cb); + +u64 gb_timesync_platform_get_counter(void) +{ + return (u64)get_cycles(); +} + +u32 gb_timesync_platform_get_clock_rate(void) +{ + if (unlikely(!gb_timesync_clock_frequency)) { + gb_timesync_clock_frequency = cpufreq_get(0); + if (!gb_timesync_clock_frequency) + gb_timesync_clock_frequency = DEFAULT_FRAMETIME_CLOCK_HZ; + } + + return gb_timesync_clock_frequency; +} + +int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata) +{ + return arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_TIME_SYNC, + pdata); +} + +void gb_timesync_platform_unlock_bus(void) +{ + arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_ACTIVE, NULL); +} + +static const struct of_device_id arch_timer_of_match[] = { + { .compatible = "google,greybus-frame-time-counter", }, + {}, +}; + +int __init gb_timesync_platform_init(void) +{ + struct device_node *np; + + np = of_find_matching_node(NULL, arch_timer_of_match); + if (!np) { + /* Tolerate not finding to allow BBB etc to continue */ + pr_warn("Unable to find a compatible ARMv7 timer\n"); + return 0; + } + + if (of_property_read_u32(np, "clock-frequency", + &gb_timesync_clock_frequency)) { + pr_err("Unable to find timer clock-frequency\n"); + return -ENODEV; + } + + return 0; +} + +void gb_timesync_platform_exit(void) {} diff --git a/drivers/staging/greybus/tools/.gitignore b/drivers/staging/greybus/tools/.gitignore new file mode 100644 index 000000000000..023654c83068 --- /dev/null +++ b/drivers/staging/greybus/tools/.gitignore @@ -0,0 +1 @@ +loopback_test diff --git a/drivers/staging/greybus/tools/Android.mk b/drivers/staging/greybus/tools/Android.mk new file mode 100644 index 000000000000..fdadbf611757 --- /dev/null +++ b/drivers/staging/greybus/tools/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= loopback_test.c +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := gb_loopback_test + +include $(BUILD_EXECUTABLE) + diff --git a/drivers/staging/greybus/tools/Makefile b/drivers/staging/greybus/tools/Makefile new file mode 100644 index 000000000000..852b12b71149 --- /dev/null +++ b/drivers/staging/greybus/tools/Makefile @@ -0,0 +1,31 @@ +ifeq ($(strip $(V)), 1) + Q = +else + Q = @ +endif + +CFLAGS += -std=gnu99 -Wall -Wextra -g \ + -D_GNU_SOURCE \ + -Wno-unused-parameter \ + -Wmaybe-uninitialized \ + -Wredundant-decls \ + -Wcast-align \ + -Wsign-compare \ + -Wno-missing-field-initializers + +CC := $(CROSS_COMPILE)gcc + +TOOLS = loopback_test + +all: $(TOOLS) + +%.o: %.c ../greybus_protocols.h + @echo ' TARGET_CC $@' + $(Q)$(CC) $(CFLAGS) -c $< -o $@ + +loopback_%: loopback_%.o + @echo ' TARGET_LD $@' + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ + +clean:: + rm -f *.o $(TOOLS) diff --git a/drivers/staging/greybus/tools/README.loopback b/drivers/staging/greybus/tools/README.loopback new file mode 100644 index 000000000000..845b08dc4696 --- /dev/null +++ b/drivers/staging/greybus/tools/README.loopback @@ -0,0 +1,198 @@ + + + 1 - LOOPBACK DRIVER + +The driver implements the main logic of the loopback test and provides +sysfs files to configure the test and retrieve the results. +A user could run a test without the need of the test application given +that he understands the sysfs interface of the loopback driver. + +The loopback kernel driver needs to be loaded and at least one module +with the loopback feature enabled must be present for the sysfs files to be +created and for the loopback test application to be able to run. + +To load the module: +# modprobe gb-loopback + + +When the module is probed, New files are available on the sysfs +directory of the detected loopback device. +(typically under "/sys/bus/graybus/devices"). + +Here is a short summary of the sysfs interface files that should be visible: + +* Loopback Configuration Files: + async - Use asynchronous operations. + iteration_max - Number of tests iterations to perform. + size - payload size of the transfer. + timeout - The number of microseconds to give an individual + asynchronous request before timing out. + us_wait - Time to wait between 2 messages + type - By writing the test type to this file, the test starts. + Valid tests are: + 0 stop the test + 2 - ping + 3 - transfer + 4 - sink + +* Loopback feedback files: + error - number of errors that have occurred. + iteration_count - Number of iterations performed. + requests_completed - Number of requests successfully completed. + requests_timedout - Number of requests that have timed out. + timeout_max - Max allowed timeout + timeout_min - Min allowed timeout. + +* Loopback result files: + apbridge_unipro_latency_avg + apbridge_unipro_latency_max + apbridge_unipro_latency_min + gpbridge_firmware_latency_avg + gpbridge_firmware_latency_max + gpbridge_firmware_latency_min + requests_per_second_avg + requests_per_second_max + requests_per_second_min + latency_avg + latency_max + latency_min + throughput_avg + throughput_max + throughput_min + + + + 2 - LOOPBACK TEST APPLICATION + +The loopback test application manages and formats the results provided by +the loopback kernel module. The purpose of this application +is to: + - Start and manage multiple loopback device tests concurrently. + - Calculate the aggregate results for multiple devices. + - Gather and format test results (csv or human readable). + +The best way to get up to date usage information for the application is +usually to pass the "-h" parameter. +Here is the summary of the available options: + + Mandatory arguments + -t must be one of the test names - sink, transfer or ping + -i iteration count - the number of iterations to run the test over + Optional arguments + -S sysfs location - location for greybus 'endo' entires default /sys/bus/greybus/devices/ + -D debugfs location - location for loopback debugfs entries default /sys/kernel/debug/gb_loopback/ + -s size of data packet to send during test - defaults to zero + -m mask - a bit mask of connections to include example: -m 8 = 4th connection -m 9 = 1st and 4th connection etc + default is zero which means broadcast to all connections + -v verbose output + -d debug output + -r raw data output - when specified the full list of latency values are included in the output CSV + -p porcelain - when specified printout is in a user-friendly non-CSV format. This option suppresses writing to CSV file + -a aggregate - show aggregation of all enabled devies + -l list found loopback devices and exit. + -x Async - Enable async transfers. + -o Timeout - Timeout in microseconds for async operations. + + + + 3 - REAL WORLD EXAMPLE USAGES + + 3.1 - Using the driver sysfs files to run a test on a single device: + +* Run a 1000 transfers of a 100 byte packet. Each transfer is started only +after the previous one finished successfully: + echo 0 > /sys/bus/greybus/devices/1-2.17/type + echo 0 > /sys/bus/greybus/devices/1-2.17/async + echo 2000 > /sys/bus/greybus/devices/1-2.17/us_wait + echo 100 > /sys/bus/greybus/devices/1-2.17/size + echo 1000 > /sys/bus/greybus/devices/1-2.17/iteration_max + echo 0 > /sys/bus/greybus/devices/1-2.17/mask + echo 200000 > /sys/bus/greybus/devices/1-2.17/timeout + echo 3 > /sys/bus/greybus/devices/1-2.17/type + +* Run a 1000 transfers of a 100 byte packet. Transfers are started without +waiting for the previous one to finish: + echo 0 > /sys/bus/greybus/devices/1-2.17/type + echo 3 > /sys/bus/greybus/devices/1-2.17/async + echo 0 > /sys/bus/greybus/devices/1-2.17/us_wait + echo 100 > /sys/bus/greybus/devices/1-2.17/size + echo 1000 > /sys/bus/greybus/devices/1-2.17/iteration_max + echo 0 > /sys/bus/greybus/devices/1-2.17/mask + echo 200000 > /sys/bus/greybus/devices/1-2.17/timeout + echo 3 > /sys/bus/greybus/devices/1-2.17/type + +* Read the results from sysfs: + cat /sys/bus/greybus/devices/1-2.17/requests_per_second_min + cat /sys/bus/greybus/devices/1-2.17/requests_per_second_max + cat /sys/bus/greybus/devices/1-2.17/requests_per_second_avg + + cat /sys/bus/greybus/devices/1-2.17/latency_min + cat /sys/bus/greybus/devices/1-2.17/latency_max + cat /sys/bus/greybus/devices/1-2.17/latency_avg + + cat /sys/bus/greybus/devices/1-2.17/apbridge_unipro_latency_min + cat /sys/bus/greybus/devices/1-2.17/apbridge_unipro_latency_max + cat /sys/bus/greybus/devices/1-2.17/apbridge_unipro_latency_avg + + cat /sys/bus/greybus/devices/1-2.17/gpbridge_firmware_latency_min + cat /sys/bus/greybus/devices/1-2.17/gpbridge_firmware_latency_max + cat /sys/bus/greybus/devices/1-2.17/gpbridge_firmware_latency_avg + + cat /sys/bus/greybus/devices/1-2.17/error + cat /sys/bus/greybus/devices/1-2.17/requests_completed + cat /sys/bus/greybus/devices/1-2.17/requests_timedout + + +3.2 - using the test application: + +* Run a transfer test 10 iterations of size 100 bytes on all available devices + #/loopback_test -t transfer -i 10 -s 100 + 1970-1-1 0:10:7,transfer,1-4.17,100,10,0,443,509,471.700012,66,1963,2256,2124.600098,293,102776,118088,109318.898438,15312,1620,1998,1894.099976,378,56,57,56.799999,1 + 1970-1-1 0:10:7,transfer,1-5.17,100,10,0,399,542,463.399994,143,1845,2505,2175.800049,660,92568,125744,107393.296875,33176,1469,2305,1806.500000,836,56,57,56.799999,1 + + +* Show the aggregate results of both devices. ("-a") + #/loopback_test -t transfer -i 10 -s 100 -a + 1970-1-1 0:10:35,transfer,1-4.17,100,10,0,448,580,494.100006,132,1722,2230,2039.400024,508,103936,134560,114515.703125,30624,1513,1980,1806.900024,467,56,57,57.299999,1 + 1970-1-1 0:10:35,transfer,1-5.17,100,10,0,383,558,478.600006,175,1791,2606,2115.199951,815,88856,129456,110919.703125,40600,1457,2246,1773.599976,789,56,57,57.099998,1 + 1970-1-1 0:10:35,transfer,aggregate,100,10,0,383,580,486.000000,197,1722,2606,2077.000000,884,88856,134560,112717.000000,45704,1457,2246,1789.000000,789,56,57,57.000000,1 + +* Example usage of the mask option to select which devices will + run the test (1st, 2nd, or both devices): + # /loopback_test -t transfer -i 10 -s 100 -m 1 + 1970-1-1 0:11:56,transfer,1-4.17,100,10,0,514,558,544.900024,44,1791,1943,1836.599976,152,119248,129456,126301.296875,10208,1600,1001609,101613.601562,1000009,56,57,56.900002,1 + # /loopback_test -t transfer -i 10 -s 100 -m 2 + 1970-1-1 0:12:0,transfer,1-5.17,100,10,0,468,554,539.000000,86,1804,2134,1859.500000,330,108576,128528,124932.500000,19952,1606,1626,1619.300049,20,56,57,57.400002,1 + # /loopback_test -t transfer -i 10 -s 100 -m 3 + 1970-1-1 0:12:3,transfer,1-4.17,100,10,0,432,510,469.399994,78,1959,2313,2135.800049,354,100224,118320,108785.296875,18096,1610,2024,1893.500000,414,56,57,57.200001,1 + 1970-1-1 0:12:3,transfer,1-5.17,100,10,0,404,542,468.799988,138,1843,2472,2152.500000,629,93728,125744,108646.101562,32016,1504,2247,1853.099976,743,56,57,57.099998,1 + +* Show output in human readable format ("-p") + # /loopback_test -t transfer -i 10 -s 100 -m 3 -p + + 1970-1-1 0:12:37 + test: transfer + path: 1-4.17 + size: 100 + iterations: 10 + errors: 0 + async: Disabled + requests per-sec: min=390, max=547, average=469.299988, jitter=157 + ap-throughput B/s: min=90480 max=126904 average=108762.101562 jitter=36424 + ap-latency usec: min=1826 max=2560 average=2146.000000 jitter=734 + apbridge-latency usec: min=1620 max=1982 average=1882.099976 jitter=362 + gpbridge-latency usec: min=56 max=57 average=57.099998 jitter=1 + + + 1970-1-1 0:12:37 + test: transfer + path: 1-5.17 + size: 100 + iterations: 10 + errors: 0 + async: Disabled + requests per-sec: min=397, max=538, average=461.700012, jitter=141 + ap-throughput B/s: min=92104 max=124816 average=106998.898438 jitter=32712 + ap-latency usec: min=1856 max=2514 average=2185.699951 jitter=658 + apbridge-latency usec: min=1460 max=2296 average=1828.599976 jitter=836 + gpbridge-latency usec: min=56 max=57 average=57.099998 jitter=1 diff --git a/drivers/staging/greybus/tools/lbtest b/drivers/staging/greybus/tools/lbtest new file mode 100755 index 000000000000..d7353f1a2a6f --- /dev/null +++ b/drivers/staging/greybus/tools/lbtest @@ -0,0 +1,168 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google, Inc. +# Copyright (c) 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: +# 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. + +from __future__ import print_function +import csv +import datetime +import sys +import time + +dict = {'ping': '2', 'transfer': '3', 'sink': '4'} +verbose = 1 + +def abort(): + sys.exit(1) + +def usage(): + print('Usage: looptest TEST SIZE ITERATIONS PATH\n\n' + ' Run TEST for a number of ITERATIONS with operation data SIZE bytes\n' + ' TEST may be \'ping\' \'transfer\' or \'sink\'\n' + ' SIZE indicates the size of transfer <= greybus max payload bytes\n' + ' ITERATIONS indicates the number of times to execute TEST at SIZE bytes\n' + ' Note if ITERATIONS is set to zero then this utility will\n' + ' initiate an infinite (non terminating) test and exit\n' + ' without logging any metrics data\n' + ' PATH indicates the sysfs path for the loopback greybus entries e.g.\n' + ' /sys/bus/greybus/devices/endo0:1:1:1:1/\n' + 'Examples:\n' + ' looptest transfer 128 10000\n' + ' looptest ping 0 128\n' + ' looptest sink 2030 32768\n' + .format(sys.argv[0]), file=sys.stderr) + + abort() + +def read_sysfs_int(path): + try: + f = open(path, "r"); + val = f.read(); + f.close() + return int(val) + except IOError as e: + print("I/O error({0}): {1}".format(e.errno, e.strerror)) + print("Invalid path %s" % path) + +def write_sysfs_val(path, val): + try: + f = open(path, "r+") + f.write(val) + f.close() + except IOError as e: + print("I/O error({0}): {1}".format(e.errno, e.strerror)) + print("Invalid path %s" % path) + +def log_csv(test_name, size, iteration_max, sys_pfx): + # file name will test_name_size_iteration_max.csv + # every time the same test with the same parameters is run we will then + # append to the same CSV with datestamp - representing each test dataset + fname = test_name + '_' + size + '_' + str(iteration_max) + '.csv' + + try: + # gather data set + date = str(datetime.datetime.now()) + error = read_sysfs_int(sys_pfx + 'error') + request_min = read_sysfs_int(sys_pfx + 'requests_per_second_min') + request_max = read_sysfs_int(sys_pfx + 'requests_per_second_max') + request_avg = read_sysfs_int(sys_pfx + 'requests_per_second_avg') + latency_min = read_sysfs_int(sys_pfx + 'latency_min') + latency_max = read_sysfs_int(sys_pfx + 'latency_max') + latency_avg = read_sysfs_int(sys_pfx + 'latency_avg') + throughput_min = read_sysfs_int(sys_pfx + 'throughput_min') + throughput_max = read_sysfs_int(sys_pfx + 'throughput_max') + throughput_avg = read_sysfs_int(sys_pfx + 'throughput_avg') + + # derive jitter + request_jitter = request_max - request_min + latency_jitter = latency_max - latency_min + throughput_jitter = throughput_max - throughput_min + + # append data set to file + with open(fname, 'a') as csvf: + row = csv.writer(csvf, delimiter=",", quotechar="'", + quoting=csv.QUOTE_MINIMAL) + row.writerow([date, test_name, size, iteration_max, error, + request_min, request_max, request_avg, request_jitter, + latency_min, latency_max, latency_avg, latency_jitter, + throughput_min, throughput_max, throughput_avg, throughput_jitter]) + except IOError as e: + print("I/O error({0}): {1}".format(e.errno, e.strerror)) + +def loopback_run(test_name, size, iteration_max, sys_pfx): + test_id = dict[test_name] + try: + # Terminate any currently running test + write_sysfs_val(sys_pfx + 'type', '0') + # Set parameter for no wait between messages + write_sysfs_val(sys_pfx + 'ms_wait', '0') + # Set operation size + write_sysfs_val(sys_pfx + 'size', size) + # Set iterations + write_sysfs_val(sys_pfx + 'iteration_max', str(iteration_max)) + # Initiate by setting loopback operation type + write_sysfs_val(sys_pfx + 'type', test_id) + time.sleep(1) + + if iteration_max == 0: + print ("Infinite test initiated CSV won't be logged\n") + return + + previous = 0 + err = 0 + while True: + # get current count bail out if it hasn't changed + iteration_count = read_sysfs_int(sys_pfx + 'iteration_count') + if previous == iteration_count: + err = 1 + break + elif iteration_count == iteration_max: + break + previous = iteration_count + if verbose: + print('%02d%% complete %d of %d ' % + (100 * iteration_count / iteration_max, + iteration_count, iteration_max)) + time.sleep(1) + if err: + print ('\nError executing test\n') + else: + log_csv(test_name, size, iteration_max, sys_pfx) + except ValueError as ve: + print("Error: %s " % format(e.strerror), file=sys.stderr) + abort() + +def main(): + if len(sys.argv) < 5: + usage() + + if sys.argv[1] in dict.keys(): + loopback_run(sys.argv[1], sys.argv[2], int(sys.argv[3]), sys.argv[4]) + else: + usage() +if __name__ == '__main__': + main() diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c new file mode 100644 index 000000000000..f7f4cd6fb55b --- /dev/null +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -0,0 +1,1000 @@ +/* + * Loopback test application + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Provided under the three clause BSD license found in the LICENSE file. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NUM_DEVICES 10 +#define MAX_SYSFS_PATH 0x200 +#define CSV_MAX_LINE 0x1000 +#define SYSFS_MAX_INT 0x20 +#define MAX_STR_LEN 255 +#define DEFAULT_ASYNC_TIMEOUT 200000 + +struct dict { + char *name; + int type; +}; + +static struct dict dict[] = { + {"ping", 2}, + {"transfer", 3}, + {"sink", 4}, + {NULL,} /* list termination */ +}; + +struct loopback_results { + float latency_avg; + uint32_t latency_max; + uint32_t latency_min; + uint32_t latency_jitter; + + float request_avg; + uint32_t request_max; + uint32_t request_min; + uint32_t request_jitter; + + float throughput_avg; + uint32_t throughput_max; + uint32_t throughput_min; + uint32_t throughput_jitter; + + float apbridge_unipro_latency_avg; + uint32_t apbridge_unipro_latency_max; + uint32_t apbridge_unipro_latency_min; + uint32_t apbridge_unipro_latency_jitter; + + float gbphy_firmware_latency_avg; + uint32_t gbphy_firmware_latency_max; + uint32_t gbphy_firmware_latency_min; + uint32_t gbphy_firmware_latency_jitter; + + uint32_t error; +}; + +struct loopback_device { + char name[MAX_SYSFS_PATH]; + char sysfs_entry[MAX_SYSFS_PATH]; + char debugfs_entry[MAX_SYSFS_PATH]; + struct loopback_results results; +}; + +struct loopback_test { + int verbose; + int debug; + int raw_data_dump; + int porcelain; + int mask; + int size; + int iteration_max; + int aggregate_output; + int test_id; + int device_count; + int list_devices; + int use_async; + int async_timeout; + int async_outstanding_operations; + int us_wait; + int file_output; + int stop_all; + int poll_count; + char test_name[MAX_STR_LEN]; + char sysfs_prefix[MAX_SYSFS_PATH]; + char debugfs_prefix[MAX_SYSFS_PATH]; + struct timespec poll_timeout; + struct loopback_device devices[MAX_NUM_DEVICES]; + struct loopback_results aggregate_results; + struct pollfd fds[MAX_NUM_DEVICES]; +}; + +struct loopback_test t; + +/* Helper macros to calculate the aggregate results for all devices */ +static inline int device_enabled(struct loopback_test *t, int dev_idx); + +#define GET_MAX(field) \ +static int get_##field##_aggregate(struct loopback_test *t) \ +{ \ + uint32_t max = 0; \ + int i; \ + for (i = 0; i < t->device_count; i++) { \ + if (!device_enabled(t, i)) \ + continue; \ + if (t->devices[i].results.field > max) \ + max = t->devices[i].results.field; \ + } \ + return max; \ +} \ + +#define GET_MIN(field) \ +static int get_##field##_aggregate(struct loopback_test *t) \ +{ \ + uint32_t min = ~0; \ + int i; \ + for (i = 0; i < t->device_count; i++) { \ + if (!device_enabled(t, i)) \ + continue; \ + if (t->devices[i].results.field < min) \ + min = t->devices[i].results.field; \ + } \ + return min; \ +} \ + +#define GET_AVG(field) \ +static int get_##field##_aggregate(struct loopback_test *t) \ +{ \ + uint32_t val = 0; \ + uint32_t count = 0; \ + int i; \ + for (i = 0; i < t->device_count; i++) { \ + if (!device_enabled(t, i)) \ + continue; \ + count++; \ + val += t->devices[i].results.field; \ + } \ + if (count) \ + val /= count; \ + return val; \ +} \ + +GET_MAX(throughput_max); +GET_MAX(request_max); +GET_MAX(latency_max); +GET_MAX(apbridge_unipro_latency_max); +GET_MAX(gbphy_firmware_latency_max); +GET_MIN(throughput_min); +GET_MIN(request_min); +GET_MIN(latency_min); +GET_MIN(apbridge_unipro_latency_min); +GET_MIN(gbphy_firmware_latency_min); +GET_AVG(throughput_avg); +GET_AVG(request_avg); +GET_AVG(latency_avg); +GET_AVG(apbridge_unipro_latency_avg); +GET_AVG(gbphy_firmware_latency_avg); + +void abort() +{ + _exit(1); +} + +void usage(void) +{ + fprintf(stderr, "Usage: loopback_test TEST [SIZE] ITERATIONS [SYSPATH] [DBGPATH]\n\n" + " Run TEST for a number of ITERATIONS with operation data SIZE bytes\n" + " TEST may be \'ping\' \'transfer\' or \'sink\'\n" + " SIZE indicates the size of transfer <= greybus max payload bytes\n" + " ITERATIONS indicates the number of times to execute TEST at SIZE bytes\n" + " Note if ITERATIONS is set to zero then this utility will\n" + " initiate an infinite (non terminating) test and exit\n" + " without logging any metrics data\n" + " SYSPATH indicates the sysfs path for the loopback greybus entries e.g.\n" + " /sys/bus/greybus/devices\n" + " DBGPATH indicates the debugfs path for the loopback greybus entries e.g.\n" + " /sys/kernel/debug/gb_loopback/\n" + " Mandatory arguments\n" + " -t must be one of the test names - sink, transfer or ping\n" + " -i iteration count - the number of iterations to run the test over\n" + " Optional arguments\n" + " -S sysfs location - location for greybus 'endo' entires default /sys/bus/greybus/devices/\n" + " -D debugfs location - location for loopback debugfs entries default /sys/kernel/debug/gb_loopback/\n" + " -s size of data packet to send during test - defaults to zero\n" + " -m mask - a bit mask of connections to include example: -m 8 = 4th connection -m 9 = 1st and 4th connection etc\n" + " default is zero which means broadcast to all connections\n" + " -v verbose output\n" + " -d debug output\n" + " -r raw data output - when specified the full list of latency values are included in the output CSV\n" + " -p porcelain - when specified printout is in a user-friendly non-CSV format. This option suppresses writing to CSV file\n" + " -a aggregate - show aggregation of all enabled devices\n" + " -l list found loopback devices and exit\n" + " -x Async - Enable async transfers\n" + " -o Async Timeout - Timeout in uSec for async operations\n" + " -O Poll loop time out in seconds(max time a test is expected to last, default: 30sec)\n" + " -c Max number of outstanding operations for async operations\n" + " -w Wait in uSec between operations\n" + " -z Enable output to a CSV file (incompatible with -p)\n" + " -f When starting new loopback test, stop currently running tests on all devices\n" + "Examples:\n" + " Send 10000 transfers with a packet size of 128 bytes to all active connections\n" + " loopback_test -t transfer -s 128 -i 10000 -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n" + " loopback_test -t transfer -s 128 -i 10000 -m 0\n" + " Send 10000 transfers with a packet size of 128 bytes to connection 1 and 4\n" + " loopback_test -t transfer -s 128 -i 10000 -m 9\n" + " loopback_test -t ping -s 0 128 -i -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n" + " loopback_test -t sink -s 2030 -i 32768 -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n"); + abort(); +} + +static inline int device_enabled(struct loopback_test *t, int dev_idx) +{ + if (!t->mask || (t->mask & (1 << dev_idx))) + return 1; + + return 0; +} + +static void show_loopback_devices(struct loopback_test *t) +{ + int i; + + if (t->device_count == 0) { + printf("No loopback devices.\n"); + return; + } + + for (i = 0; i < t->device_count; i++) + printf("device[%d] = %s\n", i, t->devices[i].name); + +} + +int open_sysfs(const char *sys_pfx, const char *node, int flags) +{ + int fd; + char path[MAX_SYSFS_PATH]; + + snprintf(path, sizeof(path), "%s%s", sys_pfx, node); + fd = open(path, flags); + if (fd < 0) { + fprintf(stderr, "unable to open %s\n", path); + abort(); + } + return fd; +} + +int read_sysfs_int_fd(int fd, const char *sys_pfx, const char *node) +{ + char buf[SYSFS_MAX_INT]; + + if (read(fd, buf, sizeof(buf)) < 0) { + fprintf(stderr, "unable to read from %s%s %s\n", sys_pfx, node, + strerror(errno)); + close(fd); + abort(); + } + return atoi(buf); +} + +float read_sysfs_float_fd(int fd, const char *sys_pfx, const char *node) +{ + char buf[SYSFS_MAX_INT]; + + if (read(fd, buf, sizeof(buf)) < 0) { + + fprintf(stderr, "unable to read from %s%s %s\n", sys_pfx, node, + strerror(errno)); + close(fd); + abort(); + } + return atof(buf); +} + +int read_sysfs_int(const char *sys_pfx, const char *node) +{ + int fd, val; + + fd = open_sysfs(sys_pfx, node, O_RDONLY); + val = read_sysfs_int_fd(fd, sys_pfx, node); + close(fd); + return val; +} + +float read_sysfs_float(const char *sys_pfx, const char *node) +{ + int fd; + float val; + + fd = open_sysfs(sys_pfx, node, O_RDONLY); + val = read_sysfs_float_fd(fd, sys_pfx, node); + close(fd); + return val; +} + +void write_sysfs_val(const char *sys_pfx, const char *node, int val) +{ + int fd, len; + char buf[SYSFS_MAX_INT]; + + fd = open_sysfs(sys_pfx, node, O_RDWR); + len = snprintf(buf, sizeof(buf), "%d", val); + if (write(fd, buf, len) < 0) { + fprintf(stderr, "unable to write to %s%s %s\n", sys_pfx, node, + strerror(errno)); + close(fd); + abort(); + } + close(fd); +} + +static int get_results(struct loopback_test *t) +{ + struct loopback_device *d; + struct loopback_results *r; + int i; + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + d = &t->devices[i]; + r = &d->results; + + r->error = read_sysfs_int(d->sysfs_entry, "error"); + r->request_min = read_sysfs_int(d->sysfs_entry, "requests_per_second_min"); + r->request_max = read_sysfs_int(d->sysfs_entry, "requests_per_second_max"); + r->request_avg = read_sysfs_float(d->sysfs_entry, "requests_per_second_avg"); + + r->latency_min = read_sysfs_int(d->sysfs_entry, "latency_min"); + r->latency_max = read_sysfs_int(d->sysfs_entry, "latency_max"); + r->latency_avg = read_sysfs_float(d->sysfs_entry, "latency_avg"); + + r->throughput_min = read_sysfs_int(d->sysfs_entry, "throughput_min"); + r->throughput_max = read_sysfs_int(d->sysfs_entry, "throughput_max"); + r->throughput_avg = read_sysfs_float(d->sysfs_entry, "throughput_avg"); + + r->apbridge_unipro_latency_min = + read_sysfs_int(d->sysfs_entry, "apbridge_unipro_latency_min"); + r->apbridge_unipro_latency_max = + read_sysfs_int(d->sysfs_entry, "apbridge_unipro_latency_max"); + r->apbridge_unipro_latency_avg = + read_sysfs_float(d->sysfs_entry, "apbridge_unipro_latency_avg"); + + r->gbphy_firmware_latency_min = + read_sysfs_int(d->sysfs_entry, "gbphy_firmware_latency_min"); + r->gbphy_firmware_latency_max = + read_sysfs_int(d->sysfs_entry, "gbphy_firmware_latency_max"); + r->gbphy_firmware_latency_avg = + read_sysfs_float(d->sysfs_entry, "gbphy_firmware_latency_avg"); + + r->request_jitter = r->request_max - r->request_min; + r->latency_jitter = r->latency_max - r->latency_min; + r->throughput_jitter = r->throughput_max - r->throughput_min; + r->apbridge_unipro_latency_jitter = + r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min; + r->gbphy_firmware_latency_jitter = + r->gbphy_firmware_latency_max - r->gbphy_firmware_latency_min; + + } + + /*calculate the aggregate results of all enabled devices */ + if (t->aggregate_output) { + r = &t->aggregate_results; + + r->request_min = get_request_min_aggregate(t); + r->request_max = get_request_max_aggregate(t); + r->request_avg = get_request_avg_aggregate(t); + + r->latency_min = get_latency_min_aggregate(t); + r->latency_max = get_latency_max_aggregate(t); + r->latency_avg = get_latency_avg_aggregate(t); + + r->throughput_min = get_throughput_min_aggregate(t); + r->throughput_max = get_throughput_max_aggregate(t); + r->throughput_avg = get_throughput_avg_aggregate(t); + + r->apbridge_unipro_latency_min = + get_apbridge_unipro_latency_min_aggregate(t); + r->apbridge_unipro_latency_max = + get_apbridge_unipro_latency_max_aggregate(t); + r->apbridge_unipro_latency_avg = + get_apbridge_unipro_latency_avg_aggregate(t); + + r->gbphy_firmware_latency_min = + get_gbphy_firmware_latency_min_aggregate(t); + r->gbphy_firmware_latency_max = + get_gbphy_firmware_latency_max_aggregate(t); + r->gbphy_firmware_latency_avg = + get_gbphy_firmware_latency_avg_aggregate(t); + + r->request_jitter = r->request_max - r->request_min; + r->latency_jitter = r->latency_max - r->latency_min; + r->throughput_jitter = r->throughput_max - r->throughput_min; + r->apbridge_unipro_latency_jitter = + r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min; + r->gbphy_firmware_latency_jitter = + r->gbphy_firmware_latency_max - r->gbphy_firmware_latency_min; + + } + + return 0; +} + +void log_csv_error(int len, int err) +{ + fprintf(stderr, "unable to write %d bytes to csv %s\n", len, + strerror(err)); +} + +int format_output(struct loopback_test *t, + struct loopback_results *r, + const char *dev_name, + char *buf, int buf_len, + struct tm *tm) +{ + int len = 0; + + memset(buf, 0x00, buf_len); + len = snprintf(buf, buf_len, "%u-%u-%u %u:%u:%u", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + if (t->porcelain) { + len += snprintf(&buf[len], buf_len - len, + "\n test:\t\t\t%s\n path:\t\t\t%s\n size:\t\t\t%u\n iterations:\t\t%u\n errors:\t\t%u\n async:\t\t\t%s\n", + t->test_name, + dev_name, + t->size, + t->iteration_max, + r->error, + t->use_async ? "Enabled" : "Disabled"); + + len += snprintf(&buf[len], buf_len - len, + " requests per-sec:\tmin=%u, max=%u, average=%f, jitter=%u\n", + r->request_min, + r->request_max, + r->request_avg, + r->request_jitter); + + len += snprintf(&buf[len], buf_len - len, + " ap-throughput B/s:\tmin=%u max=%u average=%f jitter=%u\n", + r->throughput_min, + r->throughput_max, + r->throughput_avg, + r->throughput_jitter); + len += snprintf(&buf[len], buf_len - len, + " ap-latency usec:\tmin=%u max=%u average=%f jitter=%u\n", + r->latency_min, + r->latency_max, + r->latency_avg, + r->latency_jitter); + len += snprintf(&buf[len], buf_len - len, + " apbridge-latency usec:\tmin=%u max=%u average=%f jitter=%u\n", + r->apbridge_unipro_latency_min, + r->apbridge_unipro_latency_max, + r->apbridge_unipro_latency_avg, + r->apbridge_unipro_latency_jitter); + + len += snprintf(&buf[len], buf_len - len, + " gbphy-latency usec:\tmin=%u max=%u average=%f jitter=%u\n", + r->gbphy_firmware_latency_min, + r->gbphy_firmware_latency_max, + r->gbphy_firmware_latency_avg, + r->gbphy_firmware_latency_jitter); + + } else { + len += snprintf(&buf[len], buf_len- len, ",%s,%s,%u,%u,%u", + t->test_name, dev_name, t->size, t->iteration_max, + r->error); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->request_min, + r->request_max, + r->request_avg, + r->request_jitter); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->latency_min, + r->latency_max, + r->latency_avg, + r->latency_jitter); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->throughput_min, + r->throughput_max, + r->throughput_avg, + r->throughput_jitter); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->apbridge_unipro_latency_min, + r->apbridge_unipro_latency_max, + r->apbridge_unipro_latency_avg, + r->apbridge_unipro_latency_jitter); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->gbphy_firmware_latency_min, + r->gbphy_firmware_latency_max, + r->gbphy_firmware_latency_avg, + r->gbphy_firmware_latency_jitter); + } + + printf("\n%s\n", buf); + + return len; +} + +static int log_results(struct loopback_test *t) +{ + int fd, i, len, ret; + struct tm tm; + time_t local_time; + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + char file_name[MAX_SYSFS_PATH]; + char data[CSV_MAX_LINE]; + + local_time = time(NULL); + tm = *localtime(&local_time); + + /* + * file name will test_name_size_iteration_max.csv + * every time the same test with the same parameters is run we will then + * append to the same CSV with datestamp - representing each test + * dataset. + */ + if (t->file_output && !t->porcelain) { + snprintf(file_name, sizeof(file_name), "%s_%d_%d.csv", + t->test_name, t->size, t->iteration_max); + + fd = open(file_name, O_WRONLY | O_CREAT | O_APPEND, mode); + if (fd < 0) { + fprintf(stderr, "unable to open %s for appendation\n", file_name); + abort(); + } + + } + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + len = format_output(t, &t->devices[i].results, + t->devices[i].name, + data, sizeof(data), &tm); + if (t->file_output && !t->porcelain) { + ret = write(fd, data, len); + if (ret == -1) + fprintf(stderr, "unable to write %d bytes to csv.\n", len); + } + + } + + + if (t->aggregate_output) { + len = format_output(t, &t->aggregate_results, "aggregate", + data, sizeof(data), &tm); + if (t->file_output && !t->porcelain) { + ret = write(fd, data, len); + if (ret == -1) + fprintf(stderr, "unable to write %d bytes to csv.\n", len); + } + } + + if (t->file_output && !t->porcelain) + close(fd); + + return 0; +} + +int is_loopback_device(const char *path, const char *node) +{ + char file[MAX_SYSFS_PATH]; + + snprintf(file, MAX_SYSFS_PATH, "%s%s/iteration_count", path, node); + if (access(file, F_OK) == 0) + return 1; + return 0; +} + +int find_loopback_devices(struct loopback_test *t) +{ + struct dirent **namelist; + int i, n, ret; + unsigned int dev_id; + struct loopback_device *d; + + n = scandir(t->sysfs_prefix, &namelist, NULL, alphasort); + if (n < 0) { + perror("scandir"); + ret = -ENODEV; + goto baddir; + } + + /* Don't include '.' and '..' */ + if (n <= 2) { + ret = -ENOMEM; + goto done; + } + + for (i = 0; i < n; i++) { + ret = sscanf(namelist[i]->d_name, "gb_loopback%u", &dev_id); + if (ret != 1) + continue; + + if (!is_loopback_device(t->sysfs_prefix, namelist[i]->d_name)) + continue; + + if (t->device_count == MAX_NUM_DEVICES) { + fprintf(stderr, "max number of devices reached!\n"); + break; + } + + d = &t->devices[t->device_count++]; + snprintf(d->name, MAX_STR_LEN, "gb_loopback%u", dev_id); + + snprintf(d->sysfs_entry, MAX_SYSFS_PATH, "%s%s/", + t->sysfs_prefix, d->name); + + snprintf(d->debugfs_entry, MAX_SYSFS_PATH, "%sraw_latency_%s", + t->debugfs_prefix, d->name); + + if (t->debug) + printf("add %s %s\n", d->sysfs_entry, + d->debugfs_entry); + } + + ret = 0; +done: + for (i = 0; i < n; i++) + free(namelist[n]); + free(namelist); +baddir: + return ret; +} + +static int open_poll_files(struct loopback_test *t) +{ + struct loopback_device *dev; + char buf[MAX_STR_LEN]; + char dummy; + int fds_idx = 0; + int i; + + for (i = 0; i < t->device_count; i++) { + dev = &t->devices[i]; + + if (!device_enabled(t, i)) + continue; + + snprintf(buf, sizeof(buf), "%s%s", dev->sysfs_entry, "iteration_count"); + t->fds[fds_idx].fd = open(buf, O_RDONLY); + if (t->fds[fds_idx].fd < 0) { + fprintf(stderr, "Error opening poll file!\n"); + goto err; + } + read(t->fds[fds_idx].fd, &dummy, 1); + t->fds[fds_idx].events = POLLERR|POLLPRI; + t->fds[fds_idx].revents = 0; + fds_idx++; + } + + t->poll_count = fds_idx; + + return 0; + +err: + for (i = 0; i < fds_idx; i++) + close(t->fds[fds_idx].fd); + + return -1; +} + +static int close_poll_files(struct loopback_test *t) +{ + int i; + for (i = 0; i < t->poll_count; i++) + close(t->fds[i].fd); + + return 0; +} +static int is_complete(struct loopback_test *t) +{ + int iteration_count; + int i; + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + iteration_count = read_sysfs_int(t->devices[i].sysfs_entry, + "iteration_count"); + + /* at least one device did not finish yet */ + if (iteration_count != t->iteration_max) + return 0; + } + + return 1; +} + +static void stop_tests(struct loopback_test *t) +{ + int i; + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + write_sysfs_val(t->devices[i].sysfs_entry, "type", 0); + } +} + +static void handler(int sig) { /* do nothing */ } + +static int wait_for_complete(struct loopback_test *t) +{ + int number_of_events = 0; + char dummy; + int ret; + int i; + struct timespec *ts = NULL; + struct sigaction sa; + sigset_t mask_old, mask; + + sigemptyset(&mask); + sigemptyset(&mask_old); + sigaddset(&mask, SIGINT); + sigprocmask(SIG_BLOCK, &mask, &mask_old); + + sa.sa_handler = handler; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGINT, &sa, NULL) == -1) { + fprintf(stderr, "sigaction error\n"); + return -1; + } + + if (t->poll_timeout.tv_sec != 0) + ts = &t->poll_timeout; + + while (1) { + + ret = ppoll(t->fds, t->poll_count, ts, &mask_old); + if (ret <= 0) { + stop_tests(t); + fprintf(stderr, "Poll exit with errno %d\n", errno); + return -1; + } + + for (i = 0; i < t->poll_count; i++) { + if (t->fds[i].revents & POLLPRI) { + /* Dummy read to clear the event */ + read(t->fds[i].fd, &dummy, 1); + number_of_events++; + } + } + + if (number_of_events == t->poll_count) + break; + } + + if (!is_complete(t)) { + fprintf(stderr, "Iteration count did not finish!\n"); + return -1; + } + + return 0; +} + +static void prepare_devices(struct loopback_test *t) +{ + int i; + + /* Cancel any running tests on enabled devices. If + * stop_all option is given, stop test on all devices. + */ + for (i = 0; i < t->device_count; i++) + if (t->stop_all || device_enabled(t, i)) + write_sysfs_val(t->devices[i].sysfs_entry, "type", 0); + + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + write_sysfs_val(t->devices[i].sysfs_entry, "us_wait", + t->us_wait); + + /* Set operation size */ + write_sysfs_val(t->devices[i].sysfs_entry, "size", t->size); + + /* Set iterations */ + write_sysfs_val(t->devices[i].sysfs_entry, "iteration_max", + t->iteration_max); + + if (t->use_async) { + write_sysfs_val(t->devices[i].sysfs_entry, + "async", 1); + write_sysfs_val(t->devices[i].sysfs_entry, + "timeout", t->async_timeout); + write_sysfs_val(t->devices[i].sysfs_entry, + "outstanding_operations_max", + t->async_outstanding_operations); + } else + write_sysfs_val(t->devices[i].sysfs_entry, + "async", 0); + } +} + +static int start(struct loopback_test *t) +{ + int i; + + /* the test starts by writing test_id to the type file. */ + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + write_sysfs_val(t->devices[i].sysfs_entry, "type", t->test_id); + } + + return 0; +} + + +void loopback_run(struct loopback_test *t) +{ + int i; + int ret; + + for (i = 0; dict[i].name != NULL; i++) { + if (strstr(dict[i].name, t->test_name)) + t->test_id = dict[i].type; + } + if (!t->test_id) { + fprintf(stderr, "invalid test %s\n", t->test_name); + usage(); + return; + } + + prepare_devices(t); + + ret = open_poll_files(t); + if (ret) + goto err; + + start(t); + + ret = wait_for_complete(t); + close_poll_files(t); + if (ret) + goto err; + + + get_results(t); + + log_results(t); + + return; + +err: + printf("Error running test\n"); + return; +} + +static int sanity_check(struct loopback_test *t) +{ + int i; + + if (t->device_count == 0) { + fprintf(stderr, "No loopback devices found\n"); + return -1; + } + + for (i = 0; i < MAX_NUM_DEVICES; i++) { + if (!device_enabled(t, i)) + continue; + + if (t->mask && !strcmp(t->devices[i].name, "")) { + fprintf(stderr, "Bad device mask %x\n", (1 << i)); + return -1; + } + + } + + + return 0; +} + +int main(int argc, char *argv[]) +{ + int o, ret; + char *sysfs_prefix = "/sys/class/gb_loopback/"; + char *debugfs_prefix = "/sys/kernel/debug/gb_loopback/"; + + memset(&t, 0, sizeof(t)); + + while ((o = getopt(argc, argv, + "t:s:i:S:D:m:v::d::r::p::a::l::x::o:O:c:w:z::f::")) != -1) { + switch (o) { + case 't': + snprintf(t.test_name, MAX_STR_LEN, "%s", optarg); + break; + case 's': + t.size = atoi(optarg); + break; + case 'i': + t.iteration_max = atoi(optarg); + break; + case 'S': + snprintf(t.sysfs_prefix, MAX_SYSFS_PATH, "%s", optarg); + break; + case 'D': + snprintf(t.debugfs_prefix, MAX_SYSFS_PATH, "%s", optarg); + break; + case 'm': + t.mask = atol(optarg); + break; + case 'v': + t.verbose = 1; + break; + case 'd': + t.debug = 1; + break; + case 'r': + t.raw_data_dump = 1; + break; + case 'p': + t.porcelain = 1; + break; + case 'a': + t.aggregate_output = 1; + break; + case 'l': + t.list_devices = 1; + break; + case 'x': + t.use_async = 1; + break; + case 'o': + t.async_timeout = atoi(optarg); + break; + case 'O': + t.poll_timeout.tv_sec = atoi(optarg); + break; + case 'c': + t.async_outstanding_operations = atoi(optarg); + break; + case 'w': + t.us_wait = atoi(optarg); + break; + case 'z': + t.file_output = 1; + break; + case 'f': + t.stop_all = 1; + break; + default: + usage(); + return -EINVAL; + } + } + + if (!strcmp(t.sysfs_prefix, "")) + snprintf(t.sysfs_prefix, MAX_SYSFS_PATH, "%s", sysfs_prefix); + + if (!strcmp(t.debugfs_prefix, "")) + snprintf(t.debugfs_prefix, MAX_SYSFS_PATH, "%s", debugfs_prefix); + + ret = find_loopback_devices(&t); + if (ret) + return ret; + ret = sanity_check(&t); + if (ret) + return ret; + + if (t.list_devices) { + show_loopback_devices(&t); + return 0; + } + + if (t.test_name[0] == '\0' || t.iteration_max == 0) + usage(); + + if (t.async_timeout == 0) + t.async_timeout = DEFAULT_ASYNC_TIMEOUT; + + loopback_run(&t); + + return 0; +} diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c new file mode 100644 index 000000000000..5ee7954bd9f9 --- /dev/null +++ b/drivers/staging/greybus/uart.c @@ -0,0 +1,1075 @@ +/* + * UART driver for the Greybus "generic" UART module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + * + * Heavily based on drivers/usb/class/cdc-acm.c and + * drivers/usb/serial/usb-serial.c. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "gbphy.h" + +#define GB_NUM_MINORS 16 /* 16 is is more than enough */ +#define GB_NAME "ttyGB" + +#define GB_UART_WRITE_FIFO_SIZE PAGE_SIZE +#define GB_UART_WRITE_ROOM_MARGIN 1 /* leave some space in fifo */ +#define GB_UART_FIRMWARE_CREDITS 4096 +#define GB_UART_CREDIT_WAIT_TIMEOUT_MSEC 10000 + +struct gb_tty_line_coding { + __le32 rate; + __u8 format; + __u8 parity; + __u8 data_bits; + __u8 flow_control; +}; + +struct gb_tty { + struct gbphy_device *gbphy_dev; + struct tty_port port; + void *buffer; + size_t buffer_payload_max; + struct gb_connection *connection; + u16 cport_id; + unsigned int minor; + unsigned char clocal; + bool disconnected; + spinlock_t read_lock; + spinlock_t write_lock; + struct async_icount iocount; + struct async_icount oldcount; + wait_queue_head_t wioctl; + struct mutex mutex; + u8 ctrlin; /* input control lines */ + u8 ctrlout; /* output control lines */ + struct gb_tty_line_coding line_coding; + struct work_struct tx_work; + struct kfifo write_fifo; + bool close_pending; + unsigned int credits; + struct completion credits_complete; +}; + +static struct tty_driver *gb_tty_driver; +static DEFINE_IDR(tty_minors); +static DEFINE_MUTEX(table_lock); + +static int gb_uart_receive_data_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = gb_connection_get_data(connection); + struct tty_port *port = &gb_tty->port; + struct gb_message *request = op->request; + struct gb_uart_recv_data_request *receive_data; + u16 recv_data_size; + int count; + unsigned long tty_flags = TTY_NORMAL; + + if (request->payload_size < sizeof(*receive_data)) { + dev_err(&gb_tty->gbphy_dev->dev, + "short receive-data request received (%zu < %zu)\n", + request->payload_size, sizeof(*receive_data)); + return -EINVAL; + } + + receive_data = op->request->payload; + recv_data_size = le16_to_cpu(receive_data->size); + + if (recv_data_size != request->payload_size - sizeof(*receive_data)) { + dev_err(&gb_tty->gbphy_dev->dev, + "malformed receive-data request received (%u != %zu)\n", + recv_data_size, + request->payload_size - sizeof(*receive_data)); + return -EINVAL; + } + + if (!recv_data_size) + return -EINVAL; + + if (receive_data->flags) { + if (receive_data->flags & GB_UART_RECV_FLAG_BREAK) + tty_flags = TTY_BREAK; + else if (receive_data->flags & GB_UART_RECV_FLAG_PARITY) + tty_flags = TTY_PARITY; + else if (receive_data->flags & GB_UART_RECV_FLAG_FRAMING) + tty_flags = TTY_FRAME; + + /* overrun is special, not associated with a char */ + if (receive_data->flags & GB_UART_RECV_FLAG_OVERRUN) + tty_insert_flip_char(port, 0, TTY_OVERRUN); + } + count = tty_insert_flip_string_fixed_flag(port, receive_data->data, + tty_flags, recv_data_size); + if (count != recv_data_size) { + dev_err(&gb_tty->gbphy_dev->dev, + "UART: RX 0x%08x bytes only wrote 0x%08x\n", + recv_data_size, count); + } + if (count) + tty_flip_buffer_push(port); + return 0; +} + +static int gb_uart_serial_state_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = gb_connection_get_data(connection); + struct gb_message *request = op->request; + struct gb_uart_serial_state_request *serial_state; + + if (request->payload_size < sizeof(*serial_state)) { + dev_err(&gb_tty->gbphy_dev->dev, + "short serial-state event received (%zu < %zu)\n", + request->payload_size, sizeof(*serial_state)); + return -EINVAL; + } + + serial_state = request->payload; + gb_tty->ctrlin = serial_state->control; + + return 0; +} + +static int gb_uart_receive_credits_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = gb_connection_get_data(connection); + struct gb_message *request = op->request; + struct gb_uart_receive_credits_request *credit_request; + unsigned long flags; + unsigned int incoming_credits; + int ret = 0; + + if (request->payload_size < sizeof(*credit_request)) { + dev_err(&gb_tty->gbphy_dev->dev, + "short receive_credits event received (%zu < %zu)\n", + request->payload_size, + sizeof(*credit_request)); + return -EINVAL; + } + + credit_request = request->payload; + incoming_credits = le16_to_cpu(credit_request->count); + + spin_lock_irqsave(&gb_tty->write_lock, flags); + gb_tty->credits += incoming_credits; + if (gb_tty->credits > GB_UART_FIRMWARE_CREDITS) { + gb_tty->credits -= incoming_credits; + ret = -EINVAL; + } + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + if (ret) { + dev_err(&gb_tty->gbphy_dev->dev, + "invalid number of incoming credits: %d\n", + incoming_credits); + return ret; + } + + if (!gb_tty->close_pending) + schedule_work(&gb_tty->tx_work); + + /* + * the port the tty layer may be waiting for credits + */ + tty_port_tty_wakeup(&gb_tty->port); + + if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) + complete(&gb_tty->credits_complete); + + return ret; +} + +static int gb_uart_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = gb_connection_get_data(connection); + int type = op->type; + int ret; + + switch (type) { + case GB_UART_TYPE_RECEIVE_DATA: + ret = gb_uart_receive_data_handler(op); + break; + case GB_UART_TYPE_SERIAL_STATE: + ret = gb_uart_serial_state_handler(op); + break; + case GB_UART_TYPE_RECEIVE_CREDITS: + ret = gb_uart_receive_credits_handler(op); + break; + default: + dev_err(&gb_tty->gbphy_dev->dev, + "unsupported unsolicited request: 0x%02x\n", type); + ret = -EINVAL; + } + + return ret; +} + +static void gb_uart_tx_write_work(struct work_struct *work) +{ + struct gb_uart_send_data_request *request; + struct gb_tty *gb_tty; + unsigned long flags; + unsigned int send_size; + int ret; + + gb_tty = container_of(work, struct gb_tty, tx_work); + request = gb_tty->buffer; + + while (1) { + if (gb_tty->close_pending) + break; + + spin_lock_irqsave(&gb_tty->write_lock, flags); + send_size = gb_tty->buffer_payload_max; + if (send_size > gb_tty->credits) + send_size = gb_tty->credits; + + send_size = kfifo_out_peek(&gb_tty->write_fifo, + &request->data[0], + send_size); + if (!send_size) { + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + break; + } + + gb_tty->credits -= send_size; + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + request->size = cpu_to_le16(send_size); + ret = gb_operation_sync(gb_tty->connection, + GB_UART_TYPE_SEND_DATA, + request, sizeof(*request) + send_size, + NULL, 0); + if (ret) { + dev_err(&gb_tty->gbphy_dev->dev, + "send data error: %d\n", ret); + spin_lock_irqsave(&gb_tty->write_lock, flags); + gb_tty->credits += send_size; + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + if (!gb_tty->close_pending) + schedule_work(work); + return; + } + + spin_lock_irqsave(&gb_tty->write_lock, flags); + ret = kfifo_out(&gb_tty->write_fifo, &request->data[0], + send_size); + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + tty_port_tty_wakeup(&gb_tty->port); + } +} + +static int send_line_coding(struct gb_tty *tty) +{ + struct gb_uart_set_line_coding_request request; + + memcpy(&request, &tty->line_coding, + sizeof(tty->line_coding)); + return gb_operation_sync(tty->connection, GB_UART_TYPE_SET_LINE_CODING, + &request, sizeof(request), NULL, 0); +} + +static int send_control(struct gb_tty *gb_tty, u8 control) +{ + struct gb_uart_set_control_line_state_request request; + + request.control = control; + return gb_operation_sync(gb_tty->connection, + GB_UART_TYPE_SET_CONTROL_LINE_STATE, + &request, sizeof(request), NULL, 0); +} + +static int send_break(struct gb_tty *gb_tty, u8 state) +{ + struct gb_uart_set_break_request request; + + if ((state != 0) && (state != 1)) { + dev_err(&gb_tty->gbphy_dev->dev, + "invalid break state of %d\n", state); + return -EINVAL; + } + + request.state = state; + return gb_operation_sync(gb_tty->connection, GB_UART_TYPE_SEND_BREAK, + &request, sizeof(request), NULL, 0); +} + +static int gb_uart_wait_for_all_credits(struct gb_tty *gb_tty) +{ + int ret; + + if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) + return 0; + + ret = wait_for_completion_timeout(&gb_tty->credits_complete, + msecs_to_jiffies(GB_UART_CREDIT_WAIT_TIMEOUT_MSEC)); + if (!ret) { + dev_err(&gb_tty->gbphy_dev->dev, + "time out waiting for credits\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int gb_uart_flush(struct gb_tty *gb_tty, u8 flags) +{ + struct gb_uart_serial_flush_request request; + + request.flags = flags; + return gb_operation_sync(gb_tty->connection, GB_UART_TYPE_FLUSH_FIFOS, + &request, sizeof(request), NULL, 0); +} + +static struct gb_tty *get_gb_by_minor(unsigned int minor) +{ + struct gb_tty *gb_tty; + + mutex_lock(&table_lock); + gb_tty = idr_find(&tty_minors, minor); + if (gb_tty) { + mutex_lock(&gb_tty->mutex); + if (gb_tty->disconnected) { + mutex_unlock(&gb_tty->mutex); + gb_tty = NULL; + } else { + tty_port_get(&gb_tty->port); + mutex_unlock(&gb_tty->mutex); + } + } + mutex_unlock(&table_lock); + return gb_tty; +} + +static int alloc_minor(struct gb_tty *gb_tty) +{ + int minor; + + mutex_lock(&table_lock); + minor = idr_alloc(&tty_minors, gb_tty, 0, GB_NUM_MINORS, GFP_KERNEL); + mutex_unlock(&table_lock); + if (minor >= 0) + gb_tty->minor = minor; + return minor; +} + +static void release_minor(struct gb_tty *gb_tty) +{ + int minor = gb_tty->minor; + + gb_tty->minor = 0; /* Maybe should use an invalid value instead */ + mutex_lock(&table_lock); + idr_remove(&tty_minors, minor); + mutex_unlock(&table_lock); +} + +static int gb_tty_install(struct tty_driver *driver, struct tty_struct *tty) +{ + struct gb_tty *gb_tty; + int retval; + + gb_tty = get_gb_by_minor(tty->index); + if (!gb_tty) + return -ENODEV; + + retval = tty_standard_install(driver, tty); + if (retval) + goto error; + + tty->driver_data = gb_tty; + return 0; +error: + tty_port_put(&gb_tty->port); + return retval; +} + +static int gb_tty_open(struct tty_struct *tty, struct file *file) +{ + struct gb_tty *gb_tty = tty->driver_data; + + return tty_port_open(&gb_tty->port, tty, file); +} + +static void gb_tty_close(struct tty_struct *tty, struct file *file) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_close(&gb_tty->port, tty, file); +} + +static void gb_tty_cleanup(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_put(&gb_tty->port); +} + +static void gb_tty_hangup(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_hangup(&gb_tty->port); +} + +static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, + int count) +{ + struct gb_tty *gb_tty = tty->driver_data; + + count = kfifo_in_spinlocked(&gb_tty->write_fifo, buf, count, + &gb_tty->write_lock); + if (count && !gb_tty->close_pending) + schedule_work(&gb_tty->tx_work); + + return count; +} + +static int gb_tty_write_room(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + unsigned long flags; + int room; + + spin_lock_irqsave(&gb_tty->write_lock, flags); + room = kfifo_avail(&gb_tty->write_fifo); + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + room -= GB_UART_WRITE_ROOM_MARGIN; + if (room < 0) + return 0; + + return room; +} + +static int gb_tty_chars_in_buffer(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + unsigned long flags; + int chars; + + spin_lock_irqsave(&gb_tty->write_lock, flags); + chars = kfifo_len(&gb_tty->write_fifo); + if (gb_tty->credits < GB_UART_FIRMWARE_CREDITS) + chars += GB_UART_FIRMWARE_CREDITS - gb_tty->credits; + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + return chars; +} + +static int gb_tty_break_ctl(struct tty_struct *tty, int state) +{ + struct gb_tty *gb_tty = tty->driver_data; + + return send_break(gb_tty, state ? 1 : 0); +} + +static void gb_tty_set_termios(struct tty_struct *tty, + struct ktermios *termios_old) +{ + struct gb_tty *gb_tty = tty->driver_data; + struct ktermios *termios = &tty->termios; + struct gb_tty_line_coding newline; + u8 newctrl = gb_tty->ctrlout; + + newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); + newline.format = termios->c_cflag & CSTOPB ? + GB_SERIAL_2_STOP_BITS : GB_SERIAL_1_STOP_BITS; + newline.parity = termios->c_cflag & PARENB ? + (termios->c_cflag & PARODD ? 1 : 2) + + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; + + switch (termios->c_cflag & CSIZE) { + case CS5: + newline.data_bits = 5; + break; + case CS6: + newline.data_bits = 6; + break; + case CS7: + newline.data_bits = 7; + break; + case CS8: + default: + newline.data_bits = 8; + break; + } + + /* FIXME: needs to clear unsupported bits in the termios */ + gb_tty->clocal = ((termios->c_cflag & CLOCAL) != 0); + + if (C_BAUD(tty) == B0) { + newline.rate = gb_tty->line_coding.rate; + newctrl &= ~(GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); + } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { + newctrl |= (GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); + } + + if (newctrl != gb_tty->ctrlout) { + gb_tty->ctrlout = newctrl; + send_control(gb_tty, newctrl); + } + + if (C_CRTSCTS(tty) && C_BAUD(tty) != B0) + newline.flow_control |= GB_SERIAL_AUTO_RTSCTS_EN; + else + newline.flow_control &= ~GB_SERIAL_AUTO_RTSCTS_EN; + + if (memcmp(&gb_tty->line_coding, &newline, sizeof(newline))) { + memcpy(&gb_tty->line_coding, &newline, sizeof(newline)); + send_line_coding(gb_tty); + } +} + +static int gb_tty_tiocmget(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + return (gb_tty->ctrlout & GB_UART_CTRL_DTR ? TIOCM_DTR : 0) | + (gb_tty->ctrlout & GB_UART_CTRL_RTS ? TIOCM_RTS : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_DSR ? TIOCM_DSR : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_RI ? TIOCM_RI : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_DCD ? TIOCM_CD : 0) | + TIOCM_CTS; +} + +static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set, + unsigned int clear) +{ + struct gb_tty *gb_tty = tty->driver_data; + u8 newctrl = gb_tty->ctrlout; + + set = (set & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | + (set & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); + clear = (clear & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | + (clear & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); + + newctrl = (newctrl & ~clear) | set; + if (gb_tty->ctrlout == newctrl) + return 0; + + gb_tty->ctrlout = newctrl; + return send_control(gb_tty, newctrl); +} + +static void gb_tty_throttle(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + unsigned char stop_char; + int retval; + + if (I_IXOFF(tty)) { + stop_char = STOP_CHAR(tty); + retval = gb_tty_write(tty, &stop_char, 1); + if (retval <= 0) + return; + } + + if (tty->termios.c_cflag & CRTSCTS) { + gb_tty->ctrlout &= ~GB_UART_CTRL_RTS; + retval = send_control(gb_tty, gb_tty->ctrlout); + } +} + +static void gb_tty_unthrottle(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + unsigned char start_char; + int retval; + + if (I_IXOFF(tty)) { + start_char = START_CHAR(tty); + retval = gb_tty_write(tty, &start_char, 1); + if (retval <= 0) + return; + } + + if (tty->termios.c_cflag & CRTSCTS) { + gb_tty->ctrlout |= GB_UART_CTRL_RTS; + retval = send_control(gb_tty, gb_tty->ctrlout); + } +} + +static int get_serial_info(struct gb_tty *gb_tty, + struct serial_struct __user *info) +{ + struct serial_struct tmp; + + if (!info) + return -EINVAL; + + memset(&tmp, 0, sizeof(tmp)); + tmp.flags = ASYNC_LOW_LATENCY | ASYNC_SKIP_TEST; + tmp.type = PORT_16550A; + tmp.line = gb_tty->minor; + tmp.xmit_fifo_size = 16; + tmp.baud_base = 9600; + tmp.close_delay = gb_tty->port.close_delay / 10; + tmp.closing_wait = gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : gb_tty->port.closing_wait / 10; + + if (copy_to_user(info, &tmp, sizeof(tmp))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct gb_tty *gb_tty, + struct serial_struct __user *newinfo) +{ + struct serial_struct new_serial; + unsigned int closing_wait; + unsigned int close_delay; + int retval = 0; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; + + mutex_lock(&gb_tty->port.mutex); + if (!capable(CAP_SYS_ADMIN)) { + if ((close_delay != gb_tty->port.close_delay) || + (closing_wait != gb_tty->port.closing_wait)) + retval = -EPERM; + else + retval = -EOPNOTSUPP; + } else { + gb_tty->port.close_delay = close_delay; + gb_tty->port.closing_wait = closing_wait; + } + mutex_unlock(&gb_tty->port.mutex); + return retval; +} + +static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) +{ + int retval = 0; + DECLARE_WAITQUEUE(wait, current); + struct async_icount old; + struct async_icount new; + + if (!(arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD))) + return -EINVAL; + + do { + spin_lock_irq(&gb_tty->read_lock); + old = gb_tty->oldcount; + new = gb_tty->iocount; + gb_tty->oldcount = new; + spin_unlock_irq(&gb_tty->read_lock); + + if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) + break; + if ((arg & TIOCM_CD) && (old.dcd != new.dcd)) + break; + if ((arg & TIOCM_RI) && (old.rng != new.rng)) + break; + + add_wait_queue(&gb_tty->wioctl, &wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + remove_wait_queue(&gb_tty->wioctl, &wait); + if (gb_tty->disconnected) { + if (arg & TIOCM_CD) + break; + retval = -ENODEV; + } else if (signal_pending(current)) { + retval = -ERESTARTSYS; + } + } while (!retval); + + return retval; +} + +static int get_serial_usage(struct gb_tty *gb_tty, + struct serial_icounter_struct __user *count) +{ + struct serial_icounter_struct icount; + int retval = 0; + + memset(&icount, 0, sizeof(icount)); + icount.dsr = gb_tty->iocount.dsr; + icount.rng = gb_tty->iocount.rng; + icount.dcd = gb_tty->iocount.dcd; + icount.frame = gb_tty->iocount.frame; + icount.overrun = gb_tty->iocount.overrun; + icount.parity = gb_tty->iocount.parity; + icount.brk = gb_tty->iocount.brk; + + if (copy_to_user(count, &icount, sizeof(icount)) > 0) + retval = -EFAULT; + + return retval; +} + +static int gb_tty_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg) +{ + struct gb_tty *gb_tty = tty->driver_data; + + switch (cmd) { + case TIOCGSERIAL: + return get_serial_info(gb_tty, + (struct serial_struct __user *)arg); + case TIOCSSERIAL: + return set_serial_info(gb_tty, + (struct serial_struct __user *)arg); + case TIOCMIWAIT: + return wait_serial_change(gb_tty, arg); + case TIOCGICOUNT: + return get_serial_usage(gb_tty, + (struct serial_icounter_struct __user *)arg); + } + + return -ENOIOCTLCMD; +} + +static void gb_tty_dtr_rts(struct tty_port *port, int on) +{ + struct gb_tty *gb_tty; + u8 newctrl; + + gb_tty = container_of(port, struct gb_tty, port); + newctrl = gb_tty->ctrlout; + + if (on) + newctrl |= (GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); + else + newctrl &= ~(GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); + + gb_tty->ctrlout = newctrl; + send_control(gb_tty, newctrl); +} + +static int gb_tty_port_activate(struct tty_port *port, + struct tty_struct *tty) +{ + struct gb_tty *gb_tty; + + gb_tty = container_of(port, struct gb_tty, port); + + return gbphy_runtime_get_sync(gb_tty->gbphy_dev); +} + +static void gb_tty_port_shutdown(struct tty_port *port) +{ + struct gb_tty *gb_tty; + unsigned long flags; + int ret; + + gb_tty = container_of(port, struct gb_tty, port); + + gb_tty->close_pending = true; + + cancel_work_sync(&gb_tty->tx_work); + + spin_lock_irqsave(&gb_tty->write_lock, flags); + kfifo_reset_out(&gb_tty->write_fifo); + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) + goto out; + + ret = gb_uart_flush(gb_tty, GB_SERIAL_FLAG_FLUSH_TRANSMITTER); + if (ret) { + dev_err(&gb_tty->gbphy_dev->dev, + "error flushing transmitter: %d\n", ret); + } + + gb_uart_wait_for_all_credits(gb_tty); + +out: + gb_tty->close_pending = false; + + gbphy_runtime_put_autosuspend(gb_tty->gbphy_dev); +} + +static const struct tty_operations gb_ops = { + .install = gb_tty_install, + .open = gb_tty_open, + .close = gb_tty_close, + .cleanup = gb_tty_cleanup, + .hangup = gb_tty_hangup, + .write = gb_tty_write, + .write_room = gb_tty_write_room, + .ioctl = gb_tty_ioctl, + .throttle = gb_tty_throttle, + .unthrottle = gb_tty_unthrottle, + .chars_in_buffer = gb_tty_chars_in_buffer, + .break_ctl = gb_tty_break_ctl, + .set_termios = gb_tty_set_termios, + .tiocmget = gb_tty_tiocmget, + .tiocmset = gb_tty_tiocmset, +}; + +static struct tty_port_operations gb_port_ops = { + .dtr_rts = gb_tty_dtr_rts, + .activate = gb_tty_port_activate, + .shutdown = gb_tty_port_shutdown, +}; + +static int gb_uart_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) +{ + struct gb_connection *connection; + size_t max_payload; + struct gb_tty *gb_tty; + struct device *tty_dev; + int retval; + int minor; + + gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); + if (!gb_tty) + return -ENOMEM; + + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), + gb_uart_request_handler); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto exit_tty_free; + } + + max_payload = gb_operation_get_payload_size_max(connection); + if (max_payload < sizeof(struct gb_uart_send_data_request)) { + retval = -EINVAL; + goto exit_connection_destroy; + } + + gb_tty->buffer_payload_max = max_payload - + sizeof(struct gb_uart_send_data_request); + + gb_tty->buffer = kzalloc(gb_tty->buffer_payload_max, GFP_KERNEL); + if (!gb_tty->buffer) { + retval = -ENOMEM; + goto exit_connection_destroy; + } + + INIT_WORK(&gb_tty->tx_work, gb_uart_tx_write_work); + + retval = kfifo_alloc(&gb_tty->write_fifo, GB_UART_WRITE_FIFO_SIZE, + GFP_KERNEL); + if (retval) + goto exit_buf_free; + + gb_tty->credits = GB_UART_FIRMWARE_CREDITS; + init_completion(&gb_tty->credits_complete); + + minor = alloc_minor(gb_tty); + if (minor < 0) { + if (minor == -ENOSPC) { + dev_err(&connection->bundle->dev, + "no more free minor numbers\n"); + retval = -ENODEV; + } else { + retval = minor; + } + goto exit_kfifo_free; + } + + gb_tty->minor = minor; + spin_lock_init(&gb_tty->write_lock); + spin_lock_init(&gb_tty->read_lock); + init_waitqueue_head(&gb_tty->wioctl); + mutex_init(&gb_tty->mutex); + + tty_port_init(&gb_tty->port); + gb_tty->port.ops = &gb_port_ops; + + gb_tty->connection = connection; + gb_tty->gbphy_dev = gbphy_dev; + gb_connection_set_data(connection, gb_tty); + gb_gbphy_set_data(gbphy_dev, gb_tty); + + retval = gb_connection_enable_tx(connection); + if (retval) + goto exit_release_minor; + + send_control(gb_tty, gb_tty->ctrlout); + + /* initialize the uart to be 9600n81 */ + gb_tty->line_coding.rate = cpu_to_le32(9600); + gb_tty->line_coding.format = GB_SERIAL_1_STOP_BITS; + gb_tty->line_coding.parity = GB_SERIAL_NO_PARITY; + gb_tty->line_coding.data_bits = 8; + send_line_coding(gb_tty); + + retval = gb_connection_enable(connection); + if (retval) + goto exit_connection_disable; + + tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, + &gbphy_dev->dev); + if (IS_ERR(tty_dev)) { + retval = PTR_ERR(tty_dev); + goto exit_connection_disable; + } + + gbphy_runtime_put_autosuspend(gbphy_dev); + return 0; + +exit_connection_disable: + gb_connection_disable(connection); +exit_release_minor: + release_minor(gb_tty); +exit_kfifo_free: + kfifo_free(&gb_tty->write_fifo); +exit_buf_free: + kfree(gb_tty->buffer); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_tty_free: + kfree(gb_tty); + + return retval; +} + +static void gb_uart_remove(struct gbphy_device *gbphy_dev) +{ + struct gb_tty *gb_tty = gb_gbphy_get_data(gbphy_dev); + struct gb_connection *connection = gb_tty->connection; + struct tty_struct *tty; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); + + mutex_lock(&gb_tty->mutex); + gb_tty->disconnected = true; + + wake_up_all(&gb_tty->wioctl); + mutex_unlock(&gb_tty->mutex); + + tty = tty_port_tty_get(&gb_tty->port); + if (tty) { + tty_vhangup(tty); + tty_kref_put(tty); + } + + gb_connection_disable_rx(connection); + tty_unregister_device(gb_tty_driver, gb_tty->minor); + + /* FIXME - free transmit / receive buffers */ + + gb_connection_disable(connection); + tty_port_destroy(&gb_tty->port); + gb_connection_destroy(connection); + release_minor(gb_tty); + kfifo_free(&gb_tty->write_fifo); + kfree(gb_tty->buffer); + kfree(gb_tty); +} + +static int gb_tty_init(void) +{ + int retval = 0; + + gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); + if (IS_ERR(gb_tty_driver)) { + pr_err("Can not allocate tty driver\n"); + retval = -ENOMEM; + goto fail_unregister_dev; + } + + gb_tty_driver->driver_name = "gb"; + gb_tty_driver->name = GB_NAME; + gb_tty_driver->major = 0; + gb_tty_driver->minor_start = 0; + gb_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + gb_tty_driver->subtype = SERIAL_TYPE_NORMAL; + gb_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + gb_tty_driver->init_termios = tty_std_termios; + gb_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + tty_set_operations(gb_tty_driver, &gb_ops); + + retval = tty_register_driver(gb_tty_driver); + if (retval) { + pr_err("Can not register tty driver: %d\n", retval); + goto fail_put_gb_tty; + } + + return 0; + +fail_put_gb_tty: + put_tty_driver(gb_tty_driver); +fail_unregister_dev: + return retval; +} + +static void gb_tty_exit(void) +{ + tty_unregister_driver(gb_tty_driver); + put_tty_driver(gb_tty_driver); + idr_destroy(&tty_minors); +} + +static const struct gbphy_device_id gb_uart_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_UART) }, + { }, +}; +MODULE_DEVICE_TABLE(gbphy, gb_uart_id_table); + +static struct gbphy_driver uart_driver = { + .name = "uart", + .probe = gb_uart_probe, + .remove = gb_uart_remove, + .id_table = gb_uart_id_table, +}; + +static int gb_uart_driver_init(void) +{ + int ret; + + ret = gb_tty_init(); + if (ret) + return ret; + + ret = gb_gbphy_register(&uart_driver); + if (ret) { + gb_tty_exit(); + return ret; + } + + return 0; +} +module_init(gb_uart_driver_init); + +static void gb_uart_driver_exit(void) +{ + gb_gbphy_deregister(&uart_driver); + gb_tty_exit(); +} + +module_exit(gb_uart_driver_exit); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c new file mode 100644 index 000000000000..ccadda084b76 --- /dev/null +++ b/drivers/staging/greybus/usb.c @@ -0,0 +1,247 @@ +/* + * USB host driver for the Greybus "generic" USB module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + * + */ +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "gbphy.h" + +/* Greybus USB request types */ +#define GB_USB_TYPE_HCD_START 0x02 +#define GB_USB_TYPE_HCD_STOP 0x03 +#define GB_USB_TYPE_HUB_CONTROL 0x04 + +struct gb_usb_hub_control_request { + __le16 typeReq; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +}; + +struct gb_usb_hub_control_response { + u8 buf[0]; +}; + +struct gb_usb_device { + struct gb_connection *connection; + struct gbphy_device *gbphy_dev; +}; + +static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd) +{ + return (struct gb_usb_device *)hcd->hcd_priv; +} + +static inline struct usb_hcd *gb_usb_device_to_hcd(struct gb_usb_device *dev) +{ + return container_of((void *)dev, struct usb_hcd, hcd_priv); +} + +static void hcd_stop(struct usb_hcd *hcd) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + int ret; + + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP, + NULL, 0, NULL, 0); + if (ret) + dev_err(&dev->gbphy_dev->dev, "HCD stop failed '%d'\n", ret); +} + +static int hcd_start(struct usb_hcd *hcd) +{ + struct usb_bus *bus = hcd_to_bus(hcd); + struct gb_usb_device *dev = to_gb_usb_device(hcd); + int ret; + + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START, + NULL, 0, NULL, 0); + if (ret) { + dev_err(&dev->gbphy_dev->dev, "HCD start failed '%d'\n", ret); + return ret; + } + + hcd->state = HC_STATE_RUNNING; + if (bus->root_hub) + usb_hcd_resume_root_hub(hcd); + return 0; +} + +static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) +{ + return -ENXIO; +} + +static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) +{ + return -ENXIO; +} + +static int get_frame_number(struct usb_hcd *hcd) +{ + return 0; +} + +static int hub_status_data(struct usb_hcd *hcd, char *buf) +{ + return 0; +} + +static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, + char *buf, u16 wLength) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + struct gb_operation *operation; + struct gb_usb_hub_control_request *request; + struct gb_usb_hub_control_response *response; + size_t response_size; + int ret; + + /* FIXME: handle unspecified lengths */ + response_size = sizeof(*response) + wLength; + + operation = gb_operation_create(dev->connection, + GB_USB_TYPE_HUB_CONTROL, + sizeof(*request), + response_size, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + request = operation->request->payload; + request->typeReq = cpu_to_le16(typeReq); + request->wValue = cpu_to_le16(wValue); + request->wIndex = cpu_to_le16(wIndex); + request->wLength = cpu_to_le16(wLength); + + ret = gb_operation_request_send_sync(operation); + if (ret) + goto out; + + if (wLength) { + /* Greybus core has verified response size */ + response = operation->response->payload; + memcpy(buf, response->buf, wLength); + } +out: + gb_operation_put(operation); + + return ret; +} + +static struct hc_driver usb_gb_hc_driver = { + .description = "greybus-hcd", + .product_desc = "Greybus USB Host Controller", + .hcd_priv_size = sizeof(struct gb_usb_device), + + .flags = HCD_USB2, + + .start = hcd_start, + .stop = hcd_stop, + + .urb_enqueue = urb_enqueue, + .urb_dequeue = urb_dequeue, + + .get_frame_number = get_frame_number, + .hub_status_data = hub_status_data, + .hub_control = hub_control, +}; + +static int gb_usb_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) +{ + struct gb_connection *connection; + struct device *dev = &gbphy_dev->dev; + struct gb_usb_device *gb_usb_dev; + struct usb_hcd *hcd; + int retval; + + hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); + if (!hcd) + return -ENOMEM; + + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), + NULL); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto exit_usb_put; + } + + gb_usb_dev = to_gb_usb_device(hcd); + gb_usb_dev->connection = connection; + gb_connection_set_data(connection, gb_usb_dev); + gb_usb_dev->gbphy_dev = gbphy_dev; + gb_gbphy_set_data(gbphy_dev, gb_usb_dev); + + hcd->has_tt = 1; + + retval = gb_connection_enable(connection); + if (retval) + goto exit_connection_destroy; + + /* + * FIXME: The USB bridged-PHY protocol driver depends on changes to + * USB core which are not yet upstream. + * + * Disable for now. + */ + if (1) { + dev_warn(dev, "USB protocol disabled\n"); + retval = -EPROTONOSUPPORT; + goto exit_connection_disable; + } + + retval = usb_add_hcd(hcd, 0, 0); + if (retval) + goto exit_connection_disable; + + return 0; + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_usb_put: + usb_put_hcd(hcd); + + return retval; +} + +static void gb_usb_remove(struct gbphy_device *gbphy_dev) +{ + struct gb_usb_device *gb_usb_dev = gb_gbphy_get_data(gbphy_dev); + struct gb_connection *connection = gb_usb_dev->connection; + struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev); + + usb_remove_hcd(hcd); + gb_connection_disable(connection); + gb_connection_destroy(connection); + usb_put_hcd(hcd); +} + +static const struct gbphy_device_id gb_usb_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_USB) }, + { }, +}; +MODULE_DEVICE_TABLE(gbphy, gb_usb_id_table); + +static struct gbphy_driver usb_driver = { + .name = "usb", + .probe = gb_usb_probe, + .remove = gb_usb_remove, + .id_table = gb_usb_id_table, +}; + +module_gbphy_driver(usb_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c new file mode 100644 index 000000000000..4ba0e168930f --- /dev/null +++ b/drivers/staging/greybus/vibrator.c @@ -0,0 +1,249 @@ +/* + * Greybus Vibrator protocol driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + +struct gb_vibrator_device { + struct gb_connection *connection; + struct device *dev; + int minor; /* vibrator minor number */ + struct delayed_work delayed_work; +}; + +/* Greybus Vibrator operation types */ +#define GB_VIBRATOR_TYPE_ON 0x02 +#define GB_VIBRATOR_TYPE_OFF 0x03 + +static int turn_off(struct gb_vibrator_device *vib) +{ + struct gb_bundle *bundle = vib->connection->bundle; + int ret; + + ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, + NULL, 0, NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; +} + +static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) +{ + struct gb_bundle *bundle = vib->connection->bundle; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + /* Vibrator was switched ON earlier */ + if (cancel_delayed_work_sync(&vib->delayed_work)) + turn_off(vib); + + ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, + NULL, 0, NULL, 0); + if (ret) { + gb_pm_runtime_put_autosuspend(bundle); + return ret; + } + + schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms)); + + return 0; +} + +static void gb_vibrator_worker(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct gb_vibrator_device *vib = + container_of(delayed_work, struct gb_vibrator_device, delayed_work); + + turn_off(vib); +} + +static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gb_vibrator_device *vib = dev_get_drvdata(dev); + unsigned long val; + int retval; + + retval = kstrtoul(buf, 10, &val); + if (retval < 0) { + dev_err(dev, "could not parse timeout value %d\n", retval); + return retval; + } + + if (val) + retval = turn_on(vib, (u16)val); + else + retval = turn_off(vib); + if (retval) + return retval; + + return count; +} +static DEVICE_ATTR_WO(timeout); + +static struct attribute *vibrator_attrs[] = { + &dev_attr_timeout.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vibrator); + +static struct class vibrator_class = { + .name = "vibrator", + .owner = THIS_MODULE, + .dev_groups = vibrator_groups, +}; + +static DEFINE_IDA(minors); + +static int gb_vibrator_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_vibrator_device *vib; + struct device *dev; + int retval; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR) + return -ENODEV; + + vib = kzalloc(sizeof(*vib), GFP_KERNEL); + if (!vib) + return -ENOMEM; + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + NULL); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto err_free_vib; + } + gb_connection_set_data(connection, vib); + + vib->connection = connection; + + greybus_set_drvdata(bundle, vib); + + retval = gb_connection_enable(connection); + if (retval) + goto err_connection_destroy; + + /* + * For now we create a device in sysfs for the vibrator, but odds are + * there is a "real" device somewhere in the kernel for this, but I + * can't find it at the moment... + */ + vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); + if (vib->minor < 0) { + retval = vib->minor; + goto err_connection_disable; + } + dev = device_create(&vibrator_class, &bundle->dev, + MKDEV(0, 0), vib, "vibrator%d", vib->minor); + if (IS_ERR(dev)) { + retval = -EINVAL; + goto err_ida_remove; + } + vib->dev = dev; + + INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker); + + gb_pm_runtime_put_autosuspend(bundle); + + return 0; + +err_ida_remove: + ida_simple_remove(&minors, vib->minor); +err_connection_disable: + gb_connection_disable(connection); +err_connection_destroy: + gb_connection_destroy(connection); +err_free_vib: + kfree(vib); + + return retval; +} + +static void gb_vibrator_disconnect(struct gb_bundle *bundle) +{ + struct gb_vibrator_device *vib = greybus_get_drvdata(bundle); + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); + + if (cancel_delayed_work_sync(&vib->delayed_work)) + turn_off(vib); + + device_unregister(vib->dev); + ida_simple_remove(&minors, vib->minor); + gb_connection_disable(vib->connection); + gb_connection_destroy(vib->connection); + kfree(vib); +} + +static const struct greybus_bundle_id gb_vibrator_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table); + +static struct greybus_driver gb_vibrator_driver = { + .name = "vibrator", + .probe = gb_vibrator_probe, + .disconnect = gb_vibrator_disconnect, + .id_table = gb_vibrator_id_table, +}; + +static __init int gb_vibrator_init(void) +{ + int retval; + + retval = class_register(&vibrator_class); + if (retval) + return retval; + + retval = greybus_register(&gb_vibrator_driver); + if (retval) + goto err_class_unregister; + + return 0; + +err_class_unregister: + class_unregister(&vibrator_class); + + return retval; +} +module_init(gb_vibrator_init); + +static __exit void gb_vibrator_exit(void) +{ + greybus_deregister(&gb_vibrator_driver); + class_unregister(&vibrator_class); + ida_destroy(&minors); +} +module_exit(gb_vibrator_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index a221f261c3d3..8ed4d395be58 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -8,10 +8,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h index 8cc32555dbf3..7b8cc3a25214 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h @@ -7,12 +7,7 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include diff --git a/drivers/staging/gs_fpgaboot/io.h b/drivers/staging/gs_fpgaboot/io.h index 7b46ac24b74e..5e839b1fc884 100644 --- a/drivers/staging/gs_fpgaboot/io.h +++ b/drivers/staging/gs_fpgaboot/io.h @@ -66,10 +66,8 @@ enum wbus { bus_2byte = 2, }; - #define MAX_WAIT_DONE 10000 - struct gpiobus { int ngpio; void __iomem *r[4]; diff --git a/drivers/staging/i4l/act2000/act2000_isa.c b/drivers/staging/i4l/act2000/act2000_isa.c index f0eb8441deed..ad7a0391369f 100644 --- a/drivers/staging/i4l/act2000/act2000_isa.c +++ b/drivers/staging/i4l/act2000/act2000_isa.c @@ -134,9 +134,9 @@ act2000_isa_config_irq(act2000_card *card, short irq) { int old_irq; - if (card->flags & ACT2000_FLAGS_IVALID) { + if (card->flags & ACT2000_FLAGS_IVALID) free_irq(card->irq, card); - } + card->flags &= ~ACT2000_FLAGS_IVALID; outb(ISA_COR_IRQOFF, ISA_PORT_COR); if (!irq) @@ -166,7 +166,7 @@ act2000_isa_config_port(act2000_card *card, unsigned short portbase) release_region(card->port, ISA_REGION); card->flags &= ~ACT2000_FLAGS_PVALID; } - if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL) + if (!request_region(portbase, ACT2000_PORTLEN, card->regname)) return -EBUSY; else { card->port = portbase; @@ -176,7 +176,7 @@ act2000_isa_config_port(act2000_card *card, unsigned short portbase) } /* - * Release ressources, used by an adaptor. + * Release resources, used by an adaptor. */ void act2000_isa_release(act2000_card *card) @@ -244,7 +244,7 @@ act2000_isa_receive(act2000_card *card) if (valid) { card->idat.isa.rcvlen = ((actcapi_msghdr *)&card->idat.isa.rcvhdr)->len; card->idat.isa.rcvskb = dev_alloc_skb(card->idat.isa.rcvlen); - if (card->idat.isa.rcvskb == NULL) { + if (!card->idat.isa.rcvskb) { card->idat.isa.rcvignore = 1; printk(KERN_WARNING "act2000_isa_receive: no memory\n"); @@ -399,7 +399,6 @@ act2000_isa_download(act2000_card *card, act2000_ddef __user *cb) unsigned int length; int l; int c; - long timeout; u_char *b; u_char __user *p; u_char *buf; @@ -417,7 +416,6 @@ act2000_isa_download(act2000_card *card, act2000_ddef __user *cb) buf = kmalloc(1024, GFP_KERNEL); if (!buf) return -ENOMEM; - timeout = 0; while (length) { l = (length > 1024) ? 1024 : length; c = 0; diff --git a/drivers/staging/i4l/act2000/capi.c b/drivers/staging/i4l/act2000/capi.c index 3f66ca20b5e5..62f56294853c 100644 --- a/drivers/staging/i4l/act2000/capi.c +++ b/drivers/staging/i4l/act2000/capi.c @@ -113,7 +113,9 @@ actcapi_chkhdr(act2000_card *card, actcapi_msghdr *hdr) m->hdr.cmd.cmd = c; \ m->hdr.cmd.subcmd = s; \ m->hdr.msgnum = actcapi_nextsmsg(card); \ - } else m = NULL; \ + } else { \ + m = NULL; \ + } \ } #define ACTCAPI_CHKSKB if (!skb) { \ @@ -547,12 +549,11 @@ static int actcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) { __u16 plci; __u16 ncci; - __u16 controller; __u8 blocknr; int chan; actcapi_msg *msg = (actcapi_msg *)skb->data; - EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, controller, ncci); + EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, ncci); chan = find_ncci(card, ncci); if (chan < 0) return 0; @@ -617,7 +618,7 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) { spin_lock_irqsave(&card->lock, flags); tmp = skb_peek((struct sk_buff_head *)tmp); spin_unlock_irqrestore(&card->lock, flags); - if ((tmp == skb) || (tmp == NULL)) { + if ((tmp == skb) || !tmp) { /* reached end of queue */ printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); return 0; @@ -990,7 +991,8 @@ actcapi_debug_dlpd(actcapi_dlpd *dlpd) } #ifdef DEBUG_DUMP_SKB -static void dump_skb(struct sk_buff *skb) { +static void dump_skb(struct sk_buff *skb) +{ char tmp[80]; char *p = skb->data; char *t = tmp; diff --git a/drivers/staging/i4l/act2000/capi.h b/drivers/staging/i4l/act2000/capi.h index 01ccdecd43f7..34884a5efee5 100644 --- a/drivers/staging/i4l/act2000/capi.h +++ b/drivers/staging/i4l/act2000/capi.h @@ -114,9 +114,8 @@ typedef struct actcapi_ncpd { #define MAKE_NCCI(plci, contr, ncci) \ ((plci & 0x1f) | ((contr & 0x7) << 5) | ((ncci & 0xff) << 8)) -#define EVAL_NCCI(fakencci, plci, contr, ncci) { \ +#define EVAL_NCCI(fakencci, plci, ncci) { \ plci = fakencci & 0x1f; \ - contr = (fakencci >> 5) & 0x7; \ ncci = (fakencci >> 8) & 0xff; \ } @@ -128,13 +127,6 @@ typedef struct actcapi_ncpd { * Bit 5-7 = Controller * Bit 8-15 = reserved (must be 0) */ -#define MAKE_PLCI(plci, contr) \ - ((plci & 0x1f) | ((contr & 0x7) << 5)) - -#define EVAL_PLCI(fakeplci, plci, contr) { \ - plci = fakeplci & 0x1f; \ - contr = (fakeplci >> 5) & 0x7; \ - } typedef struct actcapi_msg { actcapi_msghdr hdr; diff --git a/drivers/staging/i4l/act2000/module.c b/drivers/staging/i4l/act2000/module.c index 68073d0da0e3..99c9c0a1c63e 100644 --- a/drivers/staging/i4l/act2000/module.c +++ b/drivers/staging/i4l/act2000/module.c @@ -28,7 +28,7 @@ static unsigned short act2000_isa_ports[] = static act2000_card *cards = (act2000_card *) NULL; /* Parameters to be set by insmod */ -static int act_bus = 0; +static int act_bus; static int act_port = -1; /* -1 = Autoprobe */ static int act_irq = -1; static char *act_id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; @@ -289,7 +289,8 @@ act2000_command(act2000_card *card, isdn_ctrl *c) if (copy_from_user(tmp, arg, sizeof(tmp))) return -EFAULT; - if ((ret = act2000_set_msn(card, tmp))) + ret = act2000_set_msn(card, tmp); + if (ret) return ret; if (card->flags & ACT2000_FLAGS_RUNNING) return (actcapi_manufacturer_req_msn(card)); diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index 46d957c34be1..514bfc2c5b53 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -62,7 +62,8 @@ icn_free_queue(icn_card *card, int channel) skb_queue_purge(queue); card->xlen[channel] = 0; card->sndcount[channel] = 0; - if ((skb = card->xskb[channel])) { + skb = card->xskb[channel]; + if (skb) { card->xskb[channel] = NULL; dev_kfree_skb(skb); } @@ -81,12 +82,11 @@ icn_shiftout(unsigned short port, int firstbit, int bitcount) { - register u_char s; register u_char c; for (s = firstbit, c = bitcount; c > 0; s--, c--) - OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port); + OUTB_P((u_char)((val >> s) & 1) ? 0xff : 0, port); } /* @@ -272,8 +272,10 @@ icn_pollbchan_receive(int channel, icn_card *card) rbnext; icn_maprelease_channel(card, mch & 2); if (!eflag) { - if ((cnt = card->rcvidx[channel])) { - if (!(skb = dev_alloc_skb(cnt))) { + cnt = card->rcvidx[channel]; + if (cnt) { + skb = dev_alloc_skb(cnt); + if (!skb) { printk(KERN_WARNING "icn: receive out of memory\n"); break; } @@ -382,7 +384,7 @@ icn_pollbchan_send(int channel, icn_card *card) static void icn_pollbchan(unsigned long data) { - icn_card *card = (icn_card *) data; + icn_card *card = (icn_card *)data; unsigned long flags; if (card->flags & ICN_FLAGS_B1ACTIVE) { @@ -472,7 +474,6 @@ icn_parse_status(u_char *status, int channel, icn_card *card) if (card->flags & ((channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE)) { - isdn_ctrl ncmd; card->flags &= ~((channel) ? @@ -544,7 +545,7 @@ icn_parse_status(u_char *status, int channel, icn_card *card) break; case 6: snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%d", - (int) simple_strtoul(status + 7, NULL, 16)); + (int)simple_strtoul(status + 7, NULL, 16)); break; case 7: status += 3; @@ -604,7 +605,7 @@ icn_putmsg(icn_card *card, unsigned char c) static void icn_polldchan(unsigned long data) { - icn_card *card = (icn_card *) data; + icn_card *card = (icn_card *)data; int mch = card->secondhalf ? 2 : 0; int avail = 0; int left; @@ -656,9 +657,8 @@ icn_polldchan(unsigned long data) *q = '\0'; strcat(vstr, "000"); vstr[3] = '\0'; - card->fw_rev = (int) simple_strtoul(vstr, NULL, 10); + card->fw_rev = (int)simple_strtoul(vstr, NULL, 10); continue; - } } } else { @@ -683,7 +683,7 @@ icn_polldchan(unsigned long data) card->flags |= ICN_FLAGS_RBTIMER; del_timer(&card->rb_timer); card->rb_timer.function = icn_pollbchan; - card->rb_timer.data = (unsigned long) card; + card->rb_timer.data = (unsigned long)card; card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD; add_timer(&card->rb_timer); } @@ -805,17 +805,12 @@ icn_loadboot(u_char __user *buffer, icn_card *card) unsigned long flags; #ifdef BOOT_DEBUG - printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer); + printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong)buffer); #endif - if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) { - printk(KERN_WARNING "icn: Could not allocate code buffer\n"); - ret = -ENOMEM; - goto out; - } - if (copy_from_user(codebuf, buffer, ICN_CODE_STAGE1)) { - ret = -EFAULT; - goto out_kfree; - } + codebuf = memdup_user(buffer, ICN_CODE_STAGE1); + if (IS_ERR(codebuf)) + return PTR_ERR(codebuf); + if (!card->rvalid) { if (!request_region(card->port, ICN_PORTLEN, card->regname)) { printk(KERN_WARNING @@ -878,9 +873,9 @@ icn_loadboot(u_char __user *buffer, icn_card *card) } SLEEP(1); OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */ - if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1))) { + ret = icn_check_loader(card->doubleS0 ? 2 : 1); + if (ret) goto out_kfree; - } if (!card->doubleS0) { ret = 0; goto out_kfree; @@ -898,7 +893,6 @@ icn_loadboot(u_char __user *buffer, icn_card *card) out_kfree: kfree(codebuf); -out: return ret; } @@ -980,18 +974,17 @@ icn_loadproto(u_char __user *buffer, icn_card *card) card->secondhalf); #endif spin_lock_irqsave(&card->lock, flags); - init_timer(&card->st_timer); - card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - card->st_timer.function = icn_polldchan; - card->st_timer.data = (unsigned long) card; - add_timer(&card->st_timer); + setup_timer(&card->st_timer, icn_polldchan, + (unsigned long)card); + mod_timer(&card->st_timer, + jiffies + ICN_TIMER_DCREAD); card->flags |= ICN_FLAGS_RUNNING; if (card->doubleS0) { - init_timer(&card->other->st_timer); - card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - card->other->st_timer.function = icn_polldchan; - card->other->st_timer.data = (unsigned long) card->other; - add_timer(&card->other->st_timer); + setup_timer(&card->other->st_timer, + icn_polldchan, + (unsigned long)card->other); + mod_timer(&card->other->st_timer, + jiffies + ICN_TIMER_DCREAD); card->other->flags |= ICN_FLAGS_RUNNING; } spin_unlock_irqrestore(&card->lock, flags); @@ -1022,7 +1015,8 @@ icn_readstatus(u_char __user *buf, int len, icn_card *card) /* Put command-strings into the command-queue of the Interface */ static int -icn_writecmd(const u_char *buf, int len, int user, icn_card *card) +icn_writecmd(const u_char __user *ubuf, const u_char *kbuf, int len, + int user, icn_card *card) { int mch = card->secondhalf ? 2 : 0; int pp; @@ -1045,10 +1039,10 @@ icn_writecmd(const u_char *buf, int len, int user, icn_card *card) if (count > len) count = len; if (user) { - if (copy_from_user(msg, buf, count)) + if (copy_from_user(msg, ubuf, count)) return -EFAULT; } else - memcpy(msg, buf, count); + memcpy(msg, kbuf, count); spin_lock_irqsave(&dev.devlock, flags); lastmap_card = dev.mcard; @@ -1190,28 +1184,28 @@ icn_command(isdn_ctrl *c, icn_card *card) } break; case ICN_IOCTL_GETMMIO: - return (long) dev.memaddr; + return (long)dev.memaddr; case ICN_IOCTL_SETPORT: if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330 || a == 0x340 || a == 0x350 || a == 0x360 || a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338 || a == 0x348 || a == 0x358 || a == 0x368) { - if (card->port != (unsigned short) a) { - if (!request_region((unsigned short) a, ICN_PORTLEN, "icn-isdn")) { + if (card->port != (unsigned short)a) { + if (!request_region((unsigned short)a, ICN_PORTLEN, "icn-isdn")) { printk(KERN_WARNING "icn: (%s) ports 0x%03x-0x%03x in use.\n", - CID, (int) a, (int) a + ICN_PORTLEN); + CID, (int)a, (int)a + ICN_PORTLEN); return -EINVAL; } - release_region((unsigned short) a, ICN_PORTLEN); + release_region((unsigned short)a, ICN_PORTLEN); icn_stopcard(card); spin_lock_irqsave(&card->lock, flags); if (card->rvalid) release_region(card->port, ICN_PORTLEN); - card->port = (unsigned short) a; + card->port = (unsigned short)a; card->rvalid = 0; if (card->doubleS0) { - card->other->port = (unsigned short) a; + card->other->port = (unsigned short)a; card->other->rvalid = 0; } spin_unlock_irqrestore(&card->lock, flags); @@ -1223,9 +1217,9 @@ icn_command(isdn_ctrl *c, icn_card *card) return -EINVAL; break; case ICN_IOCTL_GETPORT: - return (int) card->port; + return (int)card->port; case ICN_IOCTL_GETDOUBLE: - return (int) card->doubleS0; + return (int)card->doubleS0; case ICN_IOCTL_DEBUGVAR: if (copy_to_user(arg, &card, @@ -1246,10 +1240,11 @@ icn_command(isdn_ctrl *c, icn_card *card) dev.firstload = 0; } icn_stopcard(card); - return (icn_loadboot(arg, card)); + return icn_loadboot(arg, card); case ICN_IOCTL_LOADPROTO: icn_stopcard(card); - if ((i = (icn_loadproto(arg, card)))) + i = (icn_loadproto(arg, card)); + if (i) return i; if (card->doubleS0) i = icn_loadproto(arg + ICN_CODE_STAGE2, card->other); @@ -1262,19 +1257,20 @@ icn_command(isdn_ctrl *c, icn_card *card) arg, sizeof(cdef))) return -EFAULT; - return (icn_addcard(cdef.port, cdef.id1, cdef.id2)); + return icn_addcard(cdef.port, cdef.id1, cdef.id2); break; case ICN_IOCTL_LEASEDCFG: if (a) { if (!card->leased) { card->leased = 1; - while (card->ptype == ISDN_PTYPE_UNKNOWN) { + while (card->ptype == ISDN_PTYPE_UNKNOWN) msleep_interruptible(ICN_BOOT_TIMEOUT1); - } msleep_interruptible(ICN_BOOT_TIMEOUT1); sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n", (a & 1) ? '1' : 'C', (a & 2) ? '2' : 'C'); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, + strlen(cbuf), + 0, card); printk(KERN_INFO "icn: (%s) Leased-line mode enabled\n", CID); @@ -1287,7 +1283,9 @@ icn_command(isdn_ctrl *c, icn_card *card) if (card->leased) { card->leased = 0; sprintf(cbuf, "00;FV2OFF\n"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, + strlen(cbuf), + 0, card); printk(KERN_INFO "icn: (%s) Leased-line mode disabled\n", CID); @@ -1321,10 +1319,10 @@ icn_command(isdn_ctrl *c, icn_card *card) /* Normal Dial */ strcpy(dcode, "CAL"); snprintf(cbuf, sizeof(cbuf), - "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), + "%02d;D%s_R%s,%02d,%02d,%s\n", (int)(a + 1), dcode, p, c->parm.setup.si1, c->parm.setup.si2, c->parm.setup.eazmsn); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_ACCEPTD: @@ -1335,16 +1333,18 @@ icn_command(isdn_ctrl *c, icn_card *card) if (card->fw_rev >= 300) { switch (card->l2_proto[a - 1]) { case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) a); + sprintf(cbuf, "%02d;BX75\n", (int)a); break; case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) a); + sprintf(cbuf, "%02d;BTRA\n", (int)a); break; } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, + strlen(cbuf), 0, + card); } - sprintf(cbuf, "%02d;DCON_R\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + sprintf(cbuf, "%02d;DCON_R\n", (int)a); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_ACCEPTB: @@ -1355,14 +1355,14 @@ icn_command(isdn_ctrl *c, icn_card *card) if (card->fw_rev >= 300) switch (card->l2_proto[a - 1]) { case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a); + sprintf(cbuf, "%02d;BCON_R,BX75\n", (int)a); break; case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a); + sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int)a); break; } else - sprintf(cbuf, "%02d;BCON_R\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + sprintf(cbuf, "%02d;BCON_R\n", (int)a); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_HANGUP: @@ -1370,8 +1370,8 @@ icn_command(isdn_ctrl *c, icn_card *card) return -ENODEV; if (c->arg < ICN_BCH) { a = c->arg + 1; - sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int)a, (int)a); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_SETEAZ: @@ -1382,12 +1382,12 @@ icn_command(isdn_ctrl *c, icn_card *card) if (c->arg < ICN_BCH) { a = c->arg + 1; if (card->ptype == ISDN_PTYPE_EURO) { - sprintf(cbuf, "%02d;MS%s%s\n", (int) a, + sprintf(cbuf, "%02d;MS%s%s\n", (int)a, c->parm.num[0] ? "N" : "ALL", c->parm.num); } else - sprintf(cbuf, "%02d;EAZ%s\n", (int) a, + sprintf(cbuf, "%02d;EAZ%s\n", (int)a, c->parm.num[0] ? (char *)(c->parm.num) : "0123456789"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_CLREAZ: @@ -1398,10 +1398,10 @@ icn_command(isdn_ctrl *c, icn_card *card) if (c->arg < ICN_BCH) { a = c->arg + 1; if (card->ptype == ISDN_PTYPE_EURO) - sprintf(cbuf, "%02d;MSNC\n", (int) a); + sprintf(cbuf, "%02d;MSNC\n", (int)a); else - sprintf(cbuf, "%02d;EAZC\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + sprintf(cbuf, "%02d;EAZC\n", (int)a); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_SETL2: @@ -1411,15 +1411,15 @@ icn_command(isdn_ctrl *c, icn_card *card) a = c->arg; switch (a >> 8) { case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1); + sprintf(cbuf, "%02d;BX75\n", (int)(a & 255) + 1); break; case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1); + sprintf(cbuf, "%02d;BTRA\n", (int)(a & 255) + 1); break; default: return -EINVAL; } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); card->l2_proto[a & 255] = (a >> 8); } break; @@ -1446,7 +1446,7 @@ icn_findcard(int driverid) return p; p = p->next; } - return (icn_card *) 0; + return (icn_card *)0; } /* @@ -1458,7 +1458,7 @@ if_command(isdn_ctrl *c) icn_card *card = icn_findcard(c->driver); if (card) - return (icn_command(c, card)); + return icn_command(c, card); printk(KERN_ERR "icn: if_command %d called with invalid driverId %d!\n", c->command, c->driver); @@ -1473,7 +1473,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) if (card) { if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; - return (icn_writecmd(buf, len, 1, card)); + return icn_writecmd(buf, NULL, len, 1, card); } printk(KERN_ERR "icn: if_writecmd called with invalid driverId!\n"); @@ -1488,7 +1488,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) if (card) { if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; - return (icn_readstatus(buf, len, card)); + return icn_readstatus(buf, len, card); } printk(KERN_ERR "icn: if_readstatus called with invalid driverId!\n"); @@ -1503,7 +1503,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) if (card) { if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; - return (icn_sendbuf(channel, ack, skb, card)); + return icn_sendbuf(channel, ack, skb, card); } printk(KERN_ERR "icn: if_sendbuf called with invalid driverId!\n"); @@ -1520,10 +1520,11 @@ icn_initcard(int port, char *id) icn_card *card; int i; - if (!(card = kzalloc(sizeof(icn_card), GFP_KERNEL))) { + card = kzalloc(sizeof(icn_card), GFP_KERNEL); + if (!card) { printk(KERN_WARNING "icn: (%s) Could not allocate card-struct.\n", id); - return (icn_card *) 0; + return (icn_card *)0; } spin_lock_init(&card->lock); card->port = port; @@ -1555,7 +1556,7 @@ icn_initcard(int port, char *id) printk(KERN_WARNING "icn: Unable to register %s\n", id); kfree(card); - return (icn_card *) 0; + return (icn_card *)0; } card->myid = card->interface.channels; sprintf(card->regname, "icn-isdn (%s)", card->interface.id); @@ -1568,16 +1569,17 @@ icn_addcard(int port, char *id1, char *id2) icn_card *card; icn_card *card2; - if (!(card = icn_initcard(port, id1))) { + card = icn_initcard(port, id1); + if (!card) return -EIO; - } if (!strlen(id2)) { printk(KERN_INFO "icn: (%s) ICN-2B, port 0x%x added\n", card->interface.id, port); return 0; } - if (!(card2 = icn_initcard(port, id2))) { + card2 = icn_initcard(port, id2); + if (!card2) { printk(KERN_INFO "icn: (%s) half ICN-4B, port 0x%x added\n", id2, port); return 0; @@ -1611,13 +1613,14 @@ icn_setup(char *line) if (str && *str) { strlcpy(sid, str, sizeof(sid)); icn_id = sid; - if ((p = strchr(sid, ','))) { + p = strchr(sid, ','); + if (p) { *p++ = 0; strcpy(sid2, p); icn_id2 = sid2; } } - return (1); + return 1; } __setup("icn=", icn_setup); #endif /* MODULE */ @@ -1634,7 +1637,8 @@ static int __init icn_init(void) dev.firstload = 1; spin_lock_init(&dev.devlock); - if ((p = strchr(revision, ':'))) { + p = strchr(revision, ':'); + if (p) { strncpy(rev, p + 1, 20); rev[20] = '\0'; p = strchr(rev, '$'); @@ -1644,7 +1648,7 @@ static int __init icn_init(void) strcpy(rev, " ??? "); printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev, dev.memaddr); - return (icn_addcard(portbase, icn_id, icn_id2)); + return icn_addcard(portbase, icn_id, icn_id2); } static void __exit icn_exit(void) diff --git a/drivers/staging/i4l/pcbit/capi.c b/drivers/staging/i4l/pcbit/capi.c index 4e3cbf857d60..373f90feda5a 100644 --- a/drivers/staging/i4l/pcbit/capi.c +++ b/drivers/staging/i4l/pcbit/capi.c @@ -92,9 +92,7 @@ int capi_conn_req(const char *calledPN, struct sk_buff **skb, int proto) *(skb_put(*skb, 1)) = 0x80; /* Speech */ *(skb_put(*skb, 1)) = 0x10; /* Circuit Mode */ *(skb_put(*skb, 1)) = 0x23; /* A-law */ - } - else - { + } else { /* Bearer Capability - Mandatory*/ *(skb_put(*skb, 1)) = 2; /* BC0.Length */ *(skb_put(*skb, 1)) = 0x88; /* Digital Information */ diff --git a/drivers/staging/i4l/pcbit/drv.c b/drivers/staging/i4l/pcbit/drv.c index c5270e229efb..d417df5efb5f 100644 --- a/drivers/staging/i4l/pcbit/drv.c +++ b/drivers/staging/i4l/pcbit/drv.c @@ -359,11 +359,9 @@ static int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb) */ #ifdef BLOCK_TIMER if (chan->block_timer.function == NULL) { - init_timer(&chan->block_timer); - chan->block_timer.function = &pcbit_block_timer; - chan->block_timer.data = (long) chan; - chan->block_timer.expires = jiffies + 1 * HZ; - add_timer(&chan->block_timer); + setup_timer(&chan->block_timer, &pcbit_block_timer, + (long)chan); + mod_timer(&chan->block_timer, jiffies + 1 * HZ); } #endif return 0; @@ -804,11 +802,7 @@ static int set_protocol_running(struct pcbit_dev *dev) { isdn_ctrl ctl; - init_timer(&dev->set_running_timer); - - dev->set_running_timer.function = &set_running_timeout; - dev->set_running_timer.data = (ulong) dev; - dev->set_running_timer.expires = jiffies + SET_RUN_TIMEOUT; + setup_timer(&dev->set_running_timer, &set_running_timeout, (ulong)dev); /* kick it */ @@ -817,7 +811,7 @@ static int set_protocol_running(struct pcbit_dev *dev) writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), dev->sh_mem + BANK4); - add_timer(&dev->set_running_timer); + mod_timer(&dev->set_running_timer, jiffies + SET_RUN_TIMEOUT); wait_event(dev->set_running_wq, dev->l2_state == L2_RUNNING || dev->l2_state == L2_DOWN); diff --git a/drivers/staging/i4l/pcbit/edss1.c b/drivers/staging/i4l/pcbit/edss1.c index e72c16420712..6d291d548423 100644 --- a/drivers/staging/i4l/pcbit/edss1.c +++ b/drivers/staging/i4l/pcbit/edss1.c @@ -298,11 +298,8 @@ void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan, break; if (tentry->init != 0xff) { - init_timer(&chan->fsm_timer); - chan->fsm_timer.function = &pcbit_fsm_timer; - chan->fsm_timer.data = (ulong) chan; - chan->fsm_timer.expires = jiffies + tentry->timeout * HZ; - add_timer(&chan->fsm_timer); + setup_timer(&chan->fsm_timer, &pcbit_fsm_timer, (ulong)chan); + mod_timer(&chan->fsm_timer, jiffies + tentry->timeout * HZ); } spin_unlock_irqrestore(&dev->lock, flags); diff --git a/drivers/staging/i4l/pcbit/layer2.c b/drivers/staging/i4l/pcbit/layer2.c index 46e1240ae074..a136c72547e5 100644 --- a/drivers/staging/i4l/pcbit/layer2.c +++ b/drivers/staging/i4l/pcbit/layer2.c @@ -645,11 +645,9 @@ pcbit_l2_error(struct pcbit_dev *dev) dev->l2_state = L2_DOWN; - init_timer(&dev->error_recover_timer); - dev->error_recover_timer.function = &pcbit_l2_err_recover; - dev->error_recover_timer.data = (ulong) dev; - dev->error_recover_timer.expires = jiffies + ERRTIME; - add_timer(&dev->error_recover_timer); + setup_timer(&dev->error_recover_timer, &pcbit_l2_err_recover, + (ulong)dev); + mod_timer(&dev->error_recover_timer, jiffies + ERRTIME); } } diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h index 9c8a9587df7d..4dcc8575cbe3 100644 --- a/drivers/staging/iio/accel/sca3000.h +++ b/drivers/staging/iio/accel/sca3000.h @@ -113,6 +113,7 @@ #define SCA3000_OUT_CTRL_BUF_X_EN 0x10 #define SCA3000_OUT_CTRL_BUF_Y_EN 0x08 #define SCA3000_OUT_CTRL_BUF_Z_EN 0x04 +#define SCA3000_OUT_CTRL_BUF_DIV_MASK 0x03 #define SCA3000_OUT_CTRL_BUF_DIV_4 0x02 #define SCA3000_OUT_CTRL_BUF_DIV_2 0x01 diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index b5625f5d5e0e..d626125d7af9 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -402,6 +402,7 @@ static const struct iio_event_spec sca3000_event = { .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 = index, \ .scan_index = index, \ .scan_type = { \ @@ -412,7 +413,7 @@ static const struct iio_event_spec sca3000_event = { }, \ .event_spec = &sca3000_event, \ .num_event_specs = 1, \ - } + } static const struct iio_chan_spec sca3000_channels[] = { SCA3000_CHAN(0, IIO_MOD_X), @@ -443,6 +444,97 @@ static u8 sca3000_addresses[3][3] = { SCA3000_MD_CTRL_OR_Z}, }; +/** + * __sca3000_get_base_freq() obtain mode specific base frequency + * + * lock must be held + **/ +static inline int __sca3000_get_base_freq(struct sca3000_state *st, + const struct sca3000_chip_info *info, + int *base_freq) +{ + int ret; + + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + switch (0x03 & st->rx[0]) { + case SCA3000_MEAS_MODE_NORMAL: + *base_freq = info->measurement_mode_freq; + break; + case SCA3000_MEAS_MODE_OP_1: + *base_freq = info->option_mode_1_freq; + break; + case SCA3000_MEAS_MODE_OP_2: + *base_freq = info->option_mode_2_freq; + break; + } +error_ret: + return ret; +} + +/** + * read_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * + * lock must be held + **/ +static int read_raw_samp_freq(struct sca3000_state *st, int *val) +{ + int ret; + + ret = __sca3000_get_base_freq(st, st->info, val); + if (ret) + return ret; + + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + return ret; + + if (*val > 0) { + ret &= SCA3000_OUT_CTRL_BUF_DIV_MASK; + switch (ret) { + case SCA3000_OUT_CTRL_BUF_DIV_2: + *val /= 2; + break; + case SCA3000_OUT_CTRL_BUF_DIV_4: + *val /= 4; + break; + } + } + + return 0; +} + +/** + * write_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * + * lock must be held + **/ +static int write_raw_samp_freq(struct sca3000_state *st, int val) +{ + int ret, base_freq, ctrlval; + + ret = __sca3000_get_base_freq(st, st->info, &base_freq); + if (ret) + return ret; + + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + return ret; + + ctrlval = ret & ~SCA3000_OUT_CTRL_BUF_DIV_MASK; + + if (val == base_freq / 2) + ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2; + if (val == base_freq / 4) + ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4; + else if (val != base_freq) + return -EINVAL; + + return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, + ctrlval); +} + static int sca3000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -495,11 +587,38 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, *val = -214; *val2 = 600000; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&st->lock); + ret = read_raw_samp_freq(st, val); + mutex_unlock(&st->lock); + return ret ? ret : IIO_VAL_INT; default: return -EINVAL; } } +static int sca3000_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&st->lock); + ret = write_raw_samp_freq(st, val); + mutex_unlock(&st->lock); + return ret; + default: + return -EINVAL; + } + + return ret; +} + /** * sca3000_read_av_freq() sysfs function to get available frequencies * @@ -548,133 +667,12 @@ error_ret: return ret; } -/** - * __sca3000_get_base_freq() obtain mode specific base frequency - * - * lock must be held - **/ -static inline int __sca3000_get_base_freq(struct sca3000_state *st, - const struct sca3000_chip_info *info, - int *base_freq) -{ - int ret; - - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - switch (0x03 & st->rx[0]) { - case SCA3000_MEAS_MODE_NORMAL: - *base_freq = info->measurement_mode_freq; - break; - case SCA3000_MEAS_MODE_OP_1: - *base_freq = info->option_mode_1_freq; - break; - case SCA3000_MEAS_MODE_OP_2: - *base_freq = info->option_mode_2_freq; - break; - } -error_ret: - return ret; -} - -/** - * sca3000_read_frequency() sysfs interface to get the current frequency - **/ -static ssize_t sca3000_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int ret, len = 0, base_freq = 0, val; - - mutex_lock(&st->lock); - ret = __sca3000_get_base_freq(st, st->info, &base_freq); - if (ret) - goto error_ret_mut; - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - mutex_unlock(&st->lock); - if (ret < 0) - goto error_ret; - val = ret; - if (base_freq > 0) - switch (val & 0x03) { - case 0x00: - case 0x03: - len = sprintf(buf, "%d\n", base_freq); - break; - case 0x01: - len = sprintf(buf, "%d\n", base_freq / 2); - break; - case 0x02: - len = sprintf(buf, "%d\n", base_freq / 4); - break; - } - - return len; -error_ret_mut: - mutex_unlock(&st->lock); -error_ret: - return ret; -} - -/** - * sca3000_set_frequency() sysfs interface to set the current frequency - **/ -static ssize_t sca3000_set_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int ret, base_freq = 0; - int ctrlval; - int val; - - ret = kstrtoint(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&st->lock); - /* What mode are we in? */ - ret = __sca3000_get_base_freq(st, st->info, &base_freq); - if (ret) - goto error_free_lock; - - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - if (ret < 0) - goto error_free_lock; - ctrlval = ret; - /* clear the bits */ - ctrlval &= ~0x03; - - if (val == base_freq / 2) { - ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2; - } else if (val == base_freq / 4) { - ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4; - } else if (val != base_freq) { - ret = -EINVAL; - goto error_free_lock; - } - ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, - ctrlval); -error_free_lock: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - /* * Should only really be registered if ring buffer support is compiled in. * Does no harm however and doing it right would add a fair bit of complexity */ static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - sca3000_read_frequency, - sca3000_set_frequency); - /** * sca3000_read_thresh() - query of a threshold **/ @@ -751,7 +749,6 @@ static struct attribute *sca3000_attributes[] = { &iio_dev_attr_measurement_mode_available.dev_attr.attr, &iio_dev_attr_measurement_mode.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, NULL, }; @@ -1086,6 +1083,7 @@ error_ret: static const struct iio_info sca3000_info = { .attrs = &sca3000_attribute_group, .read_raw = &sca3000_read_raw, + .write_raw = &sca3000_write_raw, .event_attrs = &sca3000_event_attribute_group, .read_event_value = &sca3000_read_thresh, .write_event_value = &sca3000_write_thresh, diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 2177f1dd2b5d..b460dda7eb65 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -478,7 +478,7 @@ static ssize_t ad7280_store_balance_timer(struct device *dev, static struct attribute *ad7280_attributes[AD7280A_MAX_CHAIN * AD7280A_CELLS_PER_DEV * 2 + 1]; -static struct attribute_group ad7280_attrs_group = { +static const struct attribute_group ad7280_attrs_group = { .attrs = ad7280_attributes, }; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 24c348d2f5bb..5eecf1cb1028 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -156,8 +156,7 @@ static const struct iio_chan_spec ad5933_channels[] = { }, }; -static int ad5933_i2c_write(struct i2c_client *client, - u8 reg, u8 len, u8 *data) +static int ad5933_i2c_write(struct i2c_client *client, u8 reg, u8 len, u8 *data) { int ret; @@ -171,8 +170,7 @@ static int ad5933_i2c_write(struct i2c_client *client, return 0; } -static int ad5933_i2c_read(struct i2c_client *client, - u8 reg, u8 len, u8 *data) +static int ad5933_i2c_read(struct i2c_client *client, u8 reg, u8 len, u8 *data) { int ret; @@ -269,7 +267,8 @@ static int ad5933_setup(struct ad5933_state *st) dat = cpu_to_be16(st->settling_cycles); ret = ad5933_i2c_write(st->client, - AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); + AD5933_REG_SETTLING_CYCLES, + 2, (u8 *)&dat); if (ret < 0) return ret; @@ -294,8 +293,8 @@ static void ad5933_calc_out_ranges(struct ad5933_state *st) */ static ssize_t ad5933_show_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); @@ -322,9 +321,9 @@ static ssize_t ad5933_show_frequency(struct device *dev, } static ssize_t ad5933_store_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); @@ -357,8 +356,8 @@ static IIO_DEVICE_ATTR(out_voltage0_freq_increment, S_IRUGO | S_IWUSR, AD5933_REG_FREQ_INC); static ssize_t ad5933_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); @@ -399,9 +398,9 @@ static ssize_t ad5933_show(struct device *dev, } static ssize_t ad5933_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); @@ -451,7 +450,8 @@ static ssize_t ad5933_store(struct device *dev, dat = cpu_to_be16(val); ret = ad5933_i2c_write(st->client, - AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); + AD5933_REG_SETTLING_CYCLES, + 2, (u8 *)&dat); break; case AD5933_FREQ_POINTS: val = clamp(val, (u16)0, (u16)511); @@ -545,8 +545,8 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, goto out; ret = ad5933_i2c_read(st->client, - AD5933_REG_TEMP_DATA, 2, - (u8 *)&dat); + AD5933_REG_TEMP_DATA, + 2, (u8 *)&dat); if (ret < 0) goto out; mutex_unlock(&indio_dev->mlock); @@ -705,7 +705,7 @@ static void ad5933_work(struct work_struct *work) } static int ad5933_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { int ret, voltage_uv = 0; struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev); diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 76d9f74e7dcb..a767a43c995c 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -15,10 +15,6 @@ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include @@ -32,25 +28,25 @@ #include #include -#define CONVERSION_TIME_MS 100 +#define ISL29018_CONV_TIME_MS 100 #define ISL29018_REG_ADD_COMMAND1 0x00 -#define COMMMAND1_OPMODE_SHIFT 5 -#define COMMMAND1_OPMODE_MASK (7 << COMMMAND1_OPMODE_SHIFT) -#define COMMMAND1_OPMODE_POWER_DOWN 0 -#define COMMMAND1_OPMODE_ALS_ONCE 1 -#define COMMMAND1_OPMODE_IR_ONCE 2 -#define COMMMAND1_OPMODE_PROX_ONCE 3 +#define ISL29018_CMD1_OPMODE_SHIFT 5 +#define ISL29018_CMD1_OPMODE_MASK (7 << ISL29018_CMD1_OPMODE_SHIFT) +#define ISL29018_CMD1_OPMODE_POWER_DOWN 0 +#define ISL29018_CMD1_OPMODE_ALS_ONCE 1 +#define ISL29018_CMD1_OPMODE_IR_ONCE 2 +#define ISL29018_CMD1_OPMODE_PROX_ONCE 3 -#define ISL29018_REG_ADD_COMMANDII 0x01 -#define COMMANDII_RESOLUTION_SHIFT 2 -#define COMMANDII_RESOLUTION_MASK (0x3 << COMMANDII_RESOLUTION_SHIFT) +#define ISL29018_REG_ADD_COMMAND2 0x01 +#define ISL29018_CMD2_RESOLUTION_SHIFT 2 +#define ISL29018_CMD2_RESOLUTION_MASK (0x3 << ISL29018_CMD2_RESOLUTION_SHIFT) -#define COMMANDII_RANGE_SHIFT 0 -#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT) +#define ISL29018_CMD2_RANGE_SHIFT 0 +#define ISL29018_CMD2_RANGE_MASK (0x3 << ISL29018_CMD2_RANGE_SHIFT) -#define COMMANDII_SCHEME_SHIFT 7 -#define COMMANDII_SCHEME_MASK (0x1 << COMMANDII_SCHEME_SHIFT) +#define ISL29018_CMD2_SCHEME_SHIFT 7 +#define ISL29018_CMD2_SCHEME_MASK (0x1 << ISL29018_CMD2_SCHEME_SHIFT) #define ISL29018_REG_ADD_DATA_LSB 0x02 #define ISL29018_REG_ADD_DATA_MSB 0x03 @@ -127,13 +123,13 @@ static int isl29018_set_integration_time(struct isl29018_chip *chip, if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type])) return -EINVAL; - ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_RESOLUTION_MASK, - i << COMMANDII_RESOLUTION_SHIFT); + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_RESOLUTION_MASK, + i << ISL29018_CMD2_RESOLUTION_SHIFT); if (ret < 0) return ret; - /* keep the same range when integration time changes */ + /* Keep the same range when integration time changes */ int_time = chip->int_time; for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) { if (chip->scale.scale == isl29018_scales[int_time][i].scale && @@ -163,9 +159,9 @@ static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale) if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time])) return -EINVAL; - ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_RANGE_MASK, - i << COMMANDII_RANGE_SHIFT); + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_RANGE_MASK, + i << ISL29018_CMD2_RANGE_SHIFT); if (ret < 0) return ret; @@ -183,13 +179,13 @@ static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) /* Set mode */ status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, - mode << COMMMAND1_OPMODE_SHIFT); + mode << ISL29018_CMD1_OPMODE_SHIFT); if (status) { dev_err(dev, "Error in setting operating mode err %d\n", status); return status; } - msleep(CONVERSION_TIME_MS); + msleep(ISL29018_CONV_TIME_MS); status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb); if (status < 0) { dev_err(dev, @@ -213,8 +209,8 @@ static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) int lux_data; unsigned int data_x_range; - lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE); - + lux_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_ALS_ONCE); if (lux_data < 0) return lux_data; @@ -230,8 +226,8 @@ static int isl29018_read_ir(struct isl29018_chip *chip, int *ir) { int ir_data; - ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE); - + ir_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_IR_ONCE); if (ir_data < 0) return ir_data; @@ -249,16 +245,16 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, struct device *dev = regmap_get_device(chip->regmap); /* Do proximity sensing with required scheme */ - status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_SCHEME_MASK, - scheme << COMMANDII_SCHEME_SHIFT); + status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_SCHEME_MASK, + scheme << ISL29018_CMD2_SCHEME_SHIFT); if (status) { dev_err(dev, "Error in setting operating mode\n"); return status; } prox_data = isl29018_read_sensor_input(chip, - COMMMAND1_OPMODE_PROX_ONCE); + ISL29018_CMD1_OPMODE_PROX_ONCE); if (prox_data < 0) return prox_data; @@ -267,8 +263,8 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, return 0; } - ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE); - + ir_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_IR_ONCE); if (ir_data < 0) return ir_data; @@ -280,7 +276,7 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, return 0; } -static ssize_t show_scale_available(struct device *dev, +static ssize_t isl29018_show_scale_available(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -297,7 +293,7 @@ static ssize_t show_scale_available(struct device *dev, return len; } -static ssize_t show_int_time_available(struct device *dev, +static ssize_t isl29018_show_int_time_available(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -313,8 +309,7 @@ static ssize_t show_int_time_available(struct device *dev, return len; } -/* proximity scheme */ -static ssize_t show_prox_infrared_suppression(struct device *dev, +static ssize_t isl29018_show_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, char *buf) { @@ -322,13 +317,13 @@ static ssize_t show_prox_infrared_suppression(struct device *dev, struct isl29018_chip *chip = iio_priv(indio_dev); /* - * return the "proximity scheme" i.e. if the chip does on chip + * Return the "proximity scheme" i.e. if the chip does on chip * infrared suppression (1 means perform on chip suppression) */ return sprintf(buf, "%d\n", chip->prox_scheme); } -static ssize_t store_prox_infrared_suppression(struct device *dev, +static ssize_t isl29018_store_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -338,13 +333,11 @@ static ssize_t store_prox_infrared_suppression(struct device *dev, if (kstrtoint(buf, 10, &val)) return -EINVAL; - if (!(val == 0 || val == 1)) { - dev_err(dev, "The mode is not supported\n"); + if (!(val == 0 || val == 1)) return -EINVAL; - } /* - * get the "proximity scheme" i.e. if the chip does on chip + * Get the "proximity scheme" i.e. if the chip does on chip * infrared suppression (1 means perform on chip suppression) */ mutex_lock(&chip->lock); @@ -354,7 +347,6 @@ static ssize_t store_prox_infrared_suppression(struct device *dev, return count; } -/* Channel IO */ static int isl29018_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, @@ -491,13 +483,13 @@ static const struct iio_chan_spec isl29023_channels[] = { }; static IIO_DEVICE_ATTR(in_illuminance_integration_time_available, S_IRUGO, - show_int_time_available, NULL, 0); + isl29018_show_int_time_available, NULL, 0); static IIO_DEVICE_ATTR(in_illuminance_scale_available, S_IRUGO, - show_scale_available, NULL, 0); + isl29018_show_scale_available, NULL, 0); static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, S_IRUGO | S_IWUSR, - show_prox_infrared_suppression, - store_prox_infrared_suppression, 0); + isl29018_show_prox_infrared_suppression, + isl29018_store_prox_infrared_suppression, 0); #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) @@ -541,7 +533,7 @@ static int isl29035_detect(struct isl29018_chip *chip) if (id != ISL29035_DEVICE_ID) return -ENODEV; - /* clear out brownout bit */ + /* Clear brownout bit */ return regmap_update_bits(chip->regmap, ISL29035_REG_DEVICE_ID, ISL29035_BOUT_MASK, 0); } @@ -574,7 +566,7 @@ static int isl29018_chip_init(struct isl29018_chip *chip) * conversions, clear the test registers, and then rewrite all * registers to the desired values. * ... - * FOR ISL29011, ISL29018, ISL29021, ISL29023 + * For ISL29011, ISL29018, ISL29021, ISL29023 * 1. Write 0x00 to register 0x08 (TEST) * 2. Write 0x00 to register 0x00 (CMD1) * 3. Rewrite all registers to the desired values @@ -603,7 +595,7 @@ static int isl29018_chip_init(struct isl29018_chip *chip) usleep_range(1000, 2000); /* per data sheet, page 10 */ - /* set defaults */ + /* Set defaults */ status = isl29018_set_scale(chip, chip->scale.scale, chip->scale.uscale); if (status < 0) { @@ -635,7 +627,7 @@ static const struct iio_info isl29023_info = { .write_raw = isl29018_write_raw, }; -static bool is_volatile_reg(struct device *dev, unsigned int reg) +static bool isl29018_is_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case ISL29018_REG_ADD_DATA_LSB: @@ -649,37 +641,32 @@ static bool is_volatile_reg(struct device *dev, unsigned int reg) } } -/* - * isl29018_regmap_config: regmap configuration. - * Use RBTREE mechanism for caching. - */ static const struct regmap_config isl29018_regmap_config = { .reg_bits = 8, .val_bits = 8, - .volatile_reg = is_volatile_reg, + .volatile_reg = isl29018_is_volatile_reg, .max_register = ISL29018_REG_TEST, .num_reg_defaults_raw = ISL29018_REG_TEST + 1, .cache_type = REGCACHE_RBTREE, }; -/* isl29035_regmap_config: regmap configuration for ISL29035 */ static const struct regmap_config isl29035_regmap_config = { .reg_bits = 8, .val_bits = 8, - .volatile_reg = is_volatile_reg, + .volatile_reg = isl29018_is_volatile_reg, .max_register = ISL29035_REG_DEVICE_ID, .num_reg_defaults_raw = ISL29035_REG_DEVICE_ID + 1, .cache_type = REGCACHE_RBTREE, }; -struct chip_info { +struct isl29018_chip_info { const struct iio_chan_spec *channels; int num_channels; const struct iio_info *indio_info; const struct regmap_config *regmap_cfg; }; -static const struct chip_info chip_info_tbl[] = { +static const struct isl29018_chip_info isl29018_chip_info_tbl[] = { [isl29018] = { .channels = isl29018_channels, .num_channels = ARRAY_SIZE(isl29018_channels), @@ -724,10 +711,8 @@ static int isl29018_probe(struct i2c_client *client, int dev_id = 0; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); - if (!indio_dev) { - dev_err(&client->dev, "iio allocation fails\n"); + if (!indio_dev) return -ENOMEM; - } chip = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); @@ -750,7 +735,7 @@ static int isl29018_probe(struct i2c_client *client, chip->suspended = false; chip->regmap = devm_regmap_init_i2c(client, - chip_info_tbl[dev_id].regmap_cfg); + isl29018_chip_info_tbl[dev_id].regmap_cfg); if (IS_ERR(chip->regmap)) { err = PTR_ERR(chip->regmap); dev_err(&client->dev, "regmap initialization fails: %d\n", err); @@ -761,19 +746,13 @@ static int isl29018_probe(struct i2c_client *client, if (err) return err; - indio_dev->info = chip_info_tbl[dev_id].indio_info; - indio_dev->channels = chip_info_tbl[dev_id].channels; - indio_dev->num_channels = chip_info_tbl[dev_id].num_channels; + indio_dev->info = isl29018_chip_info_tbl[dev_id].indio_info; + indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels; + indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels; indio_dev->name = name; indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; - err = devm_iio_device_register(&client->dev, indio_dev); - if (err) { - dev_err(&client->dev, "iio registration fails\n"); - return err; - } - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } #ifdef CONFIG_PM_SLEEP @@ -840,7 +819,6 @@ static const struct of_device_id isl29018_of_match[] = { MODULE_DEVICE_TABLE(of, isl29018_of_match); static struct i2c_driver isl29018_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "isl29018", .acpi_match_table = ACPI_PTR(isl29018_acpi_match), diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 2e3b1d64e32a..aa413e5878b9 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -27,29 +27,27 @@ #include #include -#define CONVERSION_TIME_MS 100 +#define ISL29028_CONV_TIME_MS 100 #define ISL29028_REG_CONFIGURE 0x01 -#define CONFIGURE_ALS_IR_MODE_ALS 0 -#define CONFIGURE_ALS_IR_MODE_IR BIT(0) -#define CONFIGURE_ALS_IR_MODE_MASK BIT(0) +#define ISL29028_CONF_ALS_IR_MODE_ALS 0 +#define ISL29028_CONF_ALS_IR_MODE_IR BIT(0) +#define ISL29028_CONF_ALS_IR_MODE_MASK BIT(0) -#define CONFIGURE_ALS_RANGE_LOW_LUX 0 -#define CONFIGURE_ALS_RANGE_HIGH_LUX BIT(1) -#define CONFIGURE_ALS_RANGE_MASK BIT(1) +#define ISL29028_CONF_ALS_RANGE_LOW_LUX 0 +#define ISL29028_CONF_ALS_RANGE_HIGH_LUX BIT(1) +#define ISL29028_CONF_ALS_RANGE_MASK BIT(1) -#define CONFIGURE_ALS_DIS 0 -#define CONFIGURE_ALS_EN BIT(2) -#define CONFIGURE_ALS_EN_MASK BIT(2) +#define ISL29028_CONF_ALS_DIS 0 +#define ISL29028_CONF_ALS_EN BIT(2) +#define ISL29028_CONF_ALS_EN_MASK BIT(2) -#define CONFIGURE_PROX_DRIVE BIT(3) +#define ISL29028_CONF_PROX_SLP_SH 4 +#define ISL29028_CONF_PROX_SLP_MASK (7 << ISL29028_CONF_PROX_SLP_SH) -#define CONFIGURE_PROX_SLP_SH 4 -#define CONFIGURE_PROX_SLP_MASK (7 << CONFIGURE_PROX_SLP_SH) - -#define CONFIGURE_PROX_EN BIT(7) -#define CONFIGURE_PROX_EN_MASK BIT(7) +#define ISL29028_CONF_PROX_EN BIT(7) +#define ISL29028_CONF_PROX_EN_MASK BIT(7) #define ISL29028_REG_INTERRUPT 0x02 @@ -62,10 +60,10 @@ #define ISL29028_NUM_REGS (ISL29028_REG_TEST2_MODE + 1) -enum als_ir_mode { - MODE_NONE = 0, - MODE_ALS, - MODE_IR +enum isl29028_als_ir_mode { + ISL29028_MODE_NONE = 0, + ISL29028_MODE_ALS, + ISL29028_MODE_IR, }; struct isl29028_chip { @@ -76,7 +74,7 @@ struct isl29028_chip { bool enable_prox; int lux_scale; - int als_ir_mode; + enum isl29028_als_ir_mode als_ir_mode; }; static int isl29028_set_proxim_sampling(struct isl29028_chip *chip, @@ -91,7 +89,8 @@ static int isl29028_set_proxim_sampling(struct isl29028_chip *chip, break; } return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_PROX_SLP_MASK, sel << CONFIGURE_PROX_SLP_SH); + ISL29028_CONF_PROX_SLP_MASK, + sel << ISL29028_CONF_PROX_SLP_SH); } static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable) @@ -100,9 +99,9 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable) int val = 0; if (enable) - val = CONFIGURE_PROX_EN; + val = ISL29028_CONF_PROX_EN; ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_PROX_EN_MASK, val); + ISL29028_CONF_PROX_EN_MASK, val); if (ret < 0) return ret; @@ -113,40 +112,40 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable) static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale) { - int val = (lux_scale == 2000) ? CONFIGURE_ALS_RANGE_HIGH_LUX : - CONFIGURE_ALS_RANGE_LOW_LUX; + int val = (lux_scale == 2000) ? ISL29028_CONF_ALS_RANGE_HIGH_LUX : + ISL29028_CONF_ALS_RANGE_LOW_LUX; return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_RANGE_MASK, val); + ISL29028_CONF_ALS_RANGE_MASK, val); } static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, - enum als_ir_mode mode) + enum isl29028_als_ir_mode mode) { int ret = 0; switch (mode) { - case MODE_ALS: + case ISL29028_MODE_ALS: ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_IR_MODE_MASK, - CONFIGURE_ALS_IR_MODE_ALS); + ISL29028_CONF_ALS_IR_MODE_MASK, + ISL29028_CONF_ALS_IR_MODE_ALS); if (ret < 0) return ret; ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_RANGE_MASK, - CONFIGURE_ALS_RANGE_HIGH_LUX); + ISL29028_CONF_ALS_RANGE_MASK, + ISL29028_CONF_ALS_RANGE_HIGH_LUX); break; - case MODE_IR: + case ISL29028_MODE_IR: ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_IR_MODE_MASK, - CONFIGURE_ALS_IR_MODE_IR); + ISL29028_CONF_ALS_IR_MODE_MASK, + ISL29028_CONF_ALS_IR_MODE_IR); break; - case MODE_NONE: + case ISL29028_MODE_NONE: return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_DIS); + ISL29028_CONF_ALS_EN_MASK, ISL29028_CONF_ALS_DIS); } if (ret < 0) @@ -154,12 +153,13 @@ static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, /* Enable the ALS/IR */ ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_EN); + ISL29028_CONF_ALS_EN_MASK, + ISL29028_CONF_ALS_EN); if (ret < 0) return ret; /* Need to wait for conversion time if ALS/IR mode enabled */ - mdelay(CONVERSION_TIME_MS); + mdelay(ISL29028_CONV_TIME_MS); return 0; } @@ -223,14 +223,14 @@ static int isl29028_als_get(struct isl29028_chip *chip, int *als_data) int ret; int als_ir_data; - if (chip->als_ir_mode != MODE_ALS) { - ret = isl29028_set_als_ir_mode(chip, MODE_ALS); + if (chip->als_ir_mode != ISL29028_MODE_ALS) { + ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_ALS); if (ret < 0) { dev_err(dev, "Error in enabling ALS mode err %d\n", ret); return ret; } - chip->als_ir_mode = MODE_ALS; + chip->als_ir_mode = ISL29028_MODE_ALS; } ret = isl29028_read_als_ir(chip, &als_ir_data); @@ -256,14 +256,14 @@ static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data) struct device *dev = regmap_get_device(chip->regmap); int ret; - if (chip->als_ir_mode != MODE_IR) { - ret = isl29028_set_als_ir_mode(chip, MODE_IR); + if (chip->als_ir_mode != ISL29028_MODE_IR) { + ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_IR); if (ret < 0) { dev_err(dev, "Error in enabling IR mode err %d\n", ret); return ret; } - chip->als_ir_mode = MODE_IR; + chip->als_ir_mode = ISL29028_MODE_IR; } return isl29028_read_als_ir(chip, ir_data); } @@ -383,8 +383,8 @@ static int isl29028_read_raw(struct iio_dev *indio_dev, } static IIO_CONST_ATTR(in_proximity_sampling_frequency_available, - "1, 3, 5, 10, 13, 20, 83, 100"); -static IIO_CONST_ATTR(in_illuminance_scale_available, "125, 2000"); + "1 3 5 10 13 20 83 100"); +static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000"); #define ISL29028_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) #define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) @@ -428,7 +428,7 @@ static int isl29028_chip_init(struct isl29028_chip *chip) chip->enable_prox = false; chip->prox_sampling = 20; chip->lux_scale = 2000; - chip->als_ir_mode = MODE_NONE; + chip->als_ir_mode = ISL29028_MODE_NONE; ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0); if (ret < 0) { @@ -462,7 +462,7 @@ static int isl29028_chip_init(struct isl29028_chip *chip) return ret; } -static bool is_volatile_reg(struct device *dev, unsigned int reg) +static bool isl29028_is_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case ISL29028_REG_INTERRUPT: @@ -478,7 +478,7 @@ static bool is_volatile_reg(struct device *dev, unsigned int reg) static const struct regmap_config isl29028_regmap_config = { .reg_bits = 8, .val_bits = 8, - .volatile_reg = is_volatile_reg, + .volatile_reg = isl29028_is_volatile_reg, .max_register = ISL29028_NUM_REGS - 1, .num_reg_defaults_raw = ISL29028_NUM_REGS, .cache_type = REGCACHE_RBTREE, @@ -546,7 +546,6 @@ static const struct of_device_id isl29028_of_match[] = { MODULE_DEVICE_TABLE(of, isl29028_of_match); static struct i2c_driver isl29028_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "isl29028", .of_match_table = isl29028_of_match, diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 05b4ad4e941c..08f1583ee34e 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -803,7 +803,7 @@ static struct attribute *sysfs_attrs_ctrl[] = { NULL }; -static struct attribute_group tsl2583_attribute_group = { +static const struct attribute_group tsl2583_attribute_group = { .attrs = sysfs_attrs_ctrl, }; diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index c46bef641613..17309591ca57 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -23,9 +23,7 @@ #include "meter.h" #include "ade7754.h" -static int ade7754_spi_write_reg_8(struct device *dev, - u8 reg_address, - u8 val) +static int ade7754_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -42,8 +40,7 @@ static int ade7754_spi_write_reg_8(struct device *dev, } static int ade7754_spi_write_reg_16(struct device *dev, - u8 reg_address, - u16 value) + u8 reg_address, u16 value) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -59,9 +56,7 @@ static int ade7754_spi_write_reg_16(struct device *dev, return ret; } -static int ade7754_spi_read_reg_8(struct device *dev, - u8 reg_address, - u8 *val) +static int ade7754_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); @@ -70,7 +65,7 @@ static int ade7754_spi_read_reg_8(struct device *dev, ret = spi_w8r8(st->us, ADE7754_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", - reg_address); + reg_address); return ret; } *val = ret; @@ -79,8 +74,7 @@ static int ade7754_spi_read_reg_8(struct device *dev, } static int ade7754_spi_read_reg_16(struct device *dev, - u8 reg_address, - u16 *val) + u8 reg_address, u16 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); @@ -99,8 +93,7 @@ static int ade7754_spi_read_reg_16(struct device *dev, } static int ade7754_spi_read_reg_24(struct device *dev, - u8 reg_address, - u32 *val) + u8 reg_address, u32 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); @@ -123,7 +116,7 @@ static int ade7754_spi_read_reg_24(struct device *dev, ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", - reg_address); + reg_address); goto error_ret; } *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; @@ -134,8 +127,8 @@ error_ret: } static ssize_t ade7754_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u8 val = 0; @@ -149,8 +142,8 @@ static ssize_t ade7754_read_8bit(struct device *dev, } static ssize_t ade7754_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u16 val = 0; @@ -164,8 +157,8 @@ static ssize_t ade7754_read_16bit(struct device *dev, } static ssize_t ade7754_read_24bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u32 val = 0; @@ -179,9 +172,9 @@ static ssize_t ade7754_read_24bit(struct device *dev, } static ssize_t ade7754_write_8bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -197,9 +190,9 @@ error_ret: } static ssize_t ade7754_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -403,16 +396,14 @@ err_ret: } static ssize_t ade7754_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u8 t; int sps; - ret = ade7754_spi_read_reg_8(dev, - ADE7754_WAVMODE, - &t); + ret = ade7754_spi_read_reg_8(dev, ADE7754_WAVMODE, &t); if (ret) return ret; @@ -423,9 +414,9 @@ static ssize_t ade7754_read_frequency(struct device *dev, } static ssize_t ade7754_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index a6b76d4b1c80..57c213dfadcc 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -38,18 +38,14 @@ static int ade7758_write_waveform_type(struct device *dev, unsigned int type) int ret; u8 reg; - ret = ade7758_spi_read_reg_8(dev, - ADE7758_WAVMODE, - ®); + ret = ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, ®); if (ret) goto out; reg &= ~0x1F; reg |= type & 0x1F; - ret = ade7758_spi_write_reg_8(dev, - ADE7758_WAVMODE, - reg); + ret = ade7758_spi_write_reg_8(dev, ADE7758_WAVMODE, reg); out: return ret; } @@ -94,7 +90,7 @@ static int ade7758_ring_preenable(struct iio_dev *indio_dev) indio_dev->masklength); ade7758_write_waveform_type(&indio_dev->dev, - indio_dev->channels[channel].address); + indio_dev->channels[channel].address); return 0; } diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index 75e8685e6df2..24edbc39ab4e 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -23,8 +23,8 @@ #include "ade7854.h" static ssize_t ade7854_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u8 val = 0; @@ -40,8 +40,8 @@ static ssize_t ade7854_read_8bit(struct device *dev, } static ssize_t ade7854_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u16 val = 0; @@ -57,8 +57,8 @@ static ssize_t ade7854_read_16bit(struct device *dev, } static ssize_t ade7854_read_24bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u32 val; @@ -74,8 +74,8 @@ static ssize_t ade7854_read_24bit(struct device *dev, } static ssize_t ade7854_read_32bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u32 val = 0; @@ -91,9 +91,9 @@ static ssize_t ade7854_read_32bit(struct device *dev, } static ssize_t ade7854_write_8bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -112,9 +112,9 @@ error_ret: } static ssize_t ade7854_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -133,9 +133,9 @@ error_ret: } static ssize_t ade7854_write_24bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -154,9 +154,9 @@ error_ret: } static ssize_t ade7854_write_32bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_to_iio_dev(dev); diff --git a/drivers/staging/ks7010/eap_packet.h b/drivers/staging/ks7010/eap_packet.h index 16a392abdaec..df7f760e4110 100644 --- a/drivers/staging/ks7010/eap_packet.h +++ b/drivers/staging/ks7010/eap_packet.h @@ -1,6 +1,8 @@ #ifndef EAP_PACKET_H #define EAP_PACKET_H +#include + #define WBIT(n) (1 << (n)) #ifndef ETH_ALEN @@ -19,14 +21,14 @@ struct ether_hdr { #define ETHER_PROTOCOL_TYPE_IP 0x0800 #define ETHER_PROTOCOL_TYPE_ARP 0x0806 /* followed by length octets of data */ -} __attribute__ ((packed)); +} __packed; struct ieee802_1x_hdr { unsigned char version; unsigned char type; unsigned short length; /* followed by length octets of data */ -} __attribute__ ((packed)); +} __packed; #define EAPOL_VERSION 2 @@ -51,25 +53,33 @@ enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2, struct ieee802_1x_eapol_key { unsigned char type; unsigned short key_length; - /* does not repeat within the life of the keying material used to - * encrypt the Key field; 64-bit NTP timestamp MAY be used here */ + /* + * does not repeat within the life of the keying material used to + * encrypt the Key field; 64-bit NTP timestamp MAY be used here + */ unsigned char replay_counter[IEEE8021X_REPLAY_COUNTER_LEN]; unsigned char key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */ - unsigned char key_index; /* key flag in the most significant bit: + unsigned char key_index; /* + * key flag in the most significant bit: * 0 = broadcast (default key), * 1 = unicast (key mapping key); key index is in the - * 7 least significant bits */ - /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as - * the key */ + * 7 least significant bits + */ + /* + * HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as + * the key + */ unsigned char key_signature[IEEE8021X_KEY_SIGN_LEN]; - /* followed by key: if packet body length = 44 + key length, then the + /* + * followed by key: if packet body length = 44 + key length, then the * key field (of key_length bytes) contains the key in encrypted form; * if packet body length = 44, key field is absent and key_length * represents the number of least significant octets from * MS-MPPE-Send-Key attribute to be used as the keying material; - * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ -} __attribute__ ((packed)); + * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key + */ +} __packed; #define WPA_NONCE_LEN 32 #define WPA_REPLAY_COUNTER_LEN 8 @@ -86,7 +96,7 @@ struct wpa_eapol_key { unsigned char key_mic[16]; unsigned short key_data_length; /* followed by key_data_length bytes of key_data */ -} __attribute__ ((packed)); +} __packed; #define WPA_KEY_INFO_TYPE_MASK (WBIT(0) | WBIT(1) | WBIT(2)) #define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 WBIT(0) diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index b7337fd813d5..81c46f4d0935 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "ks_wlan.h" #include "ks_wlan_ioctl.h" @@ -35,18 +35,18 @@ MODULE_DEVICE_TABLE(sdio, ks7010_sdio_ids); /* macro */ #define inc_txqhead(priv) \ - ( priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE ) + (priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE) #define inc_txqtail(priv) \ - ( priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE ) + (priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE) #define cnt_txqbody(priv) \ - (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE ) + (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE) #define inc_rxqhead(priv) \ - ( priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE ) + (priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE) #define inc_rxqtail(priv) \ - ( priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE ) + (priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE) #define cnt_rxqbody(priv) \ - (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE ) + (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE) static int ks7010_sdio_read(struct ks_wlan_private *priv, unsigned int address, unsigned char *buffer, int length) @@ -87,7 +87,7 @@ static int ks7010_sdio_write(struct ks_wlan_private *priv, unsigned int address, return rc; } -void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv) +static void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv) { unsigned char rw_data; int retval; @@ -115,10 +115,9 @@ void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv) out: priv->sleep_mode = atomic_read(&priv->sleepstatus.status); - return; } -void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv) +static void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv) { unsigned char rw_data; int retval; @@ -146,7 +145,6 @@ void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv) out: priv->sleep_mode = atomic_read(&priv->sleepstatus.status); - return; } void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv) @@ -159,9 +157,9 @@ void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv) rw_data = WAKEUP_REQ; retval = ks7010_sdio_write(priv, WAKEUP, &rw_data, sizeof(rw_data)); - if (retval) { + if (retval) DPRINTK(1, " error : WAKEUP=%02X\n", rw_data); - } + DPRINTK(4, "wake up : WAKEUP=%02X\n", rw_data); priv->last_wakeup = jiffies; ++priv->wakeup_count; @@ -171,19 +169,16 @@ void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv) } } -int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) +static int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) { - int rc = 0; unsigned char rw_data; int retval; if (priv->reg.powermgt == POWMGT_ACTIVE_MODE) - return rc; + return 0; if (priv->reg.operation_mode == MODE_INFRASTRUCTURE && (priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { - - //DPRINTK(1,"psstatus.status=%d\n",atomic_read(&priv->psstatus.status)); if (priv->dev_state == DEVICE_STATE_SLEEP) { switch (atomic_read(&priv->psstatus.status)) { case PS_SNOOZE: /* 4 */ @@ -246,10 +241,9 @@ int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) break; } } - } - return rc; + return 0; } int ks_wlan_hw_power_save(struct ks_wlan_private *priv) @@ -268,7 +262,7 @@ static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p, if (priv->dev_state < DEVICE_STATE_BOOT) { kfree(p); - if (complete_handler != NULL) + if (complete_handler) (*complete_handler) (arg1, arg2); return 1; } @@ -277,7 +271,7 @@ static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p, /* in case of buffer overflow */ DPRINTK(1, "tx buffer overflow\n"); kfree(p); - if (complete_handler != NULL) + if (complete_handler) (*complete_handler) (arg1, arg2); return 1; } @@ -297,11 +291,10 @@ static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p, static int write_to_device(struct ks_wlan_private *priv, unsigned char *buffer, unsigned long size) { - int rc, retval; + int retval; unsigned char rw_data; struct hostif_hdr *hdr; hdr = (struct hostif_hdr *)buffer; - rc = 0; DPRINTK(4, "size=%d\n", hdr->size); if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) { @@ -346,10 +339,9 @@ static void tx_device_task(void *dev) &priv->ks_wlan_hw.rw_wq, 1); return; } - } kfree(sp->sendp); /* allocated memory free */ - if (sp->complete_handler != NULL) /* TX Complete */ + if (sp->complete_handler) /* TX Complete */ (*sp->complete_handler) (sp->arg1, sp->arg2); inc_txqhead(priv); @@ -358,7 +350,6 @@ static void tx_device_task(void *dev) &priv->ks_wlan_hw.rw_wq, 0); } } - return; } int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size, @@ -402,12 +393,9 @@ static void rx_event_task(unsigned long dev) hostif_receive(priv, rp->data, rp->size); inc_rxqhead(priv); - if (cnt_rxqbody(priv) > 0) { + if (cnt_rxqbody(priv) > 0) tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task); - } } - - return; } static void ks_wlan_hw_rx(void *dev, uint16_t size) @@ -432,9 +420,8 @@ static void ks_wlan_hw_rx(void *dev, uint16_t size) retval = ks7010_sdio_read(priv, DATA_WINDOW, &rx_buffer->data[0], hif_align_size(size)); - if (retval) { + if (retval) goto error_out; - } /* length check */ if (size > 2046 || size == 0) { @@ -449,9 +436,9 @@ static void ks_wlan_hw_rx(void *dev, uint16_t size) retval = ks7010_sdio_write(priv, READ_STATUS, &read_status, sizeof(read_status)); - if (retval) { + if (retval) DPRINTK(1, " error : READ_STATUS=%02X\n", read_status); - } + goto error_out; } @@ -465,9 +452,9 @@ static void ks_wlan_hw_rx(void *dev, uint16_t size) retval = ks7010_sdio_write(priv, READ_STATUS, &read_status, sizeof(read_status)); - if (retval) { + if (retval) DPRINTK(1, " error : READ_STATUS=%02X\n", read_status); - } + DPRINTK(4, "READ_STATUS=%02X\n", read_status); if (atomic_read(&priv->psstatus.confirm_wait)) { @@ -498,7 +485,7 @@ static void ks7010_rw_function(struct work_struct *work) /* wiat after DOZE */ if (time_after(priv->last_doze + ((30 * HZ) / 1000), jiffies)) { - DPRINTK(4, "wait after DOZE \n"); + DPRINTK(4, "wait after DOZE\n"); queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, &priv->ks_wlan_hw.rw_wq, 1); return; @@ -506,11 +493,13 @@ static void ks7010_rw_function(struct work_struct *work) /* wiat after WAKEUP */ while (time_after(priv->last_wakeup + ((30 * HZ) / 1000), jiffies)) { - DPRINTK(4, "wait after WAKEUP \n"); + DPRINTK(4, "wait after WAKEUP\n"); /* queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, (priv->last_wakeup + ((30*HZ)/1000) - jiffies));*/ - printk("wake: %lu %lu\n", priv->last_wakeup + (30 * HZ) / 1000, - jiffies); + dev_info(&priv->ks_wlan_hw.sdio_card->func->dev, + "wake: %lu %lu\n", + priv->last_wakeup + (30 * HZ) / 1000, + jiffies); msleep(30); } @@ -549,17 +538,15 @@ static void ks7010_rw_function(struct work_struct *work) if (rw_data & RSIZE_MASK) { /* Read schedule */ ks_wlan_hw_rx((void *)priv, - (uint16_t) (((rw_data & RSIZE_MASK) << 4))); + (uint16_t)((rw_data & RSIZE_MASK) << 4)); } - if ((rw_data & WSTATUS_MASK)) { + if ((rw_data & WSTATUS_MASK)) tx_device_task((void *)priv); - } + _ks_wlan_hw_power_save(priv); err_out: sdio_release_host(priv->ks_wlan_hw.sdio_card->func); - - return; } static void ks_sdio_interrupt(struct sdio_func *func) @@ -607,7 +594,6 @@ static void ks_sdio_interrupt(struct sdio_func *func) } complete(&priv->psstatus.wakeup_wait); } - } do { @@ -624,7 +610,7 @@ static void ks_sdio_interrupt(struct sdio_func *func) rsize = rw_data & RSIZE_MASK; if (rsize) { /* Read schedule */ ks_wlan_hw_rx((void *)priv, - (uint16_t) (((rsize) << 4))); + (uint16_t)(rsize << 4)); } if (rw_data & WSTATUS_MASK) { #if 0 @@ -667,7 +653,6 @@ static void ks_sdio_interrupt(struct sdio_func *func) intr_out: queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, &priv->ks_wlan_hw.rw_wq, 0); - return; } static int trx_device_init(struct ks_wlan_private *priv) @@ -696,14 +681,12 @@ static void trx_device_exit(struct ks_wlan_private *priv) while (cnt_txqbody(priv) > 0) { sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead]; kfree(sp->sendp); /* allocated memory free */ - if (sp->complete_handler != NULL) /* TX Complete */ + if (sp->complete_handler) /* TX Complete */ (*sp->complete_handler) (sp->arg1, sp->arg2); inc_txqhead(priv); } tasklet_kill(&priv->ks_wlan_hw.rx_bh_task); - - return; } static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index) @@ -711,7 +694,6 @@ static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index) int rc = 0; int retval; unsigned char *data_buf; - data_buf = NULL; data_buf = kmalloc(sizeof(u32), GFP_KERNEL); if (!data_buf) { @@ -732,8 +714,7 @@ static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index) goto error_out; } error_out: - if (data_buf) - kfree(data_buf); + kfree(data_buf); return rc; } @@ -744,7 +725,7 @@ static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address, int rc = 0; int retval; unsigned char *read_buf; - read_buf = NULL; + read_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); if (!read_buf) { rc = 1; @@ -758,13 +739,12 @@ static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address, retval = memcmp(data, read_buf, size); if (retval) { - DPRINTK(0, "data compare error (%d) \n", retval); + DPRINTK(0, "data compare error (%d)\n", retval); rc = 3; goto error_out; } error_out: - if (read_buf) - kfree(read_buf); + kfree(read_buf); return rc; } @@ -778,14 +758,10 @@ static int ks7010_upload_firmware(struct ks_wlan_private *priv, int length; const struct firmware *fw_entry = NULL; - rom_buf = NULL; - /* buffer allocate */ rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); - if (!rom_buf) { - rc = 3; - goto error_out0; - } + if (!rom_buf) + return 3; sdio_claim_host(card->func); @@ -799,7 +775,7 @@ static int ks7010_upload_firmware(struct ks_wlan_private *priv, retval = request_firmware(&fw_entry, ROM_FILE, &priv->ks_wlan_hw.sdio_card->func->dev); if (retval) - return retval; + goto error_out0; length = fw_entry->size; @@ -879,8 +855,7 @@ static int ks7010_upload_firmware(struct ks_wlan_private *priv, release_firmware(fw_entry); error_out0: sdio_release_host(card->func); - if (rom_buf) - kfree(rom_buf); + kfree(rom_buf); return rc; } @@ -903,9 +878,9 @@ static void ks7010_card_init(struct ks_wlan_private *priv) DPRINTK(1, "wait time out!! SME_START\n"); } - if (priv->mac_address_valid && priv->version_size) { + if (priv->mac_address_valid && priv->version_size) priv->dev_state = DEVICE_STATE_PREINIT; - } + hostif_sme_enqueue(priv, SME_GET_EEPROM_CKSUM); @@ -981,7 +956,7 @@ static int ks7010_sdio_probe(struct sdio_func *func, netdev = NULL; /* initilize ks_sdio_card */ - card = kzalloc(sizeof(struct ks_sdio_card), GFP_KERNEL); + card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; @@ -1029,12 +1004,13 @@ static int ks7010_sdio_probe(struct sdio_func *func, /* private memory allocate */ netdev = alloc_etherdev(sizeof(*priv)); - if (netdev == NULL) { - printk(KERN_ERR "ks7010 : Unable to alloc new net device\n"); + if (!netdev) { + dev_err(&card->func->dev, "ks7010 : Unable to alloc new net device\n"); goto error_release_irq; } if (dev_alloc_name(netdev, "wlan%d") < 0) { - printk(KERN_ERR "ks7010 : Couldn't get name!\n"); + dev_err(&card->func->dev, + "ks7010 : Couldn't get name!\n"); goto error_free_netdev; } @@ -1048,9 +1024,9 @@ static int ks7010_sdio_probe(struct sdio_func *func, init_completion(&priv->ks_wlan_hw.ks7010_sdio_wait); priv->ks_wlan_hw.read_buf = NULL; priv->ks_wlan_hw.read_buf = kmalloc(RX_DATA_SIZE, GFP_KERNEL); - if (!priv->ks_wlan_hw.read_buf) { + if (!priv->ks_wlan_hw.read_buf) goto error_free_netdev; - } + priv->dev_state = DEVICE_STATE_PREBOOT; priv->net_dev = netdev; priv->firmware_version[0] = '\0'; @@ -1074,9 +1050,9 @@ static int ks7010_sdio_probe(struct sdio_func *func, /* Upload firmware */ ret = ks7010_upload_firmware(priv, card); /* firmware load */ if (ret) { - printk(KERN_ERR - "ks7010: firmware load failed !! retern code = %d\n", - ret); + dev_err(&card->func->dev, + "ks7010: firmware load failed !! return code = %d\n", + ret); goto error_free_read_buf; } @@ -1086,9 +1062,9 @@ static int ks7010_sdio_probe(struct sdio_func *func, sdio_claim_host(func); ret = ks7010_sdio_write(priv, INT_PENDING, &rw_data, sizeof(rw_data)); sdio_release_host(func); - if (ret) { + if (ret) DPRINTK(1, " error : INT_PENDING=%02X\n", rw_data); - } + DPRINTK(4, " clear Interrupt : INT_PENDING=%02X\n", rw_data); /* enable ks7010sdio interrupt (INT_GCR_B|INT_READ_STATUS|INT_WRITE_STATUS) */ @@ -1096,9 +1072,9 @@ static int ks7010_sdio_probe(struct sdio_func *func, sdio_claim_host(func); ret = ks7010_sdio_write(priv, INT_ENABLE, &rw_data, sizeof(rw_data)); sdio_release_host(func); - if (ret) { + if (ret) DPRINTK(1, " error : INT_ENABLE=%02X\n", rw_data); - } + DPRINTK(4, " enable Interrupt : INT_ENABLE=%02X\n", rw_data); priv->dev_state = DEVICE_STATE_BOOT; @@ -1141,18 +1117,18 @@ static void ks7010_sdio_remove(struct sdio_func *func) int ret; struct ks_sdio_card *card; struct ks_wlan_private *priv; - struct net_device *netdev; DPRINTK(1, "ks7010_sdio_remove()\n"); card = sdio_get_drvdata(func); - if (card == NULL) + if (!card) return; DPRINTK(1, "priv = card->priv\n"); priv = card->priv; - netdev = priv->net_dev; if (priv) { + struct net_device *netdev = priv->net_dev; + ks_wlan_net_stop(netdev); DPRINTK(1, "ks_wlan_net_stop\n"); @@ -1166,9 +1142,8 @@ static void ks7010_sdio_remove(struct sdio_func *func) /* send stop request to MAC */ { struct hostif_stop_request_t *pp; - pp = (struct hostif_stop_request_t *) - kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL); - if (pp == NULL) { + pp = kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; /* to do goto ni suru */ } @@ -1176,7 +1151,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); - pp->header.event = cpu_to_le16((uint16_t) HIF_STOP_REQ); + pp->header.event = cpu_to_le16((uint16_t)HIF_STOP_REQ); sdio_claim_host(func); write_to_device(priv, (unsigned char *)pp, @@ -1199,9 +1174,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) unregister_netdev(netdev); trx_device_exit(priv); - if (priv->ks_wlan_hw.read_buf) { - kfree(priv->ks_wlan_hw.read_buf); - } + kfree(priv->ks_wlan_hw.read_buf); free_netdev(priv->net_dev); card->priv = NULL; } @@ -1219,7 +1192,6 @@ static void ks7010_sdio_remove(struct sdio_func *func) DPRINTK(1, "kfree()\n"); DPRINTK(5, " Bye !!\n"); - return; } static struct sdio_driver ks7010_sdio_driver = { diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index a8822fe2bd60..c57ca581550a 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -14,21 +14,13 @@ #include "eap_packet.h" #include "michael_mic.h" +#include #include #include /* Include Wireless Extension definition and check version */ #include /* New driver API */ -extern int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, - unsigned long size, - void (*complete_handler) (void *arg1, void *arg2), - void *arg1, void *arg2); -extern void send_packet_complete(void *, void *); - -extern void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv); -extern int ks_wlan_hw_power_save(struct ks_wlan_private *priv); - /* macro */ #define inc_smeqhead(priv) \ ( priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE ) @@ -43,6 +35,7 @@ static inline u8 get_BYTE(struct ks_wlan_private *priv) { u8 data; + data = *(priv->rxp)++; /* length check in advance ! */ --(priv->rx_size); @@ -53,6 +46,7 @@ static inline u16 get_WORD(struct ks_wlan_private *priv) { u16 data; + data = (get_BYTE(priv) & 0xff); data |= ((get_BYTE(priv) << 8) & 0xff00); return data; @@ -62,6 +56,7 @@ static inline u32 get_DWORD(struct ks_wlan_private *priv) { u32 data; + data = (get_BYTE(priv) & 0xff); data |= ((get_BYTE(priv) << 8) & 0x0000ff00); data |= ((get_BYTE(priv) << 16) & 0x00ff0000); @@ -69,16 +64,20 @@ inline u32 get_DWORD(struct ks_wlan_private *priv) return data; } -void ks_wlan_hw_wakeup_task(struct work_struct *work) +static void ks_wlan_hw_wakeup_task(struct work_struct *work) { struct ks_wlan_private *priv = container_of(work, struct ks_wlan_private, ks_wlan_wakeup_task); int ps_status = atomic_read(&priv->psstatus.status); + long time_left; if (ps_status == PS_SNOOZE) { ks_wlan_hw_wakeup_request(priv); - if (!wait_for_completion_interruptible_timeout(&priv->psstatus.wakeup_wait, HZ / 50)) { /* 20ms timeout */ - DPRINTK(1, "wake up timeout !!!\n"); + time_left = wait_for_completion_interruptible_timeout( + &priv->psstatus.wakeup_wait, + msecs_to_jiffies(20)); + if (time_left <= 0) { + DPRINTK(1, "wake up timeout or interrupted !!!\n"); schedule_work(&priv->ks_wlan_wakeup_task); return; } @@ -96,8 +95,6 @@ void ks_wlan_hw_wakeup_task(struct work_struct *work) static int ks_wlan_do_power_save(struct ks_wlan_private *priv) { - int rc = 0; - DPRINTK(4, "psstatus.status=%d\n", atomic_read(&priv->psstatus.status)); if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { @@ -105,7 +102,7 @@ int ks_wlan_do_power_save(struct ks_wlan_private *priv) } else { priv->dev_state = DEVICE_STATE_READY; } - return rc; + return 0; } static @@ -217,7 +214,6 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, { unsigned char *bp; int bsize, offset; - int rc = 0; DPRINTK(3, "\n"); memset(ap, 0, sizeof(struct local_ap_t)); @@ -240,13 +236,13 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, offset = 0; while (bsize > offset) { - /* DPRINTK(4, "Element ID=%d \n",*bp); */ + /* DPRINTK(4, "Element ID=%d\n",*bp); */ switch (*bp) { case 0: /* ssid */ if (*(bp + 1) <= SSID_MAX_SIZE) { ap->ssid.size = *(bp + 1); } else { - DPRINTK(1, "size over :: ssid size=%d \n", + DPRINTK(1, "size over :: ssid size=%d\n", *(bp + 1)); ap->ssid.size = SSID_MAX_SIZE; } @@ -260,7 +256,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, bp + 2, *(bp + 1)); ap->rate_set.size += *(bp + 1); } else { - DPRINTK(1, "size over :: rate size=%d \n", + DPRINTK(1, "size over :: rate size=%d\n", (*(bp + 1) + ap->rate_set.size)); memcpy(&(ap->rate_set.body[ap->rate_set.size]), bp + 2, @@ -276,7 +272,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, if (*(bp + 1) <= RSN_IE_BODY_MAX) { ap->rsn_ie.size = *(bp + 1); } else { - DPRINTK(1, "size over :: rsn size=%d \n", + DPRINTK(1, "size over :: rsn size=%d\n", *(bp + 1)); ap->rsn_ie.size = RSN_IE_BODY_MAX; } @@ -289,7 +285,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, ap->wpa_ie.size = *(bp + 1); } else { DPRINTK(1, - "size over :: wpa size=%d \n", + "size over :: wpa size=%d\n", *(bp + 1)); ap->wpa_ie.size = RSN_IE_BODY_MAX; } @@ -307,7 +303,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, case 47: /* Reserve ID 47 Broadcom AP */ break; default: - DPRINTK(4, "unknown Element ID=%d \n", *bp); + DPRINTK(4, "unknown Element ID=%d\n", *bp); break; } offset += 2; /* id & size field */ @@ -315,7 +311,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, bp += (*(bp + 1) + 2); /* pointer update */ } - return rc; + return 0; } static @@ -404,7 +400,7 @@ void hostif_data_indication(struct ks_wlan_private *priv) HZ >= 60) { mic_failure->failure = 0; } - DPRINTK(4, "MIC FAILURE \n"); + DPRINTK(4, "MIC FAILURE\n"); if (mic_failure->failure == 0) { mic_failure->failure = 1; mic_failure->counter = 0; @@ -481,8 +477,7 @@ void hostif_data_indication(struct ks_wlan_private *priv) netif_rx(skb); } else { printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - skb->dev->name); + "ks_wlan: Memory squeeze, dropping packet.\n"); priv->nstats.rx_dropped++; } break; @@ -517,8 +512,7 @@ void hostif_data_indication(struct ks_wlan_private *priv) netif_rx(skb); } else { printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - skb->dev->name); + "ks_wlan: Memory squeeze, dropping packet.\n"); priv->nstats.rx_dropped++; } break; @@ -778,7 +772,7 @@ void hostif_start_confirm(struct ks_wlan_private *priv) wrqu.data.flags = 0; wrqu.ap_addr.sa_family = ARPHRD_ETHER; if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { - memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); + eth_zero_addr(wrqu.ap_addr.sa_data); DPRINTK(3, "IWEVENT: disconnect\n"); wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); } @@ -836,7 +830,7 @@ void hostif_connect_indication(struct ks_wlan_private *priv) wrqu0.ap_addr.sa_family = ARPHRD_ETHER; if ((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS && (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { - memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN); + eth_zero_addr(wrqu0.ap_addr.sa_data); DPRINTK(3, "IWEVENT: disconnect\n"); DPRINTK(3, "disconnect :: scan_ind_count=%d\n", priv->scan_ind_count); @@ -908,7 +902,7 @@ void hostif_stop_confirm(struct ks_wlan_private *priv) if ((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS && (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { - memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN); + eth_zero_addr(wrqu0.ap_addr.sa_data); DPRINTK(3, "IWEVENT: disconnect\n"); printk("IWEVENT: disconnect\n"); DPRINTK(3, "disconnect :: scan_ind_count=%d\n", @@ -1148,7 +1142,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) packet_len = packet->len; if (packet_len > ETH_FRAME_LEN) { - DPRINTK(1, "bad length packet_len=%d \n", packet_len); + DPRINTK(1, "bad length packet_len=%d\n", packet_len); dev_kfree_skb(packet); return -1; } @@ -1172,11 +1166,10 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) } DPRINTK(4, "skb_buff length=%d\n", packet_len); - pp = (struct hostif_data_request_t *) - kmalloc(hif_align_size(sizeof(*pp) + 6 + packet_len + 8), - KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp) + 6 + packet_len + 8), + KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); dev_kfree_skb(packet); return -2; @@ -1194,6 +1187,8 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) DPRINTK(1, "ethernet->h_source=%02X:%02X:%02X:%02X:%02X:%02X\n", eth->h_source[0], eth->h_source[1], eth->h_source[2], eth->h_source[3], eth->h_source[4], eth->h_source[5]); + dev_kfree_skb(packet); + kfree(pp); return -3; } @@ -1231,7 +1226,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) eth_hdr = (struct ether_hdr *)&pp->data[0]; eth_proto = ntohs(eth_hdr->h_proto); - /* for MIC FAILUER REPORT check */ + /* for MIC FAILURE REPORT check */ if (eth_proto == ETHER_PROTOCOL_TYPE_EAP && priv->wpa.mic_failure.failure > 0) { aa1x_hdr = (struct ieee802_1x_hdr *)(eth_hdr + 1); @@ -1284,7 +1279,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) (void *)send_packet_complete, (void *)priv, (void *)packet); - /* MIC FAILUER REPORT check */ + /* MIC FAILURE REPORT check */ if (eth_proto == ETHER_PROTOCOL_TYPE_EAP && priv->wpa.mic_failure.failure > 0) { if (keyinfo & WPA_KEY_INFO_ERROR @@ -1313,9 +1308,8 @@ void hostif_mib_get_request(struct ks_wlan_private *priv, DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_mib_get_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1344,9 +1338,8 @@ void hostif_mib_set_request(struct ks_wlan_private *priv, } /* make primitive */ - pp = (struct hostif_mib_set_request_t *) - kmalloc(hif_align_size(sizeof(*pp) + size), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp) + size), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1374,9 +1367,8 @@ void hostif_start_request(struct ks_wlan_private *priv, unsigned char mode) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_start_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1402,9 +1394,8 @@ void hostif_ps_adhoc_set_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_ps_adhoc_set_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1443,12 +1434,11 @@ void hostif_infrastructure_set_request(struct ks_wlan_private *priv) struct hostif_infrastructure_set_request_t *pp; uint16_t capability; - DPRINTK(3, "ssid.size=%d \n", priv->reg.ssid.size); + DPRINTK(3, "ssid.size=%d\n", priv->reg.ssid.size); /* make primitive */ - pp = (struct hostif_infrastructure_set_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1505,17 +1495,16 @@ void hostif_infrastructure_set_request(struct ks_wlan_private *priv) ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); } -void hostif_infrastructure_set2_request(struct ks_wlan_private *priv) +static void hostif_infrastructure_set2_request(struct ks_wlan_private *priv) { struct hostif_infrastructure_set2_request_t *pp; uint16_t capability; - DPRINTK(2, "ssid.size=%d \n", priv->reg.ssid.size); + DPRINTK(2, "ssid.size=%d\n", priv->reg.ssid.size); /* make primitive */ - pp = (struct hostif_infrastructure_set2_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1583,9 +1572,8 @@ void hostif_adhoc_set_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_adhoc_set_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1629,9 +1617,8 @@ void hostif_adhoc_set2_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_adhoc_set2_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1677,9 +1664,8 @@ void hostif_stop_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_stop_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1700,9 +1686,8 @@ void hostif_phy_information_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_phy_information_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1732,9 +1717,8 @@ void hostif_power_mngmt_request(struct ks_wlan_private *priv, DPRINTK(3, "mode=%lu wake_up=%lu receiveDTIMs=%lu\n", mode, wake_up, receiveDTIMs); /* make primitive */ - pp = (struct hostif_power_mngmt_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1755,13 +1739,12 @@ void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode) { struct hostif_sleep_request_t *pp; - DPRINTK(3, "mode=%lu \n", mode); + DPRINTK(3, "mode=%lu\n", mode); if (mode == SLP_SLEEP) { /* make primitive */ - pp = (struct hostif_sleep_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1779,23 +1762,22 @@ void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode) queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, &priv->ks_wlan_hw.rw_wq, 1); } else { - DPRINTK(3, "invalid mode %ld \n", mode); + DPRINTK(3, "invalid mode %ld\n", mode); return; } } static void hostif_bss_scan_request(struct ks_wlan_private *priv, - unsigned long scan_type, uint8_t * scan_ssid, + unsigned long scan_type, uint8_t *scan_ssid, uint8_t scan_ssid_len) { struct hostif_bss_scan_request_t *pp; DPRINTK(2, "\n"); /* make primitive */ - pp = (struct hostif_bss_scan_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1850,9 +1832,8 @@ void hostif_mic_failure_request(struct ks_wlan_private *priv, DPRINTK(3, "count=%d :: timer=%d\n", failure_count, timer); /* make primitive */ - pp = (struct hostif_mic_failure_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1867,7 +1848,7 @@ void hostif_mic_failure_request(struct ks_wlan_private *priv, ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); } -/* Device I/O Recieve indicate */ +/* Device I/O Receive indicate */ static void devio_rec_ind(struct ks_wlan_private *priv, unsigned char *p, unsigned int size) { @@ -2700,7 +2681,6 @@ void hostif_sme_enqueue(struct ks_wlan_private *priv, unsigned short event) int hostif_init(struct ks_wlan_private *priv) { - int rc = 0; int i; DPRINTK(3, "\n"); @@ -2750,7 +2730,7 @@ int hostif_init(struct ks_wlan_private *priv) tasklet_init(&priv->sme_task, hostif_sme_task, (unsigned long)priv); - return rc; + return 0; } void hostif_exit(struct ks_wlan_private *priv) diff --git a/drivers/staging/ks7010/ks_hostif.h b/drivers/staging/ks7010/ks_hostif.h index dc806b5b47be..743f31ead56e 100644 --- a/drivers/staging/ks7010/ks_hostif.h +++ b/drivers/staging/ks7010/ks_hostif.h @@ -11,6 +11,9 @@ #ifndef _KS_HOSTIF_H_ #define _KS_HOSTIF_H_ + +#include + /* * HOST-MAC I/F events */ @@ -61,7 +64,7 @@ struct hostif_hdr { uint16_t size; uint16_t event; -} __attribute__ ((packed)); +} __packed; struct hostif_data_request_t { struct hostif_hdr header; @@ -70,7 +73,7 @@ struct hostif_data_request_t { #define TYPE_AUTH 0x0001 uint16_t reserved; uint8_t data[0]; -} __attribute__ ((packed)); +} __packed; struct hostif_data_indication_t { struct hostif_hdr header; @@ -81,14 +84,14 @@ struct hostif_data_indication_t { #define TYPE_GMK2 0x0003 uint16_t reserved; uint8_t data[0]; -} __attribute__ ((packed)); +} __packed; #define CHANNEL_LIST_MAX_SIZE 14 struct channel_list_t { uint8_t size; uint8_t body[CHANNEL_LIST_MAX_SIZE]; uint8_t pad; -} __attribute__ ((packed)); +} __packed; /* MIB Attribute */ #define DOT11_MAC_ADDRESS 0x21010100 /* MAC Address (R) */ @@ -141,7 +144,7 @@ struct channel_list_t { struct hostif_mib_get_request_t { struct hostif_hdr header; uint32_t mib_attribute; -} __attribute__ ((packed)); +} __packed; struct hostif_mib_value_t { uint16_t size; @@ -152,7 +155,7 @@ struct hostif_mib_value_t { #define MIB_VALUE_TYPE_COUNT32 3 #define MIB_VALUE_TYPE_OSTRING 4 uint8_t body[0]; -} __attribute__ ((packed)); +} __packed; struct hostif_mib_get_confirm_t { struct hostif_hdr header; @@ -163,19 +166,19 @@ struct hostif_mib_get_confirm_t { #define MIB_WRITE_ONLY 3 uint32_t mib_attribute; struct hostif_mib_value_t mib_value; -} __attribute__ ((packed)); +} __packed; struct hostif_mib_set_request_t { struct hostif_hdr header; uint32_t mib_attribute; struct hostif_mib_value_t mib_value; -} __attribute__ ((packed)); +} __packed; struct hostif_mib_set_confirm_t { struct hostif_hdr header; uint32_t mib_status; uint32_t mib_attribute; -} __attribute__ ((packed)); +} __packed; struct hostif_power_mngmt_request_t { struct hostif_hdr header; @@ -188,7 +191,7 @@ struct hostif_power_mngmt_request_t { uint32_t receiveDTIMs; #define DTIM_FALSE 0 #define DTIM_TRUE 1 -} __attribute__ ((packed)); +} __packed; /* power management mode */ enum { @@ -206,7 +209,7 @@ enum { struct hostif_power_mngmt_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_start_request_t { struct hostif_hdr header; @@ -215,64 +218,64 @@ struct hostif_start_request_t { #define MODE_INFRASTRUCTURE 1 #define MODE_AP 2 /* not used */ #define MODE_ADHOC 3 -} __attribute__ ((packed)); +} __packed; struct hostif_start_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; #define SSID_MAX_SIZE 32 struct ssid_t { uint8_t size; uint8_t body[SSID_MAX_SIZE]; uint8_t ssid_pad; -} __attribute__ ((packed)); +} __packed; #define RATE_SET_MAX_SIZE 16 struct rate_set8_t { uint8_t size; uint8_t body[8]; uint8_t rate_pad; -} __attribute__ ((packed)); +} __packed; struct FhParms_t { uint16_t dwellTime; uint8_t hopSet; uint8_t hopPattern; uint8_t hopIndex; -} __attribute__ ((packed)); +} __packed; struct DsParms_t { uint8_t channel; -} __attribute__ ((packed)); +} __packed; struct CfParms_t { uint8_t count; uint8_t period; uint16_t maxDuration; uint16_t durRemaining; -} __attribute__ ((packed)); +} __packed; struct IbssParms_t { uint16_t atimWindow; -} __attribute__ ((packed)); +} __packed; struct rsn_t { uint8_t size; #define RSN_BODY_SIZE 64 uint8_t body[RSN_BODY_SIZE]; -} __attribute__ ((packed)); +} __packed; struct ErpParams_t { uint8_t erp_info; -} __attribute__ ((packed)); +} __packed; struct rate_set16_t { uint8_t size; uint8_t body[16]; uint8_t rate_pad; -} __attribute__ ((packed)); +} __packed; struct ap_info_t { uint8_t bssid[6]; /* +00 */ @@ -299,7 +302,7 @@ struct ap_info_t { uint16_t body_size; /* +16 */ uint8_t body[1024]; /* +18 */ /* +1032 */ -} __attribute__ ((packed)); +} __packed; struct link_ap_info_t { uint8_t bssid[6]; /* +00 */ @@ -325,8 +328,8 @@ struct link_ap_info_t { struct { uint8_t size; /* +52 */ uint8_t body[128]; /* +53 */ - } __attribute__ ((packed)) rsn; -} __attribute__ ((packed)); + } __packed rsn; +} __packed; struct hostif_connect_indication_t { struct hostif_hdr header; @@ -334,16 +337,16 @@ struct hostif_connect_indication_t { #define RESULT_CONNECT 0 #define RESULT_DISCONNECT 1 struct link_ap_info_t link_ap_info; -} __attribute__ ((packed)); +} __packed; struct hostif_stop_request_t { struct hostif_hdr header; -} __attribute__ ((packed)); +} __packed; struct hostif_stop_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_ps_adhoc_set_request_t { struct hostif_hdr header; @@ -360,12 +363,12 @@ struct hostif_ps_adhoc_set_request_t { uint16_t capability; /* bit5:preamble bit6:pbcc pbcc not supported always 0 * bit10:ShortSlotTime bit13:DSSS-OFDM DSSS-OFDM not supported always 0 */ uint16_t scan_type; -} __attribute__ ((packed)); +} __packed; struct hostif_ps_adhoc_set_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_infrastructure_set_request_t { struct hostif_hdr header; @@ -381,7 +384,7 @@ struct hostif_infrastructure_set_request_t { #define AUTH_TYPE_SHARED_KEY 1 struct channel_list_t channel_list; uint16_t scan_type; -} __attribute__ ((packed)); +} __packed; struct hostif_infrastructure_set2_request_t { struct hostif_hdr header; @@ -398,12 +401,12 @@ struct hostif_infrastructure_set2_request_t { struct channel_list_t channel_list; uint16_t scan_type; uint8_t bssid[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct hostif_infrastructure_set_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_adhoc_set_request_t { struct hostif_hdr header; @@ -415,7 +418,7 @@ struct hostif_adhoc_set_request_t { uint16_t capability; /* bit5:preamble bit6:pbcc pbcc not supported always 0 * bit10:ShortSlotTime bit13:DSSS-OFDM DSSS-OFDM not supported always 0 */ uint16_t scan_type; -} __attribute__ ((packed)); +} __packed; struct hostif_adhoc_set2_request_t { struct hostif_hdr header; @@ -429,17 +432,17 @@ struct hostif_adhoc_set2_request_t { uint16_t scan_type; struct channel_list_t channel_list; uint8_t bssid[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct hostif_adhoc_set_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct last_associate_t { uint8_t type; uint8_t status; -} __attribute__ ((packed)); +} __packed; struct association_request_t { uint8_t type; @@ -450,7 +453,7 @@ struct association_request_t { uint16_t listen_interval; uint8_t ap_address[6]; uint16_t reqIEs_size; -} __attribute__ ((packed)); +} __packed; struct association_response_t { uint8_t type; @@ -461,7 +464,7 @@ struct association_response_t { uint16_t status; uint16_t association_id; uint16_t respIEs_size; -} __attribute__ ((packed)); +} __packed; struct hostif_associate_indication_t { struct hostif_hdr header; @@ -469,7 +472,7 @@ struct hostif_associate_indication_t { struct association_response_t assoc_resp; /* followed by (reqIEs_size + respIEs_size) octets of data */ /* reqIEs data *//* respIEs data */ -} __attribute__ ((packed)); +} __packed; struct hostif_bss_scan_request_t { struct hostif_hdr header; @@ -481,13 +484,13 @@ struct hostif_bss_scan_request_t { uint32_t ch_time_max; struct channel_list_t channel_list; struct ssid_t ssid; -} __attribute__ ((packed)); +} __packed; struct hostif_bss_scan_confirm_t { struct hostif_hdr header; uint16_t result_code; uint16_t reserved; -} __attribute__ ((packed)); +} __packed; struct hostif_phy_information_request_t { struct hostif_hdr header; @@ -495,7 +498,7 @@ struct hostif_phy_information_request_t { #define NORMAL_TYPE 0 #define TIME_TYPE 1 uint16_t time; /* unit 100ms */ -} __attribute__ ((packed)); +} __packed; struct hostif_phy_information_confirm_t { struct hostif_hdr header; @@ -507,30 +510,30 @@ struct hostif_phy_information_confirm_t { uint32_t rx_frame; uint32_t tx_error; uint32_t rx_error; -} __attribute__ ((packed)); +} __packed; /* sleep mode */ #define SLP_ACTIVE 0 #define SLP_SLEEP 1 struct hostif_sleep_request_t { struct hostif_hdr header; -} __attribute__ ((packed)); +} __packed; struct hostif_sleep_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_mic_failure_request_t { struct hostif_hdr header; uint16_t failure_count; uint16_t timer; -} __attribute__ ((packed)); +} __packed; struct hostif_mic_failure_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; #define BASIC_RATE 0x80 #define RATE_MASK 0x7F @@ -616,13 +619,21 @@ enum { #include "ks_wlan.h" /* function prototype */ -extern int hostif_data_request(struct ks_wlan_private *priv, - struct sk_buff *packet); -extern void hostif_receive(struct ks_wlan_private *priv, unsigned char *p, - unsigned int size); -extern void hostif_sme_enqueue(struct ks_wlan_private *priv, uint16_t event); -extern int hostif_init(struct ks_wlan_private *priv); -extern void hostif_exit(struct ks_wlan_private *priv); +int hostif_data_request(struct ks_wlan_private *priv, + struct sk_buff *packet); +void hostif_receive(struct ks_wlan_private *priv, unsigned char *p, + unsigned int size); +void hostif_sme_enqueue(struct ks_wlan_private *priv, uint16_t event); +int hostif_init(struct ks_wlan_private *priv); +void hostif_exit(struct ks_wlan_private *priv); +int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, + unsigned long size, + void (*complete_handler) (void *arg1, void *arg2), + void *arg1, void *arg2); +void send_packet_complete(void *, void *); + +void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv); +int ks_wlan_hw_power_save(struct ks_wlan_private *priv); static inline int hif_align_size(int size) diff --git a/drivers/staging/ks7010/ks_wlan.h b/drivers/staging/ks7010/ks_wlan.h index f05dc0122fcb..c2cc288ae899 100644 --- a/drivers/staging/ks7010/ks_wlan.h +++ b/drivers/staging/ks7010/ks_wlan.h @@ -219,7 +219,7 @@ struct rsn_ie_t { uint8_t id; /* 0xdd = WPA or 0x30 = RSN */ uint8_t size; /* max ? 255 ? */ uint8_t body[RSN_IE_BODY_MAX]; -} __attribute__ ((packed)); +} __packed; #ifdef WPS #define WPS_IE_BODY_MAX 255 @@ -227,7 +227,7 @@ struct wps_ie_t { uint8_t id; /* 221 'dd 00 50 F2 04' */ uint8_t size; /* max ? 255 ? */ uint8_t body[WPS_IE_BODY_MAX]; -} __attribute__ ((packed)); +} __packed; #endif /* WPS */ struct local_ap_t { @@ -499,7 +499,7 @@ struct ks_wlan_private { uint wakeup_count; /* for detect wakeup loop */ }; -extern int ks_wlan_net_start(struct net_device *dev); -extern int ks_wlan_net_stop(struct net_device *dev); +int ks_wlan_net_start(struct net_device *dev); +int ks_wlan_net_stop(struct net_device *dev); #endif /* _KS_WLAN_H */ diff --git a/drivers/staging/ks7010/ks_wlan_ioctl.h b/drivers/staging/ks7010/ks_wlan_ioctl.h index 49369e497808..84554b6bb239 100644 --- a/drivers/staging/ks7010/ks_wlan_ioctl.h +++ b/drivers/staging/ks7010/ks_wlan_ioctl.h @@ -58,9 +58,9 @@ #include "ks_wlan.h" #include -extern int ks_wlan_read_config_file(struct ks_wlan_private *priv); -extern int ks_wlan_setup_parameter(struct ks_wlan_private *priv, - unsigned int commit_flag); +int ks_wlan_read_config_file(struct ks_wlan_private *priv); +int ks_wlan_setup_parameter(struct ks_wlan_private *priv, + unsigned int commit_flag); #endif /* __KERNEL__ */ diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 1e21eb1c4667..b2b4fa4c3834 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -9,7 +9,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include @@ -70,10 +69,6 @@ static const struct iw_handler_def ks_wlan_handler_def; /* * function prototypes */ -extern int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, - unsigned long size, - void (*complete_handler) (void *arg1, void *arg2), - void *arg1, void *arg2); static int ks_wlan_open(struct net_device *dev); static void ks_wlan_tx_timeout(struct net_device *dev); static int ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev); @@ -238,9 +233,9 @@ static int ks_wlan_set_freq(struct net_device *dev, /* We should do a better check than that, * based on the card capability !!! */ if ((channel < 1) || (channel > 14)) { - printk(KERN_DEBUG - "%s: New channel value of %d is invalid!\n", - dev->name, fwrq->m); + netdev_dbg(dev, + "%s: New channel value of %d is invalid!\n", + dev->name, fwrq->m); rc = -EINVAL; } else { /* Yes ! We can set it !!! */ @@ -402,7 +397,7 @@ static int ks_wlan_set_wap(struct net_device *dev, struct iw_request_info *info, priv->need_commit |= SME_MODE_SET; } } else { - memset(priv->reg.bssid, 0x0, ETH_ALEN); + eth_zero_addr(priv->reg.bssid); return -EOPNOTSUPP; } @@ -433,7 +428,7 @@ static int ks_wlan_get_wap(struct net_device *dev, struct iw_request_info *info, if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { memcpy(awrq->sa_data, &(priv->current_ap.bssid[0]), ETH_ALEN); } else { - memset(awrq->sa_data, 0, ETH_ALEN); + eth_zero_addr(awrq->sa_data); } awrq->sa_family = ARPHRD_ETHER; @@ -2092,7 +2087,7 @@ static int ks_wlan_set_pmksa(struct net_device *dev, list_for_each(ptr, &priv->pmklist.head) { pmk = list_entry(ptr, struct pmk_t, list); if (!memcmp(pmksa->bssid.sa_data, pmk->bssid, ETH_ALEN)) { /* match address! list del. */ - memset(pmk->bssid, 0, ETH_ALEN); + eth_zero_addr(pmk->bssid); memset(pmk->pmkid, 0, IW_PMKID_LEN); list_del_init(&pmk->list); break; @@ -2676,17 +2671,17 @@ static int ks_wlan_set_sleep_mode(struct net_device *dev, if (*uwrq == SLP_SLEEP) { priv->sleep_mode = *uwrq; - printk("SET_SLEEP_MODE %d\n", priv->sleep_mode); + netdev_info(dev, "SET_SLEEP_MODE %d\n", priv->sleep_mode); hostif_sme_enqueue(priv, SME_STOP_REQUEST); hostif_sme_enqueue(priv, SME_SLEEP_REQUEST); } else if (*uwrq == SLP_ACTIVE) { priv->sleep_mode = *uwrq; - printk("SET_SLEEP_MODE %d\n", priv->sleep_mode); + netdev_info(dev, "SET_SLEEP_MODE %d\n", priv->sleep_mode); hostif_sme_enqueue(priv, SME_SLEEP_REQUEST); } else { - printk("SET_SLEEP_MODE %d errror\n", *uwrq); + netdev_err(dev, "SET_SLEEP_MODE %d errror\n", *uwrq); return -EINVAL; } @@ -2788,7 +2783,7 @@ static int ks_wlan_get_wps_enable(struct net_device *dev, } /* for SLEEP MODE */ *uwrq = priv->wps.wps_enabled; - printk("return=%d\n", *uwrq); + netdev_info(dev, "return=%d\n", *uwrq); return 0; } @@ -2978,117 +2973,117 @@ static int ks_wlan_get_eeprom_cksum(struct net_device *dev, return 0; } -static void print_hif_event(int event) +static void print_hif_event(struct net_device *dev, int event) { switch (event) { case HIF_DATA_REQ: - printk("HIF_DATA_REQ\n"); + netdev_info(dev, "HIF_DATA_REQ\n"); break; case HIF_DATA_IND: - printk("HIF_DATA_IND\n"); + netdev_info(dev, "HIF_DATA_IND\n"); break; case HIF_MIB_GET_REQ: - printk("HIF_MIB_GET_REQ\n"); + netdev_info(dev, "HIF_MIB_GET_REQ\n"); break; case HIF_MIB_GET_CONF: - printk("HIF_MIB_GET_CONF\n"); + netdev_info(dev, "HIF_MIB_GET_CONF\n"); break; case HIF_MIB_SET_REQ: - printk("HIF_MIB_SET_REQ\n"); + netdev_info(dev, "HIF_MIB_SET_REQ\n"); break; case HIF_MIB_SET_CONF: - printk("HIF_MIB_SET_CONF\n"); + netdev_info(dev, "HIF_MIB_SET_CONF\n"); break; case HIF_POWERMGT_REQ: - printk("HIF_POWERMGT_REQ\n"); + netdev_info(dev, "HIF_POWERMGT_REQ\n"); break; case HIF_POWERMGT_CONF: - printk("HIF_POWERMGT_CONF\n"); + netdev_info(dev, "HIF_POWERMGT_CONF\n"); break; case HIF_START_REQ: - printk("HIF_START_REQ\n"); + netdev_info(dev, "HIF_START_REQ\n"); break; case HIF_START_CONF: - printk("HIF_START_CONF\n"); + netdev_info(dev, "HIF_START_CONF\n"); break; case HIF_CONNECT_IND: - printk("HIF_CONNECT_IND\n"); + netdev_info(dev, "HIF_CONNECT_IND\n"); break; case HIF_STOP_REQ: - printk("HIF_STOP_REQ\n"); + netdev_info(dev, "HIF_STOP_REQ\n"); break; case HIF_STOP_CONF: - printk("HIF_STOP_CONF\n"); + netdev_info(dev, "HIF_STOP_CONF\n"); break; case HIF_PS_ADH_SET_REQ: - printk("HIF_PS_ADH_SET_REQ\n"); + netdev_info(dev, "HIF_PS_ADH_SET_REQ\n"); break; case HIF_PS_ADH_SET_CONF: - printk("HIF_PS_ADH_SET_CONF\n"); + netdev_info(dev, "HIF_PS_ADH_SET_CONF\n"); break; case HIF_INFRA_SET_REQ: - printk("HIF_INFRA_SET_REQ\n"); + netdev_info(dev, "HIF_INFRA_SET_REQ\n"); break; case HIF_INFRA_SET_CONF: - printk("HIF_INFRA_SET_CONF\n"); + netdev_info(dev, "HIF_INFRA_SET_CONF\n"); break; case HIF_ADH_SET_REQ: - printk("HIF_ADH_SET_REQ\n"); + netdev_info(dev, "HIF_ADH_SET_REQ\n"); break; case HIF_ADH_SET_CONF: - printk("HIF_ADH_SET_CONF\n"); + netdev_info(dev, "HIF_ADH_SET_CONF\n"); break; case HIF_AP_SET_REQ: - printk("HIF_AP_SET_REQ\n"); + netdev_info(dev, "HIF_AP_SET_REQ\n"); break; case HIF_AP_SET_CONF: - printk("HIF_AP_SET_CONF\n"); + netdev_info(dev, "HIF_AP_SET_CONF\n"); break; case HIF_ASSOC_INFO_IND: - printk("HIF_ASSOC_INFO_IND\n"); + netdev_info(dev, "HIF_ASSOC_INFO_IND\n"); break; case HIF_MIC_FAILURE_REQ: - printk("HIF_MIC_FAILURE_REQ\n"); + netdev_info(dev, "HIF_MIC_FAILURE_REQ\n"); break; case HIF_MIC_FAILURE_CONF: - printk("HIF_MIC_FAILURE_CONF\n"); + netdev_info(dev, "HIF_MIC_FAILURE_CONF\n"); break; case HIF_SCAN_REQ: - printk("HIF_SCAN_REQ\n"); + netdev_info(dev, "HIF_SCAN_REQ\n"); break; case HIF_SCAN_CONF: - printk("HIF_SCAN_CONF\n"); + netdev_info(dev, "HIF_SCAN_CONF\n"); break; case HIF_PHY_INFO_REQ: - printk("HIF_PHY_INFO_REQ\n"); + netdev_info(dev, "HIF_PHY_INFO_REQ\n"); break; case HIF_PHY_INFO_CONF: - printk("HIF_PHY_INFO_CONF\n"); + netdev_info(dev, "HIF_PHY_INFO_CONF\n"); break; case HIF_SLEEP_REQ: - printk("HIF_SLEEP_REQ\n"); + netdev_info(dev, "HIF_SLEEP_REQ\n"); break; case HIF_SLEEP_CONF: - printk("HIF_SLEEP_CONF\n"); + netdev_info(dev, "HIF_SLEEP_CONF\n"); break; case HIF_PHY_INFO_IND: - printk("HIF_PHY_INFO_IND\n"); + netdev_info(dev, "HIF_PHY_INFO_IND\n"); break; case HIF_SCAN_IND: - printk("HIF_SCAN_IND\n"); + netdev_info(dev, "HIF_SCAN_IND\n"); break; case HIF_INFRA_SET2_REQ: - printk("HIF_INFRA_SET2_REQ\n"); + netdev_info(dev, "HIF_INFRA_SET2_REQ\n"); break; case HIF_INFRA_SET2_CONF: - printk("HIF_INFRA_SET2_CONF\n"); + netdev_info(dev, "HIF_INFRA_SET2_CONF\n"); break; case HIF_ADH_SET2_REQ: - printk("HIF_ADH_SET2_REQ\n"); + netdev_info(dev, "HIF_ADH_SET2_REQ\n"); break; case HIF_ADH_SET2_CONF: - printk("HIF_ADH_SET2_CONF\n"); + netdev_info(dev, "HIF_ADH_SET2_CONF\n"); } } @@ -3105,7 +3100,7 @@ static int ks_wlan_hostt(struct net_device *dev, struct iw_request_info *info, event = priv->hostt.buff[(priv->hostt.qtail - 1 - i) % SME_EVENT_BUFF_SIZE]; - print_hif_event(event); + print_hif_event(dev, event); } return 0; } @@ -3335,7 +3330,7 @@ int ks_wlan_set_mac_address(struct net_device *dev, void *addr) priv->mac_address_valid = 0; hostif_sme_enqueue(priv, SME_MACADDRESS_SET_REQUEST); - printk(KERN_INFO + netdev_info(dev, "ks_wlan: MAC ADDRESS = %02x:%02x:%02x:%02x:%02x:%02x\n", priv->eth_addr[0], priv->eth_addr[1], priv->eth_addr[2], priv->eth_addr[3], priv->eth_addr[4], priv->eth_addr[5]); @@ -3354,8 +3349,6 @@ void ks_wlan_tx_timeout(struct net_device *dev) } priv->nstats.tx_errors++; netif_wake_queue(dev); - - return; } static @@ -3366,8 +3359,8 @@ int ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev) DPRINTK(3, "in_interrupt()=%ld\n", in_interrupt()); - if (skb == NULL) { - printk(KERN_ERR "ks_wlan: skb == NULL!!!\n"); + if (!skb) { + netdev_err(dev, "ks_wlan: skb == NULL!!!\n"); return 0; } if (priv->dev_state < DEVICE_STATE_READY) { @@ -3396,13 +3389,13 @@ void send_packet_complete(void *arg1, void *arg2) DPRINTK(3, "\n"); - priv->nstats.tx_bytes += packet->len; priv->nstats.tx_packets++; if (netif_queue_stopped(priv->net_dev)) netif_wake_queue(priv->net_dev); if (packet) { + priv->nstats.tx_bytes += packet->len; dev_kfree_skb(packet); packet = NULL; } @@ -3421,8 +3414,6 @@ void ks_wlan_set_multicast_list(struct net_device *dev) return; /* not finished initialize */ } hostif_sme_enqueue(priv, SME_MULTICAST_REQUEST); - - return; } static @@ -3433,7 +3424,7 @@ int ks_wlan_open(struct net_device *dev) priv->cur_rx = 0; if (!priv->mac_address_valid) { - printk(KERN_ERR "ks_wlan : %s Not READY !!\n", dev->name); + netdev_err(dev, "ks_wlan : %s Not READY !!\n", dev->name); return -EBUSY; } else netif_start_queue(dev); @@ -3512,17 +3503,11 @@ int ks_wlan_net_stop(struct net_device *dev) { struct ks_wlan_private *priv = netdev_priv(dev); - int ret = 0; priv->device_open_status = 0; del_timer_sync(&update_phyinfo_timer); if (netif_running(dev)) netif_stop_queue(dev); - return ret; -} - -int ks_wlan_reset(struct net_device *dev) -{ return 0; } diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c index e14c109b3cab..78ae2b8fb7f3 100644 --- a/drivers/staging/ks7010/michael_mic.c +++ b/drivers/staging/ks7010/michael_mic.c @@ -20,18 +20,24 @@ #define getUInt32( A, B ) (uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24) // Convert from UInt32 to Byte[] in a portable way -#define putUInt32( A, B, C ) A[B+0] = (uint8_t) (C & 0xff); \ - A[B+1] = (uint8_t) ((C>>8) & 0xff); \ - A[B+2] = (uint8_t) ((C>>16) & 0xff); \ - A[B+3] = (uint8_t) ((C>>24) & 0xff) +#define putUInt32(A, B, C) \ +do { \ + A[B + 0] = (uint8_t)(C & 0xff); \ + A[B + 1] = (uint8_t)((C >> 8) & 0xff); \ + A[B + 2] = (uint8_t)((C >> 16) & 0xff); \ + A[B + 3] = (uint8_t)((C >> 24) & 0xff); \ +} while (0) // Reset the state to the empty message. -#define MichaelClear( A ) A->L = A->K0; \ - A->R = A->K1; \ - A->nBytesInM = 0; +#define MichaelClear(A) \ +do { \ + A->L = A->K0; \ + A->R = A->K1; \ + A->nBytesInM = 0; \ +} while (0) static -void MichaelInitializeFunction(struct michel_mic_t *Mic, uint8_t * key) +void MichaelInitializeFunction(struct michel_mic_t *Mic, uint8_t *key) { // Set the key Mic->K0 = getUInt32(key, 0); @@ -54,7 +60,7 @@ do{ \ }while(0) static -void MichaelAppend(struct michel_mic_t *Mic, uint8_t * src, int nBytes) +void MichaelAppend(struct michel_mic_t *Mic, uint8_t *src, int nBytes) { int addlen; if (Mic->nBytesInM) { @@ -88,7 +94,7 @@ void MichaelAppend(struct michel_mic_t *Mic, uint8_t * src, int nBytes) } static -void MichaelGetMIC(struct michel_mic_t *Mic, uint8_t * dst) +void MichaelGetMIC(struct michel_mic_t *Mic, uint8_t *dst) { uint8_t *data = Mic->M; switch (Mic->nBytesInM) { @@ -116,9 +122,9 @@ void MichaelGetMIC(struct michel_mic_t *Mic, uint8_t * dst) MichaelClear(Mic); } -void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t * Key, - uint8_t * Data, int Len, uint8_t priority, - uint8_t * Result) +void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t *Key, + uint8_t *Data, int Len, uint8_t priority, + uint8_t *Result) { uint8_t pad_data[4] = { priority, 0, 0, 0 }; // Compute the MIC value diff --git a/drivers/staging/ks7010/michael_mic.h b/drivers/staging/ks7010/michael_mic.h index c7e4eb280961..efaa21788fc7 100644 --- a/drivers/staging/ks7010/michael_mic.h +++ b/drivers/staging/ks7010/michael_mic.h @@ -20,7 +20,6 @@ struct michel_mic_t { uint8_t Result[8]; }; -extern -void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t * Key, - uint8_t * Data, int Len, uint8_t priority, - uint8_t * Result); +void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t *Key, + uint8_t *Data, int Len, uint8_t priority, + uint8_t *Result); diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 3f6447c65042..3b92d38d37e2 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -138,8 +138,8 @@ struct lnet_debugfs_symlink_def { void lustre_insert_debugfs(struct ctl_table *table, const struct lnet_debugfs_symlink_def *symlinks); int lprocfs_call_handler(void *data, int write, loff_t *ppos, - void __user *buffer, size_t *lenp, - int (*handler)(void *data, int write, - loff_t pos, void __user *buffer, int len)); + void __user *buffer, size_t *lenp, + int (*handler)(void *data, int write, loff_t pos, + void __user *buffer, int len)); #endif /* _LIBCFS_H */ diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 25adab19fd86..b7bd6e8ab33f 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -247,19 +247,19 @@ do { \ #define LCONSOLE_EMERG(format, ...) CDEBUG(D_CONSOLE | D_EMERG, format, ## __VA_ARGS__) int libcfs_debug_msg(struct libcfs_debug_msg_data *msgdata, - const char *format1, ...) + const char *format1, ...) __printf(2, 3); int libcfs_debug_vmsg2(struct libcfs_debug_msg_data *msgdata, - const char *format1, - va_list args, const char *format2, ...) + const char *format1, + va_list args, const char *format2, ...) __printf(4, 5); /* other external symbols that tracefile provides: */ int cfs_trace_copyin_string(char *knl_buffer, int knl_buffer_nob, - const char __user *usr_buffer, int usr_buffer_nob); + const char __user *usr_buffer, int usr_buffer_nob); int cfs_trace_copyout_string(char __user *usr_buffer, int usr_buffer_nob, - const char *knl_buffer, char *append); + const char *knl_buffer, char *append); #define LIBCFS_DEBUG_FILE_PATH_DEFAULT "/tmp/lustre-log" diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h index d3f9a6020ee3..bdbbe934584c 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h @@ -143,6 +143,9 @@ static inline int cfs_fail_timeout_set(__u32 id, __u32 value, int ms, int set) #define CFS_FAIL_TIMEOUT_ORSET(id, value, secs) \ cfs_fail_timeout_set(id, value, secs * 1000, CFS_FAIL_LOC_ORSET) +#define CFS_FAIL_TIMEOUT_RESET(id, value, secs) \ + cfs_fail_timeout_set(id, value, secs * 1000, CFS_FAIL_LOC_RESET) + #define CFS_FAIL_TIMEOUT_MS_ORSET(id, value, ms) \ cfs_fail_timeout_set(id, value, ms, CFS_FAIL_LOC_ORSET) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index 4daa3823f60a..e0e1a5d0949d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -310,13 +310,13 @@ do { \ #define MKSTR(ptr) ((ptr)) ? (ptr) : "" -static inline int cfs_size_round4(int val) +static inline size_t cfs_size_round4(int val) { return (val + 3) & (~0x3); } #ifndef HAVE_CFS_SIZE_ROUND -static inline int cfs_size_round(int val) +static inline size_t cfs_size_round(int val) { return (val + 7) & (~0x7); } @@ -324,17 +324,17 @@ static inline int cfs_size_round(int val) #define HAVE_CFS_SIZE_ROUND #endif -static inline int cfs_size_round16(int val) +static inline size_t cfs_size_round16(int val) { return (val + 0xf) & (~0xf); } -static inline int cfs_size_round32(int val) +static inline size_t cfs_size_round32(int val) { return (val + 0x1f) & (~0x1f); } -static inline int cfs_size_round0(int val) +static inline size_t cfs_size_round0(int val) { if (!val) return 0; @@ -343,7 +343,7 @@ static inline int cfs_size_round0(int val) static inline size_t cfs_round_strlen(char *fset) { - return (size_t)cfs_size_round((int)strlen(fset) + 1); + return cfs_size_round((int)strlen(fset) + 1); } #define LOGL(var, len, ptr) \ @@ -360,13 +360,4 @@ do { \ ptr += cfs_size_round(len); \ } while (0) -#define LOGL0(var, len, ptr) \ -do { \ - if (!len) \ - break; \ - memcpy((char *)ptr, (const char *)var, len); \ - *((char *)(ptr) + len) = 0; \ - ptr += cfs_size_round(len + 1); \ -} while (0) - #endif diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 513a8225f888..a59c5e99cbd3 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -605,73 +605,20 @@ void lnet_counters_reset(void); unsigned int lnet_iov_nob(unsigned int niov, struct kvec *iov); int lnet_extract_iov(int dst_niov, struct kvec *dst, - int src_niov, struct kvec *src, + int src_niov, const struct kvec *src, unsigned int offset, unsigned int len); unsigned int lnet_kiov_nob(unsigned int niov, lnet_kiov_t *iov); int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, - int src_niov, lnet_kiov_t *src, + int src_niov, const lnet_kiov_t *src, unsigned int offset, unsigned int len); -void lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, - unsigned int doffset, - unsigned int nsiov, struct kvec *siov, +void lnet_copy_iov2iter(struct iov_iter *to, + unsigned int nsiov, const struct kvec *siov, unsigned int soffset, unsigned int nob); -void lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, - unsigned int iovoffset, - unsigned int nkiov, lnet_kiov_t *kiov, +void lnet_copy_kiov2iter(struct iov_iter *to, + unsigned int nkiov, const lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int nob); -void lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, - unsigned int kiovoffset, - unsigned int niov, struct kvec *iov, - unsigned int iovoffset, unsigned int nob); -void lnet_copy_kiov2kiov(unsigned int ndkiov, lnet_kiov_t *dkiov, - unsigned int doffset, - unsigned int nskiov, lnet_kiov_t *skiov, - unsigned int soffset, unsigned int nob); - -static inline void -lnet_copy_iov2flat(int dlen, void *dest, unsigned int doffset, - unsigned int nsiov, struct kvec *siov, unsigned int soffset, - unsigned int nob) -{ - struct kvec diov = {/*.iov_base = */ dest, /*.iov_len = */ dlen}; - - lnet_copy_iov2iov(1, &diov, doffset, - nsiov, siov, soffset, nob); -} - -static inline void -lnet_copy_kiov2flat(int dlen, void *dest, unsigned int doffset, - unsigned int nsiov, lnet_kiov_t *skiov, - unsigned int soffset, unsigned int nob) -{ - struct kvec diov = {/* .iov_base = */ dest, /* .iov_len = */ dlen}; - - lnet_copy_kiov2iov(1, &diov, doffset, - nsiov, skiov, soffset, nob); -} - -static inline void -lnet_copy_flat2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, - int slen, void *src, unsigned int soffset, unsigned int nob) -{ - struct kvec siov = {/*.iov_base = */ src, /*.iov_len = */slen}; - - lnet_copy_iov2iov(ndiov, diov, doffset, - 1, &siov, soffset, nob); -} - -static inline void -lnet_copy_flat2kiov(unsigned int ndiov, lnet_kiov_t *dkiov, - unsigned int doffset, int slen, void *src, - unsigned int soffset, unsigned int nob) -{ - struct kvec siov = {/* .iov_base = */ src, /* .iov_len = */ slen}; - - lnet_copy_iov2kiov(ndiov, dkiov, doffset, - 1, &siov, soffset, nob); -} void lnet_me_unlink(lnet_me_t *me); diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index 7967b013cbae..b84a5bb9186c 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -220,10 +220,7 @@ typedef struct lnet_lnd { * credit if the LND does flow control. */ int (*lnd_recv)(struct lnet_ni *ni, void *private, lnet_msg_t *msg, - int delayed, unsigned int niov, - struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, - unsigned int rlen); + int delayed, struct iov_iter *to, unsigned int rlen); /* * lnet_parse() has had to delay processing of this message @@ -278,6 +275,8 @@ typedef struct lnet_ni { struct lnet_ioctl_config_lnd_tunables *ni_lnd_tunables; /* equivalent interfaces to use */ char *ni_interfaces[LNET_MAX_INTERFACES]; + /* original net namespace */ + struct net *ni_net_ns; } lnet_ni_t; #define LNET_PROTO_PING_MATCHBITS 0x8000000000000000LL diff --git a/drivers/staging/lustre/include/linux/lnet/types.h b/drivers/staging/lustre/include/linux/lnet/types.h index e098b6c086e1..f8be0e2f7bf7 100644 --- a/drivers/staging/lustre/include/linux/lnet/types.h +++ b/drivers/staging/lustre/include/linux/lnet/types.h @@ -503,21 +503,7 @@ typedef struct { /* NB lustre portals uses struct iovec internally! */ typedef struct iovec lnet_md_iovec_t; -/** - * A page-based fragment of a MD. - */ -typedef struct { - /** Pointer to the page where the fragment resides */ - struct page *kiov_page; - /** Length in bytes of the fragment */ - unsigned int kiov_len; - /** - * Starting offset of the fragment within the page. Note that the - * end of the fragment must not pass the end of the page; i.e., - * kiov_len + kiov_offset <= PAGE_SIZE. - */ - unsigned int kiov_offset; -} lnet_kiov_t; +typedef struct bio_vec lnet_kiov_t; /** @} lnet_md */ /** \addtogroup lnet_eq diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 4f5978b3767b..c7a5d49e487f 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -128,6 +128,7 @@ static int kiblnd_msgtype2size(int type) static int kiblnd_unpack_rd(struct kib_msg *msg, int flip) { struct kib_rdma_desc *rd; + int msg_size; int nob; int n; int i; @@ -146,12 +147,6 @@ static int kiblnd_unpack_rd(struct kib_msg *msg, int flip) n = rd->rd_nfrags; - if (n <= 0 || n > IBLND_MAX_RDMA_FRAGS) { - CERROR("Bad nfrags: %d, should be 0 < n <= %d\n", - n, IBLND_MAX_RDMA_FRAGS); - return 1; - } - nob = offsetof(struct kib_msg, ibm_u) + kiblnd_rd_msg_size(rd, msg->ibm_type, n); @@ -161,6 +156,13 @@ static int kiblnd_unpack_rd(struct kib_msg *msg, int flip) return 1; } + msg_size = kiblnd_rd_size(rd); + if (msg_size <= 0 || msg_size > LNET_MAX_PAYLOAD) { + CERROR("Bad msg_size: %d, should be 0 < n <= %d\n", + msg_size, LNET_MAX_PAYLOAD); + return 1; + } + if (!flip) return 0; @@ -618,7 +620,7 @@ static int kiblnd_get_completion_vector(struct kib_conn *conn, int cpt) } struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cmid, - int state, int version) + int state, int version) { /* * CAVEAT EMPTOR: diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index 078a0c3e8845..14576977200f 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -113,8 +113,9 @@ extern struct kib_tunables kiblnd_tunables; #define IBLND_OOB_CAPABLE(v) ((v) != IBLND_MSG_VERSION_1) #define IBLND_OOB_MSGS(v) (IBLND_OOB_CAPABLE(v) ? 2 : 0) -#define IBLND_MSG_SIZE (4 << 10) /* max size of queued messages (inc hdr) */ -#define IBLND_MAX_RDMA_FRAGS LNET_MAX_IOV /* max # of fragments supported */ +#define IBLND_FRAG_SHIFT (PAGE_SHIFT - 12) /* frag size on wire is in 4K units */ +#define IBLND_MSG_SIZE (4 << 10) /* max size of queued messages (inc hdr) */ +#define IBLND_MAX_RDMA_FRAGS (LNET_MAX_PAYLOAD >> 12)/* max # of fragments supported in 4K size */ /************************/ /* derived constants... */ @@ -133,8 +134,8 @@ extern struct kib_tunables kiblnd_tunables; /* WRs and CQEs (per connection) */ #define IBLND_RECV_WRS(c) IBLND_RX_MSGS(c) #define IBLND_SEND_WRS(c) \ - ((c->ibc_max_frags + 1) * kiblnd_concurrent_sends(c->ibc_version, \ - c->ibc_peer->ibp_ni)) + (((c->ibc_max_frags + 1) << IBLND_FRAG_SHIFT) * \ + kiblnd_concurrent_sends(c->ibc_version, c->ibc_peer->ibp_ni)) #define IBLND_CQ_ENTRIES(c) (IBLND_RECV_WRS(c) + IBLND_SEND_WRS(c)) struct kib_hca_dev; @@ -582,6 +583,8 @@ struct kib_peer { unsigned short ibp_connecting; /* reconnect this peer later */ unsigned short ibp_reconnecting:1; + /* counter of how many times we triggered a conn race */ + unsigned char ibp_races; /* # consecutive reconnection attempts to this peer */ unsigned int ibp_reconnected; /* errno on closing this peer */ @@ -607,14 +610,14 @@ kiblnd_cfg_rdma_frags(struct lnet_ni *ni) tunables = &ni->ni_lnd_tunables->lt_tun_u.lt_o2ib; mod = tunables->lnd_map_on_demand; - return mod ? mod : IBLND_MAX_RDMA_FRAGS; + return mod ? mod : IBLND_MAX_RDMA_FRAGS >> IBLND_FRAG_SHIFT; } static inline int kiblnd_rdma_frags(int version, struct lnet_ni *ni) { return version == IBLND_MSG_VERSION_1 ? - IBLND_MAX_RDMA_FRAGS : + (IBLND_MAX_RDMA_FRAGS >> IBLND_FRAG_SHIFT) : kiblnd_cfg_rdma_frags(ni); } @@ -1034,5 +1037,4 @@ int kiblnd_post_rx(struct kib_rx *rx, int credit); int kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen); + struct iov_iter *to, unsigned int rlen); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 596a697b9d39..b27de8888149 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -36,16 +36,19 @@ #include "o2iblnd.h" +#define MAX_CONN_RACES_BEFORE_ABORT 20 + static void kiblnd_peer_alive(struct kib_peer *peer); static void kiblnd_peer_connect_failed(struct kib_peer *peer, int active, int error); -static void kiblnd_check_sends(struct kib_conn *conn); static void kiblnd_init_tx_msg(lnet_ni_t *ni, struct kib_tx *tx, - int type, int body_nob); + int type, int body_nob); static int kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, - int resid, struct kib_rdma_desc *dstrd, __u64 dstcookie); + int resid, struct kib_rdma_desc *dstrd, + __u64 dstcookie); static void kiblnd_queue_tx_locked(struct kib_tx *tx, struct kib_conn *conn); static void kiblnd_queue_tx(struct kib_tx *tx, struct kib_conn *conn); static void kiblnd_unmap_tx(lnet_ni_t *ni, struct kib_tx *tx); +static void kiblnd_check_sends_locked(struct kib_conn *conn); static void kiblnd_tx_done(lnet_ni_t *ni, struct kib_tx *tx) @@ -211,9 +214,9 @@ kiblnd_post_rx(struct kib_rx *rx, int credit) conn->ibc_outstanding_credits++; else conn->ibc_reserved_credits++; + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); - kiblnd_check_sends(conn); out: kiblnd_conn_decref(conn); return rc; @@ -344,8 +347,8 @@ kiblnd_handle_rx(struct kib_rx *rx) !IBLND_OOB_CAPABLE(conn->ibc_version)) /* v1 only */ conn->ibc_outstanding_credits++; + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); - kiblnd_check_sends(conn); } switch (msg->ibm_type) { @@ -648,7 +651,7 @@ static int kiblnd_map_tx(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc static int kiblnd_setup_rd_iov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, - unsigned int niov, struct kvec *iov, int offset, int nob) + unsigned int niov, const struct kvec *iov, int offset, int nob) { struct kib_net *net = ni->ni_data; struct page *page; @@ -705,7 +708,7 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, static int kiblnd_setup_rd_kiov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, - int nkiov, lnet_kiov_t *kiov, int offset, int nob) + int nkiov, const lnet_kiov_t *kiov, int offset, int nob) { struct kib_net *net = ni->ni_data; struct scatterlist *sg; @@ -717,8 +720,8 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, LASSERT(nkiov > 0); LASSERT(net); - while (offset >= kiov->kiov_len) { - offset -= kiov->kiov_len; + while (offset >= kiov->bv_len) { + offset -= kiov->bv_len; nkiov--; kiov++; LASSERT(nkiov > 0); @@ -728,10 +731,10 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, do { LASSERT(nkiov > 0); - fragnob = min((int)(kiov->kiov_len - offset), nob); + fragnob = min((int)(kiov->bv_len - offset), nob); - sg_set_page(sg, kiov->kiov_page, fragnob, - kiov->kiov_offset + offset); + sg_set_page(sg, kiov->bv_page, fragnob, + kiov->bv_offset + offset); sg = sg_next(sg); if (!sg) { CERROR("lacking enough sg entries to map tx\n"); @@ -761,7 +764,6 @@ kiblnd_post_tx_locked(struct kib_conn *conn, struct kib_tx *tx, int credit) LASSERT(tx->tx_queued); /* We rely on this for QP sizing */ LASSERT(tx->tx_nwrq > 0); - LASSERT(tx->tx_nwrq <= 1 + conn->ibc_max_frags); LASSERT(!credit || credit == 1); LASSERT(conn->ibc_outstanding_credits >= 0); @@ -800,7 +802,7 @@ kiblnd_post_tx_locked(struct kib_conn *conn, struct kib_tx *tx, int credit) conn->ibc_noops_posted == IBLND_OOB_MSGS(ver)))) { /* * OK to drop when posted enough NOOPs, since - * kiblnd_check_sends will queue NOOP again when + * kiblnd_check_sends_locked will queue NOOP again when * posted NOOPs complete */ spin_unlock(&conn->ibc_lock); @@ -905,7 +907,7 @@ kiblnd_post_tx_locked(struct kib_conn *conn, struct kib_tx *tx, int credit) } static void -kiblnd_check_sends(struct kib_conn *conn) +kiblnd_check_sends_locked(struct kib_conn *conn) { int ver = conn->ibc_version; lnet_ni_t *ni = conn->ibc_peer->ibp_ni; @@ -918,8 +920,6 @@ kiblnd_check_sends(struct kib_conn *conn) return; } - spin_lock(&conn->ibc_lock); - LASSERT(conn->ibc_nsends_posted <= kiblnd_concurrent_sends(ver, ni)); LASSERT(!IBLND_OOB_CAPABLE(ver) || conn->ibc_noops_posted <= IBLND_OOB_MSGS(ver)); @@ -969,8 +969,6 @@ kiblnd_check_sends(struct kib_conn *conn) if (kiblnd_post_tx_locked(conn, tx, credit)) break; } - - spin_unlock(&conn->ibc_lock); } static void @@ -1016,16 +1014,11 @@ kiblnd_tx_complete(struct kib_tx *tx, int status) if (idle) list_del(&tx->tx_list); - kiblnd_conn_addref(conn); /* 1 ref for me.... */ - + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); if (idle) kiblnd_tx_done(conn->ibc_peer->ibp_ni, tx); - - kiblnd_check_sends(conn); - - kiblnd_conn_decref(conn); /* ...until here */ } static void @@ -1078,6 +1071,15 @@ kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, LASSERT(type == IBLND_MSG_GET_DONE || type == IBLND_MSG_PUT_DONE); + if (kiblnd_rd_size(srcrd) > conn->ibc_max_frags << PAGE_SHIFT) { + CERROR("RDMA is too large for peer %s (%d), src size: %d dst size: %d\n", + libcfs_nid2str(conn->ibc_peer->ibp_nid), + conn->ibc_max_frags << PAGE_SHIFT, + kiblnd_rd_size(srcrd), kiblnd_rd_size(dstrd)); + rc = -EMSGSIZE; + goto too_big; + } + while (resid > 0) { if (srcidx >= srcrd->rd_nfrags) { CERROR("Src buffer exhausted: %d frags\n", srcidx); @@ -1091,10 +1093,10 @@ kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, break; } - if (tx->tx_nwrq >= conn->ibc_max_frags) { + if (tx->tx_nwrq >= IBLND_MAX_RDMA_FRAGS) { CERROR("RDMA has too many fragments for peer %s (%d), src idx/frags: %d/%d dst idx/frags: %d/%d\n", libcfs_nid2str(conn->ibc_peer->ibp_nid), - conn->ibc_max_frags, + IBLND_MAX_RDMA_FRAGS, srcidx, srcrd->rd_nfrags, dstidx, dstrd->rd_nfrags); rc = -EMSGSIZE; @@ -1132,7 +1134,7 @@ kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, wrq++; sge++; } - +too_big: if (rc < 0) /* no RDMA if completing with failure */ tx->tx_nwrq = 0; @@ -1204,9 +1206,8 @@ kiblnd_queue_tx(struct kib_tx *tx, struct kib_conn *conn) { spin_lock(&conn->ibc_lock); kiblnd_queue_tx_locked(tx, conn); + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); - - kiblnd_check_sends(conn); } static int kiblnd_resolve_addr(struct rdma_cm_id *cmid, @@ -1499,6 +1500,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) lnet_kiov_t *payload_kiov = lntmsg->msg_kiov; unsigned int payload_offset = lntmsg->msg_offset; unsigned int payload_nob = lntmsg->msg_len; + struct iov_iter from; struct kib_msg *ibmsg; struct kib_rdma_desc *rd; struct kib_tx *tx; @@ -1518,6 +1520,17 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) /* payload is either all vaddrs or all pages */ LASSERT(!(payload_kiov && payload_iov)); + if (payload_kiov) + iov_iter_bvec(&from, ITER_BVEC | WRITE, + payload_kiov, payload_niov, + payload_nob + payload_offset); + else + iov_iter_kvec(&from, ITER_KVEC | WRITE, + payload_iov, payload_niov, + payload_nob + payload_offset); + + iov_iter_advance(&from, payload_offset); + switch (type) { default: LBUG(); @@ -1637,17 +1650,8 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) ibmsg = tx->tx_msg; ibmsg->ibm_u.immediate.ibim_hdr = *hdr; - if (payload_kiov) - lnet_copy_kiov2flat(IBLND_MSG_SIZE, ibmsg, - offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - payload_niov, payload_kiov, - payload_offset, payload_nob); - else - lnet_copy_iov2flat(IBLND_MSG_SIZE, ibmsg, - offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - payload_niov, payload_iov, - payload_offset, payload_nob); - + copy_from_iter(&ibmsg->ibm_u.immediate.ibim_payload, IBLND_MSG_SIZE, + &from); nob = offsetof(struct kib_immediate_msg, ibim_payload[payload_nob]); kiblnd_init_tx_msg(ni, tx, IBLND_MSG_IMMEDIATE, nob); @@ -1719,8 +1723,7 @@ kiblnd_reply(lnet_ni_t *ni, struct kib_rx *rx, lnet_msg_t *lntmsg) int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + struct iov_iter *to, unsigned int rlen) { struct kib_rx *rx = private; struct kib_msg *rxmsg = rx->rx_msg; @@ -1730,10 +1733,9 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, int post_credit = IBLND_POSTRX_PEER_CREDIT; int rc = 0; - LASSERT(mlen <= rlen); + LASSERT(iov_iter_count(to) <= rlen); LASSERT(!in_interrupt()); /* Either all pages or all vaddrs */ - LASSERT(!(kiov && iov)); switch (rxmsg->ibm_type) { default: @@ -1749,16 +1751,8 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, break; } - if (kiov) - lnet_copy_flat2kiov(niov, kiov, offset, - IBLND_MSG_SIZE, rxmsg, - offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - mlen); - else - lnet_copy_flat2iov(niov, iov, offset, - IBLND_MSG_SIZE, rxmsg, - offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - mlen); + copy_to_iter(&rxmsg->ibm_u.immediate.ibim_payload, + IBLND_MSG_SIZE, to); lnet_finalize(ni, lntmsg, 0); break; @@ -1766,7 +1760,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, struct kib_msg *txmsg; struct kib_rdma_desc *rd; - if (!mlen) { + if (!iov_iter_count(to)) { lnet_finalize(ni, lntmsg, 0); kiblnd_send_completion(rx->rx_conn, IBLND_MSG_PUT_NAK, 0, rxmsg->ibm_u.putreq.ibprm_cookie); @@ -1784,12 +1778,16 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, txmsg = tx->tx_msg; rd = &txmsg->ibm_u.putack.ibpam_rd; - if (!kiov) + if (!(to->type & ITER_BVEC)) rc = kiblnd_setup_rd_iov(ni, tx, rd, - niov, iov, offset, mlen); + to->nr_segs, to->kvec, + to->iov_offset, + iov_iter_count(to)); else rc = kiblnd_setup_rd_kiov(ni, tx, rd, - niov, kiov, offset, mlen); + to->nr_segs, to->bvec, + to->iov_offset, + iov_iter_count(to)); if (rc) { CERROR("Can't setup PUT sink for %s: %d\n", libcfs_nid2str(conn->ibc_peer->ibp_nid), rc); @@ -2183,14 +2181,11 @@ kiblnd_connreq_done(struct kib_conn *conn, int status) return; } - /** - * refcount taken by cmid is not reliable after I released the glock - * because this connection is visible to other threads now, another - * thread can find and close this connection right after I released - * the glock, if kiblnd_cm_callback for RDMA_CM_EVENT_DISCONNECTED is - * called, it can release the connection refcount taken by cmid. - * It means the connection could be destroyed before I finish my - * operations on it. + /* + * +1 ref for myself, this connection is visible to other threads + * now, refcount of peer:ibp_conns can be released by connection + * close from either a different thread, or the calling of + * kiblnd_check_sends_locked() below. See bz21911 for details. */ kiblnd_conn_addref(conn); write_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); @@ -2202,10 +2197,9 @@ kiblnd_connreq_done(struct kib_conn *conn, int status) kiblnd_queue_tx_locked(tx, conn); } + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); - kiblnd_check_sends(conn); - /* schedule blocked rxs */ kiblnd_handle_early_rxs(conn); @@ -2240,6 +2234,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) struct kib_rej rej; int version = IBLND_MSG_VERSION; unsigned long flags; + int max_frags; int rc; struct sockaddr_in *peer_addr; @@ -2346,22 +2341,20 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) goto failed; } - if (reqmsg->ibm_u.connparams.ibcp_max_frags > - kiblnd_rdma_frags(version, ni)) { - CWARN("Can't accept conn from %s (version %x): max_frags %d too large (%d wanted)\n", - libcfs_nid2str(nid), version, - reqmsg->ibm_u.connparams.ibcp_max_frags, + max_frags = reqmsg->ibm_u.connparams.ibcp_max_frags >> IBLND_FRAG_SHIFT; + if (max_frags > kiblnd_rdma_frags(version, ni)) { + CWARN("Can't accept conn from %s (version %x): max message size %d is too large (%d wanted)\n", + libcfs_nid2str(nid), version, max_frags, kiblnd_rdma_frags(version, ni)); if (version >= IBLND_MSG_VERSION) rej.ibr_why = IBLND_REJECT_RDMA_FRAGS; goto failed; - } else if (reqmsg->ibm_u.connparams.ibcp_max_frags < - kiblnd_rdma_frags(version, ni) && !net->ibn_fmr_ps) { - CWARN("Can't accept conn from %s (version %x): max_frags %d incompatible without FMR pool (%d wanted)\n", - libcfs_nid2str(nid), version, - reqmsg->ibm_u.connparams.ibcp_max_frags, + } else if (max_frags < kiblnd_rdma_frags(version, ni) && + !net->ibn_fmr_ps) { + CWARN("Can't accept conn from %s (version %x): max message size %d incompatible without FMR pool (%d wanted)\n", + libcfs_nid2str(nid), version, max_frags, kiblnd_rdma_frags(version, ni)); if (version == IBLND_MSG_VERSION) @@ -2387,7 +2380,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) } /* We have validated the peer's parameters so use those */ - peer->ibp_max_frags = reqmsg->ibm_u.connparams.ibcp_max_frags; + peer->ibp_max_frags = max_frags; peer->ibp_queue_depth = reqmsg->ibm_u.connparams.ibcp_queue_depth; write_lock_irqsave(g_lock, flags); @@ -2419,23 +2412,37 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) goto failed; } - /* tie-break connection race in favour of the higher NID */ + /* + * Tie-break connection race in favour of the higher NID. + * If we keep running into a race condition multiple times, + * we have to assume that the connection attempt with the + * higher NID is stuck in a connecting state and will never + * recover. As such, we pass through this if-block and let + * the lower NID connection win so we can move forward. + */ if (peer2->ibp_connecting && - nid < ni->ni_nid) { + nid < ni->ni_nid && peer2->ibp_races < + MAX_CONN_RACES_BEFORE_ABORT) { + peer2->ibp_races++; write_unlock_irqrestore(g_lock, flags); - CWARN("Conn race %s\n", libcfs_nid2str(peer2->ibp_nid)); + CDEBUG(D_NET, "Conn race %s\n", + libcfs_nid2str(peer2->ibp_nid)); kiblnd_peer_decref(peer); rej.ibr_why = IBLND_REJECT_CONN_RACE; goto failed; } - + if (peer2->ibp_races >= MAX_CONN_RACES_BEFORE_ABORT) + CNETERR("Conn race %s: unresolved after %d attempts, letting lower NID win\n", + libcfs_nid2str(peer2->ibp_nid), + MAX_CONN_RACES_BEFORE_ABORT); /** * passive connection is allowed even this peer is waiting for * reconnection. */ peer2->ibp_reconnecting = 0; + peer2->ibp_races = 0; peer2->ibp_accepting++; kiblnd_peer_addref(peer2); @@ -2494,7 +2501,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) kiblnd_init_msg(ackmsg, IBLND_MSG_CONNACK, sizeof(ackmsg->ibm_u.connparams)); ackmsg->ibm_u.connparams.ibcp_queue_depth = conn->ibc_queue_depth; - ackmsg->ibm_u.connparams.ibcp_max_frags = conn->ibc_max_frags; + ackmsg->ibm_u.connparams.ibcp_max_frags = conn->ibc_max_frags << IBLND_FRAG_SHIFT; ackmsg->ibm_u.connparams.ibcp_max_msg_size = IBLND_MSG_SIZE; kiblnd_pack_msg(ni, ackmsg, version, 0, nid, reqmsg->ibm_srcstamp); @@ -2526,9 +2533,9 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) failed: if (ni) { - lnet_ni_decref(ni); rej.ibr_cp.ibcp_queue_depth = kiblnd_msg_queue_size(version, ni); rej.ibr_cp.ibcp_max_frags = kiblnd_rdma_frags(version, ni); + lnet_ni_decref(ni); } rej.ibr_version = version; @@ -2556,7 +2563,7 @@ kiblnd_check_reconnect(struct kib_conn *conn, int version, if (cp) { msg_size = cp->ibcp_max_msg_size; - frag_num = cp->ibcp_max_frags; + frag_num = cp->ibcp_max_frags << IBLND_FRAG_SHIFT; queue_dep = cp->ibcp_queue_depth; } @@ -2821,11 +2828,11 @@ kiblnd_check_connreply(struct kib_conn *conn, void *priv, int priv_nob) goto failed; } - if (msg->ibm_u.connparams.ibcp_max_frags > + if ((msg->ibm_u.connparams.ibcp_max_frags >> IBLND_FRAG_SHIFT) > conn->ibc_max_frags) { CERROR("%s has incompatible max_frags %d (<=%d wanted)\n", libcfs_nid2str(peer->ibp_nid), - msg->ibm_u.connparams.ibcp_max_frags, + msg->ibm_u.connparams.ibcp_max_frags >> IBLND_FRAG_SHIFT, conn->ibc_max_frags); rc = -EPROTO; goto failed; @@ -2859,7 +2866,7 @@ kiblnd_check_connreply(struct kib_conn *conn, void *priv, int priv_nob) conn->ibc_credits = msg->ibm_u.connparams.ibcp_queue_depth; conn->ibc_reserved_credits = msg->ibm_u.connparams.ibcp_queue_depth; conn->ibc_queue_depth = msg->ibm_u.connparams.ibcp_queue_depth; - conn->ibc_max_frags = msg->ibm_u.connparams.ibcp_max_frags; + conn->ibc_max_frags = msg->ibm_u.connparams.ibcp_max_frags >> IBLND_FRAG_SHIFT; LASSERT(conn->ibc_credits + conn->ibc_reserved_credits + IBLND_OOB_MSGS(ver) <= IBLND_RX_MSGS(conn)); @@ -2916,7 +2923,7 @@ kiblnd_active_connect(struct rdma_cm_id *cmid) memset(msg, 0, sizeof(*msg)); kiblnd_init_msg(msg, IBLND_MSG_CONNREQ, sizeof(msg->ibm_u.connparams)); msg->ibm_u.connparams.ibcp_queue_depth = conn->ibc_queue_depth; - msg->ibm_u.connparams.ibcp_max_frags = conn->ibc_max_frags; + msg->ibm_u.connparams.ibcp_max_frags = conn->ibc_max_frags << IBLND_FRAG_SHIFT; msg->ibm_u.connparams.ibcp_max_msg_size = IBLND_MSG_SIZE; kiblnd_pack_msg(peer->ibp_ni, msg, version, @@ -3233,7 +3240,11 @@ kiblnd_check_conns(int idx) */ list_for_each_entry_safe(conn, temp, &checksends, ibc_connd_list) { list_del(&conn->ibc_connd_list); - kiblnd_check_sends(conn); + + spin_lock(&conn->ibc_lock); + kiblnd_check_sends_locked(conn); + spin_unlock(&conn->ibc_lock); + kiblnd_conn_decref(conn); } } @@ -3419,6 +3430,12 @@ kiblnd_qp_event(struct ib_event *event, void *arg) case IB_EVENT_COMM_EST: CDEBUG(D_NET, "%s established\n", libcfs_nid2str(conn->ibc_peer->ibp_nid)); + /* + * We received a packet but connection isn't established + * probably handshake packet was lost, so free to + * force make connection established + */ + rdma_notify(conn->ibc_cmid, IB_EVENT_COMM_EST); return; default: diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 07ec540946cd..cbc9a9c5385f 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -1468,11 +1468,6 @@ ksocknal_close_conn_locked(struct ksock_conn *conn, int error) conn->ksnc_route = NULL; -#if 0 /* irrelevant with only eager routes */ - /* make route least favourite */ - list_del(&route->ksnr_list); - list_add_tail(&route->ksnr_list, &peer->ksnp_routes); -#endif ksocknal_route_decref(route); /* drop conn's ref on route */ } diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index a56632b4ee37..e6ca0cf52691 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -86,8 +86,6 @@ struct ksock_sched { /* per scheduler state */ int kss_nconns; /* # connections assigned to * this scheduler */ struct ksock_sched_info *kss_info; /* owner of it */ - struct page *kss_rx_scratch_pgs[LNET_MAX_IOV]; - struct kvec kss_scratch_iov[LNET_MAX_IOV]; }; struct ksock_sched_info { @@ -616,9 +614,7 @@ void ksocknal_shutdown(lnet_ni_t *ni); int ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg); int ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, - int delayed, unsigned int niov, - struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen); + int delayed, struct iov_iter *to, unsigned int rlen); int ksocknal_accept(lnet_ni_t *ni, struct socket *sock); int ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip, int port); @@ -635,7 +631,7 @@ int ksocknal_close_peer_conns_locked(struct ksock_peer *peer, int ksocknal_close_conn_and_siblings(struct ksock_conn *conn, int why); int ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr); struct ksock_conn *ksocknal_find_conn_locked(struct ksock_peer *peer, - struct ksock_tx *tx, int nonblk); + struct ksock_tx *tx, int nonblk); int ksocknal_launch_packet(lnet_ni_t *ni, struct ksock_tx *tx, lnet_process_id_t id); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 303576d815c6..c1c6f604e6ad 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -35,8 +35,8 @@ ksocknal_alloc_tx(int type, int size) spin_lock(&ksocknal_data.ksnd_tx_lock); if (!list_empty(&ksocknal_data.ksnd_idle_noop_txs)) { - tx = list_entry(ksocknal_data.ksnd_idle_noop_txs. \ - next, struct ksock_tx, tx_list); + tx = list_entry(ksocknal_data.ksnd_idle_noop_txs.next, + struct ksock_tx, tx_list); LASSERT(tx->tx_desc_size == size); list_del(&tx->tx_list); } @@ -164,13 +164,13 @@ ksocknal_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) do { LASSERT(tx->tx_nkiov > 0); - if (nob < (int)kiov->kiov_len) { - kiov->kiov_offset += nob; - kiov->kiov_len -= nob; + if (nob < (int)kiov->bv_len) { + kiov->bv_offset += nob; + kiov->bv_len -= nob; return rc; } - nob -= (int)kiov->kiov_len; + nob -= (int)kiov->bv_len; tx->tx_kiov = ++kiov; tx->tx_nkiov--; } while (nob); @@ -326,13 +326,13 @@ ksocknal_recv_kiov(struct ksock_conn *conn) do { LASSERT(conn->ksnc_rx_nkiov > 0); - if (nob < (int)kiov->kiov_len) { - kiov->kiov_offset += nob; - kiov->kiov_len -= nob; + if (nob < (int)kiov->bv_len) { + kiov->bv_offset += nob; + kiov->bv_len -= nob; return -EAGAIN; } - nob -= kiov->kiov_len; + nob -= kiov->bv_len; conn->ksnc_rx_kiov = ++kiov; conn->ksnc_rx_nkiov--; } while (nob); @@ -1325,39 +1325,36 @@ ksocknal_process_receive(struct ksock_conn *conn) int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, - unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + struct iov_iter *to, unsigned int rlen) { struct ksock_conn *conn = private; struct ksock_sched *sched = conn->ksnc_scheduler; - LASSERT(mlen <= rlen); - LASSERT(niov <= LNET_MAX_IOV); + LASSERT(iov_iter_count(to) <= rlen); + LASSERT(to->nr_segs <= LNET_MAX_IOV); conn->ksnc_cookie = msg; - conn->ksnc_rx_nob_wanted = mlen; + conn->ksnc_rx_nob_wanted = iov_iter_count(to); conn->ksnc_rx_nob_left = rlen; - if (!mlen || iov) { + if (to->type & ITER_KVEC) { conn->ksnc_rx_nkiov = 0; conn->ksnc_rx_kiov = NULL; conn->ksnc_rx_iov = conn->ksnc_rx_iov_space.iov; conn->ksnc_rx_niov = lnet_extract_iov(LNET_MAX_IOV, conn->ksnc_rx_iov, - niov, iov, offset, mlen); + to->nr_segs, to->kvec, + to->iov_offset, iov_iter_count(to)); } else { conn->ksnc_rx_niov = 0; conn->ksnc_rx_iov = NULL; conn->ksnc_rx_kiov = conn->ksnc_rx_iov_space.kiov; conn->ksnc_rx_nkiov = lnet_extract_kiov(LNET_MAX_IOV, conn->ksnc_rx_kiov, - niov, kiov, offset, mlen); + to->nr_segs, to->bvec, + to->iov_offset, iov_iter_count(to)); } - LASSERT(mlen == - lnet_iov_nob(conn->ksnc_rx_niov, conn->ksnc_rx_iov) + - lnet_kiov_nob(conn->ksnc_rx_nkiov, conn->ksnc_rx_kiov)); - LASSERT(conn->ksnc_rx_scheduled); spin_lock_bh(&sched->kss_lock); @@ -2008,13 +2005,6 @@ ksocknal_connect(struct ksock_route *route) list_splice_init(&peer->ksnp_tx_queue, &zombies); } -#if 0 /* irrelevant with only eager routes */ - if (!route->ksnr_deleted) { - /* make this route least-favourite for re-selection */ - list_del(&route->ksnr_list); - list_add_tail(&route->ksnr_list, &peer->ksnp_routes); - } -#endif write_unlock_bh(&ksocknal_data.ksnd_global_lock); ksocknal_peer_failed(peer); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 6a17757fce1e..6c95e989ca12 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -73,9 +73,9 @@ ksocknal_lib_zc_capable(struct ksock_conn *conn) int ksocknal_lib_send_iov(struct ksock_conn *conn, struct ksock_tx *tx) { + struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; struct socket *sock = conn->ksnc_sock; - int nob; - int rc; + int nob, i; if (*ksocknal_tunables.ksnd_enable_csum && /* checksum enabled */ conn->ksnc_proto == &ksocknal_protocol_v2x && /* V2.x connection */ @@ -83,34 +83,16 @@ ksocknal_lib_send_iov(struct ksock_conn *conn, struct ksock_tx *tx) !tx->tx_msg.ksm_csum) /* not checksummed */ ksocknal_lib_csum_tx(tx); - /* - * NB we can't trust socket ops to either consume our iovs - * or leave them alone. - */ - { -#if SOCKNAL_SINGLE_FRAG_TX - struct kvec scratch; - struct kvec *scratchiov = &scratch; - unsigned int niov = 1; -#else - struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; - unsigned int niov = tx->tx_niov; -#endif - struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; - int i; + for (nob = i = 0; i < tx->tx_niov; i++) + nob += tx->tx_iov[i].iov_len; - for (nob = i = 0; i < niov; i++) { - scratchiov[i] = tx->tx_iov[i]; - nob += scratchiov[i].iov_len; - } + if (!list_empty(&conn->ksnc_tx_queue) || + nob < tx->tx_resid) + msg.msg_flags |= MSG_MORE; - if (!list_empty(&conn->ksnc_tx_queue) || - nob < tx->tx_resid) - msg.msg_flags |= MSG_MORE; - - rc = kernel_sendmsg(sock, &msg, scratchiov, niov, nob); - } - return rc; + iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, + tx->tx_iov, tx->tx_niov, nob); + return sock_sendmsg(sock, &msg); } int @@ -124,20 +106,16 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) /* Not NOOP message */ LASSERT(tx->tx_lnetmsg); - /* - * NB we can't trust socket ops to either consume our iovs - * or leave them alone. - */ if (tx->tx_msg.ksm_zc_cookies[0]) { /* Zero copy is enabled */ struct sock *sk = sock->sk; - struct page *page = kiov->kiov_page; - int offset = kiov->kiov_offset; - int fragsize = kiov->kiov_len; + struct page *page = kiov->bv_page; + int offset = kiov->bv_offset; + int fragsize = kiov->bv_len; int msgflg = MSG_DONTWAIT; CDEBUG(D_NET, "page %p + offset %x for %d\n", - page, offset, kiov->kiov_len); + page, offset, kiov->bv_len); if (!list_empty(&conn->ksnc_tx_queue) || fragsize < tx->tx_resid) @@ -150,34 +128,19 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) rc = tcp_sendpage(sk, page, offset, fragsize, msgflg); } } else { -#if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK - struct kvec scratch; - struct kvec *scratchiov = &scratch; - unsigned int niov = 1; -#else -#ifdef CONFIG_HIGHMEM -#warning "XXX risk of kmap deadlock on multiple frags..." -#endif - struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; - unsigned int niov = tx->tx_nkiov; -#endif struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; int i; - for (nob = i = 0; i < niov; i++) { - scratchiov[i].iov_base = kmap(kiov[i].kiov_page) + - kiov[i].kiov_offset; - nob += scratchiov[i].iov_len = kiov[i].kiov_len; - } + for (nob = i = 0; i < tx->tx_nkiov; i++) + nob += kiov[i].bv_len; if (!list_empty(&conn->ksnc_tx_queue) || nob < tx->tx_resid) msg.msg_flags |= MSG_MORE; - rc = kernel_sendmsg(sock, &msg, (struct kvec *)scratchiov, niov, nob); - - for (i = 0; i < niov; i++) - kunmap(kiov[i].kiov_page); + iov_iter_bvec(&msg.msg_iter, WRITE | ITER_BVEC, + kiov, tx->tx_nkiov, nob); + rc = sock_sendmsg(sock, &msg); } return rc; } @@ -201,14 +164,7 @@ ksocknal_lib_eager_ack(struct ksock_conn *conn) int ksocknal_lib_recv_iov(struct ksock_conn *conn) { -#if SOCKNAL_SINGLE_FRAG_RX - struct kvec scratch; - struct kvec *scratchiov = &scratch; - unsigned int niov = 1; -#else - struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; unsigned int niov = conn->ksnc_rx_niov; -#endif struct kvec *iov = conn->ksnc_rx_iov; struct msghdr msg = { .msg_flags = 0 @@ -220,20 +176,15 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) int sum; __u32 saved_csum; - /* - * NB we can't trust socket ops to either consume our iovs - * or leave them alone. - */ LASSERT(niov > 0); - for (nob = i = 0; i < niov; i++) { - scratchiov[i] = iov[i]; - nob += scratchiov[i].iov_len; - } + for (nob = i = 0; i < niov; i++) + nob += iov[i].iov_len; + LASSERT(nob <= conn->ksnc_rx_nob_wanted); - rc = kernel_recvmsg(conn->ksnc_sock, &msg, scratchiov, niov, nob, - MSG_DONTWAIT); + iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, niov, nob); + rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); saved_csum = 0; if (conn->ksnc_proto == &ksocknal_protocol_v2x) { @@ -259,67 +210,10 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) return rc; } -static void -ksocknal_lib_kiov_vunmap(void *addr) -{ - if (!addr) - return; - - vunmap(addr); -} - -static void * -ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov, - struct kvec *iov, struct page **pages) -{ - void *addr; - int nob; - int i; - - if (!*ksocknal_tunables.ksnd_zc_recv || !pages) - return NULL; - - LASSERT(niov <= LNET_MAX_IOV); - - if (niov < 2 || - niov < *ksocknal_tunables.ksnd_zc_recv_min_nfrags) - return NULL; - - for (nob = i = 0; i < niov; i++) { - if ((kiov[i].kiov_offset && i > 0) || - (kiov[i].kiov_offset + kiov[i].kiov_len != PAGE_SIZE && i < niov - 1)) - return NULL; - - pages[i] = kiov[i].kiov_page; - nob += kiov[i].kiov_len; - } - - addr = vmap(pages, niov, VM_MAP, PAGE_KERNEL); - if (!addr) - return NULL; - - iov->iov_base = addr + kiov[0].kiov_offset; - iov->iov_len = nob; - - return addr; -} - int ksocknal_lib_recv_kiov(struct ksock_conn *conn) { -#if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK - struct kvec scratch; - struct kvec *scratchiov = &scratch; - struct page **pages = NULL; - unsigned int niov = 1; -#else -#ifdef CONFIG_HIGHMEM -#warning "XXX risk of kmap deadlock on multiple frags..." -#endif - struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; - struct page **pages = conn->ksnc_scheduler->kss_rx_scratch_pgs; unsigned int niov = conn->ksnc_rx_nkiov; -#endif lnet_kiov_t *kiov = conn->ksnc_rx_kiov; struct msghdr msg = { .msg_flags = 0 @@ -328,63 +222,32 @@ ksocknal_lib_recv_kiov(struct ksock_conn *conn) int i; int rc; void *base; - void *addr; int sum; int fragnob; - int n; - /* - * NB we can't trust socket ops to either consume our iovs - * or leave them alone. - */ - addr = ksocknal_lib_kiov_vmap(kiov, niov, scratchiov, pages); - if (addr) { - nob = scratchiov[0].iov_len; - n = 1; - - } else { - for (nob = i = 0; i < niov; i++) { - nob += scratchiov[i].iov_len = kiov[i].kiov_len; - scratchiov[i].iov_base = kmap(kiov[i].kiov_page) + - kiov[i].kiov_offset; - } - n = niov; - } + for (nob = i = 0; i < niov; i++) + nob += kiov[i].bv_len; LASSERT(nob <= conn->ksnc_rx_nob_wanted); - rc = kernel_recvmsg(conn->ksnc_sock, &msg, (struct kvec *)scratchiov, - n, nob, MSG_DONTWAIT); + iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, kiov, niov, nob); + rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); if (conn->ksnc_msg.ksm_csum) { for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { LASSERT(i < niov); - /* - * Dang! have to kmap again because I have nowhere to - * stash the mapped address. But by doing it while the - * page is still mapped, the kernel just bumps the map - * count and returns me the address it stashed. - */ - base = kmap(kiov[i].kiov_page) + kiov[i].kiov_offset; - fragnob = kiov[i].kiov_len; + base = kmap(kiov[i].bv_page) + kiov[i].bv_offset; + fragnob = kiov[i].bv_len; if (fragnob > sum) fragnob = sum; conn->ksnc_rx_csum = ksocknal_csum(conn->ksnc_rx_csum, base, fragnob); - kunmap(kiov[i].kiov_page); + kunmap(kiov[i].bv_page); } } - - if (addr) { - ksocknal_lib_kiov_vunmap(addr); - } else { - for (i = 0; i < niov; i++) - kunmap(kiov[i].kiov_page); - } - return rc; } @@ -406,12 +269,12 @@ ksocknal_lib_csum_tx(struct ksock_tx *tx) if (tx->tx_kiov) { for (i = 0; i < tx->tx_nkiov; i++) { - base = kmap(tx->tx_kiov[i].kiov_page) + - tx->tx_kiov[i].kiov_offset; + base = kmap(tx->tx_kiov[i].bv_page) + + tx->tx_kiov[i].bv_offset; - csum = ksocknal_csum(csum, base, tx->tx_kiov[i].kiov_len); + csum = ksocknal_csum(csum, base, tx->tx_kiov[i].bv_len); - kunmap(tx->tx_kiov[i].kiov_page); + kunmap(tx->tx_kiov[i].bv_page); } } else { for (i = 1; i < tx->tx_niov; i++) diff --git a/drivers/staging/lustre/lnet/libcfs/debug.c b/drivers/staging/lustre/lnet/libcfs/debug.c index 42b15a769183..23b36b890964 100644 --- a/drivers/staging/lustre/lnet/libcfs/debug.c +++ b/drivers/staging/lustre/lnet/libcfs/debug.c @@ -328,15 +328,20 @@ libcfs_debug_str2mask(int *mask, const char *str, int is_subsys) */ void libcfs_debug_dumplog_internal(void *arg) { + static time64_t last_dump_time; + time64_t current_time; void *journal_info; journal_info = current->journal_info; current->journal_info = NULL; + current_time = ktime_get_real_seconds(); - if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) != 0) { + if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) && + current_time > last_dump_time) { + last_dump_time = current_time; snprintf(debug_file_name, sizeof(debug_file_name) - 1, "%s.%lld.%ld", libcfs_debug_file_path_arr, - (s64)ktime_get_real_seconds(), (long_ptr_t)arg); + (s64)current_time, (long_ptr_t)arg); pr_alert("LustreError: dumping log to %s\n", debug_file_name); cfs_tracefile_dump_all_pages(debug_file_name); libcfs_run_debug_log_upcall(debug_file_name); diff --git a/drivers/staging/lustre/lnet/libcfs/fail.c b/drivers/staging/lustre/lnet/libcfs/fail.c index 9288ee08d1f7..e4b1a0a86eae 100644 --- a/drivers/staging/lustre/lnet/libcfs/fail.c +++ b/drivers/staging/lustre/lnet/libcfs/fail.c @@ -90,8 +90,10 @@ int __cfs_fail_check_set(__u32 id, __u32 value, int set) } } - if ((set == CFS_FAIL_LOC_ORSET || set == CFS_FAIL_LOC_RESET) && - (value & CFS_FAIL_ONCE)) + /* Take into account the current call for FAIL_ONCE for ORSET only, + * as RESET is a new fail_loc, it does not change the current call + */ + if ((set == CFS_FAIL_LOC_ORSET) && (value & CFS_FAIL_ONCE)) set_bit(CFS_FAIL_ONCE_BIT, &cfs_fail_loc); /* Lost race to set CFS_FAILED_BIT. */ if (test_and_set_bit(CFS_FAILED_BIT, &cfs_fail_loc)) { diff --git a/drivers/staging/lustre/lnet/libcfs/libcfs_string.c b/drivers/staging/lustre/lnet/libcfs/libcfs_string.c index fc697cdfcdaf..56a614d7713b 100644 --- a/drivers/staging/lustre/lnet/libcfs/libcfs_string.c +++ b/drivers/staging/lustre/lnet/libcfs/libcfs_string.c @@ -229,8 +229,6 @@ cfs_str2num_check(char *str, int nob, unsigned *num, char *endp, cache; int rc; - str = cfs_trimwhite(str); - /** * kstrouint can only handle strings composed * of only numbers. We need to scan the string diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c index b52518c54efe..e8b1a61420de 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c @@ -74,6 +74,17 @@ struct cfs_cpt_data { static struct cfs_cpt_data cpt_data; +static void +cfs_node_to_cpumask(int node, cpumask_t *mask) +{ + const cpumask_t *tmp = cpumask_of_node(node); + + if (tmp) + cpumask_copy(mask, tmp); + else + cpumask_clear(mask); +} + void cfs_cpt_table_free(struct cfs_cpt_table *cptab) { @@ -403,7 +414,7 @@ cfs_cpt_set_node(struct cfs_cpt_table *cptab, int cpt, int node) mutex_lock(&cpt_data.cpt_mutex); mask = cpt_data.cpt_cpumask; - cpumask_copy(mask, cpumask_of_node(node)); + cfs_node_to_cpumask(node, mask); rc = cfs_cpt_set_cpumask(cptab, cpt, mask); @@ -427,7 +438,7 @@ cfs_cpt_unset_node(struct cfs_cpt_table *cptab, int cpt, int node) mutex_lock(&cpt_data.cpt_mutex); mask = cpt_data.cpt_cpumask; - cpumask_copy(mask, cpumask_of_node(node)); + cfs_node_to_cpumask(node, mask); cfs_cpt_unset_cpumask(cptab, cpt, mask); @@ -749,7 +760,7 @@ cfs_cpt_table_create(int ncpt) } for_each_online_node(i) { - cpumask_copy(mask, cpumask_of_node(i)); + cfs_node_to_cpumask(i, mask); while (!cpumask_empty(mask)) { struct cfs_cpu_partition *part; diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 5c0116ade909..7f56d2c9dd00 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -95,8 +95,8 @@ static int cfs_crypto_hash_alloc(enum cfs_crypto_hash_alg hash_alg, err = crypto_ahash_setkey(tfm, key, key_len); else if ((*type)->cht_key != 0) err = crypto_ahash_setkey(tfm, - (unsigned char *)&((*type)->cht_key), - (*type)->cht_size); + (unsigned char *)&((*type)->cht_key), + (*type)->cht_size); if (err != 0) { ahash_request_free(*req); diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 346db892f275..4daf828198c3 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1286,6 +1286,25 @@ lnet_startup_lndni(struct lnet_ni *ni, struct lnet_ioctl_config_data *conf) sizeof(*ni->ni_lnd_tunables)); } + /* + * If given some LND tunable parameters, parse those now to + * override the values in the NI structure. + */ + if (conf) { + if (conf->cfg_config_u.cfg_net.net_peer_rtr_credits >= 0) + ni->ni_peerrtrcredits = + conf->cfg_config_u.cfg_net.net_peer_rtr_credits; + if (conf->cfg_config_u.cfg_net.net_peer_timeout >= 0) + ni->ni_peertimeout = + conf->cfg_config_u.cfg_net.net_peer_timeout; + if (conf->cfg_config_u.cfg_net.net_peer_tx_credits != -1) + ni->ni_peertxcredits = + conf->cfg_config_u.cfg_net.net_peer_tx_credits; + if (conf->cfg_config_u.cfg_net.net_max_tx_credits >= 0) + ni->ni_maxtxcredits = + conf->cfg_config_u.cfg_net.net_max_tx_credits; + } + rc = lnd->lnd_startup(ni); mutex_unlock(&the_lnet.ln_lnd_mutex); @@ -1299,33 +1318,6 @@ lnet_startup_lndni(struct lnet_ni *ni, struct lnet_ioctl_config_data *conf) goto failed0; } - /* - * If given some LND tunable parameters, parse those now to - * override the values in the NI structure. - */ - if (conf && conf->cfg_config_u.cfg_net.net_peer_rtr_credits >= 0) { - ni->ni_peerrtrcredits = - conf->cfg_config_u.cfg_net.net_peer_rtr_credits; - } - if (conf && conf->cfg_config_u.cfg_net.net_peer_timeout >= 0) { - ni->ni_peertimeout = - conf->cfg_config_u.cfg_net.net_peer_timeout; - } - /* - * TODO - * Note: For now, don't allow the user to change - * peertxcredits as this number is used in the - * IB LND to control queue depth. - * - * if (conf && conf->cfg_config_u.cfg_net.net_peer_tx_credits != -1) - * ni->ni_peertxcredits = - * conf->cfg_config_u.cfg_net.net_peer_tx_credits; - */ - if (conf && conf->cfg_config_u.cfg_net.net_max_tx_credits >= 0) { - ni->ni_maxtxcredits = - conf->cfg_config_u.cfg_net.net_max_tx_credits; - } - LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query); lnet_net_lock(LNET_LOCK_EX); diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index a72afdf68bb2..9e2183ff847e 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -31,6 +31,8 @@ */ #define DEBUG_SUBSYSTEM S_LNET +#include +#include #include "../../include/linux/lnet/lib-lnet.h" struct lnet_text_buf { /* tmp struct for parsing routes */ @@ -110,6 +112,11 @@ lnet_ni_free(struct lnet_ni *ni) LIBCFS_FREE(ni->ni_interfaces[i], strlen(ni->ni_interfaces[i]) + 1); } + + /* release reference to net namespace */ + if (ni->ni_net_ns) + put_net(ni->ni_net_ns); + LIBCFS_FREE(ni, sizeof(*ni)); } @@ -171,6 +178,13 @@ lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) /* LND will fill in the address part of the NID */ ni->ni_nid = LNET_MKNID(net, 0); + + /* Store net namespace in which current ni is being created */ + if (current->nsproxy->net_ns) + ni->ni_net_ns = get_net(current->nsproxy->net_ns); + else + ni->ni_net_ns = NULL; + ni->ni_last_alive = ktime_get_real_seconds(); list_add_tail(&ni->ni_list, nilist); return ni; diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index 1834bf7a27ef..eab53cd57296 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -134,11 +134,11 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) for (i = 0; i < (int)niov; i++) { /* We take the page pointer on trust */ - if (lmd->md_iov.kiov[i].kiov_offset + - lmd->md_iov.kiov[i].kiov_len > PAGE_SIZE) + if (lmd->md_iov.kiov[i].bv_offset + + lmd->md_iov.kiov[i].bv_len > PAGE_SIZE) return -EINVAL; /* invalid length */ - total_length += lmd->md_iov.kiov[i].kiov_len; + total_length += lmd->md_iov.kiov[i].bv_len; } lmd->md_length = total_length; @@ -292,11 +292,12 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, return -ENOMEM; rc = lnet_md_build(md, &umd, unlink); + if (rc) + goto out_free; + cpt = lnet_cpt_of_cookie(meh.cookie); lnet_res_lock(cpt); - if (rc) - goto failed; me = lnet_handle2me(&meh); if (!me) @@ -307,7 +308,7 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, rc = lnet_md_link(md, umd.eq_handle, cpt); if (rc) - goto failed; + goto out_unlock; /* * attach this MD to portal of ME and check if it matches any @@ -324,10 +325,10 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, return 0; - failed: - lnet_md_free(md); - +out_unlock: lnet_res_unlock(cpt); +out_free: + lnet_md_free(md); return rc; } EXPORT_SYMBOL(LNetMDAttach); @@ -370,24 +371,25 @@ LNetMDBind(lnet_md_t umd, lnet_unlink_t unlink, lnet_handle_md_t *handle) return -ENOMEM; rc = lnet_md_build(md, &umd, unlink); + if (rc) + goto out_free; cpt = lnet_res_lock_current(); - if (rc) - goto failed; rc = lnet_md_link(md, umd.eq_handle, cpt); if (rc) - goto failed; + goto out_unlock; lnet_md2handle(handle, md); lnet_res_unlock(cpt); return 0; - failed: +out_unlock: + lnet_res_unlock(cpt); +out_free: lnet_md_free(md); - lnet_res_unlock(cpt); return rc; } EXPORT_SYMBOL(LNetMDBind); diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index e6d3b801d87d..48e6f8f2392f 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -37,6 +37,8 @@ #define DEBUG_SUBSYSTEM S_LNET #include "../../include/linux/lnet/lib-lnet.h" +#include +#include static int local_nid_dist_zero = 1; module_param(local_nid_dist_zero, int, 0444); @@ -166,25 +168,17 @@ lnet_iov_nob(unsigned int niov, struct kvec *iov) EXPORT_SYMBOL(lnet_iov_nob); void -lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, - unsigned int nsiov, struct kvec *siov, unsigned int soffset, - unsigned int nob) +lnet_copy_iov2iter(struct iov_iter *to, + unsigned int nsiov, const struct kvec *siov, + unsigned int soffset, unsigned int nob) { /* NB diov, siov are READ-ONLY */ - unsigned int this_nob; + const char *s; + size_t left; if (!nob) return; - /* skip complete frags before 'doffset' */ - LASSERT(ndiov > 0); - while (doffset >= diov->iov_len) { - doffset -= diov->iov_len; - diov++; - ndiov--; - LASSERT(ndiov > 0); - } - /* skip complete frags before 'soffset' */ LASSERT(nsiov > 0); while (soffset >= siov->iov_len) { @@ -194,39 +188,68 @@ lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, LASSERT(nsiov > 0); } + s = (char *)siov->iov_base + soffset; + left = siov->iov_len - soffset; do { - LASSERT(ndiov > 0); + size_t n, copy = left; LASSERT(nsiov > 0); - this_nob = min(diov->iov_len - doffset, - siov->iov_len - soffset); - this_nob = min(this_nob, nob); - memcpy((char *)diov->iov_base + doffset, - (char *)siov->iov_base + soffset, this_nob); - nob -= this_nob; + if (copy > nob) + copy = nob; + n = copy_to_iter(s, copy, to); + if (n != copy) + return; + nob -= n; - if (diov->iov_len > doffset + this_nob) { - doffset += this_nob; - } else { - diov++; - ndiov--; - doffset = 0; - } - - if (siov->iov_len > soffset + this_nob) { - soffset += this_nob; - } else { - siov++; - nsiov--; - soffset = 0; - } + siov++; + s = (char *)siov->iov_base; + left = siov->iov_len; + nsiov--; } while (nob > 0); } -EXPORT_SYMBOL(lnet_copy_iov2iov); +EXPORT_SYMBOL(lnet_copy_iov2iter); + +void +lnet_copy_kiov2iter(struct iov_iter *to, + unsigned int nsiov, const lnet_kiov_t *siov, + unsigned int soffset, unsigned int nob) +{ + if (!nob) + return; + + LASSERT(!in_interrupt()); + + LASSERT(nsiov > 0); + while (soffset >= siov->bv_len) { + soffset -= siov->bv_len; + siov++; + nsiov--; + LASSERT(nsiov > 0); + } + + do { + size_t copy = siov->bv_len - soffset, n; + + LASSERT(nsiov > 0); + + if (copy > nob) + copy = nob; + n = copy_page_to_iter(siov->bv_page, + siov->bv_offset + soffset, + copy, to); + if (n != copy) + return; + nob -= n; + siov++; + nsiov--; + soffset = 0; + } while (nob > 0); +} +EXPORT_SYMBOL(lnet_copy_kiov2iter); int lnet_extract_iov(int dst_niov, struct kvec *dst, - int src_niov, struct kvec *src, + int src_niov, const struct kvec *src, unsigned int offset, unsigned int len) { /* @@ -280,238 +303,15 @@ lnet_kiov_nob(unsigned int niov, lnet_kiov_t *kiov) LASSERT(!niov || kiov); while (niov-- > 0) - nob += (kiov++)->kiov_len; + nob += (kiov++)->bv_len; return nob; } EXPORT_SYMBOL(lnet_kiov_nob); -void -lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, - unsigned int nsiov, lnet_kiov_t *siov, unsigned int soffset, - unsigned int nob) -{ - /* NB diov, siov are READ-ONLY */ - unsigned int this_nob; - char *daddr = NULL; - char *saddr = NULL; - - if (!nob) - return; - - LASSERT(!in_interrupt()); - - LASSERT(ndiov > 0); - while (doffset >= diov->kiov_len) { - doffset -= diov->kiov_len; - diov++; - ndiov--; - LASSERT(ndiov > 0); - } - - LASSERT(nsiov > 0); - while (soffset >= siov->kiov_len) { - soffset -= siov->kiov_len; - siov++; - nsiov--; - LASSERT(nsiov > 0); - } - - do { - LASSERT(ndiov > 0); - LASSERT(nsiov > 0); - this_nob = min(diov->kiov_len - doffset, - siov->kiov_len - soffset); - this_nob = min(this_nob, nob); - - if (!daddr) - daddr = ((char *)kmap(diov->kiov_page)) + - diov->kiov_offset + doffset; - if (!saddr) - saddr = ((char *)kmap(siov->kiov_page)) + - siov->kiov_offset + soffset; - - /* - * Vanishing risk of kmap deadlock when mapping 2 pages. - * However in practice at least one of the kiovs will be mapped - * kernel pages and the map/unmap will be NOOPs - */ - memcpy(daddr, saddr, this_nob); - nob -= this_nob; - - if (diov->kiov_len > doffset + this_nob) { - daddr += this_nob; - doffset += this_nob; - } else { - kunmap(diov->kiov_page); - daddr = NULL; - diov++; - ndiov--; - doffset = 0; - } - - if (siov->kiov_len > soffset + this_nob) { - saddr += this_nob; - soffset += this_nob; - } else { - kunmap(siov->kiov_page); - saddr = NULL; - siov++; - nsiov--; - soffset = 0; - } - } while (nob > 0); - - if (daddr) - kunmap(diov->kiov_page); - if (saddr) - kunmap(siov->kiov_page); -} -EXPORT_SYMBOL(lnet_copy_kiov2kiov); - -void -lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, - unsigned int nkiov, lnet_kiov_t *kiov, - unsigned int kiovoffset, unsigned int nob) -{ - /* NB iov, kiov are READ-ONLY */ - unsigned int this_nob; - char *addr = NULL; - - if (!nob) - return; - - LASSERT(!in_interrupt()); - - LASSERT(niov > 0); - while (iovoffset >= iov->iov_len) { - iovoffset -= iov->iov_len; - iov++; - niov--; - LASSERT(niov > 0); - } - - LASSERT(nkiov > 0); - while (kiovoffset >= kiov->kiov_len) { - kiovoffset -= kiov->kiov_len; - kiov++; - nkiov--; - LASSERT(nkiov > 0); - } - - do { - LASSERT(niov > 0); - LASSERT(nkiov > 0); - this_nob = min(iov->iov_len - iovoffset, - (__kernel_size_t)kiov->kiov_len - kiovoffset); - this_nob = min(this_nob, nob); - - if (!addr) - addr = ((char *)kmap(kiov->kiov_page)) + - kiov->kiov_offset + kiovoffset; - - memcpy((char *)iov->iov_base + iovoffset, addr, this_nob); - nob -= this_nob; - - if (iov->iov_len > iovoffset + this_nob) { - iovoffset += this_nob; - } else { - iov++; - niov--; - iovoffset = 0; - } - - if (kiov->kiov_len > kiovoffset + this_nob) { - addr += this_nob; - kiovoffset += this_nob; - } else { - kunmap(kiov->kiov_page); - addr = NULL; - kiov++; - nkiov--; - kiovoffset = 0; - } - - } while (nob > 0); - - if (addr) - kunmap(kiov->kiov_page); -} -EXPORT_SYMBOL(lnet_copy_kiov2iov); - -void -lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, - unsigned int kiovoffset, unsigned int niov, - struct kvec *iov, unsigned int iovoffset, - unsigned int nob) -{ - /* NB kiov, iov are READ-ONLY */ - unsigned int this_nob; - char *addr = NULL; - - if (!nob) - return; - - LASSERT(!in_interrupt()); - - LASSERT(nkiov > 0); - while (kiovoffset >= kiov->kiov_len) { - kiovoffset -= kiov->kiov_len; - kiov++; - nkiov--; - LASSERT(nkiov > 0); - } - - LASSERT(niov > 0); - while (iovoffset >= iov->iov_len) { - iovoffset -= iov->iov_len; - iov++; - niov--; - LASSERT(niov > 0); - } - - do { - LASSERT(nkiov > 0); - LASSERT(niov > 0); - this_nob = min((__kernel_size_t)kiov->kiov_len - kiovoffset, - iov->iov_len - iovoffset); - this_nob = min(this_nob, nob); - - if (!addr) - addr = ((char *)kmap(kiov->kiov_page)) + - kiov->kiov_offset + kiovoffset; - - memcpy(addr, (char *)iov->iov_base + iovoffset, this_nob); - nob -= this_nob; - - if (kiov->kiov_len > kiovoffset + this_nob) { - addr += this_nob; - kiovoffset += this_nob; - } else { - kunmap(kiov->kiov_page); - addr = NULL; - kiov++; - nkiov--; - kiovoffset = 0; - } - - if (iov->iov_len > iovoffset + this_nob) { - iovoffset += this_nob; - } else { - iov++; - niov--; - iovoffset = 0; - } - } while (nob > 0); - - if (addr) - kunmap(kiov->kiov_page); -} -EXPORT_SYMBOL(lnet_copy_iov2kiov); - int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, - int src_niov, lnet_kiov_t *src, + int src_niov, const lnet_kiov_t *src, unsigned int offset, unsigned int len) { /* @@ -526,8 +326,8 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, return 0; /* no frags */ LASSERT(src_niov > 0); - while (offset >= src->kiov_len) { /* skip initial frags */ - offset -= src->kiov_len; + while (offset >= src->bv_len) { /* skip initial frags */ + offset -= src->bv_len; src_niov--; src++; LASSERT(src_niov > 0); @@ -538,19 +338,19 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, LASSERT(src_niov > 0); LASSERT((int)niov <= dst_niov); - frag_len = src->kiov_len - offset; - dst->kiov_page = src->kiov_page; - dst->kiov_offset = src->kiov_offset + offset; + frag_len = src->bv_len - offset; + dst->bv_page = src->bv_page; + dst->bv_offset = src->bv_offset + offset; if (len <= frag_len) { - dst->kiov_len = len; - LASSERT(dst->kiov_offset + dst->kiov_len + dst->bv_len = len; + LASSERT(dst->bv_offset + dst->bv_len <= PAGE_SIZE); return niov; } - dst->kiov_len = frag_len; - LASSERT(dst->kiov_offset + dst->kiov_len <= PAGE_SIZE); + dst->bv_len = frag_len; + LASSERT(dst->bv_offset + dst->bv_len <= PAGE_SIZE); len -= frag_len; dst++; @@ -569,6 +369,7 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, unsigned int niov = 0; struct kvec *iov = NULL; lnet_kiov_t *kiov = NULL; + struct iov_iter to; int rc; LASSERT(!in_interrupt()); @@ -594,8 +395,14 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, } } - rc = ni->ni_lnd->lnd_recv(ni, private, msg, delayed, - niov, iov, kiov, offset, mlen, rlen); + if (iov) { + iov_iter_kvec(&to, ITER_KVEC | READ, iov, niov, mlen + offset); + iov_iter_advance(&to, offset); + } else { + iov_iter_bvec(&to, ITER_BVEC | READ, kiov, niov, mlen + offset); + iov_iter_advance(&to, offset); + } + rc = ni->ni_lnd->lnd_recv(ni, private, msg, delayed, &to, rlen); if (rc < 0) lnet_finalize(ni, msg, rc); } @@ -2002,6 +1809,9 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), lnet_msgtyp2str(type), rc); lnet_msg_free(msg); + if (rc == -ESHUTDOWN) + /* We are shutting down. Don't do anything more */ + return 0; goto drop; } @@ -2512,6 +2322,15 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) } if (LNET_NIDNET(ni->ni_nid) == dstnet) { + /* + * Check if ni was originally created in + * current net namespace. + * If not, assign order above 0xffff0000, + * to make this ni not a priority. + */ + if (!net_eq(ni->ni_net_ns, current->nsproxy->net_ns)) + order += 0xffff0000; + if (srcnidp) *srcnidp = ni->ni_nid; if (orderp) diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 910e106e221d..0897e588bd54 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -449,23 +449,7 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) if (!msg) return; -#if 0 - CDEBUG(D_WARNING, "%s msg->%s Flags:%s%s%s%s%s%s%s%s%s%s%s txp %s rxp %s\n", - lnet_msgtyp2str(msg->msg_type), libcfs_id2str(msg->msg_target), - msg->msg_target_is_router ? "t" : "", - msg->msg_routing ? "X" : "", - msg->msg_ack ? "A" : "", - msg->msg_sending ? "S" : "", - msg->msg_receiving ? "R" : "", - msg->msg_delayed ? "d" : "", - msg->msg_txcredit ? "C" : "", - msg->msg_peertxcredit ? "c" : "", - msg->msg_rtrcredit ? "F" : "", - msg->msg_peerrtrcredit ? "f" : "", - msg->msg_onactivelist ? "!" : "", - !msg->msg_txpeer ? "" : libcfs_nid2str(msg->msg_txpeer->lp_nid), - !msg->msg_rxpeer ? "" : libcfs_nid2str(msg->msg_rxpeer->lp_nid)); -#endif + msg->msg_ev.status = status; if (msg->msg_md) { diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index 891fd59401d7..4e6dd5149b4f 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c @@ -265,21 +265,17 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) long jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC); unsigned long then; struct timeval tv; + struct kvec iov = { .iov_base = buffer, .iov_len = nob }; + struct msghdr msg = {NULL,}; LASSERT(nob > 0); /* * Caller may pass a zero timeout if she thinks the socket buffer is * empty enough to take the whole message immediately */ + iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1, nob); for (;;) { - struct kvec iov = { - .iov_base = buffer, - .iov_len = nob - }; - struct msghdr msg = { - .msg_flags = !timeout ? MSG_DONTWAIT : 0 - }; - + msg.msg_flags = !timeout ? MSG_DONTWAIT : 0; if (timeout) { /* Set send timeout to remaining time */ jiffies_to_timeval(jiffies_left, &tv); @@ -296,9 +292,6 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) rc = kernel_sendmsg(sock, &msg, &iov, 1, nob); jiffies_left -= jiffies - then; - if (rc == nob) - return 0; - if (rc < 0) return rc; @@ -307,11 +300,11 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) return -ECONNABORTED; } + if (!msg_data_left(&msg)) + break; + if (jiffies_left <= 0) return -EAGAIN; - - buffer = ((char *)buffer) + rc; - nob -= rc; } return 0; } diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 08402712a452..cb213b8f51cf 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -42,36 +42,23 @@ lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) static int lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, - int delayed, unsigned int niov, - struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + int delayed, struct iov_iter *to, unsigned int rlen) { lnet_msg_t *sendmsg = private; if (lntmsg) { /* not discarding */ - if (sendmsg->msg_iov) { - if (iov) - lnet_copy_iov2iov(niov, iov, offset, - sendmsg->msg_niov, - sendmsg->msg_iov, - sendmsg->msg_offset, mlen); - else - lnet_copy_iov2kiov(niov, kiov, offset, - sendmsg->msg_niov, - sendmsg->msg_iov, - sendmsg->msg_offset, mlen); - } else { - if (iov) - lnet_copy_kiov2iov(niov, iov, offset, - sendmsg->msg_niov, - sendmsg->msg_kiov, - sendmsg->msg_offset, mlen); - else - lnet_copy_kiov2kiov(niov, kiov, offset, - sendmsg->msg_niov, - sendmsg->msg_kiov, - sendmsg->msg_offset, mlen); - } + if (sendmsg->msg_iov) + lnet_copy_iov2iter(to, + sendmsg->msg_niov, + sendmsg->msg_iov, + sendmsg->msg_offset, + iov_iter_count(to)); + else + lnet_copy_kiov2iter(to, + sendmsg->msg_niov, + sendmsg->msg_kiov, + sendmsg->msg_offset, + iov_iter_count(to)); lnet_finalize(ni, lntmsg, 0); } diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 063543233035..063ad55ec950 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -1307,7 +1307,7 @@ lnet_destroy_rtrbuf(lnet_rtrbuf_t *rb, int npages) int sz = offsetof(lnet_rtrbuf_t, rb_kiov[npages]); while (--npages >= 0) - __free_page(rb->rb_kiov[npages].kiov_page); + __free_page(rb->rb_kiov[npages].bv_page); LIBCFS_FREE(rb, sz); } @@ -1333,15 +1333,15 @@ lnet_new_rtrbuf(lnet_rtrbufpool_t *rbp, int cpt) GFP_KERNEL | __GFP_ZERO, 0); if (!page) { while (--i >= 0) - __free_page(rb->rb_kiov[i].kiov_page); + __free_page(rb->rb_kiov[i].bv_page); LIBCFS_FREE(rb, sz); return NULL; } - rb->rb_kiov[i].kiov_len = PAGE_SIZE; - rb->rb_kiov[i].kiov_offset = 0; - rb->rb_kiov[i].kiov_page = page; + rb->rb_kiov[i].bv_len = PAGE_SIZE; + rb->rb_kiov[i].bv_offset = 0; + rb->rb_kiov[i].bv_page = page; } return rb; @@ -1693,7 +1693,7 @@ lnet_rtrpools_adjust(int tiny, int small, int large) int lnet_rtrpools_enable(void) { - int rc; + int rc = 0; if (the_lnet.ln_routing) return 0; @@ -1706,9 +1706,9 @@ lnet_rtrpools_enable(void) * if we are just configuring this for the first * time. */ - return lnet_rtrpools_alloc(1); - - rc = lnet_rtrpools_adjust_helper(0, 0, 0); + rc = lnet_rtrpools_alloc(1); + else + rc = lnet_rtrpools_adjust_helper(0, 0, 0); if (rc) return rc; @@ -1718,7 +1718,7 @@ lnet_rtrpools_enable(void) the_lnet.ln_ping_info->pi_features &= ~LNET_PING_FEAT_RTE_DISABLED; lnet_net_unlock(LNET_LOCK_EX); - return 0; + return rc; } void diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 13d0454e7fcb..b20c5d394e3b 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -226,7 +226,7 @@ brw_fill_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) struct page *pg; for (i = 0; i < bk->bk_niov; i++) { - pg = bk->bk_iovs[i].kiov_page; + pg = bk->bk_iovs[i].bv_page; brw_fill_page(pg, pattern, magic); } } @@ -238,7 +238,7 @@ brw_check_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) struct page *pg; for (i = 0; i < bk->bk_niov; i++) { - pg = bk->bk_iovs[i].kiov_page; + pg = bk->bk_iovs[i].bv_page; if (brw_check_page(pg, pattern, magic)) { CERROR("Bulk page %p (%d/%d) is corrupted!\n", pg, i, bk->bk_niov); diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 1be3cad727ae..55afb53b0743 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -152,10 +152,10 @@ lstcon_rpc_put(struct lstcon_rpc *crpc) LASSERT(list_empty(&crpc->crp_link)); for (i = 0; i < bulk->bk_niov; i++) { - if (!bulk->bk_iovs[i].kiov_page) + if (!bulk->bk_iovs[i].bv_page) continue; - __free_page(bulk->bk_iovs[i].kiov_page); + __free_page(bulk->bk_iovs[i].bv_page); } srpc_client_rpc_decref(crpc->crp_rpc); @@ -705,7 +705,7 @@ lstcon_next_id(int idx, int nkiov, lnet_kiov_t *kiov) LASSERT(i < nkiov); - pid = (lnet_process_id_packed_t *)page_address(kiov[i].kiov_page); + pid = (lnet_process_id_packed_t *)page_address(kiov[i].bv_page); return &pid[idx % SFW_ID_PER_PAGE]; } @@ -849,12 +849,11 @@ lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, min_t(int, nob, PAGE_SIZE); nob -= len; - bulk->bk_iovs[i].kiov_offset = 0; - bulk->bk_iovs[i].kiov_len = len; - bulk->bk_iovs[i].kiov_page = - alloc_page(GFP_KERNEL); + bulk->bk_iovs[i].bv_offset = 0; + bulk->bk_iovs[i].bv_len = len; + bulk->bk_iovs[i].bv_page = alloc_page(GFP_KERNEL); - if (!bulk->bk_iovs[i].kiov_page) { + if (!bulk->bk_iovs[i].bv_page) { lstcon_rpc_put(*crpc); return -ENOMEM; } diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 4c33621f06da..a0fcbf3bcc95 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1993,8 +1993,6 @@ static void lstcon_init_acceptor_service(void) lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX; } -extern int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr); - static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry); /* initialize console */ diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index 78b147732615..78388a611c22 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -184,6 +184,7 @@ lstcon_id2hash(lnet_process_id_t id, struct list_head *hash) return &hash[idx]; } +int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr); int lstcon_console_init(void); int lstcon_console_fini(void); int lstcon_session_match(lst_sid_t sid); diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index c2f121f44d33..abbd6287b4bd 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -784,8 +784,8 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) lnet_process_id_packed_t id; int j; - dests = page_address(bk->bk_iovs[i / SFW_ID_PER_PAGE].kiov_page); - LASSERT(dests); /* my pages are within KVM always */ + dests = page_address(bk->bk_iovs[i / SFW_ID_PER_PAGE].bv_page); + LASSERT(dests); /* my pages are within KVM always */ id = dests[i % SFW_ID_PER_PAGE]; if (msg->msg_magic != SRPC_MSG_MAGIC) sfw_unpack_id(id); diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 3b26d6eb4240..f5619d8744ef 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -91,9 +91,9 @@ srpc_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i, int nob) LASSERT(nob > 0); LASSERT(i >= 0 && i < bk->bk_niov); - bk->bk_iovs[i].kiov_offset = 0; - bk->bk_iovs[i].kiov_page = pg; - bk->bk_iovs[i].kiov_len = nob; + bk->bk_iovs[i].bv_offset = 0; + bk->bk_iovs[i].bv_page = pg; + bk->bk_iovs[i].bv_len = nob; return nob; } @@ -106,7 +106,7 @@ srpc_free_bulk(struct srpc_bulk *bk) LASSERT(bk); for (i = 0; i < bk->bk_niov; i++) { - pg = bk->bk_iovs[i].kiov_page; + pg = bk->bk_iovs[i].bv_page; if (!pg) break; diff --git a/drivers/staging/lustre/lustre/fid/fid_lib.c b/drivers/staging/lustre/lustre/fid/fid_lib.c index 99ae7eb6720e..4e49cb356d64 100644 --- a/drivers/staging/lustre/lustre/fid/fid_lib.c +++ b/drivers/staging/lustre/lustre/fid/fid_lib.c @@ -63,14 +63,12 @@ const struct lu_seq_range LUSTRE_SEQ_SPACE_RANGE = { FID_SEQ_NORMAL, (__u64)~0ULL }; -EXPORT_SYMBOL(LUSTRE_SEQ_SPACE_RANGE); /* Zero range, used for init and other purposes. */ const struct lu_seq_range LUSTRE_SEQ_ZERO_RANGE = { 0, 0 }; -EXPORT_SYMBOL(LUSTRE_SEQ_ZERO_RANGE); /* Lustre Big Fs Lock fid. */ const struct lu_fid LUSTRE_BFL_FID = { .f_seq = FID_SEQ_SPECIAL, diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c index 454744d25956..edd72b926f81 100644 --- a/drivers/staging/lustre/lustre/fid/fid_request.c +++ b/drivers/staging/lustre/lustre/fid/fid_request.c @@ -125,19 +125,19 @@ static int seq_client_rpc(struct lu_client_seq *seq, if (!range_is_sane(output)) { CERROR("%s: Invalid range received from server: " - DRANGE"\n", seq->lcs_name, PRANGE(output)); + DRANGE "\n", seq->lcs_name, PRANGE(output)); rc = -EINVAL; goto out_req; } if (range_is_exhausted(output)) { CERROR("%s: Range received from server is exhausted: " - DRANGE"]\n", seq->lcs_name, PRANGE(output)); + DRANGE "]\n", seq->lcs_name, PRANGE(output)); rc = -EINVAL; goto out_req; } - CDEBUG_LIMIT(debug_mask, "%s: Allocated %s-sequence "DRANGE"]\n", + CDEBUG_LIMIT(debug_mask, "%s: Allocated %s-sequence " DRANGE "]\n", seq->lcs_name, opcname, PRANGE(output)); out_req: @@ -179,7 +179,7 @@ static int seq_client_alloc_seq(const struct lu_env *env, seq->lcs_name, rc); return rc; } - CDEBUG(D_INFO, "%s: New range - "DRANGE"\n", + CDEBUG(D_INFO, "%s: New range - " DRANGE "\n", seq->lcs_name, PRANGE(&seq->lcs_space)); } else { rc = 0; diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c index 81b7ca9ea2fd..3ed32d77f38b 100644 --- a/drivers/staging/lustre/lustre/fid/lproc_fid.c +++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c @@ -105,7 +105,7 @@ ldebugfs_fid_space_seq_write(struct file *file, rc = ldebugfs_fid_write_common(buffer, count, &seq->lcs_space); if (rc == 0) { - CDEBUG(D_INFO, "%s: Space: "DRANGE"\n", + CDEBUG(D_INFO, "%s: Space: " DRANGE "\n", seq->lcs_name, PRANGE(&seq->lcs_space)); } diff --git a/drivers/staging/lustre/lustre/fld/fld_internal.h b/drivers/staging/lustre/lustre/fld/fld_internal.h index f0efe5b9fbec..08eaec735d6f 100644 --- a/drivers/staging/lustre/lustre/fld/fld_internal.h +++ b/drivers/staging/lustre/lustre/fld/fld_internal.h @@ -31,6 +31,25 @@ * * lustre/fld/fld_internal.h * + * Subsystem Description: + * FLD is FID Location Database, which stores where (IE, on which MDT) + * FIDs are located. + * The database is basically a record file, each record consists of a FID + * sequence range, MDT/OST index, and flags. The FLD for the whole FS + * is only stored on the sequence controller(MDT0) right now, but each target + * also has its local FLD, which only stores the local sequence. + * + * The FLD subsystem usually has two tasks: + * 1. maintain the database, i.e. when the sequence controller allocates + * new sequence ranges to some nodes, it will call the FLD API to insert the + * location information in FLDB. + * + * 2. Handle requests from other nodes, i.e. if client needs to know where + * the FID is located, if it can not find the information in the local cache, + * it will send a FLD lookup RPC to the FLD service, and the FLD service will + * look up the FLDB entry and return the location information to client. + * + * * Author: Yury Umanets * Author: Tom WangDi */ diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index e59d626a1548..0de72b717ce5 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -53,57 +53,6 @@ #include "../include/lustre_mdc.h" #include "fld_internal.h" -/* TODO: these 3 functions are copies of flow-control code from mdc_lib.c - * It should be common thing. The same about mdc RPC lock - */ -static int fld_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) -{ - int rc; - - spin_lock(&cli->cl_loi_list_lock); - rc = list_empty(&mcw->mcw_entry); - spin_unlock(&cli->cl_loi_list_lock); - return rc; -}; - -static void fld_enter_request(struct client_obd *cli) -{ - struct mdc_cache_waiter mcw; - struct l_wait_info lwi = { 0 }; - - spin_lock(&cli->cl_loi_list_lock); - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { - list_add_tail(&mcw.mcw_entry, &cli->cl_cache_waiters); - init_waitqueue_head(&mcw.mcw_waitq); - spin_unlock(&cli->cl_loi_list_lock); - l_wait_event(mcw.mcw_waitq, fld_req_avail(cli, &mcw), &lwi); - } else { - cli->cl_r_in_flight++; - spin_unlock(&cli->cl_loi_list_lock); - } -} - -static void fld_exit_request(struct client_obd *cli) -{ - struct list_head *l, *tmp; - struct mdc_cache_waiter *mcw; - - spin_lock(&cli->cl_loi_list_lock); - cli->cl_r_in_flight--; - list_for_each_safe(l, tmp, &cli->cl_cache_waiters) { - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { - /* No free request slots anymore */ - break; - } - - mcw = list_entry(l, struct mdc_cache_waiter, mcw_entry); - list_del_init(&mcw->mcw_entry); - cli->cl_r_in_flight++; - wake_up(&mcw->mcw_waitq); - } - spin_unlock(&cli->cl_loi_list_lock); -} - static int fld_rrb_hash(struct lu_client_fld *fld, u64 seq) { LASSERT(fld->lcf_count > 0); @@ -270,7 +219,6 @@ int fld_client_del_target(struct lu_client_fld *fld, __u64 idx) spin_unlock(&fld->lcf_lock); return -ENOENT; } -EXPORT_SYMBOL(fld_client_del_target); static struct dentry *fld_debugfs_dir; @@ -439,9 +387,9 @@ int fld_client_rpc(struct obd_export *exp, req->rq_reply_portal = MDC_REPLY_PORTAL; ptlrpc_at_set_req_timeout(req); - fld_enter_request(&exp->exp_obd->u.cli); + obd_get_request_slot(&exp->exp_obd->u.cli); rc = ptlrpc_queue_wait(req); - fld_exit_request(&exp->exp_obd->u.cli); + obd_put_request_slot(&exp->exp_obd->u.cli); if (rc) goto out_req; @@ -505,7 +453,6 @@ void fld_client_flush(struct lu_client_fld *fld) { fld_cache_flush(fld->lcf_cache); } -EXPORT_SYMBOL(fld_client_flush); static int __init fld_init(void) { diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 3cd4a2577d90..89292c93dcd5 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -93,8 +93,8 @@ * super-class definitions. */ #include "lu_object.h" +#include "lustre_compat.h" #include -#include "linux/lustre_compat25.h" #include #include #include @@ -191,6 +191,9 @@ struct cl_attr { * Group identifier for quota purposes. */ gid_t cat_gid; + + /* nlink of the directory */ + __u64 cat_nlink; }; /** @@ -320,7 +323,7 @@ struct cl_object_operations { * to be used instead of newly created. */ int (*coo_page_init)(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, pgoff_t index); + struct cl_page *page, pgoff_t index); /** * Initialize lock slice for this layer. Called top-to-bottom through * every object layer when a new cl_lock is instantiated. Layer @@ -366,8 +369,8 @@ struct cl_object_operations { * \return the same convention as for * cl_object_operations::coo_attr_get() is used. */ - int (*coo_attr_set)(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid); + int (*coo_attr_update)(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid); /** * Update object configuration. Called top-to-bottom to modify object * configuration. @@ -392,6 +395,11 @@ struct cl_object_operations { * mainly pages and locks. */ int (*coo_prune)(const struct lu_env *env, struct cl_object *obj); + /** + * Object getstripe method. + */ + int (*coo_getstripe)(const struct lu_env *env, struct cl_object *obj, + struct lov_user_md __user *lum); }; /** @@ -686,17 +694,6 @@ enum cl_page_type { CPT_TRANSIENT, }; -/** - * Flags maintained for every cl_page. - */ -enum cl_page_flags { - /** - * Set when pagein completes. Used for debugging (read completes at - * most once for a page). - */ - CPF_READ_COMPLETED = 1 << 0 -}; - /** * Fields are protected by the lock on struct page, except for atomics and * immutables. @@ -711,24 +708,19 @@ struct cl_page { atomic_t cp_ref; /** An object this page is a part of. Immutable after creation. */ struct cl_object *cp_obj; - /** List of slices. Immutable after creation. */ - struct list_head cp_layers; /** vmpage */ struct page *cp_vmpage; + /** Linkage of pages within group. Pages must be owned */ + struct list_head cp_batch; + /** List of slices. Immutable after creation. */ + struct list_head cp_layers; + /** Linkage of pages within cl_req. */ + struct list_head cp_flight; /** * Page state. This field is const to avoid accidental update, it is * modified only internally within cl_page.c. Protected by a VM lock. */ const enum cl_page_state cp_state; - /** Linkage of pages within group. Protected by cl_page::cp_mutex. */ - struct list_head cp_batch; - /** Mutex serializing membership of a page in a batch. */ - struct mutex cp_mutex; - /** Linkage of pages within cl_req. */ - struct list_head cp_flight; - /** Transfer error. */ - int cp_error; - /** * Page type. Only CPT_TRANSIENT is used so far. Immutable after * creation. @@ -740,10 +732,6 @@ struct cl_page { * by sub-io. Protected by a VM lock. */ struct cl_io *cp_owner; - /** - * Debug information, the task is owning the page. - */ - struct task_struct *cp_task; /** * Owning IO request in cl_page_state::CPS_PAGEOUT and * cl_page_state::CPS_PAGEIN states. This field is maintained only in @@ -756,8 +744,6 @@ struct cl_page { struct lu_ref_link cp_obj_ref; /** Link to a queue, for debugging. */ struct lu_ref_link cp_queue_ref; - /** Per-page flags from enum cl_page_flags. Protected by a VM lock. */ - unsigned cp_flags; /** Assigned if doing a sync_io */ struct cl_sync_io *cp_sync_io; }; @@ -1056,23 +1042,32 @@ do { \ } \ } while (0) -static inline int __page_in_use(const struct cl_page *page, int refc) -{ - if (page->cp_type == CPT_CACHEABLE) - ++refc; - LASSERT(atomic_read(&page->cp_ref) > 0); - return (atomic_read(&page->cp_ref) > refc); -} - -#define cl_page_in_use(pg) __page_in_use(pg, 1) -#define cl_page_in_use_noref(pg) __page_in_use(pg, 0) - static inline struct page *cl_page_vmpage(struct cl_page *page) { LASSERT(page->cp_vmpage); return page->cp_vmpage; } +/** + * Check if a cl_page is in use. + * + * Client cache holds a refcount, this refcount will be dropped when + * the page is taken out of cache, see vvp_page_delete(). + */ +static inline bool __page_in_use(const struct cl_page *page, int refc) +{ + return (atomic_read(&page->cp_ref) > refc + 1); +} + +/** + * Caller itself holds a refcount of cl_page. + */ +#define cl_page_in_use(pg) __page_in_use(pg, 1) +/** + * Caller doesn't hold a refcount. + */ +#define cl_page_in_use_noref(pg) __page_in_use(pg, 0) + /** @} cl_page */ /** \addtogroup cl_lock cl_lock @@ -1771,12 +1766,14 @@ struct cl_io { struct cl_setattr_io { struct ost_lvb sa_attr; unsigned int sa_valid; + int sa_stripe_index; + struct lu_fid *sa_parent_fid; } ci_setattr; struct cl_fault_io { /** page index within file. */ pgoff_t ft_index; /** bytes valid byte on a faulted page. */ - int ft_nob; + size_t ft_nob; /** writable page? for nopage() only */ int ft_writable; /** page of an executable? */ @@ -1909,7 +1906,7 @@ struct cl_req_attr { /** Generic attributes for the server consumption. */ struct obdo *cra_oa; /** Jobid */ - char cra_jobid[JOBSTATS_JOBID_SIZE]; + char cra_jobid[LUSTRE_JOBID_SIZE]; }; /** @@ -2176,14 +2173,16 @@ void cl_object_attr_lock(struct cl_object *o); void cl_object_attr_unlock(struct cl_object *o); int cl_object_attr_get(const struct lu_env *env, struct cl_object *obj, struct cl_attr *attr); -int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid); +int cl_object_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid); int cl_object_glimpse(const struct lu_env *env, struct cl_object *obj, struct ost_lvb *lvb); int cl_conf_set(const struct lu_env *env, struct cl_object *obj, const struct cl_object_conf *conf); int cl_object_prune(const struct lu_env *env, struct cl_object *obj); void cl_object_kill(const struct lu_env *env, struct cl_object *obj); +int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, + struct lov_user_md __user *lum); /** * Returns true, iff \a o0 and \a o1 are slices of the same object. @@ -2197,6 +2196,7 @@ static inline void cl_object_page_init(struct cl_object *clob, int size) { clob->co_slice_off = cl_object_header(clob)->coh_page_bufsize; cl_object_header(clob)->coh_page_bufsize += cfs_size_round(size); + WARN_ON(cl_object_header(clob)->coh_page_bufsize > 512); } static inline void *cl_object_page_slice(struct cl_object *clob, @@ -2263,6 +2263,8 @@ void cl_page_unassume(const struct lu_env *env, struct cl_io *io, struct cl_page *pg); void cl_page_disown(const struct lu_env *env, struct cl_io *io, struct cl_page *page); +void cl_page_disown0(const struct lu_env *env, + struct cl_io *io, struct cl_page *pg); int cl_page_is_owned(const struct cl_page *pg, const struct cl_io *io); /** @} ownership */ @@ -2304,7 +2306,7 @@ int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, struct cl_page *page, pgoff_t *max_index); loff_t cl_offset(const struct cl_object *obj, pgoff_t idx); pgoff_t cl_index(const struct cl_object *obj, loff_t offset); -int cl_page_size(const struct cl_object *obj); +size_t cl_page_size(const struct cl_object *obj); int cl_pages_prune(const struct lu_env *env, struct cl_object *obj); void cl_lock_print(const struct lu_env *env, void *cookie, @@ -2333,7 +2335,7 @@ struct cl_client_cache { /** * # of LRU entries available */ - atomic_t ccc_lru_left; + atomic_long_t ccc_lru_left; /** * List of entities(OSCs) for this LRU cache */ @@ -2346,15 +2348,19 @@ struct cl_client_cache { * Lock to protect ccc_lru list */ spinlock_t ccc_lru_lock; + /** + * Set if unstable check is enabled + */ + unsigned int ccc_unstable_check:1; /** * # of unstable pages for this mount point */ - atomic_t ccc_unstable_nr; + atomic_long_t ccc_unstable_nr; /** * Waitq for awaiting unstable pages to reach zero. * Used at umounting time and signaled on BRW commit */ - wait_queue_head_t ccc_unstable_waitq; + wait_queue_head_t ccc_unstable_waitq; }; diff --git a/drivers/staging/lustre/lustre/include/interval_tree.h b/drivers/staging/lustre/lustre/include/interval_tree.h index 4a15228b5570..5d387d372547 100644 --- a/drivers/staging/lustre/lustre/include/interval_tree.h +++ b/drivers/staging/lustre/lustre/include/interval_tree.h @@ -63,6 +63,11 @@ static inline int interval_is_intree(struct interval_node *node) return node->in_intree == 1; } +static inline __u64 interval_low(struct interval_node *node) +{ + return node->in_extent.start; +} + static inline __u64 interval_high(struct interval_node *node) { return node->in_extent.end; @@ -77,8 +82,29 @@ static inline void interval_set(struct interval_node *node, node->in_max_high = end; } +/* + * Rules to write an interval callback. + * - the callback returns INTERVAL_ITER_STOP when it thinks the iteration + * should be stopped. It will then cause the iteration function to return + * immediately with return value INTERVAL_ITER_STOP. + * - callbacks for interval_iterate and interval_iterate_reverse: Every + * nodes in the tree will be set to @node before the callback being called + * - callback for interval_search: Only overlapped node will be set to @node + * before the callback being called. + */ +typedef enum interval_iter (*interval_callback_t)(struct interval_node *node, + void *args); + struct interval_node *interval_insert(struct interval_node *node, struct interval_node **root); void interval_erase(struct interval_node *node, struct interval_node **root); +/* + * Search the extents in the tree and call @func for each overlapped + * extents. + */ +enum interval_iter interval_search(struct interval_node *root, + struct interval_node_extent *ex, + interval_callback_t func, void *data); + #endif diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h b/drivers/staging/lustre/lustre/include/linux/lustre_lite.h deleted file mode 100644 index d18e8a76bb25..000000000000 --- a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef _LINUX_LL_H -#define _LINUX_LL_H - -#ifndef _LL_H -#error Do not #include this file directly. #include instead -#endif - -#include - -#include -#include - -#include "../obd_class.h" -#include "../lustre_net.h" -#include "../lustre_ha.h" - -#include -#include "../../include/linux/lustre_compat25.h" -#include - -/* lprocfs.c */ -enum { - LPROC_LL_DIRTY_HITS = 0, - LPROC_LL_DIRTY_MISSES, - LPROC_LL_READ_BYTES, - LPROC_LL_WRITE_BYTES, - LPROC_LL_BRW_READ, - LPROC_LL_BRW_WRITE, - LPROC_LL_OSC_READ, - LPROC_LL_OSC_WRITE, - LPROC_LL_IOCTL, - LPROC_LL_OPEN, - LPROC_LL_RELEASE, - LPROC_LL_MAP, - LPROC_LL_LLSEEK, - LPROC_LL_FSYNC, - LPROC_LL_READDIR, - LPROC_LL_SETATTR, - LPROC_LL_TRUNC, - LPROC_LL_FLOCK, - LPROC_LL_GETATTR, - LPROC_LL_CREATE, - LPROC_LL_LINK, - LPROC_LL_UNLINK, - LPROC_LL_SYMLINK, - LPROC_LL_MKDIR, - LPROC_LL_RMDIR, - LPROC_LL_MKNOD, - LPROC_LL_RENAME, - LPROC_LL_STAFS, - LPROC_LL_ALLOC_INODE, - LPROC_LL_SETXATTR, - LPROC_LL_GETXATTR, - LPROC_LL_GETXATTR_HITS, - LPROC_LL_LISTXATTR, - LPROC_LL_REMOVEXATTR, - LPROC_LL_INODE_PERM, - LPROC_LL_FILE_OPCODES -}; - -#endif diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_user.h b/drivers/staging/lustre/lustre/include/linux/lustre_user.h deleted file mode 100644 index e967950e8536..000000000000 --- a/drivers/staging/lustre/lustre/include/linux/lustre_user.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/include/linux/lustre_user.h - * - * Lustre public user-space interface definitions. - */ - -#ifndef _LINUX_LUSTRE_USER_H -#define _LINUX_LUSTRE_USER_H - -# include - -/* - * asm-x86_64/processor.h on some SLES 9 distros seems to use - * kernel-only typedefs. fortunately skipping it altogether is ok - * (for now). - */ -#define __ASM_X86_64_PROCESSOR_H - -#include - -/* - * We need to always use 64bit version because the structure - * is shared across entire cluster where 32bit and 64bit machines - * are co-existing. - */ -#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64) -typedef struct stat64 lstat_t; -#define lstat_f lstat64 -#else -typedef struct stat lstat_t; -#define lstat_f lstat -#endif - -#define HAVE_LOV_USER_MDS_DATA - -#endif /* _LUSTRE_USER_H */ diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index d68e60e7fef7..cc0713ef8ae5 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -165,8 +165,10 @@ struct lprocfs_percpu { struct lprocfs_counter lp_cntr[0]; }; -#define LPROCFS_GET_NUM_CPU 0x0001 -#define LPROCFS_GET_SMP_ID 0x0002 +enum lprocfs_stats_lock_ops { + LPROCFS_GET_NUM_CPU = 0x0001, /* number allocated per-CPU stats */ + LPROCFS_GET_SMP_ID = 0x0002, /* current stat to be updated */ +}; enum lprocfs_stats_flags { LPROCFS_STATS_FLAG_NONE = 0x0000, /* per cpu counter */ @@ -363,82 +365,99 @@ static inline void s2dhms(struct dhms *ts, time64_t secs64) #define JOBSTATS_PROCNAME_UID "procname_uid" #define JOBSTATS_NODELOCAL "nodelocal" +/* obd_config.c */ +void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg)); + int lprocfs_write_frac_helper(const char __user *buffer, unsigned long count, int *val, int mult); int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult); int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid); -/* - * \return value - * < 0 : on error (only possible for opc as LPROCFS_GET_SMP_ID) + +/** + * Lock statistics structure for access, possibly only on this CPU. + * + * The statistics struct may be allocated with per-CPU structures for + * efficient concurrent update (usually only on server-wide stats), or + * as a single global struct (e.g. for per-client or per-job statistics), + * so the required locking depends on the type of structure allocated. + * + * For per-CPU statistics, pin the thread to the current cpuid so that + * will only access the statistics for that CPU. If the stats structure + * for the current CPU has not been allocated (or previously freed), + * allocate it now. The per-CPU statistics do not need locking since + * the thread is pinned to the CPU during update. + * + * For global statistics, lock the stats structure to prevent concurrent update. + * + * \param[in] stats statistics structure to lock + * \param[in] opc type of operation: + * LPROCFS_GET_SMP_ID: "lock" and return current CPU index + * for incrementing statistics for that CPU + * LPROCFS_GET_NUM_CPU: "lock" and return number of used + * CPU indices to iterate over all indices + * \param[out] flags CPU interrupt saved state for IRQ-safe locking + * + * \retval cpuid of current thread or number of allocated structs + * \retval negative on error (only for opc LPROCFS_GET_SMP_ID + per-CPU stats) */ -static inline int lprocfs_stats_lock(struct lprocfs_stats *stats, int opc, +static inline int lprocfs_stats_lock(struct lprocfs_stats *stats, + enum lprocfs_stats_lock_ops opc, unsigned long *flags) { - int rc = 0; + if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { + if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) + spin_lock_irqsave(&stats->ls_lock, *flags); + else + spin_lock(&stats->ls_lock); + return opc == LPROCFS_GET_NUM_CPU ? 1 : 0; + } switch (opc) { + case LPROCFS_GET_SMP_ID: { + unsigned int cpuid = get_cpu(); + + if (unlikely(!stats->ls_percpu[cpuid])) { + int rc = lprocfs_stats_alloc_one(stats, cpuid); + + if (rc < 0) { + put_cpu(); + return rc; + } + } + return cpuid; + } + case LPROCFS_GET_NUM_CPU: + return stats->ls_biggest_alloc_num; default: LBUG(); - - case LPROCFS_GET_SMP_ID: - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { - if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) - spin_lock_irqsave(&stats->ls_lock, *flags); - else - spin_lock(&stats->ls_lock); - return 0; - } else { - unsigned int cpuid = get_cpu(); - - if (unlikely(!stats->ls_percpu[cpuid])) { - rc = lprocfs_stats_alloc_one(stats, cpuid); - if (rc < 0) { - put_cpu(); - return rc; - } - } - return cpuid; - } - - case LPROCFS_GET_NUM_CPU: - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { - if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) - spin_lock_irqsave(&stats->ls_lock, *flags); - else - spin_lock(&stats->ls_lock); - return 1; - } - return stats->ls_biggest_alloc_num; } } -static inline void lprocfs_stats_unlock(struct lprocfs_stats *stats, int opc, +/** + * Unlock statistics structure after access. + * + * Unlock the lock acquired via lprocfs_stats_lock() for global statistics, + * or unpin this thread from the current cpuid for per-CPU statistics. + * + * This function must be called using the same arguments as used when calling + * lprocfs_stats_lock() so that the correct operation can be performed. + * + * \param[in] stats statistics structure to unlock + * \param[in] opc type of operation (current cpuid or number of structs) + * \param[in] flags CPU interrupt saved state for IRQ-safe locking + */ +static inline void lprocfs_stats_unlock(struct lprocfs_stats *stats, + enum lprocfs_stats_lock_ops opc, unsigned long *flags) { - switch (opc) { - default: - LBUG(); - - case LPROCFS_GET_SMP_ID: - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { - if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) - spin_unlock_irqrestore(&stats->ls_lock, *flags); - else - spin_unlock(&stats->ls_lock); - } else { - put_cpu(); - } - return; - - case LPROCFS_GET_NUM_CPU: - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { - if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) - spin_unlock_irqrestore(&stats->ls_lock, *flags); - else - spin_unlock(&stats->ls_lock); - } - return; + if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { + if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) + spin_unlock_irqrestore(&stats->ls_lock, *flags); + else + spin_unlock(&stats->ls_lock); + } else if (opc == LPROCFS_GET_SMP_ID) { + put_cpu(); } } @@ -496,7 +515,7 @@ static inline __u64 lprocfs_stats_collector(struct lprocfs_stats *stats, int idx, enum lprocfs_fields_flags field) { - int i; + unsigned int i; unsigned int num_cpu; unsigned long flags = 0; __u64 ret = 0; @@ -681,6 +700,12 @@ static struct lustre_attr lustre_attr_##name = __ATTR(name, mode, show, store) extern const struct sysfs_ops lustre_sysfs_ops; +struct root_squash_info; +int lprocfs_wr_root_squash(const char *buffer, unsigned long count, + struct root_squash_info *squash, char *name); +int lprocfs_wr_nosquash_nids(const char *buffer, unsigned long count, + struct root_squash_info *squash, char *name); + /* all quota proc functions */ int lprocfs_quota_rd_bunit(char *page, char **start, loff_t off, int count, diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 6e25c1bb6aa3..260643ee0d48 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -327,7 +327,7 @@ struct lu_device_type { /** * Number of existing device type instances. */ - unsigned ldt_device_nr; + atomic_t ldt_device_nr; /** * Linkage into a global list of all device types. * @@ -602,7 +602,7 @@ struct lu_site { /** * index of bucket on hash table while purging */ - int ls_purge_start; + unsigned int ls_purge_start; /** * Top-level device for this stack. */ @@ -622,6 +622,11 @@ struct lu_site { struct list_head ls_ld_linkage; spinlock_t ls_ld_lock; + /** + * Lock to serialize site purge. + */ + struct mutex ls_purge_mutex; + /** * lu_site stats */ @@ -673,7 +678,6 @@ void lu_object_add(struct lu_object *before, struct lu_object *o); int lu_device_type_init(struct lu_device_type *ldt); void lu_device_type_fini(struct lu_device_type *ldt); -void lu_types_stop(void); /** @} ctors */ @@ -1025,7 +1029,8 @@ enum lu_context_tag { /** * Contexts usable in cache shrinker thread. */ - LCT_SHRINKER = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD|LCT_NOREF + LCT_SHRINKER = LCT_MD_THREAD | LCT_DT_THREAD | LCT_CL_THREAD | + LCT_NOREF }; /** @@ -1263,13 +1268,29 @@ struct lu_name { int ln_namelen; }; +/** + * Validate names (path components) + * + * To be valid \a name must be non-empty, '\0' terminated of length \a + * name_len, and not contain '/'. The maximum length of a name (before + * say -ENAMETOOLONG will be returned) is really controlled by llite + * and the server. We only check for something insane coming from bad + * integer handling here. + */ +static inline bool lu_name_is_valid_2(const char *name, size_t name_len) +{ + return name && name_len > 0 && name_len < INT_MAX && + name[name_len] == '\0' && strlen(name) == name_len && + !memchr(name, '/', name_len); +} + /** * Common buffer structure to be passed around for various xattr_{s,g}et() * methods. */ struct lu_buf { void *lb_buf; - ssize_t lb_len; + size_t lb_len; }; #define DLUBUF "(%p %zu)" @@ -1298,5 +1319,12 @@ struct lu_kmem_descr { int lu_kmem_init(struct lu_kmem_descr *caches); void lu_kmem_fini(struct lu_kmem_descr *caches); +void lu_buf_free(struct lu_buf *buf); +void lu_buf_alloc(struct lu_buf *buf, size_t size); +void lu_buf_realloc(struct lu_buf *buf, size_t size); + +int lu_buf_check_and_grow(struct lu_buf *buf, size_t len); +struct lu_buf *lu_buf_check_and_alloc(struct lu_buf *buf, size_t len); + /** @} lu */ #endif /* __LUSTRE_LU_OBJECT_H */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 051864c23b5b..72eaee95c6b8 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -93,6 +93,7 @@ /* Defn's shared with user-space. */ #include "lustre_user.h" #include "lustre_errno.h" +#include "../lustre_ver.h" /* * GENERAL STUFF @@ -196,12 +197,12 @@ static inline unsigned fld_range_type(const struct lu_seq_range *range) return range->lsr_flags & LU_SEQ_RANGE_MASK; } -static inline int fld_range_is_ost(const struct lu_seq_range *range) +static inline bool fld_range_is_ost(const struct lu_seq_range *range) { return fld_range_type(range) == LU_SEQ_RANGE_OST; } -static inline int fld_range_is_mdt(const struct lu_seq_range *range) +static inline bool fld_range_is_mdt(const struct lu_seq_range *range) { return fld_range_type(range) == LU_SEQ_RANGE_MDT; } @@ -260,23 +261,23 @@ static inline void range_init(struct lu_seq_range *range) * check if given seq id \a s is within given range \a r */ -static inline int range_within(const struct lu_seq_range *range, - __u64 s) +static inline bool range_within(const struct lu_seq_range *range, + __u64 s) { return s >= range->lsr_start && s < range->lsr_end; } -static inline int range_is_sane(const struct lu_seq_range *range) +static inline bool range_is_sane(const struct lu_seq_range *range) { return (range->lsr_end >= range->lsr_start); } -static inline int range_is_zero(const struct lu_seq_range *range) +static inline bool range_is_zero(const struct lu_seq_range *range) { return (range->lsr_start == 0 && range->lsr_end == 0); } -static inline int range_is_exhausted(const struct lu_seq_range *range) +static inline bool range_is_exhausted(const struct lu_seq_range *range) { return range_space(range) == 0; @@ -437,69 +438,69 @@ enum dot_lustre_oid { FID_OID_DOT_LUSTRE_OBF = 2UL, }; -static inline int fid_seq_is_mdt0(__u64 seq) +static inline bool fid_seq_is_mdt0(__u64 seq) { return (seq == FID_SEQ_OST_MDT0); } -static inline int fid_seq_is_mdt(const __u64 seq) +static inline bool fid_seq_is_mdt(__u64 seq) { return seq == FID_SEQ_OST_MDT0 || seq >= FID_SEQ_NORMAL; }; -static inline int fid_seq_is_echo(__u64 seq) +static inline bool fid_seq_is_echo(__u64 seq) { return (seq == FID_SEQ_ECHO); } -static inline int fid_is_echo(const struct lu_fid *fid) +static inline bool fid_is_echo(const struct lu_fid *fid) { return fid_seq_is_echo(fid_seq(fid)); } -static inline int fid_seq_is_llog(__u64 seq) +static inline bool fid_seq_is_llog(__u64 seq) { return (seq == FID_SEQ_LLOG); } -static inline int fid_is_llog(const struct lu_fid *fid) +static inline bool fid_is_llog(const struct lu_fid *fid) { /* file with OID == 0 is not llog but contains last oid */ return fid_seq_is_llog(fid_seq(fid)) && fid_oid(fid) > 0; } -static inline int fid_seq_is_rsvd(const __u64 seq) +static inline bool fid_seq_is_rsvd(__u64 seq) { return (seq > FID_SEQ_OST_MDT0 && seq <= FID_SEQ_RSVD); }; -static inline int fid_seq_is_special(const __u64 seq) +static inline bool fid_seq_is_special(__u64 seq) { return seq == FID_SEQ_SPECIAL; }; -static inline int fid_seq_is_local_file(const __u64 seq) +static inline bool fid_seq_is_local_file(__u64 seq) { return seq == FID_SEQ_LOCAL_FILE || seq == FID_SEQ_LOCAL_NAME; }; -static inline int fid_seq_is_root(const __u64 seq) +static inline bool fid_seq_is_root(__u64 seq) { return seq == FID_SEQ_ROOT; } -static inline int fid_seq_is_dot(const __u64 seq) +static inline bool fid_seq_is_dot(__u64 seq) { return seq == FID_SEQ_DOT_LUSTRE; } -static inline int fid_seq_is_default(const __u64 seq) +static inline bool fid_seq_is_default(__u64 seq) { return seq == FID_SEQ_LOV_DEFAULT; } -static inline int fid_is_mdt0(const struct lu_fid *fid) +static inline bool fid_is_mdt0(const struct lu_fid *fid) { return fid_seq_is_mdt0(fid_seq(fid)); } @@ -516,12 +517,12 @@ static inline void lu_root_fid(struct lu_fid *fid) * \param fid the fid to be tested. * \return true if the fid is a igif; otherwise false. */ -static inline int fid_seq_is_igif(const __u64 seq) +static inline bool fid_seq_is_igif(__u64 seq) { return seq >= FID_SEQ_IGIF && seq <= FID_SEQ_IGIF_MAX; } -static inline int fid_is_igif(const struct lu_fid *fid) +static inline bool fid_is_igif(const struct lu_fid *fid) { return fid_seq_is_igif(fid_seq(fid)); } @@ -531,27 +532,27 @@ static inline int fid_is_igif(const struct lu_fid *fid) * \param fid the fid to be tested. * \return true if the fid is a idif; otherwise false. */ -static inline int fid_seq_is_idif(const __u64 seq) +static inline bool fid_seq_is_idif(__u64 seq) { return seq >= FID_SEQ_IDIF && seq <= FID_SEQ_IDIF_MAX; } -static inline int fid_is_idif(const struct lu_fid *fid) +static inline bool fid_is_idif(const struct lu_fid *fid) { return fid_seq_is_idif(fid_seq(fid)); } -static inline int fid_is_local_file(const struct lu_fid *fid) +static inline bool fid_is_local_file(const struct lu_fid *fid) { return fid_seq_is_local_file(fid_seq(fid)); } -static inline int fid_seq_is_norm(const __u64 seq) +static inline bool fid_seq_is_norm(__u64 seq) { return (seq >= FID_SEQ_NORMAL); } -static inline int fid_is_norm(const struct lu_fid *fid) +static inline bool fid_is_norm(const struct lu_fid *fid) { return fid_seq_is_norm(fid_seq(fid)); } @@ -658,7 +659,7 @@ static inline void ostid_set_id(struct ost_id *oi, __u64 oid) oi->oi_fid.f_oid = oid; oi->oi_fid.f_ver = oid >> 48; } else { - if (oid > OBIF_MAX_OID) { + if (oid >= OBIF_MAX_OID) { CERROR("Bad %llu to set " DOSTID "\n", oid, POSTID(oi)); return; } @@ -683,7 +684,7 @@ static inline int fid_set_id(struct lu_fid *fid, __u64 oid) fid->f_oid = oid; fid->f_ver = oid >> 48; } else { - if (oid > OBIF_MAX_OID) { + if (oid >= OBIF_MAX_OID) { CERROR("Too large OID %#llx to set REG "DFID"\n", (unsigned long long)oid, PFID(fid)); return -EBADF; @@ -769,7 +770,7 @@ static inline int fid_to_ostid(const struct lu_fid *fid, struct ost_id *ostid) } /* Check whether the fid is for LAST_ID */ -static inline int fid_is_last_id(const struct lu_fid *fid) +static inline bool fid_is_last_id(const struct lu_fid *fid) { return (fid_oid(fid) == 0); } @@ -838,7 +839,7 @@ static inline void fid_be_to_cpu(struct lu_fid *dst, const struct lu_fid *src) dst->f_ver = be32_to_cpu(fid_ver(src)); } -static inline int fid_is_sane(const struct lu_fid *fid) +static inline bool fid_is_sane(const struct lu_fid *fid) { return fid && ((fid_seq(fid) >= FID_SEQ_START && fid_ver(fid) == 0) || @@ -846,15 +847,10 @@ static inline int fid_is_sane(const struct lu_fid *fid) fid_seq_is_rsvd(fid_seq(fid))); } -static inline int fid_is_zero(const struct lu_fid *fid) -{ - return fid_seq(fid) == 0 && fid_oid(fid) == 0; -} - void lustre_swab_lu_fid(struct lu_fid *fid); void lustre_swab_lu_seq_range(struct lu_seq_range *range); -static inline int lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1) +static inline bool lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1) { return memcmp(f0, f1, sizeof(*f0)) == 0; } @@ -1017,12 +1013,12 @@ static inline struct lu_dirent *lu_dirent_next(struct lu_dirent *ent) return next; } -static inline int lu_dirent_calc_size(int namelen, __u16 attr) +static inline size_t lu_dirent_calc_size(size_t namelen, __u16 attr) { - int size; + size_t size; if (attr & LUDA_TYPE) { - const unsigned align = sizeof(struct luda_type) - 1; + const size_t align = sizeof(struct luda_type) - 1; size = (sizeof(struct lu_dirent) + namelen + align) & ~align; size += sizeof(struct luda_type); @@ -1033,15 +1029,6 @@ static inline int lu_dirent_calc_size(int namelen, __u16 attr) return (size + 7) & ~7; } -static inline int lu_dirent_size(struct lu_dirent *ent) -{ - if (le16_to_cpu(ent->lde_reclen) == 0) { - return lu_dirent_calc_size(le16_to_cpu(ent->lde_namelen), - le32_to_cpu(ent->lde_attrs)); - } - return le16_to_cpu(ent->lde_reclen); -} - #define MDS_DIR_END_OFF 0xfffffffffffffffeULL /** @@ -1067,19 +1054,19 @@ struct lustre_handle { #define DEAD_HANDLE_MAGIC 0xdeadbeefcafebabeULL -static inline int lustre_handle_is_used(struct lustre_handle *lh) +static inline bool lustre_handle_is_used(const struct lustre_handle *lh) { return lh->cookie != 0ull; } -static inline int lustre_handle_equal(const struct lustre_handle *lh1, - const struct lustre_handle *lh2) +static inline bool lustre_handle_equal(const struct lustre_handle *lh1, + const struct lustre_handle *lh2) { return lh1->cookie == lh2->cookie; } static inline void lustre_handle_copy(struct lustre_handle *tgt, - struct lustre_handle *src) + const struct lustre_handle *src) { tgt->cookie = src->cookie; } @@ -1105,7 +1092,7 @@ struct lustre_msg_v2 { /* without gss, ptlrpc_body is put at the first buffer. */ #define PTLRPC_NUM_VERSIONS 4 -#define JOBSTATS_JOBID_SIZE 32 /* 32 bytes string */ + struct ptlrpc_body_v3 { struct lustre_handle pb_handle; __u32 pb_type; @@ -1127,7 +1114,7 @@ struct ptlrpc_body_v3 { __u64 pb_pre_versions[PTLRPC_NUM_VERSIONS]; /* padding for future needs */ __u64 pb_padding[4]; - char pb_jobid[JOBSTATS_JOBID_SIZE]; + char pb_jobid[LUSTRE_JOBID_SIZE]; }; #define ptlrpc_body ptlrpc_body_v3 @@ -1293,6 +1280,9 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); #define OBD_CONNECT_OPEN_BY_FID 0x20000000000000ULL /* open by fid won't pack * name in request */ +#define OBD_CONNECT_LFSCK 0x40000000000000ULL/* support online LFSCK */ +#define OBD_CONNECT_UNLINK_CLOSE 0x100000000000000ULL/* close file in unlink */ +#define OBD_CONNECT_DIR_STRIPE 0x400000000000000ULL/* striped DNE dir */ /* XXX README XXX: * Please DO NOT add flag values here before first ensuring that this same @@ -1318,14 +1308,6 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); #define CLIENT_CONNECT_MDT_REQD (OBD_CONNECT_IBITS | OBD_CONNECT_FID | \ OBD_CONNECT_FULL20) -#define OBD_OCD_VERSION(major, minor, patch, fix) (((major)<<24) + \ - ((minor)<<16) + \ - ((patch)<<8) + (fix)) -#define OBD_OCD_VERSION_MAJOR(version) ((int)((version)>>24)&255) -#define OBD_OCD_VERSION_MINOR(version) ((int)((version)>>16)&255) -#define OBD_OCD_VERSION_PATCH(version) ((int)((version)>>8)&255) -#define OBD_OCD_VERSION_FIX(version) ((int)(version)&255) - /* This structure is used for both request and reply. * * If we eventually have separate connect data for different types, which we @@ -1478,10 +1460,23 @@ enum obdo_flags { OBD_FL_LOCAL_MASK = 0xF0000000, }; -#define LOV_MAGIC_V1 0x0BD10BD0 -#define LOV_MAGIC LOV_MAGIC_V1 -#define LOV_MAGIC_JOIN_V1 0x0BD20BD0 -#define LOV_MAGIC_V3 0x0BD30BD0 +/* + * All LOV EA magics should have the same postfix, if some new version + * Lustre instroduces new LOV EA magic, then when down-grade to an old + * Lustre, even though the old version system does not recognizes such + * new magic, it still can distinguish the corrupted cases by checking + * the magic's postfix. + */ +#define LOV_MAGIC_MAGIC 0x0BD0 +#define LOV_MAGIC_MASK 0xFFFF + +#define LOV_MAGIC_V1 (0x0BD10000 | LOV_MAGIC_MAGIC) +#define LOV_MAGIC_JOIN_V1 (0x0BD20000 | LOV_MAGIC_MAGIC) +#define LOV_MAGIC_V3 (0x0BD30000 | LOV_MAGIC_MAGIC) +#define LOV_MAGIC_MIGRATE (0x0BD40000 | LOV_MAGIC_MAGIC) +/* reserved for specifying OSTs */ +#define LOV_MAGIC_SPECIFIC (0x0BD50000 | LOV_MAGIC_MAGIC) +#define LOV_MAGIC LOV_MAGIC_V1 /* * magic for fully defined striping @@ -1498,14 +1493,6 @@ enum obdo_flags { #define LOV_MAGIC_V1_DEF 0x0CD10BD0 #define LOV_MAGIC_V3_DEF 0x0CD30BD0 -#define LOV_PATTERN_RAID0 0x001 /* stripes are used round-robin */ -#define LOV_PATTERN_RAID1 0x002 /* stripes are mirrors of each other */ -#define LOV_PATTERN_FIRST 0x100 /* first stripe is not in round-robin */ -#define LOV_PATTERN_CMOBD 0x200 - -#define LOV_PATTERN_F_MASK 0xffff0000 -#define LOV_PATTERN_F_RELEASED 0x80000000 /* HSM released file */ - #define lov_pattern(pattern) (pattern & ~LOV_PATTERN_F_MASK) #define lov_pattern_flags(pattern) (pattern & LOV_PATTERN_F_MASK) @@ -1569,25 +1556,25 @@ static inline void lmm_oi_set_id(struct ost_id *oi, __u64 oid) oi->oi.oi_id = oid; } -static inline __u64 lmm_oi_id(struct ost_id *oi) +static inline __u64 lmm_oi_id(const struct ost_id *oi) { return oi->oi.oi_id; } -static inline __u64 lmm_oi_seq(struct ost_id *oi) +static inline __u64 lmm_oi_seq(const struct ost_id *oi) { return oi->oi.oi_seq; } static inline void lmm_oi_le_to_cpu(struct ost_id *dst_oi, - struct ost_id *src_oi) + const struct ost_id *src_oi) { dst_oi->oi.oi_id = le64_to_cpu(src_oi->oi.oi_id); dst_oi->oi.oi_seq = le64_to_cpu(src_oi->oi.oi_seq); } static inline void lmm_oi_cpu_to_le(struct ost_id *dst_oi, - struct ost_id *src_oi) + const struct ost_id *src_oi) { dst_oi->oi.oi_id = cpu_to_le64(src_oi->oi.oi_id); dst_oi->oi.oi_seq = cpu_to_le64(src_oi->oi.oi_seq); @@ -1610,6 +1597,7 @@ static inline void lmm_oi_cpu_to_le(struct ost_id *dst_oi, #define XATTR_NAME_LOV "trusted.lov" #define XATTR_NAME_LMA "trusted.lma" #define XATTR_NAME_LMV "trusted.lmv" +#define XATTR_NAME_DEFAULT_LMV "trusted.dmv" #define XATTR_NAME_LINK "trusted.link" #define XATTR_NAME_FID "trusted.fid" #define XATTR_NAME_VERSION "trusted.version" @@ -1625,7 +1613,7 @@ struct lov_mds_md_v3 { /* LOV EA mds/wire data (little-endian) */ /* lmm_stripe_count used to be __u32 */ __u16 lmm_stripe_count; /* num stripes in use for this object */ __u16 lmm_layout_gen; /* layout generation number */ - char lmm_pool_name[LOV_MAXPOOLNAME]; /* must be 32bit aligned */ + char lmm_pool_name[LOV_MAXPOOLNAME + 1]; /* must be 32bit aligned */ struct lov_ost_data_v1 lmm_objects[0]; /* per-stripe data */ }; @@ -1727,6 +1715,8 @@ lov_mds_md_max_stripe_count(size_t buf_size, __u32 lmm_magic) #define OBD_MD_FLDATAVERSION (0x0010000000000000ULL) /* iversion sum */ #define OBD_MD_FLRELEASED (0x0020000000000000ULL) /* file released */ +#define OBD_MD_DEFAULT_MEA (0x0040000000000000ULL) /* default MEA */ + #define OBD_MD_FLGETATTR (OBD_MD_FLID | OBD_MD_FLATIME | OBD_MD_FLMTIME | \ OBD_MD_FLCTIME | OBD_MD_FLSIZE | OBD_MD_FLBLKSZ | \ OBD_MD_FLMODE | OBD_MD_FLTYPE | OBD_MD_FLUID | \ @@ -1782,7 +1772,7 @@ void lustre_swab_obd_statfs(struct obd_statfs *os); * it to sync quickly */ -#define OBD_OBJECT_EOF 0xffffffffffffffffULL +#define OBD_OBJECT_EOF LUSTRE_EOF #define OST_MIN_PRECREATE 32 #define OST_MAX_PRECREATE 20000 @@ -1806,9 +1796,9 @@ void lustre_swab_obd_ioobj(struct obd_ioobj *ioo); /* multiple of 8 bytes => can array */ struct niobuf_remote { - __u64 offset; - __u32 len; - __u32 flags; + __u64 rnb_offset; + __u32 rnb_len; + __u32 rnb_flags; }; void lustre_swab_niobuf_remote(struct niobuf_remote *nbr); @@ -1878,12 +1868,6 @@ struct obd_quotactl { void lustre_swab_obd_quotactl(struct obd_quotactl *q); -#define Q_QUOTACHECK 0x800100 /* deprecated as of 2.4 */ -#define Q_INITQUOTA 0x800101 /* deprecated as of 2.4 */ -#define Q_GETOINFO 0x800102 /* get obd quota info */ -#define Q_GETOQUOTA 0x800103 /* get obd quotas */ -#define Q_FINVALIDATE 0x800104 /* deprecated as of 2.4 */ - #define Q_COPY(out, in, member) (out)->member = (in)->member #define QCTL_COPY(out, in) \ @@ -1946,8 +1930,8 @@ enum mds_cmd { MDS_DISCONNECT = 39, MDS_GETSTATUS = 40, MDS_STATFS = 41, - MDS_PIN = 42, - MDS_UNPIN = 43, + MDS_PIN = 42, /* obsolete, never used in a release */ + MDS_UNPIN = 43, /* obsolete, never used in a release */ MDS_SYNC = 44, MDS_DONE_WRITING = 45, MDS_SET_INFO = 46, @@ -1956,7 +1940,7 @@ enum mds_cmd { MDS_GETXATTR = 49, MDS_SETXATTR = 50, /* obsolete, now it's MDS_REINT op */ MDS_WRITEPAGE = 51, - MDS_IS_SUBDIR = 52, + MDS_IS_SUBDIR = 52, /* obsolete, never used in a release */ MDS_GET_INFO = 53, MDS_HSM_STATE_GET = 54, MDS_HSM_STATE_SET = 55, @@ -1984,7 +1968,7 @@ enum mdt_reint_cmd { REINT_OPEN = 6, REINT_SETXATTR = 7, REINT_RMENTRY = 8, -/* REINT_WRITE = 9, */ + REINT_MIGRATE = 9, REINT_MAX }; @@ -2003,6 +1987,7 @@ void lustre_swab_generic_32s(__u32 *val); #define DISP_OPEN_LOCK 0x02000000 #define DISP_OPEN_LEASE 0x04000000 #define DISP_OPEN_STRIPE 0x08000000 +#define DISP_OPEN_DENY 0x10000000 /* INODE LOCK PARTS */ #define MDS_INODELOCK_LOOKUP 0x000001 /* For namespace, dentry etc, and also @@ -2028,7 +2013,7 @@ void lustre_swab_generic_32s(__u32 *val); #define MDS_INODELOCK_MAXSHIFT 5 /* This FULL lock is useful to take on unlink sort of operations */ -#define MDS_INODELOCK_FULL ((1<<(MDS_INODELOCK_MAXSHIFT+1))-1) +#define MDS_INODELOCK_FULL ((1 << (MDS_INODELOCK_MAXSHIFT + 1)) - 1) /* NOTE: until Lustre 1.8.7/2.1.1 the fid_ver() was packed into name[2], * but was moved into name[1] along with the OID to avoid consuming the @@ -2108,43 +2093,43 @@ enum md_transient_state { }; struct mdt_body { - struct lu_fid fid1; - struct lu_fid fid2; - struct lustre_handle handle; - __u64 valid; - __u64 size; /* Offset, in the case of MDS_READPAGE */ - __s64 mtime; - __s64 atime; - __s64 ctime; - __u64 blocks; /* XID, in the case of MDS_READPAGE */ - __u64 ioepoch; - __u64 t_state; /* transient file state defined in - * enum md_transient_state - * was "ino" until 2.4.0 - */ - __u32 fsuid; - __u32 fsgid; - __u32 capability; - __u32 mode; - __u32 uid; - __u32 gid; - __u32 flags; /* from vfs for pin/unpin, LUSTRE_BFLAG close */ - __u32 rdev; - __u32 nlink; /* #bytes to read in the case of MDS_READPAGE */ - __u32 unused2; /* was "generation" until 2.4.0 */ - __u32 suppgid; - __u32 eadatasize; - __u32 aclsize; - __u32 max_mdsize; - __u32 max_cookiesize; - __u32 uid_h; /* high 32-bits of uid, for FUID */ - __u32 gid_h; /* high 32-bits of gid, for FUID */ - __u32 padding_5; /* also fix lustre_swab_mdt_body */ - __u64 padding_6; - __u64 padding_7; - __u64 padding_8; - __u64 padding_9; - __u64 padding_10; + struct lu_fid mbo_fid1; + struct lu_fid mbo_fid2; + struct lustre_handle mbo_handle; + __u64 mbo_valid; + __u64 mbo_size; /* Offset, in the case of MDS_READPAGE */ + __s64 mbo_mtime; + __s64 mbo_atime; + __s64 mbo_ctime; + __u64 mbo_blocks; /* XID, in the case of MDS_READPAGE */ + __u64 mbo_ioepoch; + __u64 mbo_t_state; /* transient file state defined in + * enum md_transient_state + * was "ino" until 2.4.0 + */ + __u32 mbo_fsuid; + __u32 mbo_fsgid; + __u32 mbo_capability; + __u32 mbo_mode; + __u32 mbo_uid; + __u32 mbo_gid; + __u32 mbo_flags; + __u32 mbo_rdev; + __u32 mbo_nlink; /* #bytes to read in the case of MDS_READPAGE */ + __u32 mbo_unused2; /* was "generation" until 2.4.0 */ + __u32 mbo_suppgid; + __u32 mbo_eadatasize; + __u32 mbo_aclsize; + __u32 mbo_max_mdsize; + __u32 mbo_max_cookiesize; + __u32 mbo_uid_h; /* high 32-bits of uid, for FUID */ + __u32 mbo_gid_h; /* high 32-bits of gid, for FUID */ + __u32 mbo_padding_5; /* also fix lustre_swab_mdt_body */ + __u64 mbo_padding_6; + __u64 mbo_padding_7; + __u64 mbo_padding_8; + __u64 mbo_padding_9; + __u64 mbo_padding_10; }; /* 216 */ void lustre_swab_mdt_body(struct mdt_body *b); @@ -2263,6 +2248,11 @@ void lustre_swab_mdt_rec_setattr(struct mdt_rec_setattr *sa); */ #define MDS_OPEN_RELEASE 02000000000000ULL /* Open the file for HSM release */ +#define MDS_OPEN_FL_INTERNAL (MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS | \ + MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK | \ + MDS_OPEN_BY_FID | MDS_OPEN_LEASE | \ + MDS_OPEN_RELEASE) + enum mds_op_bias { MDS_CHECK_SPLIT = 1 << 0, MDS_CROSS_REF = 1 << 1, @@ -2277,6 +2267,7 @@ enum mds_op_bias { MDS_CREATE_VOLATILE = 1 << 10, MDS_OWNEROVERRIDE = 1 << 11, MDS_HSM_RELEASE = 1 << 12, + MDS_RENAME_MIGRATE = BIT(13), }; /* instance of mdt_reint_rec */ @@ -2472,7 +2463,7 @@ struct lmv_desc { __u32 ld_tgt_count; /* how many MDS's */ __u32 ld_active_tgt_count; /* how many active */ __u32 ld_default_stripe_count; /* how many objects are used */ - __u32 ld_pattern; /* default MEA_MAGIC_* */ + __u32 ld_pattern; /* default hash pattern */ __u64 ld_default_hash_size; __u64 ld_padding_1; /* also fix lustre_swab_lmv_desc */ __u32 ld_padding_2; /* also fix lustre_swab_lmv_desc */ @@ -2482,23 +2473,129 @@ struct lmv_desc { struct obd_uuid ld_uuid; }; -/* TODO: lmv_stripe_md should contain mds capabilities for all slave fids */ -struct lmv_stripe_md { - __u32 mea_magic; - __u32 mea_count; - __u32 mea_master; - __u32 mea_padding; - char mea_pool_name[LOV_MAXPOOLNAME]; - struct lu_fid mea_ids[0]; +/* LMV layout EA, and it will be stored both in master and slave object */ +struct lmv_mds_md_v1 { + __u32 lmv_magic; + __u32 lmv_stripe_count; + __u32 lmv_master_mdt_index; /* On master object, it is master + * MDT index, on slave object, it + * is stripe index of the slave obj + */ + __u32 lmv_hash_type; /* dir stripe policy, i.e. indicate + * which hash function to be used, + * Note: only lower 16 bits is being + * used for now. Higher 16 bits will + * be used to mark the object status, + * for example migrating or dead. + */ + __u32 lmv_layout_version; /* Used for directory restriping */ + __u32 lmv_padding1; + __u64 lmv_padding2; + __u64 lmv_padding3; + char lmv_pool_name[LOV_MAXPOOLNAME + 1];/* pool name */ + struct lu_fid lmv_stripe_fids[0]; /* FIDs for each stripe */ }; -#define MEA_MAGIC_LAST_CHAR 0xb2221ca1 -#define MEA_MAGIC_ALL_CHARS 0xb222a11c -#define MEA_MAGIC_HASH_SEGMENT 0xb222a11b +#define LMV_MAGIC_V1 0x0CD20CD0 /* normal stripe lmv magic */ +#define LMV_MAGIC LMV_MAGIC_V1 -#define MAX_HASH_SIZE_32 0x7fffffffUL -#define MAX_HASH_SIZE 0x7fffffffffffffffULL -#define MAX_HASH_HIGHEST_BIT 0x1000000000000000ULL +/* #define LMV_USER_MAGIC 0x0CD30CD0 */ +#define LMV_MAGIC_STRIPE 0x0CD40CD0 /* magic for dir sub_stripe */ + +/* + *Right now only the lower part(0-16bits) of lmv_hash_type is being used, + * and the higher part will be the flag to indicate the status of object, + * for example the object is being migrated. And the hash function + * might be interpreted differently with different flags. + */ +#define LMV_HASH_TYPE_MASK 0x0000ffff + +#define LMV_HASH_FLAG_MIGRATION 0x80000000 +#define LMV_HASH_FLAG_DEAD 0x40000000 + +/** + * The FNV-1a hash algorithm is as follows: + * hash = FNV_offset_basis + * for each octet_of_data to be hashed + * hash = hash XOR octet_of_data + * hash = hash × FNV_prime + * return hash + * http://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function#FNV-1a_hash + * + * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-reference-source + * FNV_prime is 2^40 + 2^8 + 0xb3 = 0x100000001b3ULL + **/ +#define LUSTRE_FNV_1A_64_PRIME 0x100000001b3ULL +#define LUSTRE_FNV_1A_64_OFFSET_BIAS 0xcbf29ce484222325ULL +static inline __u64 lustre_hash_fnv_1a_64(const void *buf, size_t size) +{ + __u64 hash = LUSTRE_FNV_1A_64_OFFSET_BIAS; + const unsigned char *p = buf; + size_t i; + + for (i = 0; i < size; i++) { + hash ^= p[i]; + hash *= LUSTRE_FNV_1A_64_PRIME; + } + + return hash; +} + +union lmv_mds_md { + __u32 lmv_magic; + struct lmv_mds_md_v1 lmv_md_v1; + struct lmv_user_md lmv_user_md; +}; + +void lustre_swab_lmv_mds_md(union lmv_mds_md *lmm); + +static inline ssize_t lmv_mds_md_size(int stripe_count, unsigned int lmm_magic) +{ + ssize_t len = -EINVAL; + + switch (lmm_magic) { + case LMV_MAGIC_V1: { + struct lmv_mds_md_v1 *lmm1; + + len = sizeof(*lmm1); + len += stripe_count * sizeof(lmm1->lmv_stripe_fids[0]); + break; } + default: + break; + } + return len; +} + +static inline int lmv_mds_md_stripe_count_get(const union lmv_mds_md *lmm) +{ + switch (le32_to_cpu(lmm->lmv_magic)) { + case LMV_MAGIC_V1: + return le32_to_cpu(lmm->lmv_md_v1.lmv_stripe_count); + case LMV_USER_MAGIC: + return le32_to_cpu(lmm->lmv_user_md.lum_stripe_count); + default: + return -EINVAL; + } +} + +static inline int lmv_mds_md_stripe_count_set(union lmv_mds_md *lmm, + unsigned int stripe_count) +{ + int rc = 0; + + switch (le32_to_cpu(lmm->lmv_magic)) { + case LMV_MAGIC_V1: + lmm->lmv_md_v1.lmv_stripe_count = cpu_to_le32(stripe_count); + break; + case LMV_USER_MAGIC: + lmm->lmv_user_md.lum_stripe_count = cpu_to_le32(stripe_count); + break; + default: + rc = -EINVAL; + break; + } + return rc; +} enum fld_rpc_opc { FLD_QUERY = 900, @@ -2582,8 +2679,8 @@ struct ldlm_res_id { #define PLDLMRES(res) (res)->lr_name.name[0], (res)->lr_name.name[1], \ (res)->lr_name.name[2], (res)->lr_name.name[3] -static inline int ldlm_res_eq(const struct ldlm_res_id *res0, - const struct ldlm_res_id *res1) +static inline bool ldlm_res_eq(const struct ldlm_res_id *res0, + const struct ldlm_res_id *res1) { return !memcmp(res0, res1, sizeof(*res0)); } @@ -2620,17 +2717,15 @@ struct ldlm_extent { __u64 gid; }; -#define LDLM_GID_ANY ((__u64)-1) - -static inline int ldlm_extent_overlap(struct ldlm_extent *ex1, - struct ldlm_extent *ex2) +static inline int ldlm_extent_overlap(const struct ldlm_extent *ex1, + const struct ldlm_extent *ex2) { return (ex1->start <= ex2->end) && (ex2->start <= ex1->end); } /* check if @ex1 contains @ex2 */ -static inline int ldlm_extent_contain(struct ldlm_extent *ex1, - struct ldlm_extent *ex2) +static inline int ldlm_extent_contain(const struct ldlm_extent *ex1, + const struct ldlm_extent *ex2) { return (ex1->start <= ex2->start) && (ex1->end >= ex2->end); } @@ -2833,7 +2928,29 @@ enum obd_cmd { }; #define OBD_FIRST_OPC OBD_PING -/* catalog of log objects */ +/** + * llog contexts indices. + * + * There is compatibility problem with indexes below, they are not + * continuous and must keep their numbers for compatibility needs. + * See LU-5218 for details. + */ +enum llog_ctxt_id { + LLOG_CONFIG_ORIG_CTXT = 0, + LLOG_CONFIG_REPL_CTXT = 1, + LLOG_MDS_OST_ORIG_CTXT = 2, + LLOG_MDS_OST_REPL_CTXT = 3, /* kept just to avoid re-assignment */ + LLOG_SIZE_ORIG_CTXT = 4, + LLOG_SIZE_REPL_CTXT = 5, + LLOG_TEST_ORIG_CTXT = 8, + LLOG_TEST_REPL_CTXT = 9, /* kept just to avoid re-assignment */ + LLOG_CHANGELOG_ORIG_CTXT = 12, /**< changelog generation on mdd */ + LLOG_CHANGELOG_REPL_CTXT = 13, /**< changelog access on clients */ + /* for multiple changelog consumers */ + LLOG_CHANGELOG_USER_ORIG_CTXT = 14, + LLOG_AGENT_ORIG_CTXT = 15, /**< agent requests generation on cdt */ + LLOG_MAX_CTXTS +}; /** Identifier for a single log object */ struct llog_logid { @@ -2939,7 +3056,7 @@ struct llog_setattr64_rec { __u32 lsr_uid_h; __u32 lsr_gid; __u32 lsr_gid_h; - __u64 lsr_padding; + __u64 lsr_valid; struct llog_rec_tail lsr_tail; } __packed; @@ -2963,15 +3080,9 @@ struct changelog_setinfo { /** changelog record */ struct llog_changelog_rec { - struct llog_rec_hdr cr_hdr; - struct changelog_rec cr; - struct llog_rec_tail cr_tail; /**< for_sizezof_only */ -} __packed; - -struct llog_changelog_ext_rec { - struct llog_rec_hdr cr_hdr; - struct changelog_ext_rec cr; - struct llog_rec_tail cr_tail; /**< for_sizezof_only */ + struct llog_rec_hdr cr_hdr; + struct changelog_rec cr; /**< Variable length field */ + struct llog_rec_tail cr_do_not_use; /**< for_sizezof_only */ } __packed; struct llog_changelog_user_rec { @@ -2990,7 +3101,7 @@ enum agent_req_status { ARS_SUCCEED, }; -static inline char *agent_req_status2name(enum agent_req_status ars) +static inline const char *agent_req_status2name(const enum agent_req_status ars) { switch (ars) { case ARS_WAITING: @@ -3056,6 +3167,9 @@ enum llog_flag { LLOG_F_ZAP_WHEN_EMPTY = 0x1, LLOG_F_IS_CAT = 0x2, LLOG_F_IS_PLAIN = 0x4, + LLOG_F_EXT_JOBID = BIT(3), + + LLOG_F_EXT_MASK = LLOG_F_EXT_JOBID, }; struct llog_log_hdr { @@ -3068,8 +3182,8 @@ struct llog_log_hdr { __u32 llh_cat_idx; /* for a catalog the first plain slot is next to it */ struct obd_uuid llh_tgtuuid; - __u32 llh_reserved[LLOG_HEADER_SIZE/sizeof(__u32) - 23]; - __u32 llh_bitmap[LLOG_BITMAP_BYTES/sizeof(__u32)]; + __u32 llh_reserved[LLOG_HEADER_SIZE / sizeof(__u32) - 23]; + __u32 llh_bitmap[LLOG_BITMAP_BYTES / sizeof(__u32)]; struct llog_rec_tail llh_tail; } __packed; @@ -3166,7 +3280,7 @@ struct obdo { #define o_cksum o_nlink #define o_grant_used o_data_version -static inline void lustre_set_wire_obdo(struct obd_connect_data *ocd, +static inline void lustre_set_wire_obdo(const struct obd_connect_data *ocd, struct obdo *wobdo, const struct obdo *lobdo) { @@ -3185,7 +3299,7 @@ static inline void lustre_set_wire_obdo(struct obd_connect_data *ocd, } } -static inline void lustre_get_wire_obdo(struct obd_connect_data *ocd, +static inline void lustre_get_wire_obdo(const struct obd_connect_data *ocd, struct obdo *lobdo, const struct obdo *wobdo) { @@ -3284,17 +3398,17 @@ void lustre_swab_lustre_capa(struct lustre_capa *c); /** lustre_capa::lc_opc */ enum { - CAPA_OPC_BODY_WRITE = 1<<0, /**< write object data */ - CAPA_OPC_BODY_READ = 1<<1, /**< read object data */ - CAPA_OPC_INDEX_LOOKUP = 1<<2, /**< lookup object fid */ - CAPA_OPC_INDEX_INSERT = 1<<3, /**< insert object fid */ - CAPA_OPC_INDEX_DELETE = 1<<4, /**< delete object fid */ - CAPA_OPC_OSS_WRITE = 1<<5, /**< write oss object data */ - CAPA_OPC_OSS_READ = 1<<6, /**< read oss object data */ - CAPA_OPC_OSS_TRUNC = 1<<7, /**< truncate oss object */ - CAPA_OPC_OSS_DESTROY = 1<<8, /**< destroy oss object */ - CAPA_OPC_META_WRITE = 1<<9, /**< write object meta data */ - CAPA_OPC_META_READ = 1<<10, /**< read object meta data */ + CAPA_OPC_BODY_WRITE = 1 << 0, /**< write object data */ + CAPA_OPC_BODY_READ = 1 << 1, /**< read object data */ + CAPA_OPC_INDEX_LOOKUP = 1 << 2, /**< lookup object fid */ + CAPA_OPC_INDEX_INSERT = 1 << 3, /**< insert object fid */ + CAPA_OPC_INDEX_DELETE = 1 << 4, /**< delete object fid */ + CAPA_OPC_OSS_WRITE = 1 << 5, /**< write oss object data */ + CAPA_OPC_OSS_READ = 1 << 6, /**< read oss object data */ + CAPA_OPC_OSS_TRUNC = 1 << 7, /**< truncate oss object */ + CAPA_OPC_OSS_DESTROY = 1 << 8, /**< destroy oss object */ + CAPA_OPC_META_WRITE = 1 << 9, /**< write object meta data */ + CAPA_OPC_META_READ = 1 << 10, /**< read object meta data */ }; #define CAPA_OPC_OSS_RW (CAPA_OPC_OSS_READ | CAPA_OPC_OSS_WRITE) @@ -3346,6 +3460,14 @@ struct getinfo_fid2path { void lustre_swab_fid2path(struct getinfo_fid2path *gf); +/** path2parent request/reply structures */ +struct getparent { + struct lu_fid gp_fid; /**< parent FID */ + __u32 gp_linkno; /**< hardlink number */ + __u32 gp_name_size; /**< size of the name field */ + char gp_name[0]; /**< zero-terminated link name */ +} __packed; + enum { LAYOUT_INTENT_ACCESS = 0, LAYOUT_INTENT_READ = 1, diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h new file mode 100644 index 000000000000..f3d7c94c3b50 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h @@ -0,0 +1,412 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2011, 2015, Intel Corporation. + */ +#ifndef LUSTRE_IOCTL_H_ +#define LUSTRE_IOCTL_H_ + +#include +#include "../../../include/linux/libcfs/libcfs.h" +#include "lustre_idl.h" + +#ifdef __KERNEL__ +# include +# include +# include "../obd_support.h" +#else /* __KERNEL__ */ +# include +# include +#include +#endif /* !__KERNEL__ */ + +#if !defined(__KERNEL__) && !defined(LUSTRE_UTILS) +# error This file is for Lustre internal use only. +#endif + +enum md_echo_cmd { + ECHO_MD_CREATE = 1, /* Open/Create file on MDT */ + ECHO_MD_MKDIR = 2, /* Mkdir on MDT */ + ECHO_MD_DESTROY = 3, /* Unlink file on MDT */ + ECHO_MD_RMDIR = 4, /* Rmdir on MDT */ + ECHO_MD_LOOKUP = 5, /* Lookup on MDT */ + ECHO_MD_GETATTR = 6, /* Getattr on MDT */ + ECHO_MD_SETATTR = 7, /* Setattr on MDT */ + ECHO_MD_ALLOC_FID = 8, /* Get FIDs from MDT */ +}; + +#define OBD_DEV_ID 1 +#define OBD_DEV_NAME "obd" +#define OBD_DEV_PATH "/dev/" OBD_DEV_NAME +#define OBD_DEV_MAJOR 10 +#define OBD_DEV_MINOR 241 + +#define OBD_IOCTL_VERSION 0x00010004 +#define OBD_DEV_BY_DEVNAME 0xffffd0de +#define OBD_MAX_IOCTL_BUFFER CONFIG_LUSTRE_OBD_MAX_IOCTL_BUFFER + +struct obd_ioctl_data { + __u32 ioc_len; + __u32 ioc_version; + + union { + __u64 ioc_cookie; + __u64 ioc_u64_1; + }; + union { + __u32 ioc_conn1; + __u32 ioc_u32_1; + }; + union { + __u32 ioc_conn2; + __u32 ioc_u32_2; + }; + + struct obdo ioc_obdo1; + struct obdo ioc_obdo2; + + __u64 ioc_count; + __u64 ioc_offset; + __u32 ioc_dev; + __u32 ioc_command; + + __u64 ioc_nid; + __u32 ioc_nal; + __u32 ioc_type; + + /* buffers the kernel will treat as user pointers */ + __u32 ioc_plen1; + char __user *ioc_pbuf1; + __u32 ioc_plen2; + char __user *ioc_pbuf2; + + /* inline buffers for various arguments */ + __u32 ioc_inllen1; + char *ioc_inlbuf1; + __u32 ioc_inllen2; + char *ioc_inlbuf2; + __u32 ioc_inllen3; + char *ioc_inlbuf3; + __u32 ioc_inllen4; + char *ioc_inlbuf4; + + char ioc_bulk[0]; +}; + +struct obd_ioctl_hdr { + __u32 ioc_len; + __u32 ioc_version; +}; + +static inline __u32 obd_ioctl_packlen(struct obd_ioctl_data *data) +{ + __u32 len = cfs_size_round(sizeof(*data)); + + len += cfs_size_round(data->ioc_inllen1); + len += cfs_size_round(data->ioc_inllen2); + len += cfs_size_round(data->ioc_inllen3); + len += cfs_size_round(data->ioc_inllen4); + + return len; +} + +static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) +{ + if (data->ioc_len > (1 << 30)) { + CERROR("OBD ioctl: ioc_len larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inllen1 > (1 << 30)) { + CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inllen2 > (1 << 30)) { + CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inllen3 > (1 << 30)) { + CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inllen4 > (1 << 30)) { + CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inlbuf1 && !data->ioc_inllen1) { + CERROR("OBD ioctl: inlbuf1 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_inlbuf2 && !data->ioc_inllen2) { + CERROR("OBD ioctl: inlbuf2 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_inlbuf3 && !data->ioc_inllen3) { + CERROR("OBD ioctl: inlbuf3 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_inlbuf4 && !data->ioc_inllen4) { + CERROR("OBD ioctl: inlbuf4 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_pbuf1 && !data->ioc_plen1) { + CERROR("OBD ioctl: pbuf1 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_pbuf2 && !data->ioc_plen2) { + CERROR("OBD ioctl: pbuf2 pointer but 0 length\n"); + return 1; + } + + if (!data->ioc_pbuf1 && data->ioc_plen1) { + CERROR("OBD ioctl: plen1 set but NULL pointer\n"); + return 1; + } + + if (!data->ioc_pbuf2 && data->ioc_plen2) { + CERROR("OBD ioctl: plen2 set but NULL pointer\n"); + return 1; + } + + if (obd_ioctl_packlen(data) > data->ioc_len) { + CERROR("OBD ioctl: packlen exceeds ioc_len (%d > %d)\n", + obd_ioctl_packlen(data), data->ioc_len); + return 1; + } + + return 0; +} + +#ifdef __KERNEL__ + +int obd_ioctl_getdata(char **buf, int *len, void __user *arg); +int obd_ioctl_popdata(void __user *arg, void *data, int len); + +static inline void obd_ioctl_freedata(char *buf, size_t len) +{ + kvfree(buf); +} + +#else /* __KERNEL__ */ + +static inline int obd_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, + int max_len) +{ + char *ptr; + struct obd_ioctl_data *overlay; + + data->ioc_len = obd_ioctl_packlen(data); + data->ioc_version = OBD_IOCTL_VERSION; + + if (*pbuf && data->ioc_len > max_len) { + fprintf(stderr, "pbuf = %p, ioc_len = %u, max_len = %d\n", + *pbuf, data->ioc_len, max_len); + return -EINVAL; + } + + if (!*pbuf) + *pbuf = malloc(data->ioc_len); + + if (!*pbuf) + return -ENOMEM; + + overlay = (struct obd_ioctl_data *)*pbuf; + memcpy(*pbuf, data, sizeof(*data)); + + ptr = overlay->ioc_bulk; + if (data->ioc_inlbuf1) + LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr); + + if (data->ioc_inlbuf2) + LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr); + + if (data->ioc_inlbuf3) + LOGL(data->ioc_inlbuf3, data->ioc_inllen3, ptr); + + if (data->ioc_inlbuf4) + LOGL(data->ioc_inlbuf4, data->ioc_inllen4, ptr); + + if (obd_ioctl_is_invalid(overlay)) { + fprintf(stderr, "invalid ioctl data: ioc_len = %u, max_len = %d\n", + data->ioc_len, max_len); + return -EINVAL; + } + + return 0; +} + +static inline int +obd_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len) +{ + char *ptr; + struct obd_ioctl_data *overlay; + + if (!pbuf) + return 1; + + overlay = (struct obd_ioctl_data *)pbuf; + + /* Preserve the caller's buffer pointers */ + overlay->ioc_inlbuf1 = data->ioc_inlbuf1; + overlay->ioc_inlbuf2 = data->ioc_inlbuf2; + overlay->ioc_inlbuf3 = data->ioc_inlbuf3; + overlay->ioc_inlbuf4 = data->ioc_inlbuf4; + + memcpy(data, pbuf, sizeof(*data)); + + ptr = overlay->ioc_bulk; + if (data->ioc_inlbuf1) + LOGU(data->ioc_inlbuf1, data->ioc_inllen1, ptr); + + if (data->ioc_inlbuf2) + LOGU(data->ioc_inlbuf2, data->ioc_inllen2, ptr); + + if (data->ioc_inlbuf3) + LOGU(data->ioc_inlbuf3, data->ioc_inllen3, ptr); + + if (data->ioc_inlbuf4) + LOGU(data->ioc_inlbuf4, data->ioc_inllen4, ptr); + + return 0; +} + +#endif /* !__KERNEL__ */ + +/* + * OBD_IOC_DATA_TYPE is only for compatibility reasons with older + * Linux Lustre user tools. New ioctls should NOT use this macro as + * the ioctl "size". Instead the ioctl should get a "size" argument + * which is the actual data type used by the ioctl, to ensure the + * ioctl interface is versioned correctly. + */ +#define OBD_IOC_DATA_TYPE long + +/* IOC_LDLM_TEST _IOWR('f', 40, long) */ +/* IOC_LDLM_DUMP _IOWR('f', 41, long) */ +/* IOC_LDLM_REGRESS_START _IOWR('f', 42, long) */ +/* IOC_LDLM_REGRESS_STOP _IOWR('f', 43, long) */ + +#define OBD_IOC_CREATE _IOWR('f', 101, OBD_IOC_DATA_TYPE) +#define OBD_IOC_DESTROY _IOW('f', 104, OBD_IOC_DATA_TYPE) +/* OBD_IOC_PREALLOCATE _IOWR('f', 105, OBD_IOC_DATA_TYPE) */ + +#define OBD_IOC_SETATTR _IOW('f', 107, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GETATTR _IOWR('f', 108, OBD_IOC_DATA_TYPE) +#define OBD_IOC_READ _IOWR('f', 109, OBD_IOC_DATA_TYPE) +#define OBD_IOC_WRITE _IOWR('f', 110, OBD_IOC_DATA_TYPE) + +#define OBD_IOC_STATFS _IOWR('f', 113, OBD_IOC_DATA_TYPE) +#define OBD_IOC_SYNC _IOW('f', 114, OBD_IOC_DATA_TYPE) +/* OBD_IOC_READ2 _IOWR('f', 115, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_FORMAT _IOWR('f', 116, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_PARTITION _IOWR('f', 117, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_COPY _IOWR('f', 120, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_MIGR _IOWR('f', 121, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_PUNCH _IOWR('f', 122, OBD_IOC_DATA_TYPE) */ + +/* OBD_IOC_MODULE_DEBUG _IOWR('f', 124, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_BRW_READ _IOWR('f', 125, OBD_IOC_DATA_TYPE) +#define OBD_IOC_BRW_WRITE _IOWR('f', 126, OBD_IOC_DATA_TYPE) +#define OBD_IOC_NAME2DEV _IOWR('f', 127, OBD_IOC_DATA_TYPE) +#define OBD_IOC_UUID2DEV _IOWR('f', 130, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GETNAME _IOWR('f', 131, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GETMDNAME _IOR('f', 131, char[MAX_OBD_NAME]) +#define OBD_IOC_GETDTNAME OBD_IOC_GETNAME +#define OBD_IOC_LOV_GET_CONFIG _IOWR('f', 132, OBD_IOC_DATA_TYPE) +#define OBD_IOC_CLIENT_RECOVER _IOW('f', 133, OBD_IOC_DATA_TYPE) +#define OBD_IOC_PING_TARGET _IOW('f', 136, OBD_IOC_DATA_TYPE) + +/* OBD_IOC_DEC_FS_USE_COUNT _IO('f', 139) */ +#define OBD_IOC_NO_TRANSNO _IOW('f', 140, OBD_IOC_DATA_TYPE) +#define OBD_IOC_SET_READONLY _IOW('f', 141, OBD_IOC_DATA_TYPE) +#define OBD_IOC_ABORT_RECOVERY _IOR('f', 142, OBD_IOC_DATA_TYPE) +/* OBD_IOC_ROOT_SQUASH _IOWR('f', 143, OBD_IOC_DATA_TYPE) */ +#define OBD_GET_VERSION _IOWR('f', 144, OBD_IOC_DATA_TYPE) +/* OBD_IOC_GSS_SUPPORT _IOWR('f', 145, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_CLOSE_UUID _IOWR('f', 147, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_CHANGELOG_SEND _IOW('f', 148, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GETDEVICE _IOWR('f', 149, OBD_IOC_DATA_TYPE) +#define OBD_IOC_FID2PATH _IOWR('f', 150, OBD_IOC_DATA_TYPE) +/* lustre/lustre_user.h 151-153 */ +/* OBD_IOC_LOV_SETSTRIPE 154 LL_IOC_LOV_SETSTRIPE */ +/* OBD_IOC_LOV_GETSTRIPE 155 LL_IOC_LOV_GETSTRIPE */ +/* OBD_IOC_LOV_SETEA 156 LL_IOC_LOV_SETEA */ +/* lustre/lustre_user.h 157-159 */ +#define OBD_IOC_QUOTACHECK _IOW('f', 160, int) +#define OBD_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) +#define OBD_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) +/* lustre/lustre_user.h 163-176 */ +#define OBD_IOC_CHANGELOG_REG _IOW('f', 177, struct obd_ioctl_data) +#define OBD_IOC_CHANGELOG_DEREG _IOW('f', 178, struct obd_ioctl_data) +#define OBD_IOC_CHANGELOG_CLEAR _IOW('f', 179, struct obd_ioctl_data) +/* OBD_IOC_RECORD _IOWR('f', 180, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_ENDRECORD _IOWR('f', 181, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_PARSE _IOWR('f', 182, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_DORECORD _IOWR('f', 183, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_PROCESS_CFG _IOWR('f', 184, OBD_IOC_DATA_TYPE) +/* OBD_IOC_DUMP_LOG _IOWR('f', 185, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_CLEAR_LOG _IOWR('f', 186, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_PARAM _IOW('f', 187, OBD_IOC_DATA_TYPE) +#define OBD_IOC_POOL _IOWR('f', 188, OBD_IOC_DATA_TYPE) +#define OBD_IOC_REPLACE_NIDS _IOWR('f', 189, OBD_IOC_DATA_TYPE) + +#define OBD_IOC_CATLOGLIST _IOWR('f', 190, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_INFO _IOWR('f', 191, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_PRINT _IOWR('f', 192, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_CANCEL _IOWR('f', 193, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_REMOVE _IOWR('f', 194, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_CHECK _IOWR('f', 195, OBD_IOC_DATA_TYPE) +/* OBD_IOC_LLOG_CATINFO _IOWR('f', 196, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_NODEMAP _IOWR('f', 197, OBD_IOC_DATA_TYPE) + +/* ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) */ +/* ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) */ +/* ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) */ +/* ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) */ + +#define OBD_IOC_GET_OBJ_VERSION _IOR('f', 210, OBD_IOC_DATA_TYPE) + +/* lustre/lustre_user.h 212-217 */ +#define OBD_IOC_GET_MNTOPT _IOW('f', 220, mntopt_t) +#define OBD_IOC_ECHO_MD _IOR('f', 221, struct obd_ioctl_data) +#define OBD_IOC_ECHO_ALLOC_SEQ _IOWR('f', 222, struct obd_ioctl_data) +#define OBD_IOC_START_LFSCK _IOWR('f', 230, OBD_IOC_DATA_TYPE) +#define OBD_IOC_STOP_LFSCK _IOW('f', 231, OBD_IOC_DATA_TYPE) +#define OBD_IOC_QUERY_LFSCK _IOR('f', 232, struct obd_ioctl_data) +/* lustre/lustre_user.h 240-249 */ +/* LIBCFS_IOC_DEBUG_MASK 250 */ + +#define IOC_OSC_SET_ACTIVE _IOWR('h', 21, void *) + +#endif /* LUSTRE_IOCTL_H_ */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index ef6f38ff359e..6fc985571cba 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -42,8 +42,35 @@ * @{ */ +#ifdef __KERNEL__ +# include +# include /* snprintf() */ +# include +#else /* !__KERNEL__ */ +# define NEED_QUOTA_DEFS +# include /* snprintf() */ +# include +# include +# include +#endif /* __KERNEL__ */ #include "ll_fiemap.h" -#include "../linux/lustre_user.h" + +/* + * We need to always use 64bit version because the structure + * is shared across entire cluster where 32bit and 64bit machines + * are co-existing. + */ +#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64) +typedef struct stat64 lstat_t; +#define lstat_f lstat64 +#else +typedef struct stat lstat_t; +#define lstat_f lstat +#endif + +#define HAVE_LOV_USER_MDS_DATA + +#define LUSTRE_EOF 0xffffffffffffffffULL /* for statfs() */ #define LL_SUPER_MAGIC 0x0BD00BD0 @@ -117,6 +144,11 @@ struct lu_fid { __u32 f_ver; }; +static inline bool fid_is_zero(const struct lu_fid *fid) +{ + return !fid->f_seq && !fid->f_oid; +} + struct filter_fid { struct lu_fid ff_parent; /* ff_parent.f_ver == file stripe number */ }; @@ -167,7 +199,7 @@ struct lustre_mdt_attrs { */ struct ost_id { union { - struct ostid { + struct { __u64 oi_id; __u64 oi_seq; } oi; @@ -188,26 +220,20 @@ struct ost_id { * *STRIPE* - set/get lov_user_md * *INFO - set/get lov_user_mds_data */ -/* see for ioctl numberss 101-150 */ +/* lustre_ioctl.h 101-150 */ #define LL_IOC_GETFLAGS _IOR('f', 151, long) #define LL_IOC_SETFLAGS _IOW('f', 152, long) #define LL_IOC_CLRFLAGS _IOW('f', 153, long) -/* LL_IOC_LOV_SETSTRIPE: See also OBD_IOC_LOV_SETSTRIPE */ #define LL_IOC_LOV_SETSTRIPE _IOW('f', 154, long) -/* LL_IOC_LOV_GETSTRIPE: See also OBD_IOC_LOV_GETSTRIPE */ #define LL_IOC_LOV_GETSTRIPE _IOW('f', 155, long) -/* LL_IOC_LOV_SETEA: See also OBD_IOC_LOV_SETEA */ #define LL_IOC_LOV_SETEA _IOW('f', 156, long) -#define LL_IOC_RECREATE_OBJ _IOW('f', 157, long) -#define LL_IOC_RECREATE_FID _IOW('f', 157, struct lu_fid) +/* LL_IOC_RECREATE_OBJ 157 obsolete */ +/* LL_IOC_RECREATE_FID 158 obsolete */ #define LL_IOC_GROUP_LOCK _IOW('f', 158, long) #define LL_IOC_GROUP_UNLOCK _IOW('f', 159, long) -/* LL_IOC_QUOTACHECK: See also OBD_IOC_QUOTACHECK */ -#define LL_IOC_QUOTACHECK _IOW('f', 160, int) -/* LL_IOC_POLL_QUOTACHECK: See also OBD_IOC_POLL_QUOTACHECK */ -#define LL_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) -/* LL_IOC_QUOTACTL: See also OBD_IOC_QUOTACTL */ -#define LL_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) +/* #define LL_IOC_QUOTACHECK 160 OBD_IOC_QUOTACHECK */ +/* #define LL_IOC_POLL_QUOTACHECK 161 OBD_IOC_POLL_QUOTACHECK */ +/* #define LL_IOC_QUOTACTL 162 OBD_IOC_QUOTACTL */ #define IOC_OBD_STATFS _IOWR('f', 164, struct obd_statfs *) #define IOC_LOV_GETINFO _IOWR('f', 165, struct lov_user_mds_data *) #define LL_IOC_FLUSHCTX _IOW('f', 166, long) @@ -221,8 +247,7 @@ struct ost_id { #define LL_IOC_GET_CONNECT_FLAGS _IOWR('f', 174, __u64 *) #define LL_IOC_GET_MDTIDX _IOR('f', 175, int) -/* see for ioctl numbers 177-210 */ - +/* lustre_ioctl.h 177-210 */ #define LL_IOC_HSM_STATE_GET _IOR('f', 211, struct hsm_user_state) #define LL_IOC_HSM_STATE_SET _IOW('f', 212, struct hsm_state_set) #define LL_IOC_HSM_CT_START _IOW('f', 213, struct lustre_kernelcomm) @@ -242,6 +267,17 @@ struct ost_id { #define LL_IOC_SET_LEASE _IOWR('f', 243, long) #define LL_IOC_GET_LEASE _IO('f', 244) #define LL_IOC_HSM_IMPORT _IOWR('f', 245, struct hsm_user_import) +#define LL_IOC_LMV_SET_DEFAULT_STRIPE _IOWR('f', 246, struct lmv_user_md) +#define LL_IOC_MIGRATE _IOR('f', 247, int) +#define LL_IOC_FID2MDTIDX _IOWR('f', 248, struct lu_fid) +#define LL_IOC_GETPARENT _IOWR('f', 249, struct getparent) + +/* Lease types for use as arg and return of LL_IOC_{GET,SET}_LEASE ioctl. */ +enum ll_lease_type { + LL_LEASE_RDLCK = 0x1, + LL_LEASE_WRLCK = 0x2, + LL_LEASE_UNLCK = 0x4, +}; #define LL_STATFS_LMV 1 #define LL_STATFS_LOV 2 @@ -253,10 +289,6 @@ struct ost_id { #define IOC_MDC_GETFILEINFO _IOWR(IOC_MDC_TYPE, 22, struct lov_user_mds_data *) #define LL_IOC_MDC_GETINFO _IOWR(IOC_MDC_TYPE, 23, struct lov_user_mds_data *) -/* Keep these for backward compartability. */ -#define LL_IOC_OBD_STATFS IOC_OBD_STATFS -#define IOC_MDC_GETSTRIPE IOC_MDC_GETFILESTRIPE - #define MAX_OBD_NAME 128 /* If this changes, a NEW ioctl must be added */ /* Define O_LOV_DELAY_CREATE to be a mask that is not useful for regular @@ -273,20 +305,26 @@ struct ost_id { #define LL_FILE_LOCKLESS_IO 0x00000010 /* server-side locks with cio */ #define LL_FILE_RMTACL 0x00000020 -#define LOV_USER_MAGIC_V1 0x0BD10BD0 -#define LOV_USER_MAGIC LOV_USER_MAGIC_V1 -#define LOV_USER_MAGIC_JOIN_V1 0x0BD20BD0 -#define LOV_USER_MAGIC_V3 0x0BD30BD0 +#define LOV_USER_MAGIC_V1 0x0BD10BD0 +#define LOV_USER_MAGIC LOV_USER_MAGIC_V1 +#define LOV_USER_MAGIC_JOIN_V1 0x0BD20BD0 +#define LOV_USER_MAGIC_V3 0x0BD30BD0 +/* 0x0BD40BD0 is occupied by LOV_MAGIC_MIGRATE */ +#define LOV_USER_MAGIC_SPECIFIC 0x0BD50BD0 /* for specific OSTs */ -#define LMV_MAGIC_V1 0x0CD10CD0 /*normal stripe lmv magic */ -#define LMV_USER_MAGIC 0x0CD20CD0 /*default lmv magic*/ +#define LMV_USER_MAGIC 0x0CD30CD0 /*default lmv magic*/ -#define LOV_PATTERN_RAID0 0x001 -#define LOV_PATTERN_RAID1 0x002 -#define LOV_PATTERN_FIRST 0x100 +#define LOV_PATTERN_RAID0 0x001 +#define LOV_PATTERN_RAID1 0x002 +#define LOV_PATTERN_FIRST 0x100 +#define LOV_PATTERN_CMOBD 0x200 -#define LOV_MAXPOOLNAME 16 -#define LOV_POOLNAMEF "%.16s" +#define LOV_PATTERN_F_MASK 0xffff0000 +#define LOV_PATTERN_F_HOLE 0x40000000 /* there is hole in LOV EA */ +#define LOV_PATTERN_F_RELEASED 0x80000000 /* HSM released file */ + +#define LOV_MAXPOOLNAME 15 +#define LOV_POOLNAMEF "%.15s" #define LOV_MIN_STRIPE_BITS 16 /* maximum PAGE_SIZE (ia64), power of 2 */ #define LOV_MIN_STRIPE_SIZE (1 << LOV_MIN_STRIPE_BITS) @@ -344,18 +382,17 @@ struct lov_user_md_v3 { /* LOV EA user data (host-endian) */ * used when reading */ }; - char lmm_pool_name[LOV_MAXPOOLNAME]; /* pool name */ + char lmm_pool_name[LOV_MAXPOOLNAME + 1]; /* pool name */ struct lov_user_ost_data_v1 lmm_objects[0]; /* per-stripe data */ } __packed; static inline __u32 lov_user_md_size(__u16 stripes, __u32 lmm_magic) { - if (lmm_magic == LOV_USER_MAGIC_V3) - return sizeof(struct lov_user_md_v3) + - stripes * sizeof(struct lov_user_ost_data_v1); - else + if (lmm_magic == LOV_USER_MAGIC_V1) return sizeof(struct lov_user_md_v1) + stripes * sizeof(struct lov_user_ost_data_v1); + return sizeof(struct lov_user_md_v3) + + stripes * sizeof(struct lov_user_ost_data_v1); } /* Compile with -D_LARGEFILE64_SOURCE or -D_GNU_SOURCE (or #define) to @@ -374,19 +411,26 @@ struct lov_user_mds_data_v3 { } __packed; #endif -/* keep this to be the same size as lov_user_ost_data_v1 */ struct lmv_user_mds_data { struct lu_fid lum_fid; __u32 lum_padding; __u32 lum_mds; }; -/* lum_type */ -enum { - LMV_STRIPE_TYPE = 0, - LMV_DEFAULT_TYPE = 1, +enum lmv_hash_type { + LMV_HASH_TYPE_UNKNOWN = 0, /* 0 is reserved for testing purpose */ + LMV_HASH_TYPE_ALL_CHARS = 1, + LMV_HASH_TYPE_FNV_1A_64 = 2, }; +#define LMV_HASH_NAME_ALL_CHARS "all_char" +#define LMV_HASH_NAME_FNV_1A_64 "fnv_1a_64" + +/* + * Got this according to how get LOV_MAX_STRIPE_COUNT, see above, + * (max buffer size - lmv+rpc header) / sizeof(struct lmv_user_mds_data) + */ +#define LMV_MAX_STRIPE_COUNT 2000 /* ((12 * 4096 - 256) / 24) */ #define lmv_user_md lmv_user_md_v1 struct lmv_user_md_v1 { __u32 lum_magic; /* must be the first field */ @@ -397,9 +441,9 @@ struct lmv_user_md_v1 { __u32 lum_padding1; __u32 lum_padding2; __u32 lum_padding3; - char lum_pool_name[LOV_MAXPOOLNAME]; + char lum_pool_name[LOV_MAXPOOLNAME + 1]; struct lmv_user_mds_data lum_objects[0]; -}; +} __packed; static inline int lmv_user_md_size(int stripes, int lmm_magic) { @@ -407,6 +451,8 @@ static inline int lmv_user_md_size(int stripes, int lmm_magic) stripes * sizeof(struct lmv_user_mds_data); } +void lustre_swab_lmv_user_md(struct lmv_user_md *lum); + struct ll_recreate_obj { __u64 lrc_id; __u32 lrc_ost_idx; @@ -498,6 +544,12 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen) /********* Quotas **********/ +#define Q_QUOTACHECK 0x800100 /* deprecated as of 2.4 */ +#define Q_INITQUOTA 0x800101 /* deprecated as of 2.4 */ +#define Q_GETOINFO 0x800102 /* get obd quota info */ +#define Q_GETOQUOTA 0x800103 /* get obd quotas */ +#define Q_FINVALIDATE 0x800104 /* deprecated as of 2.4 */ + /* these must be explicitly translated into linux Q_* in ll_dir_ioctl */ #define LUSTRE_Q_QUOTAON 0x800002 /* turn quotas on */ #define LUSTRE_Q_QUOTAOFF 0x800003 /* turn quotas off */ @@ -648,11 +700,16 @@ static inline const char *changelog_type2str(int type) } /* per-record flags */ -#define CLF_VERSION 0x1000 -#define CLF_EXT_VERSION 0x2000 #define CLF_FLAGSHIFT 12 #define CLF_FLAGMASK ((1U << CLF_FLAGSHIFT) - 1) #define CLF_VERMASK (~CLF_FLAGMASK) +enum changelog_rec_flags { + CLF_VERSION = 0x1000, + CLF_RENAME = 0x2000, + CLF_JOBID = 0x4000, + CLF_SUPPORTED = CLF_VERSION | CLF_RENAME | CLF_JOBID +}; + /* Anything under the flagmask may be per-type (if desired) */ /* Flags for unlink */ #define CLF_UNLINK_LAST 0x0001 /* Unlink of last hardlink */ @@ -736,12 +793,35 @@ static inline void hsm_set_cl_error(int *flags, int error) *flags |= (error << CLF_HSM_ERR_L); } -#define CR_MAXSIZE cfs_size_round(2*NAME_MAX + 1 + \ - sizeof(struct changelog_ext_rec)) +enum changelog_send_flag { + /* Not yet implemented */ + CHANGELOG_FLAG_FOLLOW = BIT(0), + /* + * Blocking IO makes sense in case of slow user parsing of the records, + * but it also prevents us from cleaning up if the records are not + * consumed. + */ + CHANGELOG_FLAG_BLOCK = BIT(1), + /* Pack jobid into the changelog records if available. */ + CHANGELOG_FLAG_JOBID = BIT(2), +}; +#define CR_MAXSIZE cfs_size_round(2 * NAME_MAX + 2 + \ + changelog_rec_offset(CLF_SUPPORTED)) + +/* 31 usable bytes string + null terminator. */ +#define LUSTRE_JOBID_SIZE 32 + +/* + * This is the minimal changelog record. It can contain extensions + * such as rename fields or process jobid. Its exact content is described + * by the cr_flags. + * + * Extensions are packed in the same order as their corresponding flags. + */ struct changelog_rec { __u16 cr_namelen; - __u16 cr_flags; /**< (flags&CLF_FLAGMASK)|CLF_VERSION */ + __u16 cr_flags; /**< \a changelog_rec_flags */ __u32 cr_type; /**< \a changelog_rec_type */ __u64 cr_index; /**< changelog record number */ __u64 cr_prev; /**< last index for this target fid */ @@ -751,55 +831,138 @@ struct changelog_rec { __u32 cr_markerflags; /**< CL_MARK flags */ }; struct lu_fid cr_pfid; /**< parent fid */ - char cr_name[0]; /**< last element */ } __packed; -/* changelog_ext_rec is 2*sizeof(lu_fid) bigger than changelog_rec, to save - * space, only rename uses changelog_ext_rec, while others use changelog_rec to - * store records. - */ -struct changelog_ext_rec { - __u16 cr_namelen; - __u16 cr_flags; /**< (flags & CLF_FLAGMASK) | - * CLF_EXT_VERSION - */ - __u32 cr_type; /**< \a changelog_rec_type */ - __u64 cr_index; /**< changelog record number */ - __u64 cr_prev; /**< last index for this target fid */ - __u64 cr_time; - union { - struct lu_fid cr_tfid; /**< target fid */ - __u32 cr_markerflags; /**< CL_MARK flags */ - }; - struct lu_fid cr_pfid; /**< target parent fid */ - struct lu_fid cr_sfid; /**< source fid, or zero */ - struct lu_fid cr_spfid; /**< source parent fid, or zero */ - char cr_name[0]; /**< last element */ -} __packed; +/* Changelog extension for RENAME. */ +struct changelog_ext_rename { + struct lu_fid cr_sfid; /**< source fid, or zero */ + struct lu_fid cr_spfid; /**< source parent fid, or zero */ +}; -#define CHANGELOG_REC_EXTENDED(rec) \ - (((rec)->cr_flags & CLF_VERMASK) == CLF_EXT_VERSION) +/* Changelog extension to include JOBID. */ +struct changelog_ext_jobid { + char cr_jobid[LUSTRE_JOBID_SIZE]; /**< zero-terminated string. */ +}; -static inline int changelog_rec_size(struct changelog_rec *rec) +static inline size_t changelog_rec_offset(enum changelog_rec_flags crf) { - return CHANGELOG_REC_EXTENDED(rec) ? sizeof(struct changelog_ext_rec) : - sizeof(*rec); + size_t size = sizeof(struct changelog_rec); + + if (crf & CLF_RENAME) + size += sizeof(struct changelog_ext_rename); + + if (crf & CLF_JOBID) + size += sizeof(struct changelog_ext_jobid); + + return size; } +static inline size_t changelog_rec_size(struct changelog_rec *rec) +{ + return changelog_rec_offset(rec->cr_flags); +} + +static inline size_t changelog_rec_varsize(struct changelog_rec *rec) +{ + return changelog_rec_size(rec) - sizeof(*rec) + rec->cr_namelen; +} + +static inline +struct changelog_ext_rename *changelog_rec_rename(struct changelog_rec *rec) +{ + enum changelog_rec_flags crf = rec->cr_flags & CLF_VERSION; + + return (struct changelog_ext_rename *)((char *)rec + + changelog_rec_offset(crf)); +} + +/* The jobid follows the rename extension, if present */ +static inline +struct changelog_ext_jobid *changelog_rec_jobid(struct changelog_rec *rec) +{ + enum changelog_rec_flags crf = rec->cr_flags & + (CLF_VERSION | CLF_RENAME); + + return (struct changelog_ext_jobid *)((char *)rec + + changelog_rec_offset(crf)); +} + +/* The name follows the rename and jobid extensions, if present */ static inline char *changelog_rec_name(struct changelog_rec *rec) { - return CHANGELOG_REC_EXTENDED(rec) ? - ((struct changelog_ext_rec *)rec)->cr_name : rec->cr_name; + return (char *)rec + changelog_rec_offset(rec->cr_flags & + CLF_SUPPORTED); } -static inline int changelog_rec_snamelen(struct changelog_ext_rec *rec) +static inline size_t changelog_rec_snamelen(struct changelog_rec *rec) { - return rec->cr_namelen - strlen(rec->cr_name) - 1; + return rec->cr_namelen - strlen(changelog_rec_name(rec)) - 1; } -static inline char *changelog_rec_sname(struct changelog_ext_rec *rec) +static inline char *changelog_rec_sname(struct changelog_rec *rec) { - return rec->cr_name + strlen(rec->cr_name) + 1; + char *cr_name = changelog_rec_name(rec); + + return cr_name + strlen(cr_name) + 1; +} + +/** + * Remap a record to the desired format as specified by the crf flags. + * The record must be big enough to contain the final remapped version. + * Superfluous extension fields are removed and missing ones are added + * and zeroed. The flags of the record are updated accordingly. + * + * The jobid and rename extensions can be added to a record, to match the + * format an application expects, typically. In this case, the newly added + * fields will be zeroed. + * The Jobid field can be removed, to guarantee compatibility with older + * clients that don't expect this field in the records they process. + * + * The following assumptions are being made: + * - CLF_RENAME will not be removed + * - CLF_JOBID will not be added without CLF_RENAME being added too + * + * @param[in,out] rec The record to remap. + * @param[in] crf_wanted Flags describing the desired extensions. + */ +static inline void changelog_remap_rec(struct changelog_rec *rec, + enum changelog_rec_flags crf_wanted) +{ + char *jid_mov, *rnm_mov; + + crf_wanted &= CLF_SUPPORTED; + + if ((rec->cr_flags & CLF_SUPPORTED) == crf_wanted) + return; + + /* First move the variable-length name field */ + memmove((char *)rec + changelog_rec_offset(crf_wanted), + changelog_rec_name(rec), rec->cr_namelen); + + /* Locations of jobid and rename extensions in the remapped record */ + jid_mov = (char *)rec + + changelog_rec_offset(crf_wanted & ~CLF_JOBID); + rnm_mov = (char *)rec + + changelog_rec_offset(crf_wanted & ~(CLF_JOBID | CLF_RENAME)); + + /* Move the extension fields to the desired positions */ + if ((crf_wanted & CLF_JOBID) && (rec->cr_flags & CLF_JOBID)) + memmove(jid_mov, changelog_rec_jobid(rec), + sizeof(struct changelog_ext_jobid)); + + if ((crf_wanted & CLF_RENAME) && (rec->cr_flags & CLF_RENAME)) + memmove(rnm_mov, changelog_rec_rename(rec), + sizeof(struct changelog_ext_rename)); + + /* Clear newly added fields */ + if ((crf_wanted & CLF_JOBID) && !(rec->cr_flags & CLF_JOBID)) + memset(jid_mov, 0, sizeof(struct changelog_ext_jobid)); + + if ((crf_wanted & CLF_RENAME) && !(rec->cr_flags & CLF_RENAME)) + memset(rnm_mov, 0, sizeof(struct changelog_ext_rename)); + + /* Update the record's flags accordingly */ + rec->cr_flags = (rec->cr_flags & CLF_FLAGMASK) | crf_wanted; } struct ioc_changelog { @@ -978,7 +1141,7 @@ struct hsm_user_request { /** Return pointer to data field in a hsm user request */ static inline void *hur_data(struct hsm_user_request *hur) { - return &(hur->hur_user_item[hur->hur_request.hr_itemcount]); + return &hur->hur_user_item[hur->hur_request.hr_itemcount]; } /** diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h index 95a0be13c0fb..8eb394e64b25 100644 --- a/drivers/staging/lustre/lustre/include/lustre_cfg.h +++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h @@ -151,13 +151,11 @@ static inline void lustre_cfg_bufs_reset(struct lustre_cfg_bufs *bufs, char *nam lustre_cfg_bufs_set_string(bufs, 0, name); } -static inline void *lustre_cfg_buf(struct lustre_cfg *lcfg, int index) +static inline void *lustre_cfg_buf(struct lustre_cfg *lcfg, __u32 index) { - int i; - int offset; - int bufcount; - - LASSERT(index >= 0); + __u32 i; + size_t offset; + __u32 bufcount; bufcount = lcfg->lcfg_bufcount; if (index >= bufcount) @@ -172,7 +170,7 @@ static inline void *lustre_cfg_buf(struct lustre_cfg *lcfg, int index) static inline void lustre_cfg_bufs_init(struct lustre_cfg_bufs *bufs, struct lustre_cfg *lcfg) { - int i; + __u32 i; bufs->lcfg_bufcount = lcfg->lcfg_bufcount; for (i = 0; i < bufs->lcfg_bufcount; i++) { @@ -181,7 +179,7 @@ static inline void lustre_cfg_bufs_init(struct lustre_cfg_bufs *bufs, } } -static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, int index) +static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, __u32 index) { char *s; @@ -197,8 +195,8 @@ static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, int index) * of data. Try to use the padding first though. */ if (s[lcfg->lcfg_buflens[index] - 1] != '\0') { - int last = min((int)lcfg->lcfg_buflens[index], - cfs_size_round(lcfg->lcfg_buflens[index]) - 1); + size_t last = min((size_t)lcfg->lcfg_buflens[index], + cfs_size_round(lcfg->lcfg_buflens[index]) - 1); char lost = s[last]; s[last] = '\0'; @@ -210,10 +208,10 @@ static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, int index) return s; } -static inline int lustre_cfg_len(__u32 bufcount, __u32 *buflens) +static inline __u32 lustre_cfg_len(__u32 bufcount, __u32 *buflens) { - int i; - int len; + __u32 i; + __u32 len; len = LCFG_HDR_SIZE(bufcount); for (i = 0; i < bufcount; i++) @@ -254,7 +252,7 @@ static inline void lustre_cfg_free(struct lustre_cfg *lcfg) return; } -static inline int lustre_cfg_sanity_check(void *buf, int len) +static inline int lustre_cfg_sanity_check(void *buf, size_t len) { struct lustre_cfg *lcfg = (struct lustre_cfg *)buf; diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/lustre_compat.h similarity index 96% rename from drivers/staging/lustre/lustre/include/linux/lustre_compat25.h rename to drivers/staging/lustre/lustre/include/lustre_compat.h index 1eb64ec4bed4..567c438e93cb 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/lustre_compat.h @@ -30,8 +30,8 @@ * Lustre is a trademark of Sun Microsystems, Inc. */ -#ifndef _LINUX_COMPAT25_H -#define _LINUX_COMPAT25_H +#ifndef _LUSTRE_COMPAT_H +#define _LUSTRE_COMPAT_H #include #include @@ -74,4 +74,4 @@ # define ext2_find_next_zero_bit find_next_zero_bit_le #endif -#endif /* _COMPAT25_H */ +#endif /* _LUSTRE_COMPAT_H */ diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index 60051a5cfe20..d03534432624 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -572,6 +572,11 @@ enum lvb_type { LVB_T_LAYOUT = 3, }; +/** + * LDLM_GID_ANY is used to match any group id in ldlm_lock_match(). + */ +#define LDLM_GID_ANY ((__u64)-1) + /** * LDLM lock structure * @@ -968,6 +973,7 @@ struct ldlm_enqueue_info { void *ei_cb_cp; /** lock completion callback */ void *ei_cb_gl; /** lock glimpse callback */ void *ei_cbdata; /** Data to be passed into callbacks. */ + unsigned int ei_enq_slave:1; /* whether enqueue slave stripes */ }; extern struct obd_ops ldlm_obd_ops; @@ -1281,16 +1287,6 @@ int ldlm_cli_cancel_list(struct list_head *head, int count, int intent_disposition(struct ldlm_reply *rep, int flag); void intent_set_disposition(struct ldlm_reply *rep, int flag); -/* ioctls for trying requests */ -#define IOC_LDLM_TYPE 'f' -#define IOC_LDLM_MIN_NR 40 - -#define IOC_LDLM_TEST _IOWR('f', 40, long) -#define IOC_LDLM_DUMP _IOWR('f', 41, long) -#define IOC_LDLM_REGRESS_START _IOWR('f', 42, long) -#define IOC_LDLM_REGRESS_STOP _IOWR('f', 43, long) -#define IOC_LDLM_MAX_NR 43 - /** * "Modes" of acquiring lock_res, necessary to tell lockdep that taking more * than one lock_res is dead-lock safe. diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h index e7e0c21a9b40..a0f064d237c9 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h @@ -28,21 +28,6 @@ /** l_flags bits marked as "all_flags" bits */ #define LDLM_FL_ALL_FLAGS_MASK 0x00FFFFFFC08F932FULL -/** l_flags bits marked as "ast" bits */ -#define LDLM_FL_AST_MASK 0x0000000080008000ULL - -/** l_flags bits marked as "blocked" bits */ -#define LDLM_FL_BLOCKED_MASK 0x000000000000000EULL - -/** l_flags bits marked as "gone" bits */ -#define LDLM_FL_GONE_MASK 0x0006004000000000ULL - -/** l_flags bits marked as "inherit" bits */ -#define LDLM_FL_INHERIT_MASK 0x0000000000800000ULL - -/** l_flags bits marked as "off_wire" bits */ -#define LDLM_FL_OFF_WIRE_MASK 0x00FFFFFF00000000ULL - /** extent, mode, or resource changed */ #define LDLM_FL_LOCK_CHANGED 0x0000000000000001ULL /* bit 0 */ #define ldlm_is_lock_changed(_l) LDLM_TEST_FLAG((_l), 1ULL << 0) @@ -372,6 +357,27 @@ #define ldlm_set_excl(_l) LDLM_SET_FLAG((_l), 1ULL << 55) #define ldlm_clear_excl(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 55) +/** l_flags bits marked as "ast" bits */ +#define LDLM_FL_AST_MASK (LDLM_FL_FLOCK_DEADLOCK |\ + LDLM_FL_AST_DISCARD_DATA) + +/** l_flags bits marked as "blocked" bits */ +#define LDLM_FL_BLOCKED_MASK (LDLM_FL_BLOCK_GRANTED |\ + LDLM_FL_BLOCK_CONV |\ + LDLM_FL_BLOCK_WAIT) + +/** l_flags bits marked as "gone" bits */ +#define LDLM_FL_GONE_MASK (LDLM_FL_DESTROYED |\ + LDLM_FL_FAILED) + +/** l_flags bits marked as "inherit" bits */ +/* Flags inherited from wire on enqueue/reply between client/server. */ +/* NO_TIMEOUT flag to force ldlm_lock_match() to wait with no timeout. */ +/* TEST_LOCK flag to not let TEST lock to be granted. */ +#define LDLM_FL_INHERIT_MASK (LDLM_FL_CANCEL_ON_BLOCK |\ + LDLM_FL_NO_TIMEOUT |\ + LDLM_FL_TEST_LOCK) + /** test for ldlm_lock flag bit set */ #define LDLM_TEST_FLAG(_l, _b) (((_l)->l_flags & (_b)) != 0) diff --git a/drivers/staging/lustre/lustre/include/lustre_eacl.h b/drivers/staging/lustre/lustre/include/lustre_eacl.h index d1039e1ff70d..1e71a8638186 100644 --- a/drivers/staging/lustre/lustre/include/lustre_eacl.h +++ b/drivers/staging/lustre/lustre/include/lustre_eacl.h @@ -46,6 +46,7 @@ #ifdef CONFIG_FS_POSIX_ACL +#include #include typedef struct { diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 743671a547ef..316780693193 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -229,6 +229,7 @@ enum local_oid { MDD_LOV_OBJ_OSEQ = 4121UL, LFSCK_NAMESPACE_OID = 4122UL, REMOTE_PARENT_DIR_OID = 4123UL, + SLAVE_LLOG_CATALOGS_OID = 4124UL, }; static inline void lu_local_obj_fid(struct lu_fid *fid, __u32 oid) @@ -392,21 +393,19 @@ struct ldlm_namespace; * but was moved into name[1] along with the OID to avoid consuming the * renaming name[2,3] fields that need to be used for the quota identifier. */ -static inline struct ldlm_res_id * +static inline void fid_build_reg_res_name(const struct lu_fid *fid, struct ldlm_res_id *res) { memset(res, 0, sizeof(*res)); res->name[LUSTRE_RES_ID_SEQ_OFF] = fid_seq(fid); res->name[LUSTRE_RES_ID_VER_OID_OFF] = fid_ver_oid(fid); - - return res; } /* * Return true if resource is for object identified by FID. */ -static inline int fid_res_name_eq(const struct lu_fid *fid, - const struct ldlm_res_id *res) +static inline bool fid_res_name_eq(const struct lu_fid *fid, + const struct ldlm_res_id *res) { return res->name[LUSTRE_RES_ID_SEQ_OFF] == fid_seq(fid) && res->name[LUSTRE_RES_ID_VER_OID_OFF] == fid_ver_oid(fid); @@ -415,29 +414,25 @@ static inline int fid_res_name_eq(const struct lu_fid *fid, /* * Extract FID from LDLM resource. Reverse of fid_build_reg_res_name(). */ -static inline struct lu_fid * +static inline void fid_extract_from_res_name(struct lu_fid *fid, const struct ldlm_res_id *res) { fid->f_seq = res->name[LUSTRE_RES_ID_SEQ_OFF]; fid->f_oid = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF]); fid->f_ver = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32); LASSERT(fid_res_name_eq(fid, res)); - - return fid; } /* * Build (DLM) resource identifier from global quota FID and quota ID. */ -static inline struct ldlm_res_id * +static inline void fid_build_quota_res_name(const struct lu_fid *glb_fid, union lquota_id *qid, struct ldlm_res_id *res) { fid_build_reg_res_name(glb_fid, res); res->name[LUSTRE_RES_ID_QUOTA_SEQ_OFF] = fid_seq(&qid->qid_fid); res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF] = fid_ver_oid(&qid->qid_fid); - - return res; } /* @@ -454,14 +449,12 @@ static inline void fid_extract_from_quota_res(struct lu_fid *glb_fid, (__u32)(res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF] >> 32); } -static inline struct ldlm_res_id * +static inline void fid_build_pdo_res_name(const struct lu_fid *fid, unsigned int hash, struct ldlm_res_id *res) { fid_build_reg_res_name(fid, res); res->name[LUSTRE_RES_ID_HSH_OFF] = hash; - - return res; } /** @@ -482,7 +475,7 @@ fid_build_pdo_res_name(const struct lu_fid *fid, unsigned int hash, * res will be built from normal FID directly, i.e. res[0] = f_seq, * res[1] = f_oid + f_ver. */ -static inline void ostid_build_res_name(struct ost_id *oi, +static inline void ostid_build_res_name(const struct ost_id *oi, struct ldlm_res_id *name) { memset(name, 0, sizeof(*name)); @@ -497,8 +490,8 @@ static inline void ostid_build_res_name(struct ost_id *oi, /** * Return true if the resource is for the object identified by this id & group. */ -static inline int ostid_res_name_eq(struct ost_id *oi, - struct ldlm_res_id *name) +static inline int ostid_res_name_eq(const struct ost_id *oi, + const struct ldlm_res_id *name) { /* Note: it is just a trick here to save some effort, probably the * correct way would be turn them into the FID and compare @@ -603,13 +596,14 @@ static inline __u32 fid_flatten32(const struct lu_fid *fid) * (from OID), or up to 128M inodes without collisions for new files. */ ino = ((seq & 0x000fffffULL) << 12) + ((seq >> 8) & 0xfffff000) + - (seq >> (64 - (40-8)) & 0xffffff00) + + (seq >> (64 - (40 - 8)) & 0xffffff00) + (fid_oid(fid) & 0xff000fff) + ((fid_oid(fid) & 0x00fff000) << 8); return ino ? ino : fid_oid(fid); } -static inline int lu_fid_diff(struct lu_fid *fid1, struct lu_fid *fid2) +static inline int lu_fid_diff(const struct lu_fid *fid1, + const struct lu_fid *fid2) { LASSERTF(fid_seq(fid1) == fid_seq(fid2), "fid1:"DFID", fid2:"DFID"\n", PFID(fid1), PFID(fid2)); diff --git a/drivers/staging/lustre/lustre/include/lustre_handles.h b/drivers/staging/lustre/lustre/include/lustre_handles.h index 1a63a6b9e116..e071bac9df57 100644 --- a/drivers/staging/lustre/lustre/include/lustre_handles.h +++ b/drivers/staging/lustre/lustre/include/lustre_handles.h @@ -66,6 +66,7 @@ struct portals_handle_ops { struct portals_handle { struct list_head h_link; __u64 h_cookie; + const void *h_owner; struct portals_handle_ops *h_ops; /* newly added fields to handle the RCU issue. -jxiong */ @@ -75,15 +76,13 @@ struct portals_handle { unsigned int h_in:1; }; -#define RCU2HANDLE(rcu) container_of(rcu, struct portals_handle, h_rcu) - /* handles.c */ /* Add a handle to the hash table */ void class_handle_hash(struct portals_handle *, struct portals_handle_ops *ops); void class_handle_unhash(struct portals_handle *); -void *class_handle2object(__u64 cookie); +void *class_handle2object(__u64 cookie, const void *owner); void class_handle_free_cb(struct rcu_head *rcu); int class_handle_init(void); void class_handle_cleanup(void); diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h index 4445be7a59dd..5461ba33d90c 100644 --- a/drivers/staging/lustre/lustre/include/lustre_import.h +++ b/drivers/staging/lustre/lustre/include/lustre_import.h @@ -285,8 +285,10 @@ struct obd_import { imp_resend_replay:1, /* disable normal recovery, for test only. */ imp_no_pinger_recover:1, +#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE /* need IR MNE swab */ imp_need_mne_swab:1, +#endif /* import must be reconnected instead of * chosing new connection */ @@ -305,28 +307,6 @@ struct obd_import { time64_t imp_last_reply_time; /* for health check */ }; -typedef void (*obd_import_callback)(struct obd_import *imp, void *closure, - int event, void *event_arg, void *cb_data); - -/** - * Structure for import observer. - * It is possible to register "observer" on an import and every time - * something happens to an import (like connect/evict/disconnect) - * obderver will get its callback called with event type - */ -struct obd_import_observer { - struct list_head oio_chain; - obd_import_callback oio_cb; - void *oio_cb_data; -}; - -void class_observe_import(struct obd_import *imp, obd_import_callback cb, - void *cb_data); -void class_unobserve_import(struct obd_import *imp, obd_import_callback cb, - void *cb_data); -void class_notify_import_observers(struct obd_import *imp, int event, - void *event_arg); - /* import.c */ static inline unsigned int at_est2timeout(unsigned int val) { diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 06958f217fc8..6b231913ba2e 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -51,7 +51,6 @@ #include "lustre_cfg.h" /* target.c */ -struct kstatfs; struct ptlrpc_request; struct obd_export; struct lu_target; @@ -74,325 +73,8 @@ int do_set_info_async(struct obd_import *imp, u32 vallen, void *val, struct ptlrpc_request_set *set); -#define OBD_RECOVERY_MAX_TIME (obd_timeout * 18) /* b13079 */ -#define OBD_MAX_IOCTL_BUFFER CONFIG_LUSTRE_OBD_MAX_IOCTL_BUFFER - void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id); -/* client.c */ - -int client_sanobd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg); -struct client_obd *client_conn2cli(struct lustre_handle *conn); - -struct md_open_data; -struct obd_client_handle { - struct lustre_handle och_fh; - struct lu_fid och_fid; - struct md_open_data *och_mod; - struct lustre_handle och_lease_handle; /* open lock for lease */ - __u32 och_magic; - fmode_t och_flags; -}; - -#define OBD_CLIENT_HANDLE_MAGIC 0xd15ea5ed - -/* statfs_pack.c */ -void statfs_unpack(struct kstatfs *sfs, struct obd_statfs *osfs); - -/* - * For md echo client - */ -enum md_echo_cmd { - ECHO_MD_CREATE = 1, /* Open/Create file on MDT */ - ECHO_MD_MKDIR = 2, /* Mkdir on MDT */ - ECHO_MD_DESTROY = 3, /* Unlink file on MDT */ - ECHO_MD_RMDIR = 4, /* Rmdir on MDT */ - ECHO_MD_LOOKUP = 5, /* Lookup on MDT */ - ECHO_MD_GETATTR = 6, /* Getattr on MDT */ - ECHO_MD_SETATTR = 7, /* Setattr on MDT */ - ECHO_MD_ALLOC_FID = 8, /* Get FIDs from MDT */ -}; - -/* - * OBD IOCTLS - */ -#define OBD_IOCTL_VERSION 0x00010004 - -struct obd_ioctl_data { - __u32 ioc_len; - __u32 ioc_version; - - union { - __u64 ioc_cookie; - __u64 ioc_u64_1; - }; - union { - __u32 ioc_conn1; - __u32 ioc_u32_1; - }; - union { - __u32 ioc_conn2; - __u32 ioc_u32_2; - }; - - struct obdo ioc_obdo1; - struct obdo ioc_obdo2; - - u64 ioc_count; - u64 ioc_offset; - __u32 ioc_dev; - __u32 ioc_command; - - __u64 ioc_nid; - __u32 ioc_nal; - __u32 ioc_type; - - /* buffers the kernel will treat as user pointers */ - __u32 ioc_plen1; - void __user *ioc_pbuf1; - __u32 ioc_plen2; - void __user *ioc_pbuf2; - - /* inline buffers for various arguments */ - __u32 ioc_inllen1; - char *ioc_inlbuf1; - __u32 ioc_inllen2; - char *ioc_inlbuf2; - __u32 ioc_inllen3; - char *ioc_inlbuf3; - __u32 ioc_inllen4; - char *ioc_inlbuf4; - - char ioc_bulk[0]; -}; - -struct obd_ioctl_hdr { - __u32 ioc_len; - __u32 ioc_version; -}; - -static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) -{ - int len = cfs_size_round(sizeof(struct obd_ioctl_data)); - - len += cfs_size_round(data->ioc_inllen1); - len += cfs_size_round(data->ioc_inllen2); - len += cfs_size_round(data->ioc_inllen3); - len += cfs_size_round(data->ioc_inllen4); - return len; -} - -static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) -{ - if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_len larger than %d\n", - OBD_MAX_IOCTL_BUFFER); - return 1; - } - if (data->ioc_inllen1 > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_inllen1 larger than ioc_len\n"); - return 1; - } - if (data->ioc_inllen2 > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_inllen2 larger than ioc_len\n"); - return 1; - } - if (data->ioc_inllen3 > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_inllen3 larger than ioc_len\n"); - return 1; - } - if (data->ioc_inllen4 > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_inllen4 larger than ioc_len\n"); - return 1; - } - if (data->ioc_inlbuf1 && !data->ioc_inllen1) { - CERROR("OBD ioctl: inlbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf2 && !data->ioc_inllen2) { - CERROR("OBD ioctl: inlbuf2 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf3 && !data->ioc_inllen3) { - CERROR("OBD ioctl: inlbuf3 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf4 && !data->ioc_inllen4) { - CERROR("OBD ioctl: inlbuf4 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf1 && !data->ioc_plen1) { - CERROR("OBD ioctl: pbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf2 && !data->ioc_plen2) { - CERROR("OBD ioctl: pbuf2 pointer but 0 length\n"); - return 1; - } - if (data->ioc_plen1 && !data->ioc_pbuf1) { - CERROR("OBD ioctl: plen1 set but NULL pointer\n"); - return 1; - } - if (data->ioc_plen2 && !data->ioc_pbuf2) { - CERROR("OBD ioctl: plen2 set but NULL pointer\n"); - return 1; - } - if (obd_ioctl_packlen(data) > data->ioc_len) { - CERROR("OBD ioctl: packlen exceeds ioc_len (%d > %d)\n", - obd_ioctl_packlen(data), data->ioc_len); - return 1; - } - return 0; -} - -#include "obd_support.h" - -/* function defined in lustre/obdclass//-module.c */ -int obd_ioctl_getdata(char **buf, int *len, void __user *arg); -int obd_ioctl_popdata(void __user *arg, void *data, int len); - -static inline void obd_ioctl_freedata(char *buf, int len) -{ - kvfree(buf); - return; -} - -/* - * BSD ioctl description: - * #define IOC_V1 _IOR(g, n1, long) - * #define IOC_V2 _IOW(g, n2, long) - * - * ioctl(f, IOC_V1, arg); - * arg will be treated as a long value, - * - * ioctl(f, IOC_V2, arg) - * arg will be treated as a pointer, bsd will call - * copyin(buf, arg, sizeof(long)) - * - * To make BSD ioctl handles argument correctly and simplely, - * we change _IOR to _IOWR so BSD will copyin obd_ioctl_data - * for us. Does this change affect Linux? (XXX Liang) - */ -#define OBD_IOC_DATA_TYPE long - -#define OBD_IOC_CREATE _IOWR('f', 101, OBD_IOC_DATA_TYPE) -#define OBD_IOC_DESTROY _IOW('f', 104, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PREALLOCATE _IOWR('f', 105, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_SETATTR _IOW('f', 107, OBD_IOC_DATA_TYPE) -#define OBD_IOC_GETATTR _IOWR ('f', 108, OBD_IOC_DATA_TYPE) -#define OBD_IOC_READ _IOWR('f', 109, OBD_IOC_DATA_TYPE) -#define OBD_IOC_WRITE _IOWR('f', 110, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_STATFS _IOWR('f', 113, OBD_IOC_DATA_TYPE) -#define OBD_IOC_SYNC _IOW('f', 114, OBD_IOC_DATA_TYPE) -#define OBD_IOC_READ2 _IOWR('f', 115, OBD_IOC_DATA_TYPE) -#define OBD_IOC_FORMAT _IOWR('f', 116, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PARTITION _IOWR('f', 117, OBD_IOC_DATA_TYPE) -#define OBD_IOC_COPY _IOWR('f', 120, OBD_IOC_DATA_TYPE) -#define OBD_IOC_MIGR _IOWR('f', 121, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PUNCH _IOWR('f', 122, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_MODULE_DEBUG _IOWR('f', 124, OBD_IOC_DATA_TYPE) -#define OBD_IOC_BRW_READ _IOWR('f', 125, OBD_IOC_DATA_TYPE) -#define OBD_IOC_BRW_WRITE _IOWR('f', 126, OBD_IOC_DATA_TYPE) -#define OBD_IOC_NAME2DEV _IOWR('f', 127, OBD_IOC_DATA_TYPE) -#define OBD_IOC_UUID2DEV _IOWR('f', 130, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_GETNAME _IOWR('f', 131, OBD_IOC_DATA_TYPE) -#define OBD_IOC_GETMDNAME _IOR('f', 131, char[MAX_OBD_NAME]) -#define OBD_IOC_GETDTNAME OBD_IOC_GETNAME - -#define OBD_IOC_LOV_GET_CONFIG _IOWR('f', 132, OBD_IOC_DATA_TYPE) -#define OBD_IOC_CLIENT_RECOVER _IOW('f', 133, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PING_TARGET _IOW('f', 136, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 139) -#define OBD_IOC_NO_TRANSNO _IOW('f', 140, OBD_IOC_DATA_TYPE) -#define OBD_IOC_SET_READONLY _IOW('f', 141, OBD_IOC_DATA_TYPE) -#define OBD_IOC_ABORT_RECOVERY _IOR('f', 142, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_ROOT_SQUASH _IOWR('f', 143, OBD_IOC_DATA_TYPE) - -#define OBD_GET_VERSION _IOWR ('f', 144, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_GSS_SUPPORT _IOWR('f', 145, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_CLOSE_UUID _IOWR ('f', 147, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_CHANGELOG_SEND _IOW('f', 148, OBD_IOC_DATA_TYPE) -#define OBD_IOC_GETDEVICE _IOWR ('f', 149, OBD_IOC_DATA_TYPE) -#define OBD_IOC_FID2PATH _IOWR ('f', 150, OBD_IOC_DATA_TYPE) -/* see also for ioctls 151-153 */ -/* OBD_IOC_LOV_SETSTRIPE: See also LL_IOC_LOV_SETSTRIPE */ -#define OBD_IOC_LOV_SETSTRIPE _IOW('f', 154, OBD_IOC_DATA_TYPE) -/* OBD_IOC_LOV_GETSTRIPE: See also LL_IOC_LOV_GETSTRIPE */ -#define OBD_IOC_LOV_GETSTRIPE _IOW('f', 155, OBD_IOC_DATA_TYPE) -/* OBD_IOC_LOV_SETEA: See also LL_IOC_LOV_SETEA */ -#define OBD_IOC_LOV_SETEA _IOW('f', 156, OBD_IOC_DATA_TYPE) -/* see for ioctls 157-159 */ -/* OBD_IOC_QUOTACHECK: See also LL_IOC_QUOTACHECK */ -#define OBD_IOC_QUOTACHECK _IOW('f', 160, int) -/* OBD_IOC_POLL_QUOTACHECK: See also LL_IOC_POLL_QUOTACHECK */ -#define OBD_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) -/* OBD_IOC_QUOTACTL: See also LL_IOC_QUOTACTL */ -#define OBD_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) -/* see also for ioctls 163-176 */ -#define OBD_IOC_CHANGELOG_REG _IOW('f', 177, struct obd_ioctl_data) -#define OBD_IOC_CHANGELOG_DEREG _IOW('f', 178, struct obd_ioctl_data) -#define OBD_IOC_CHANGELOG_CLEAR _IOW('f', 179, struct obd_ioctl_data) -#define OBD_IOC_RECORD _IOWR('f', 180, OBD_IOC_DATA_TYPE) -#define OBD_IOC_ENDRECORD _IOWR('f', 181, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PARSE _IOWR('f', 182, OBD_IOC_DATA_TYPE) -#define OBD_IOC_DORECORD _IOWR('f', 183, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PROCESS_CFG _IOWR('f', 184, OBD_IOC_DATA_TYPE) -#define OBD_IOC_DUMP_LOG _IOWR('f', 185, OBD_IOC_DATA_TYPE) -#define OBD_IOC_CLEAR_LOG _IOWR('f', 186, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PARAM _IOW('f', 187, OBD_IOC_DATA_TYPE) -#define OBD_IOC_POOL _IOWR('f', 188, OBD_IOC_DATA_TYPE) -#define OBD_IOC_REPLACE_NIDS _IOWR('f', 189, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_CATLOGLIST _IOWR('f', 190, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_INFO _IOWR('f', 191, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_PRINT _IOWR('f', 192, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_CANCEL _IOWR('f', 193, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_REMOVE _IOWR('f', 194, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_CHECK _IOWR('f', 195, OBD_IOC_DATA_TYPE) -/* OBD_IOC_LLOG_CATINFO is deprecated */ -#define OBD_IOC_LLOG_CATINFO _IOWR('f', 196, OBD_IOC_DATA_TYPE) - -/* #define ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) */ -/* #define ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) */ -/* #define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) */ -/* #define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) */ - -#define OBD_IOC_GET_OBJ_VERSION _IOR('f', 210, OBD_IOC_DATA_TYPE) - -/* defines ioctl number 218-219 */ -#define OBD_IOC_GET_MNTOPT _IOW('f', 220, mntopt_t) - -#define OBD_IOC_ECHO_MD _IOR('f', 221, struct obd_ioctl_data) -#define OBD_IOC_ECHO_ALLOC_SEQ _IOWR('f', 222, struct obd_ioctl_data) - -#define OBD_IOC_START_LFSCK _IOWR('f', 230, OBD_IOC_DATA_TYPE) -#define OBD_IOC_STOP_LFSCK _IOW('f', 231, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PAUSE_LFSCK _IOW('f', 232, OBD_IOC_DATA_TYPE) - -/* XXX _IOWR('f', 250, long) has been defined in - * libcfs/include/libcfs/libcfs_private.h for debug, don't use it - */ - -/* Until such time as we get_info the per-stripe maximum from the OST, - * we define this to be 2T - 4k, which is the ext3 maxbytes. - */ -#define LUSTRE_STRIPE_MAXBYTES 0x1fffffff000ULL - -/* Special values for remove LOV EA from disk */ -#define LOVEA_DELETE_VALUES(size, count, offset) (size == 0 && count == 0 && \ - offset == (typeof(offset))(-1)) - -/* #define POISON_BULK 0 */ - /* * l_wait_event is a flexible sleeping function, permitting simple caller * configuration of interrupt and timeout sensitivity along with actions to diff --git a/drivers/staging/lustre/lustre/include/lustre_linkea.h b/drivers/staging/lustre/lustre/include/lustre_linkea.h new file mode 100644 index 000000000000..249e8bf4fa22 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_linkea.h @@ -0,0 +1,79 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2013, 2014, Intel Corporation. + * Use is subject to license terms. + * + * Author: di wang + */ + +#define DEFAULT_LINKEA_SIZE 4096 + +struct linkea_data { + /** + * Buffer to keep link EA body. + */ + struct lu_buf *ld_buf; + /** + * The matched header, entry and its length in the EA + */ + struct link_ea_header *ld_leh; + struct link_ea_entry *ld_lee; + int ld_reclen; +}; + +int linkea_data_new(struct linkea_data *ldata, struct lu_buf *buf); +int linkea_init(struct linkea_data *ldata); +void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen, + struct lu_name *lname, struct lu_fid *pfid); +int linkea_entry_pack(struct link_ea_entry *lee, const struct lu_name *lname, + const struct lu_fid *pfid); +int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname, + const struct lu_fid *pfid); +void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname); +int linkea_links_find(struct linkea_data *ldata, const struct lu_name *lname, + const struct lu_fid *pfid); + +static inline void linkea_first_entry(struct linkea_data *ldata) +{ + LASSERT(ldata); + LASSERT(ldata->ld_leh); + + if (ldata->ld_leh->leh_reccount == 0) + ldata->ld_lee = NULL; + else + ldata->ld_lee = (struct link_ea_entry *)(ldata->ld_leh + 1); +} + +static inline void linkea_next_entry(struct linkea_data *ldata) +{ + LASSERT(ldata); + LASSERT(ldata->ld_leh); + + if (ldata->ld_lee) { + ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee + + ldata->ld_reclen); + if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh + + ldata->ld_leh->leh_len)) + ldata->ld_lee = NULL; + } +} diff --git a/drivers/staging/lustre/lustre/include/lustre_lite.h b/drivers/staging/lustre/lustre/include/lustre_lite.h deleted file mode 100644 index b16897702559..000000000000 --- a/drivers/staging/lustre/lustre/include/lustre_lite.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef _LL_H -#define _LL_H - -/** \defgroup lite lite - * - * @{ - */ - -#include "linux/lustre_lite.h" - -#include "obd_class.h" -#include "lustre_net.h" -#include "lustre_mds.h" -#include "lustre_ha.h" - -/* 4UL * 1024 * 1024 */ -#define LL_MAX_BLKSIZE_BITS (22) -#define LL_MAX_BLKSIZE (1UL<lco_lock. - */ - __u64 lco_flags; - struct mutex lco_lock; - struct obd_export *lco_md_exp; - struct obd_export *lco_dt_exp; -}; - -/* - * Chain of hash overflow pages. - */ -struct ll_dir_chain { - /* XXX something. Later */ -}; - -static inline void ll_dir_chain_init(struct ll_dir_chain *chain) -{ -} - -static inline void ll_dir_chain_fini(struct ll_dir_chain *chain) -{ -} - -static inline unsigned long hash_x_index(__u64 hash, int hash64) -{ - if (BITS_PER_LONG == 32 && hash64) - hash >>= 32; - /* save hash 0 as index 0 because otherwise we'll save it at - * page index end (~0UL) and it causes truncate_inode_pages_range() - * to loop forever. - */ - return ~0UL - (hash + !hash); -} - -/** @} lite */ - -#endif diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h new file mode 100644 index 000000000000..d7f7afa8dfa7 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -0,0 +1,184 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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. A copy is + * included in the COPYING file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf + * + * GPL HEADER END + */ +/* + * Copyright (c) 2013, Intel Corporation. + */ +/* + * lustre/include/lustre_lmv.h + * + * Lustre LMV structures and functions. + * + * Author: Di Wang + */ + +#ifndef _LUSTRE_LMV_H +#define _LUSTRE_LMV_H +#include "lustre/lustre_idl.h" + +struct lmv_oinfo { + struct lu_fid lmo_fid; + u32 lmo_mds; + struct inode *lmo_root; +}; + +struct lmv_stripe_md { + __u32 lsm_md_magic; + __u32 lsm_md_stripe_count; + __u32 lsm_md_master_mdt_index; + __u32 lsm_md_hash_type; + __u32 lsm_md_layout_version; + __u32 lsm_md_default_count; + __u32 lsm_md_default_index; + char lsm_md_pool_name[LOV_MAXPOOLNAME + 1]; + struct lmv_oinfo lsm_md_oinfo[0]; +}; + +static inline bool +lsm_md_eq(const struct lmv_stripe_md *lsm1, const struct lmv_stripe_md *lsm2) +{ + __u32 idx; + + if (lsm1->lsm_md_magic != lsm2->lsm_md_magic || + lsm1->lsm_md_stripe_count != lsm2->lsm_md_stripe_count || + lsm1->lsm_md_master_mdt_index != lsm2->lsm_md_master_mdt_index || + lsm1->lsm_md_hash_type != lsm2->lsm_md_hash_type || + lsm1->lsm_md_layout_version != lsm2->lsm_md_layout_version || + !strcmp(lsm1->lsm_md_pool_name, lsm2->lsm_md_pool_name)) + return false; + + for (idx = 0; idx < lsm1->lsm_md_stripe_count; idx++) { + if (!lu_fid_eq(&lsm1->lsm_md_oinfo[idx].lmo_fid, + &lsm2->lsm_md_oinfo[idx].lmo_fid)) + return false; + } + + return true; +} + +union lmv_mds_md; + +int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, + const union lmv_mds_md *lmm, int stripe_count); + +static inline int lmv_alloc_memmd(struct lmv_stripe_md **lsmp, int stripe_count) +{ + return lmv_unpack_md(NULL, lsmp, NULL, stripe_count); +} + +static inline void lmv_free_memmd(struct lmv_stripe_md *lsm) +{ + lmv_unpack_md(NULL, &lsm, NULL, 0); +} + +static inline void lmv1_le_to_cpu(struct lmv_mds_md_v1 *lmv_dst, + const struct lmv_mds_md_v1 *lmv_src) +{ + __u32 i; + + lmv_dst->lmv_magic = le32_to_cpu(lmv_src->lmv_magic); + lmv_dst->lmv_stripe_count = le32_to_cpu(lmv_src->lmv_stripe_count); + lmv_dst->lmv_master_mdt_index = + le32_to_cpu(lmv_src->lmv_master_mdt_index); + lmv_dst->lmv_hash_type = le32_to_cpu(lmv_src->lmv_hash_type); + lmv_dst->lmv_layout_version = le32_to_cpu(lmv_src->lmv_layout_version); + + for (i = 0; i < lmv_src->lmv_stripe_count; i++) + fid_le_to_cpu(&lmv_dst->lmv_stripe_fids[i], + &lmv_src->lmv_stripe_fids[i]); +} + +static inline void lmv_le_to_cpu(union lmv_mds_md *lmv_dst, + const union lmv_mds_md *lmv_src) +{ + switch (le32_to_cpu(lmv_src->lmv_magic)) { + case LMV_MAGIC_V1: + lmv1_le_to_cpu(&lmv_dst->lmv_md_v1, &lmv_src->lmv_md_v1); + break; + default: + break; + } +} + +/* This hash is only for testing purpose */ +static inline unsigned int +lmv_hash_all_chars(unsigned int count, const char *name, int namelen) +{ + const unsigned char *p = (const unsigned char *)name; + unsigned int c = 0; + + while (--namelen >= 0) + c += p[namelen]; + + c = c % count; + + return c; +} + +static inline unsigned int +lmv_hash_fnv1a(unsigned int count, const char *name, int namelen) +{ + __u64 hash; + + hash = lustre_hash_fnv_1a_64(name, namelen); + + return do_div(hash, count); +} + +static inline int lmv_name_to_stripe_index(__u32 lmv_hash_type, + unsigned int stripe_count, + const char *name, int namelen) +{ + __u32 hash_type = lmv_hash_type & LMV_HASH_TYPE_MASK; + int idx; + + LASSERT(namelen > 0); + if (stripe_count <= 1) + return 0; + + /* for migrating object, always start from 0 stripe */ + if (lmv_hash_type & LMV_HASH_FLAG_MIGRATION) + return 0; + + switch (hash_type) { + case LMV_HASH_TYPE_ALL_CHARS: + idx = lmv_hash_all_chars(stripe_count, name, namelen); + break; + case LMV_HASH_TYPE_FNV_1A_64: + idx = lmv_hash_fnv1a(stripe_count, name, namelen); + break; + default: + idx = -EBADFD; + break; + } + CDEBUG(D_INFO, "name %.*s hash_type %d idx %d\n", namelen, name, + hash_type, idx); + + return idx; +} + +static inline bool lmv_is_known_hash_type(__u32 type) +{ + return (type & LMV_HASH_TYPE_MASK) == LMV_HASH_TYPE_FNV_1A_64 || + (type & LMV_HASH_TYPE_MASK) == LMV_HASH_TYPE_ALL_CHARS; +} + +#endif diff --git a/drivers/staging/lustre/lustre/include/lustre_log.h b/drivers/staging/lustre/lustre/include/lustre_log.h index b96e02317bfc..995b266932e3 100644 --- a/drivers/staging/lustre/lustre/include/lustre_log.h +++ b/drivers/staging/lustre/lustre/include/lustre_log.h @@ -277,12 +277,11 @@ static inline void llog_ctxt_put(struct llog_ctxt *ctxt) __llog_ctxt_put(NULL, ctxt); } -static inline void llog_group_init(struct obd_llog_group *olg, int group) +static inline void llog_group_init(struct obd_llog_group *olg) { init_waitqueue_head(&olg->olg_waitq); spin_lock_init(&olg->olg_lock); mutex_init(&olg->olg_cat_processing); - olg->olg_seq = group; } static inline int llog_group_set_ctxt(struct obd_llog_group *olg, diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index fa62b95d351f..8fc2d3f2dfd6 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -96,7 +96,7 @@ static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck, struct lookup_intent *it) { if (it && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || - it->it_op == IT_LAYOUT)) + it->it_op == IT_LAYOUT || it->it_op == IT_READDIR)) return; /* This would normally block until the existing request finishes. @@ -136,7 +136,7 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, struct lookup_intent *it) { if (it && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || - it->it_op == IT_LAYOUT)) + it->it_op == IT_LAYOUT || it->it_op == IT_READDIR)) return; if (lck->rpcl_it == MDC_FAKE_RPCL_IT) { /* OBD_FAIL_MDC_RPCS_SEM */ @@ -156,34 +156,44 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, mutex_unlock(&lck->rpcl_mutex); } -/* Update the maximum observed easize and cookiesize. The default easize - * and cookiesize is initialized to the minimum value but allowed to grow - * up to a single page in size if required to handle the common case. +/** + * Update the maximum possible easize and cookiesize. + * + * The values are learned from ptlrpc replies sent by the MDT. The + * default easize and cookiesize is initialized to the minimum value but + * allowed to grow up to a single page in size if required to handle the + * common case. + * + * \see client_obd::cl_default_mds_easize and + * client_obd::cl_default_mds_cookiesize + * + * \param[in] exp export for MDC device + * \param[in] body body of ptlrpc reply from MDT + * */ static inline void mdc_update_max_ea_from_body(struct obd_export *exp, struct mdt_body *body) { - if (body->valid & OBD_MD_FLMODEASIZE) { + if (body->mbo_valid & OBD_MD_FLMODEASIZE) { struct client_obd *cli = &exp->exp_obd->u.cli; + u32 def_cookiesize, def_easize; - if (cli->cl_max_mds_easize < body->max_mdsize) { - cli->cl_max_mds_easize = body->max_mdsize; - cli->cl_default_mds_easize = - min_t(__u32, body->max_mdsize, PAGE_SIZE); - } - if (cli->cl_max_mds_cookiesize < body->max_cookiesize) { - cli->cl_max_mds_cookiesize = body->max_cookiesize; - cli->cl_default_mds_cookiesize = - min_t(__u32, body->max_cookiesize, PAGE_SIZE); - } + if (cli->cl_max_mds_easize < body->mbo_max_mdsize) + cli->cl_max_mds_easize = body->mbo_max_mdsize; + + def_easize = min_t(__u32, body->mbo_max_mdsize, + OBD_MAX_DEFAULT_EA_SIZE); + cli->cl_default_mds_easize = def_easize; + + if (cli->cl_max_mds_cookiesize < body->mbo_max_cookiesize) + cli->cl_max_mds_cookiesize = body->mbo_max_cookiesize; + + def_cookiesize = min_t(__u32, body->mbo_max_cookiesize, + OBD_MAX_DEFAULT_COOKIE_SIZE); + cli->cl_default_mds_cookiesize = def_cookiesize; } } -struct mdc_cache_waiter { - struct list_head mcw_entry; - wait_queue_head_t mcw_waitq; -}; - /* mdc/mdc_locks.c */ int it_open_error(int phase, struct lookup_intent *it); diff --git a/drivers/staging/lustre/lustre/include/lustre_mds.h b/drivers/staging/lustre/lustre/include/lustre_mds.h index 4104bd9bd5c4..23a7e4f78e9a 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mds.h +++ b/drivers/staging/lustre/lustre/include/lustre_mds.h @@ -58,9 +58,6 @@ struct mds_group_info { #define MDD_OBD_NAME "mdd_obd" #define MDD_OBD_UUID "mdd_obd_uuid" -/* these are local flags, used only on the client, private */ -#define M_CHECK_STALE 0200000000 - /** @} mds */ #endif diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index d5debd615fdf..e9aba99ee52a 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -261,7 +261,10 @@ #define MDS_MAXREQSIZE (5 * 1024) /* >= 4736 */ -#define OST_MAXREQSIZE (5 * 1024) +/** + * FIEMAP request can be 4K+ for now + */ +#define OST_MAXREQSIZE (16 * 1024) /* Macro to hide a typecast. */ #define ptlrpc_req_async_args(req) ((void *)&req->rq_async_args) @@ -570,13 +573,13 @@ struct ptlrpc_nrs_pol_ops { * * \param[in,out] policy The policy being initialized */ - int (*op_policy_init) (struct ptlrpc_nrs_policy *policy); + int (*op_policy_init)(struct ptlrpc_nrs_policy *policy); /** * Called during policy unregistration; this operation is optional. * * \param[in,out] policy The policy being unregistered/finalized */ - void (*op_policy_fini) (struct ptlrpc_nrs_policy *policy); + void (*op_policy_fini)(struct ptlrpc_nrs_policy *policy); /** * Called when activating a policy via lprocfs; policies allocate and * initialize their resources here; this operation is optional. @@ -585,7 +588,7 @@ struct ptlrpc_nrs_pol_ops { * * \see nrs_policy_start_locked() */ - int (*op_policy_start) (struct ptlrpc_nrs_policy *policy); + int (*op_policy_start)(struct ptlrpc_nrs_policy *policy); /** * Called when deactivating a policy via lprocfs; policies deallocate * their resources here; this operation is optional @@ -594,7 +597,7 @@ struct ptlrpc_nrs_pol_ops { * * \see nrs_policy_stop0() */ - void (*op_policy_stop) (struct ptlrpc_nrs_policy *policy); + void (*op_policy_stop)(struct ptlrpc_nrs_policy *policy); /** * Used for policy-specific operations; i.e. not generic ones like * \e PTLRPC_NRS_CTL_START and \e PTLRPC_NRS_CTL_GET_INFO; analogous @@ -610,8 +613,8 @@ struct ptlrpc_nrs_pol_ops { * * \see ptlrpc_nrs_policy_control() */ - int (*op_policy_ctl) (struct ptlrpc_nrs_policy *policy, - enum ptlrpc_nrs_ctl opc, void *arg); + int (*op_policy_ctl)(struct ptlrpc_nrs_policy *policy, + enum ptlrpc_nrs_ctl opc, void *arg); /** * Called when obtaining references to the resources of the resource @@ -648,11 +651,11 @@ struct ptlrpc_nrs_pol_ops { * \see ptlrpc_nrs_req_initialize() * \see ptlrpc_nrs_hpreq_add_nolock() */ - int (*op_res_get) (struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq, - const struct ptlrpc_nrs_resource *parent, - struct ptlrpc_nrs_resource **resp, - bool moving_req); + int (*op_res_get)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq, + const struct ptlrpc_nrs_resource *parent, + struct ptlrpc_nrs_resource **resp, + bool moving_req); /** * Called when releasing references taken for resources in the resource * hierarchy for the request; this operation is optional. @@ -663,8 +666,8 @@ struct ptlrpc_nrs_pol_ops { * \see ptlrpc_nrs_req_finalize() * \see ptlrpc_nrs_hpreq_add_nolock() */ - void (*op_res_put) (struct ptlrpc_nrs_policy *policy, - const struct ptlrpc_nrs_resource *res); + void (*op_res_put)(struct ptlrpc_nrs_policy *policy, + const struct ptlrpc_nrs_resource *res); /** * Obtains a request for handling from the policy, and optionally @@ -683,8 +686,8 @@ struct ptlrpc_nrs_pol_ops { * \see ptlrpc_nrs_req_get_nolock() */ struct ptlrpc_nrs_request * - (*op_req_get) (struct ptlrpc_nrs_policy *policy, bool peek, - bool force); + (*op_req_get)(struct ptlrpc_nrs_policy *policy, bool peek, + bool force); /** * Called when attempting to add a request to a policy for later * handling; this operation is mandatory. @@ -697,8 +700,8 @@ struct ptlrpc_nrs_pol_ops { * * \see ptlrpc_nrs_req_add_nolock() */ - int (*op_req_enqueue) (struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); + int (*op_req_enqueue)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); /** * Removes a request from the policy's set of pending requests. Normally * called after a request has been polled successfully from the policy @@ -707,8 +710,8 @@ struct ptlrpc_nrs_pol_ops { * \param[in,out] policy The policy the request \a nrq belongs to * \param[in,out] nrq The request to dequeue */ - void (*op_req_dequeue) (struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); + void (*op_req_dequeue)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); /** * Called after the request being carried out. Could be used for * job/resource control; this operation is optional. @@ -721,8 +724,8 @@ struct ptlrpc_nrs_pol_ops { * * \see ptlrpc_nrs_req_stop_nolock() */ - void (*op_req_stop) (struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); + void (*op_req_stop)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); /** * Registers the policy's lprocfs interface with a PTLRPC service. * @@ -731,7 +734,7 @@ struct ptlrpc_nrs_pol_ops { * \retval 0 success * \retval != 0 error */ - int (*op_lprocfs_init) (struct ptlrpc_service *svc); + int (*op_lprocfs_init)(struct ptlrpc_service *svc); /** * Unegisters the policy's lprocfs interface with a PTLRPC service. * @@ -743,7 +746,7 @@ struct ptlrpc_nrs_pol_ops { * * \param[in] svc The service */ - void (*op_lprocfs_fini) (struct ptlrpc_service *svc); + void (*op_lprocfs_fini)(struct ptlrpc_service *svc); }; /** @@ -1628,7 +1631,7 @@ static inline bool ptlrpc_nrs_req_can_move(struct ptlrpc_request *req) /** * Returns 1 if request buffer at offset \a index was already swabbed */ -static inline int lustre_req_swabbed(struct ptlrpc_request *req, int index) +static inline int lustre_req_swabbed(struct ptlrpc_request *req, size_t index) { LASSERT(index < sizeof(req->rq_req_swab_mask) * 8); return req->rq_req_swab_mask & (1 << index); @@ -1637,7 +1640,7 @@ static inline int lustre_req_swabbed(struct ptlrpc_request *req, int index) /** * Returns 1 if request reply buffer at offset \a index was already swabbed */ -static inline int lustre_rep_swabbed(struct ptlrpc_request *req, int index) +static inline int lustre_rep_swabbed(struct ptlrpc_request *req, size_t index) { LASSERT(index < sizeof(req->rq_rep_swab_mask) * 8); return req->rq_rep_swab_mask & (1 << index); @@ -1662,7 +1665,8 @@ static inline int ptlrpc_rep_need_swab(struct ptlrpc_request *req) /** * Mark request buffer at offset \a index that it was already swabbed */ -static inline void lustre_set_req_swabbed(struct ptlrpc_request *req, int index) +static inline void lustre_set_req_swabbed(struct ptlrpc_request *req, + size_t index) { LASSERT(index < sizeof(req->rq_req_swab_mask) * 8); LASSERT((req->rq_req_swab_mask & (1 << index)) == 0); @@ -1672,7 +1676,8 @@ static inline void lustre_set_req_swabbed(struct ptlrpc_request *req, int index) /** * Mark request reply buffer at offset \a index that it was already swabbed */ -static inline void lustre_set_rep_swabbed(struct ptlrpc_request *req, int index) +static inline void lustre_set_rep_swabbed(struct ptlrpc_request *req, + size_t index) { LASSERT(index < sizeof(req->rq_rep_swab_mask) * 8); LASSERT((req->rq_rep_swab_mask & (1 << index)) == 0); @@ -2403,7 +2408,6 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags); int ptlrpc_reply(struct ptlrpc_request *req); int ptlrpc_send_error(struct ptlrpc_request *req, int difficult); int ptlrpc_error(struct ptlrpc_request *req); -void ptlrpc_resend_req(struct ptlrpc_request *request); int ptlrpc_at_get_net_latency(struct ptlrpc_request *req); int ptl_send_rpc(struct ptlrpc_request *request, int noreply); int ptlrpc_register_rqbd(struct ptlrpc_request_buffer_desc *rqbd); @@ -2423,23 +2427,17 @@ struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid); int ptlrpc_queue_wait(struct ptlrpc_request *req); int ptlrpc_replay_req(struct ptlrpc_request *req); -int ptlrpc_unregister_reply(struct ptlrpc_request *req, int async); void ptlrpc_abort_inflight(struct obd_import *imp); void ptlrpc_abort_set(struct ptlrpc_request_set *set); struct ptlrpc_request_set *ptlrpc_prep_set(void); struct ptlrpc_request_set *ptlrpc_prep_fcset(int max, set_producer_func func, void *arg); -int ptlrpc_set_next_timeout(struct ptlrpc_request_set *); int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set); int ptlrpc_set_wait(struct ptlrpc_request_set *); -int ptlrpc_expired_set(void *data); -void ptlrpc_interrupted_set(void *data); void ptlrpc_mark_interrupted(struct ptlrpc_request *req); void ptlrpc_set_destroy(struct ptlrpc_request_set *); void ptlrpc_set_add_req(struct ptlrpc_request_set *, struct ptlrpc_request *); -void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc, - struct ptlrpc_request *req); void ptlrpc_free_rq_pool(struct ptlrpc_request_pool *pool); int ptlrpc_add_rqs_to_pool(struct ptlrpc_request_pool *pool, int num_rq); @@ -2611,9 +2609,9 @@ int ptlrpc_reconnect_import(struct obd_import *imp); * @{ */ int ptlrpc_buf_need_swab(struct ptlrpc_request *req, const int inout, - int index); + u32 index); void ptlrpc_buf_set_swabbed(struct ptlrpc_request *req, const int inout, - int index); + u32 index); int ptlrpc_unpack_rep_msg(struct ptlrpc_request *req, int len); int ptlrpc_unpack_req_msg(struct ptlrpc_request *req, int len); @@ -2632,27 +2630,27 @@ int lustre_shrink_msg(struct lustre_msg *msg, int segment, unsigned int newlen, int move_data); void lustre_free_reply_state(struct ptlrpc_reply_state *rs); int __lustre_unpack_msg(struct lustre_msg *m, int len); -int lustre_msg_hdr_size(__u32 magic, int count); -int lustre_msg_size(__u32 magic, int count, __u32 *lengths); -int lustre_msg_size_v2(int count, __u32 *lengths); -int lustre_packed_msg_size(struct lustre_msg *msg); -int lustre_msg_early_size(void); -void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, int n, int min_size); -void *lustre_msg_buf(struct lustre_msg *m, int n, int minlen); -int lustre_msg_buflen(struct lustre_msg *m, int n); -int lustre_msg_bufcount(struct lustre_msg *m); -char *lustre_msg_string(struct lustre_msg *m, int n, int max_len); +u32 lustre_msg_hdr_size(__u32 magic, u32 count); +u32 lustre_msg_size(__u32 magic, int count, __u32 *lengths); +u32 lustre_msg_size_v2(int count, __u32 *lengths); +u32 lustre_packed_msg_size(struct lustre_msg *msg); +u32 lustre_msg_early_size(void); +void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, u32 n, u32 min_size); +void *lustre_msg_buf(struct lustre_msg *m, u32 n, u32 minlen); +u32 lustre_msg_buflen(struct lustre_msg *m, u32 n); +u32 lustre_msg_bufcount(struct lustre_msg *m); +char *lustre_msg_string(struct lustre_msg *m, u32 n, u32 max_len); __u32 lustre_msghdr_get_flags(struct lustre_msg *msg); void lustre_msghdr_set_flags(struct lustre_msg *msg, __u32 flags); __u32 lustre_msg_get_flags(struct lustre_msg *msg); -void lustre_msg_add_flags(struct lustre_msg *msg, int flags); -void lustre_msg_set_flags(struct lustre_msg *msg, int flags); -void lustre_msg_clear_flags(struct lustre_msg *msg, int flags); +void lustre_msg_add_flags(struct lustre_msg *msg, u32 flags); +void lustre_msg_set_flags(struct lustre_msg *msg, u32 flags); +void lustre_msg_clear_flags(struct lustre_msg *msg, u32 flags); __u32 lustre_msg_get_op_flags(struct lustre_msg *msg); -void lustre_msg_add_op_flags(struct lustre_msg *msg, int flags); +void lustre_msg_add_op_flags(struct lustre_msg *msg, u32 flags); struct lustre_handle *lustre_msg_get_handle(struct lustre_msg *msg); __u32 lustre_msg_get_type(struct lustre_msg *msg); -void lustre_msg_add_version(struct lustre_msg *msg, int version); +void lustre_msg_add_version(struct lustre_msg *msg, u32 version); __u32 lustre_msg_get_opc(struct lustre_msg *msg); __u64 lustre_msg_get_last_committed(struct lustre_msg *msg); __u64 *lustre_msg_get_versions(struct lustre_msg *msg); diff --git a/drivers/staging/lustre/lustre/include/lustre_param.h b/drivers/staging/lustre/lustre/include/lustre_param.h index 82aadd32c2b8..8061a04ee806 100644 --- a/drivers/staging/lustre/lustre/include/lustre_param.h +++ b/drivers/staging/lustre/lustre/include/lustre_param.h @@ -39,6 +39,9 @@ #ifndef _LUSTRE_PARAM_H #define _LUSTRE_PARAM_H +#include "../../include/linux/libcfs/libcfs.h" +#include "../../include/linux/lnet/types.h" + /** \defgroup param param * * @{ diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h b/drivers/staging/lustre/lustre/include/lustre_patchless_compat.h similarity index 100% rename from drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h rename to drivers/staging/lustre/lustre/include/lustre_patchless_compat.h diff --git a/drivers/staging/lustre/lustre/include/lustre_req_layout.h b/drivers/staging/lustre/lustre/include/lustre_req_layout.h index 544a43c862b9..a13558e53274 100644 --- a/drivers/staging/lustre/lustre/include/lustre_req_layout.h +++ b/drivers/staging/lustre/lustre/include/lustre_req_layout.h @@ -76,7 +76,8 @@ void req_capsule_init(struct req_capsule *pill, struct ptlrpc_request *req, void req_capsule_fini(struct req_capsule *pill); void req_capsule_set(struct req_capsule *pill, const struct req_format *fmt); -int req_capsule_filled_sizes(struct req_capsule *pill, enum req_location loc); +size_t req_capsule_filled_sizes(struct req_capsule *pill, + enum req_location loc); int req_capsule_server_pack(struct req_capsule *pill); void *req_capsule_client_get(struct req_capsule *pill, @@ -86,27 +87,27 @@ void *req_capsule_client_swab_get(struct req_capsule *pill, void *swabber); void *req_capsule_client_sized_get(struct req_capsule *pill, const struct req_msg_field *field, - int len); + u32 len); void *req_capsule_server_get(struct req_capsule *pill, const struct req_msg_field *field); void *req_capsule_server_sized_get(struct req_capsule *pill, const struct req_msg_field *field, - int len); + u32 len); void *req_capsule_server_swab_get(struct req_capsule *pill, const struct req_msg_field *field, void *swabber); void *req_capsule_server_sized_swab_get(struct req_capsule *pill, const struct req_msg_field *field, - int len, void *swabber); + u32 len, void *swabber); void req_capsule_set_size(struct req_capsule *pill, const struct req_msg_field *field, - enum req_location loc, int size); -int req_capsule_get_size(const struct req_capsule *pill, + enum req_location loc, u32 size); +u32 req_capsule_get_size(const struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc); -int req_capsule_msg_size(struct req_capsule *pill, enum req_location loc); -int req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, +u32 req_capsule_msg_size(struct req_capsule *pill, enum req_location loc); +u32 req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, enum req_location loc); void req_capsule_extend(struct req_capsule *pill, const struct req_format *fmt); @@ -115,8 +116,7 @@ int req_capsule_has_field(const struct req_capsule *pill, enum req_location loc); void req_capsule_shrink(struct req_capsule *pill, const struct req_msg_field *field, - unsigned int newlen, - enum req_location loc); + u32 newlen, enum req_location loc); int req_layout_init(void); void req_layout_fini(void); @@ -149,14 +149,11 @@ extern struct req_format RQF_MDS_GETATTR; extern struct req_format RQF_MDS_GETATTR_NAME; extern struct req_format RQF_MDS_CLOSE; extern struct req_format RQF_MDS_RELEASE_CLOSE; -extern struct req_format RQF_MDS_PIN; -extern struct req_format RQF_MDS_UNPIN; extern struct req_format RQF_MDS_CONNECT; extern struct req_format RQF_MDS_DISCONNECT; extern struct req_format RQF_MDS_GET_INFO; extern struct req_format RQF_MDS_READPAGE; extern struct req_format RQF_MDS_WRITEPAGE; -extern struct req_format RQF_MDS_IS_SUBDIR; extern struct req_format RQF_MDS_DONE_WRITING; extern struct req_format RQF_MDS_REINT; extern struct req_format RQF_MDS_REINT_CREATE; diff --git a/drivers/staging/lustre/lustre/include/lustre_ver.h b/drivers/staging/lustre/lustre/include/lustre_ver.h index 64559a16f4de..19c9135e2273 100644 --- a/drivers/staging/lustre/lustre/include/lustre_ver.h +++ b/drivers/staging/lustre/lustre/include/lustre_ver.h @@ -2,14 +2,21 @@ #define _LUSTRE_VER_H_ #define LUSTRE_MAJOR 2 -#define LUSTRE_MINOR 4 -#define LUSTRE_PATCH 60 +#define LUSTRE_MINOR 6 +#define LUSTRE_PATCH 99 #define LUSTRE_FIX 0 -#define LUSTRE_VERSION_STRING "2.4.60" +#define LUSTRE_VERSION_STRING "2.6.99" -#define LUSTRE_VERSION_CODE OBD_OCD_VERSION(LUSTRE_MAJOR, \ - LUSTRE_MINOR, LUSTRE_PATCH, \ - LUSTRE_FIX) +#define OBD_OCD_VERSION(major, minor, patch, fix) \ + (((major) << 24) + ((minor) << 16) + ((patch) << 8) + (fix)) + +#define OBD_OCD_VERSION_MAJOR(version) ((int)((version) >> 24) & 255) +#define OBD_OCD_VERSION_MINOR(version) ((int)((version) >> 16) & 255) +#define OBD_OCD_VERSION_PATCH(version) ((int)((version) >> 8) & 255) +#define OBD_OCD_VERSION_FIX(version) ((int)((version) >> 0) & 255) + +#define LUSTRE_VERSION_CODE \ + OBD_OCD_VERSION(LUSTRE_MAJOR, LUSTRE_MINOR, LUSTRE_PATCH, LUSTRE_FIX) /* * If lustre version of client and servers it connects to differs by more diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index a1bc2c478ff9..f6fc4dd05bd6 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -35,21 +35,13 @@ #include -#define IOC_OSC_TYPE 'h' -#define IOC_OSC_MIN_NR 20 -#define IOC_OSC_SET_ACTIVE _IOWR(IOC_OSC_TYPE, 21, struct obd_device *) -#define IOC_OSC_MAX_NR 50 - -#define IOC_MDC_TYPE 'i' -#define IOC_MDC_MIN_NR 20 -#define IOC_MDC_MAX_NR 50 - #include "lustre/lustre_idl.h" #include "lustre_lib.h" #include "lu_ref.h" #include "lustre_export.h" #include "lustre_fid.h" #include "lustre_fld.h" +#include "lustre_handles.h" #include "lustre_intent.h" #define MAX_OBD_DEVICES 8192 @@ -81,6 +73,13 @@ static inline void loi_init(struct lov_oinfo *loi) { } +/* + * If we are unable to get the maximum object size from the OST in + * ocd_maxbytes using OBD_CONNECT_MAXBYTES, then we fall back to using + * the old maximum object size from ext3. + */ +#define LUSTRE_EXT3_STRIPE_MAXBYTES 0x1fffffff000ULL + struct lov_stripe_md { atomic_t lsm_refc; spinlock_t lsm_lock; @@ -89,31 +88,17 @@ struct lov_stripe_md { /* maximum possible file size, might change as OSTs status changes, * e.g. disconnected, deactivated */ - __u64 lsm_maxbytes; - struct { - /* Public members. */ - struct ost_id lw_object_oi; /* lov object id/seq */ - - /* LOV-private members start here -- only for use in lov/. */ - __u32 lw_magic; - __u32 lw_stripe_size; /* size of the stripe */ - __u32 lw_pattern; /* striping pattern (RAID0, RAID1) */ - __u16 lw_stripe_count; /* number of objects being striped over */ - __u16 lw_layout_gen; /* generation of the layout */ - char lw_pool_name[LOV_MAXPOOLNAME]; /* pool name */ - } lsm_wire; - + __u64 lsm_maxbytes; + struct ost_id lsm_oi; + __u32 lsm_magic; + __u32 lsm_stripe_size; + __u32 lsm_pattern; /* striping pattern (RAID0, RAID1) */ + __u16 lsm_stripe_count; + __u16 lsm_layout_gen; + char lsm_pool_name[LOV_MAXPOOLNAME + 1]; struct lov_oinfo *lsm_oinfo[0]; }; -#define lsm_oi lsm_wire.lw_object_oi -#define lsm_magic lsm_wire.lw_magic -#define lsm_layout_gen lsm_wire.lw_layout_gen -#define lsm_stripe_size lsm_wire.lw_stripe_size -#define lsm_pattern lsm_wire.lw_pattern -#define lsm_stripe_count lsm_wire.lw_stripe_count -#define lsm_pool_name lsm_wire.lw_pool_name - static inline bool lsm_is_released(struct lov_stripe_md *lsm) { return !!(lsm->lsm_pattern & LOV_PATTERN_F_RELEASED); @@ -177,31 +162,10 @@ struct obd_type { struct brw_page { u64 off; struct page *pg; - int count; + unsigned int count; u32 flag; }; -/* llog contexts */ -enum llog_ctxt_id { - LLOG_CONFIG_ORIG_CTXT = 0, - LLOG_CONFIG_REPL_CTXT, - LLOG_MDS_OST_ORIG_CTXT, - LLOG_MDS_OST_REPL_CTXT, - LLOG_SIZE_ORIG_CTXT, - LLOG_SIZE_REPL_CTXT, - LLOG_RD1_ORIG_CTXT, - LLOG_RD1_REPL_CTXT, - LLOG_TEST_ORIG_CTXT, - LLOG_TEST_REPL_CTXT, - LLOG_LOVEA_ORIG_CTXT, - LLOG_LOVEA_REPL_CTXT, - LLOG_CHANGELOG_ORIG_CTXT, /**< changelog generation on mdd */ - LLOG_CHANGELOG_REPL_CTXT, /**< changelog access on clients */ - LLOG_CHANGELOG_USER_ORIG_CTXT, /**< for multiple changelog consumers */ - LLOG_AGENT_ORIG_CTXT, /**< agent requests generation on cdt */ - LLOG_MAX_CTXTS -}; - struct timeout_item { enum timeout_event ti_event; unsigned long ti_timeout; @@ -211,11 +175,12 @@ struct timeout_item { struct list_head ti_chain; }; -#define OSC_MAX_RIF_DEFAULT 8 -#define OSC_MAX_RIF_MAX 256 -#define OSC_MAX_DIRTY_DEFAULT (OSC_MAX_RIF_DEFAULT * 4) -#define OSC_MAX_DIRTY_MB_MAX 2048 /* arbitrary, but < MAX_LONG bytes */ -#define OSC_DEFAULT_RESENDS 10 +#define OBD_MAX_RIF_DEFAULT 8 +#define OBD_MAX_RIF_MAX 512 +#define OSC_MAX_RIF_MAX 256 +#define OSC_MAX_DIRTY_DEFAULT (OBD_MAX_RIF_DEFAULT * 4) +#define OSC_MAX_DIRTY_MB_MAX 2048 /* arbitrary, but < MAX_LONG bytes */ +#define OSC_DEFAULT_RESENDS 10 /* possible values for fo_sync_lock_cancel */ enum { @@ -225,40 +190,74 @@ enum { NUM_SYNC_ON_CANCEL_STATES }; -#define MDC_MAX_RIF_DEFAULT 8 -#define MDC_MAX_RIF_MAX 512 - enum obd_cl_sem_lock_class { OBD_CLI_SEM_NORMAL, OBD_CLI_SEM_MGC, OBD_CLI_SEM_MDCOSC, }; +/* + * Limit reply buffer size for striping data to one x86_64 page. This + * value is chosen to fit the striping data for common use cases while + * staying well below the limit at which the buffer must be backed by + * vmalloc(). Excessive use of vmalloc() may cause spinlock contention + * on the MDS. + */ +#define OBD_MAX_DEFAULT_EA_SIZE 4096 +#define OBD_MAX_DEFAULT_COOKIE_SIZE 4096 + struct mdc_rpc_lock; struct obd_import; struct client_obd { struct rw_semaphore cl_sem; struct obd_uuid cl_target_uuid; struct obd_import *cl_import; /* ptlrpc connection state */ - int cl_conn_count; - /* max_mds_easize is purely a performance thing so we don't have to - * call obd_size_diskmd() all the time. + size_t cl_conn_count; + /* + * Cache maximum and default values for easize and cookiesize. This is + * strictly a performance optimization to minimize calls to + * obd_size_diskmd(). The default values are used to calculate the + * initial size of a request buffer. The ptlrpc layer will resize the + * buffer as needed to accommodate a larger reply from the + * server. The default values should be small enough to avoid wasted + * memory and excessive use of vmalloc(), yet large enough to avoid + * reallocating the buffer in the common use case. */ - int cl_default_mds_easize; - int cl_max_mds_easize; - int cl_default_mds_cookiesize; - int cl_max_mds_cookiesize; + /* + * Default EA size for striping attributes. It is initialized at + * mount-time based on the default stripe width of the filesystem, + * then it tracks the largest observed EA size advertised by + * the MDT, up to a maximum value of OBD_MAX_DEFAULT_EA_SIZE. + */ + u32 cl_default_mds_easize; + /* Maximum possible EA size computed at mount-time based on + * the number of OSTs in the filesystem. May be increased at + * run-time if a larger observed size is advertised by the MDT. + */ + u32 cl_max_mds_easize; + /* Default cookie size for llog cookies (see struct llog_cookie). It is + * initialized to zero at mount-time, then it tracks the largest + * observed cookie size advertised by the MDT, up to a maximum value of + * OBD_MAX_DEFAULT_COOKIE_SIZE. Note that llog_cookies are not + * used by clients communicating with MDS versions 2.4.0 and later. + */ + u32 cl_default_mds_cookiesize; + /* Maximum possible cookie size computed at mount-time based on + * the number of OSTs in the filesystem. May be increased at + * run-time if a larger observed size is advertised by the MDT. + */ + u32 cl_max_mds_cookiesize; enum lustre_sec_part cl_sp_me; enum lustre_sec_part cl_sp_to; struct sptlrpc_flavor cl_flvr_mgc; /* fixed flavor of mgc->mgs */ /* the grant values are protected by loi_list_lock below */ - long cl_dirty; /* all _dirty_ in bytes */ - long cl_dirty_max; /* allowed w/o rpc */ - long cl_dirty_transit; /* dirty synchronous */ - long cl_avail_grant; /* bytes of credit for ost */ - long cl_lost_grant; /* lost credits (trunc) */ + unsigned long cl_dirty_pages; /* all _dirty_ in pahges */ + unsigned long cl_dirty_max_pages; /* allowed w/o rpc */ + unsigned long cl_dirty_transit; /* dirty synchronous */ + unsigned long cl_avail_grant; /* bytes of credit for ost */ + unsigned long cl_lost_grant; /* lost credits (trunc) */ /* since we allocate grant by blocks, we don't know how many grant will * be used to add a page into cache. As a solution, we reserve maximum @@ -275,8 +274,7 @@ struct client_obd { * the extent size. A chunk is max(PAGE_SIZE, OST block size) */ int cl_chunkbits; - int cl_chunk; - int cl_extent_tax; /* extent overhead, by bytes */ + unsigned int cl_extent_tax; /* extent overhead, by bytes */ /* keep track of objects that have lois that contain pages which * have been queued for async brw. this lock also protects the @@ -301,13 +299,13 @@ struct client_obd { struct list_head cl_loi_hp_ready_list; struct list_head cl_loi_write_list; struct list_head cl_loi_read_list; - int cl_r_in_flight; - int cl_w_in_flight; + __u32 cl_r_in_flight; + __u32 cl_w_in_flight; /* just a sum of the loi/lop pending numbers to be exported by sysfs */ atomic_t cl_pending_w_pages; atomic_t cl_pending_r_pages; __u32 cl_max_pages_per_rpc; - int cl_max_rpcs_in_flight; + __u32 cl_max_rpcs_in_flight; struct obd_histogram cl_read_rpc_hist; struct obd_histogram cl_write_rpc_hist; struct obd_histogram cl_read_page_hist; @@ -318,13 +316,13 @@ struct client_obd { /* lru for osc caching pages */ struct cl_client_cache *cl_cache; struct list_head cl_lru_osc; /* member of cl_cache->ccc_lru */ - atomic_t *cl_lru_left; - atomic_t cl_lru_busy; + atomic_long_t *cl_lru_left; + atomic_long_t cl_lru_busy; + atomic_long_t cl_lru_in_list; atomic_t cl_lru_shrinkers; - atomic_t cl_lru_in_list; struct list_head cl_lru_list; /* lru page list */ spinlock_t cl_lru_list_lock; /* page list protector */ - atomic_t cl_unstable_count; + atomic_long_t cl_unstable_count; /* number of in flight destroy rpcs is limited to max_rpcs_in_flight */ atomic_t cl_destroy_in_flight; @@ -350,7 +348,7 @@ struct client_obd { /* used by quotacheck when the servers are older than 2.4 */ int cl_qchk_stat; /* quotacheck stat of the peer */ #define CL_NOT_QUOTACHECKED 1 /* client->cl_qchk_stat init value */ -#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 7, 50, 0) +#if OBD_OCD_VERSION(2, 7, 53, 0) < LUSTRE_VERSION_CODE #warning "please consider removing quotacheck compatibility code" #endif @@ -431,7 +429,7 @@ struct lov_obd { struct lmv_tgt_desc { struct obd_uuid ltd_uuid; struct obd_export *ltd_exp; - int ltd_idx; + u32 ltd_idx; struct mutex ltd_fid_mutex; unsigned long ltd_active:1; /* target up for requests */ }; @@ -458,9 +456,8 @@ struct lmv_obd { int max_def_easize; int max_cookiesize; int max_def_cookiesize; - int server_timeout; - int tgts_size; /* size of tgts array */ + u32 tgts_size; /* size of tgts array */ struct lmv_tgt_desc **tgts; struct obd_connect_data conn_data; @@ -470,12 +467,11 @@ struct lmv_obd { struct niobuf_local { __u64 lnb_file_offset; __u32 lnb_page_offset; - __u32 len; - __u32 flags; - struct page *page; - struct dentry *dentry; - int lnb_grant_used; - int rc; + __u32 lnb_len; + __u32 lnb_flags; + struct page *lnb_page; + void *lnb_data; + int lnb_rc; }; #define LUSTRE_FLD_NAME "fld" @@ -517,7 +513,6 @@ struct niobuf_local { #define N_LOCAL_TEMP_PAGE 0x10000000 struct obd_trans_info { - __u64 oti_transno; __u64 oti_xid; /* Only used on the server side for tracking acks. */ struct oti_req_ack_lock { @@ -527,50 +522,11 @@ struct obd_trans_info { void *oti_handle; struct llog_cookie oti_onecookie; struct llog_cookie *oti_logcookies; - int oti_numcookies; - /** synchronous write is needed */ - unsigned long oti_sync_write:1; - /* initial thread handling transaction */ - struct ptlrpc_thread *oti_thread; - __u32 oti_conn_cnt; /** VBR: versions */ __u64 oti_pre_version; - /** JobID */ - char *oti_jobid; - - struct obd_uuid *oti_ost_uuid; }; -static inline void oti_alloc_cookies(struct obd_trans_info *oti, - int num_cookies) -{ - if (!oti) - return; - - if (num_cookies == 1) - oti->oti_logcookies = &oti->oti_onecookie; - else - oti->oti_logcookies = libcfs_kvzalloc(num_cookies * sizeof(oti->oti_onecookie), - GFP_NOFS); - - oti->oti_numcookies = num_cookies; -} - -static inline void oti_free_cookies(struct obd_trans_info *oti) -{ - if (!oti || !oti->oti_logcookies) - return; - - if (oti->oti_logcookies == &oti->oti_onecookie) - LASSERT(oti->oti_numcookies == 1); - else - kvfree(oti->oti_logcookies); - - oti->oti_logcookies = NULL; - oti->oti_numcookies = 0; -} - /* * Events signalled through obd_notify() upcall-chain. */ @@ -616,7 +572,6 @@ struct target_recovery_data { }; struct obd_llog_group { - int olg_seq; struct llog_ctxt *olg_ctxts[LLOG_MAX_CTXTS]; wait_queue_head_t olg_waitq; spinlock_t olg_lock; @@ -625,7 +580,6 @@ struct obd_llog_group { /* corresponds to one of the obd's */ #define OBD_DEVICE_MAGIC 0XAB5CD6EF -#define OBD_DEV_BY_DEVNAME 0xffffd0de struct lvfs_run_ctxt { struct dt_device *dt; @@ -653,7 +607,6 @@ struct obd_device { obd_starting:1, /* started setup */ obd_force:1, /* cleanup with > 0 obd refcount */ obd_fail:1, /* cleanup with failover */ - obd_async_recov:1, /* allow asynchronous orphan cleanup */ obd_no_conn:1, /* deny new connections */ obd_inactive:1, /* device active/inactive * (for sysfs status only!!) @@ -728,9 +681,6 @@ struct obd_device { struct completion obd_kobj_unregister; }; -#define OBD_LLOG_FL_SENDNOW 0x0001 -#define OBD_LLOG_FL_EXIT 0x0002 - enum obd_cleanup_stage { /* Special case hack for MDS LOVs */ OBD_CLEANUP_EARLY, @@ -740,8 +690,6 @@ enum obd_cleanup_stage { /* get/set_info keys */ #define KEY_ASYNC "async" -#define KEY_BLOCKSIZE_BITS "blocksize_bits" -#define KEY_BLOCKSIZE "blocksize" #define KEY_CHANGELOG_CLEAR "changelog_clear" #define KEY_FID2PATH "fid2path" #define KEY_CHECKSUM "checksum" @@ -753,30 +701,22 @@ enum obd_cleanup_stage { #define KEY_GRANT_SHRINK "grant_shrink" #define KEY_HSM_COPYTOOL_SEND "hsm_send" #define KEY_INIT_RECOV_BACKUP "init_recov_bk" -#define KEY_INIT_RECOV "initial_recov" #define KEY_INTERMDS "inter_mds" #define KEY_LAST_ID "last_id" #define KEY_LAST_FID "last_fid" -#define KEY_LOCK_TO_STRIPE "lock_to_stripe" #define KEY_LOVDESC "lovdesc" -#define KEY_LOV_IDX "lov_idx" #define KEY_MAX_EASIZE "max_easize" #define KEY_DEFAULT_EASIZE "default_easize" -#define KEY_MDS_CONN "mds_conn" #define KEY_MGSSEC "mgssec" -#define KEY_NEXT_ID "next_id" #define KEY_READ_ONLY "read-only" #define KEY_REGISTER_TARGET "register_target" #define KEY_SET_FS "set_fs" #define KEY_TGT_COUNT "tgt_count" /* KEY_SET_INFO in lustre_idl.h */ #define KEY_SPTLRPC_CONF "sptlrpc_conf" -#define KEY_CONNECT_FLAG "connect_flags" -#define KEY_SYNC_LOCK_CANCEL "sync_lock_cancel" #define KEY_CACHE_SET "cache_set" #define KEY_CACHE_LRU_SHRINK "cache_lru_shrink" -#define KEY_CHANGELOG_INDEX "changelog_index" struct lu_context; @@ -801,9 +741,11 @@ static inline int it_to_lock_mode(struct lookup_intent *it) /* CREAT needs to be tested before open (both could be set) */ if (it->it_op & IT_CREAT) return LCK_CW; - else if (it->it_op & (IT_READDIR | IT_GETATTR | IT_OPEN | IT_LOOKUP | + else if (it->it_op & (IT_GETATTR | IT_OPEN | IT_LOOKUP | IT_LAYOUT)) return LCK_CR; + else if (it->it_op & IT_READDIR) + return LCK_PR; else if (it->it_op & IT_GETXATTR) return LCK_PR; else if (it->it_op & IT_SETXATTR) @@ -813,6 +755,14 @@ static inline int it_to_lock_mode(struct lookup_intent *it) return -EINVAL; } +enum md_cli_flags { + CLI_SET_MEA = BIT(0), + CLI_RM_ENTRY = BIT(1), + CLI_HASH64 = BIT(2), + CLI_API32 = BIT(3), + CLI_MIGRATE = BIT(4), +}; + struct md_op_data { struct lu_fid op_fid1; /* operation fid1 (usually parent) */ struct lu_fid op_fid2; /* operation fid2 (usually child) */ @@ -822,7 +772,7 @@ struct md_op_data { struct lustre_handle op_handle; s64 op_mod_time; const char *op_name; - int op_namelen; + size_t op_namelen; __u32 op_mode; struct lmv_stripe_md *op_mea1; struct lmv_stripe_md *op_mea2; @@ -831,6 +781,7 @@ struct md_op_data { __u32 op_fsgid; cfs_cap_t op_cap; void *op_data; + size_t op_data_size; /* iattr fields and blocks. */ struct iattr op_attr; @@ -845,28 +796,29 @@ struct md_op_data { /* Various operation flags. */ enum mds_op_bias op_bias; - /* Operation type */ - __u32 op_opc; - /* Used by readdir */ __u64 op_offset; /* Used by readdir */ - __u32 op_npages; + __u32 op_max_pages; /* used to transfer info between the stacks of MD client * see enum op_cli_flags */ - __u32 op_cli_flags; + enum md_cli_flags op_cli_flags; /* File object data version for HSM release, on client */ __u64 op_data_version; struct lustre_handle op_lease_handle; + + /* default stripe offset */ + __u32 op_default_stripe_offset; }; -enum op_cli_flags { - CLI_SET_MEA = 1 << 0, - CLI_RM_ENTRY = 1 << 1, +struct md_callback { + int (*md_blocking_ast)(struct ldlm_lock *lock, + struct ldlm_lock_desc *desc, + void *data, int flag); }; struct md_enqueue_info; @@ -879,8 +831,7 @@ struct md_enqueue_info { struct inode *mi_dir; int (*mi_cb)(struct ptlrpc_request *req, struct md_enqueue_info *minfo, int rc); - __u64 mi_cbdata; - unsigned int mi_generation; + void *mi_cbdata; }; struct obd_ops { @@ -894,8 +845,6 @@ struct obd_ops { __u32 keylen, void *key, __u32 vallen, void *val, struct ptlrpc_request_set *set); - int (*attach)(struct obd_device *dev, u32 len, void *data); - int (*detach)(struct obd_device *dev); int (*setup)(struct obd_device *dev, struct lustre_cfg *cfg); int (*precleanup)(struct obd_device *dev, enum obd_cleanup_stage cleanup_stage); @@ -927,8 +876,8 @@ struct obd_ops { int (*fid_fini)(struct obd_device *obd); /* Allocate new fid according to passed @hint. */ - int (*fid_alloc)(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data); + int (*fid_alloc)(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data); /* * Object with @fid is getting deleted, we may want to do something @@ -943,13 +892,10 @@ struct obd_ops { int (*unpackmd)(struct obd_export *exp, struct lov_stripe_md **mem_tgt, struct lov_mds_md *disk_src, int disk_len); - int (*preallocate)(struct lustre_handle *, u32 *req, u64 *ids); int (*create)(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md **ea, - struct obd_trans_info *oti); + struct obdo *oa, struct obd_trans_info *oti); int (*destroy)(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md *ea, - struct obd_trans_info *oti, struct obd_export *md_exp); + struct obdo *oa, struct obd_trans_info *oti); int (*setattr)(const struct lu_env *, struct obd_export *exp, struct obd_info *oinfo, struct obd_trans_info *oti); int (*setattr_async)(struct obd_export *exp, struct obd_info *oinfo, @@ -959,8 +905,6 @@ struct obd_ops { struct obd_info *oinfo); int (*getattr_async)(struct obd_export *exp, struct obd_info *oinfo, struct ptlrpc_request_set *set); - int (*adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm, - u64 size, int shrink); int (*preprw)(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *remote, @@ -972,8 +916,6 @@ struct obd_ops { struct niobuf_remote *remote, int pages, struct niobuf_local *local, struct obd_trans_info *oti, int rc); - int (*find_cbdata)(struct obd_export *, struct lov_stripe_md *, - ldlm_iterator_t it, void *data); int (*init_export)(struct obd_export *exp); int (*destroy_export)(struct obd_export *exp); @@ -1009,27 +951,11 @@ struct obd_ops { */ }; -enum { - LUSTRE_OPC_MKDIR = (1 << 0), - LUSTRE_OPC_SYMLINK = (1 << 1), - LUSTRE_OPC_MKNOD = (1 << 2), - LUSTRE_OPC_CREATE = (1 << 3), - LUSTRE_OPC_ANY = (1 << 4) -}; - /* lmv structures */ -#define MEA_MAGIC_LAST_CHAR 0xb2221ca1 -#define MEA_MAGIC_ALL_CHARS 0xb222a11c -#define MEA_MAGIC_HASH_SEGMENT 0xb222a11b - -#define MAX_HASH_SIZE_32 0x7fffffffUL -#define MAX_HASH_SIZE 0x7fffffffffffffffULL -#define MAX_HASH_HIGHEST_BIT 0x1000000000000000ULL - struct lustre_md { struct mdt_body *body; struct lov_stripe_md *lsm; - struct lmv_stripe_md *mea; + struct lmv_stripe_md *lmv; #ifdef CONFIG_FS_POSIX_ACL struct posix_acl *posix_acl; #endif @@ -1044,48 +970,55 @@ struct md_open_data { bool mod_is_create; }; +struct obd_client_handle { + struct lustre_handle och_fh; + struct lu_fid och_fid; + struct md_open_data *och_mod; + struct lustre_handle och_lease_handle; /* open lock for lease */ + __u32 och_magic; + int och_flags; +}; + +#define OBD_CLIENT_HANDLE_MAGIC 0xd15ea5ed + struct lookup_intent; +struct cl_attr; struct md_ops { int (*getstatus)(struct obd_export *, struct lu_fid *); int (*null_inode)(struct obd_export *, const struct lu_fid *); - int (*find_cbdata)(struct obd_export *, const struct lu_fid *, - ldlm_iterator_t, void *); int (*close)(struct obd_export *, struct md_op_data *, struct md_open_data *, struct ptlrpc_request **); int (*create)(struct obd_export *, struct md_op_data *, - const void *, int, int, __u32, __u32, cfs_cap_t, - __u64, struct ptlrpc_request **); + const void *, size_t, umode_t, uid_t, gid_t, + cfs_cap_t, __u64, struct ptlrpc_request **); int (*done_writing)(struct obd_export *, struct md_op_data *, struct md_open_data *); int (*enqueue)(struct obd_export *, struct ldlm_enqueue_info *, + const ldlm_policy_data_t *, struct lookup_intent *, struct md_op_data *, - struct lustre_handle *, void *, int, - struct ptlrpc_request **, __u64); + struct lustre_handle *, __u64); int (*getattr)(struct obd_export *, struct md_op_data *, struct ptlrpc_request **); int (*getattr_name)(struct obd_export *, struct md_op_data *, struct ptlrpc_request **); int (*intent_lock)(struct obd_export *, struct md_op_data *, - void *, int, struct lookup_intent *, int, + struct lookup_intent *, struct ptlrpc_request **, ldlm_blocking_callback, __u64); int (*link)(struct obd_export *, struct md_op_data *, struct ptlrpc_request **); int (*rename)(struct obd_export *, struct md_op_data *, - const char *, int, const char *, int, + const char *, size_t, const char *, size_t, struct ptlrpc_request **); - int (*is_subdir)(struct obd_export *, const struct lu_fid *, - const struct lu_fid *, - struct ptlrpc_request **); int (*setattr)(struct obd_export *, struct md_op_data *, void *, - int, void *, int, struct ptlrpc_request **, + size_t, void *, size_t, struct ptlrpc_request **, struct md_open_data **mod); int (*sync)(struct obd_export *, const struct lu_fid *, struct ptlrpc_request **); - int (*readpage)(struct obd_export *, struct md_op_data *, - struct page **, struct ptlrpc_request **); - + int (*read_page)(struct obd_export *, struct md_op_data *, + struct md_callback *cb_op, __u64 hash_offset, + struct page **ppage); int (*unlink)(struct obd_export *, struct md_op_data *, struct ptlrpc_request **); @@ -1097,7 +1030,7 @@ struct md_ops { u64, const char *, const char *, int, int, int, struct ptlrpc_request **); - int (*init_ea_size)(struct obd_export *, int, int, int, int); + int (*init_ea_size)(struct obd_export *, u32, u32, u32, u32); int (*get_lustre_md)(struct obd_export *, struct ptlrpc_request *, struct obd_export *, struct obd_export *, @@ -1105,12 +1038,17 @@ struct md_ops { int (*free_lustre_md)(struct obd_export *, struct lustre_md *); + int (*merge_attr)(struct obd_export *, + const struct lmv_stripe_md *lsm, + struct cl_attr *attr, ldlm_blocking_callback); + int (*set_open_replay_data)(struct obd_export *, struct obd_client_handle *, struct lookup_intent *); int (*clear_open_replay_data)(struct obd_export *, struct obd_client_handle *); - int (*set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *); + int (*set_lock_data)(struct obd_export *, const struct lustre_handle *, + void *, __u64 *); enum ldlm_mode (*lock_match)(struct obd_export *, __u64, const struct lu_fid *, enum ldlm_type, @@ -1121,6 +1059,11 @@ struct md_ops { ldlm_policy_data_t *, enum ldlm_mode, enum ldlm_cancel_flags flags, void *opaque); + int (*get_fid_from_lsm)(struct obd_export *, + const struct lmv_stripe_md *, + const char *name, int namelen, + struct lu_fid *fid); + int (*intent_getattr_async)(struct obd_export *, struct md_enqueue_info *, struct ldlm_enqueue_info *); @@ -1137,8 +1080,6 @@ struct md_ops { struct lsm_operations { void (*lsm_free)(struct lov_stripe_md *); - int (*lsm_destroy)(struct lov_stripe_md *, struct obdo *oa, - struct obd_export *md_exp); void (*lsm_stripe_by_index)(struct lov_stripe_md *, int *, u64 *, u64 *); void (*lsm_stripe_by_offset)(struct lov_stripe_md *, int *, u64 *, @@ -1164,10 +1105,6 @@ static inline const struct lsm_operations *lsm_op_find(int magic) } } -/* Requests for obd_extent_calc() */ -#define OBD_CALC_STRIPE_START 1 -#define OBD_CALC_STRIPE_END 2 - static inline struct md_open_data *obd_mod_alloc(void) { struct md_open_data *mod; @@ -1211,7 +1148,8 @@ static inline const char *lu_dev_name(const struct lu_device *lu_dev) return lu_dev->ld_obd->obd_name; } -static inline bool filename_is_volatile(const char *name, int namelen, int *idx) +static inline bool filename_is_volatile(const char *name, size_t namelen, + int *idx) { const char *start; char *end; @@ -1259,4 +1197,28 @@ static inline int cli_brw_size(struct obd_device *obd) return obd->u.cli.cl_max_pages_per_rpc << PAGE_SHIFT; } +/* + * when RPC size or the max RPCs in flight is increased, the max dirty pages + * of the client should be increased accordingly to avoid sending fragmented + * RPCs over the network when the client runs out of the maximum dirty space + * when so many RPCs are being generated. + */ +static inline void client_adjust_max_dirty(struct client_obd *cli) +{ + /* initializing */ + if (cli->cl_dirty_max_pages <= 0) + cli->cl_dirty_max_pages = + (OSC_MAX_DIRTY_DEFAULT * 1024 * 1024) >> PAGE_SHIFT; + else { + unsigned long dirty_max = cli->cl_max_rpcs_in_flight * + cli->cl_max_pages_per_rpc; + + if (dirty_max > cli->cl_dirty_max_pages) + cli->cl_dirty_max_pages = dirty_max; + } + + if (cli->cl_dirty_max_pages > totalram_pages / 8) + cli->cl_dirty_max_pages = totalram_pages / 8; +} + #endif /* __OBD_H */ diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 6482a937000b..16094dbec08b 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -56,7 +56,6 @@ #define OBD_STATFS_FOR_MDT0 0x0008 /* The statfs is only for retrieving * information from MDT0. */ -#define OBD_FL_PUNCH 0x00000001 /* To indicate it is punch operation */ /* OBD Device Declarations */ extern struct obd_device *obd_devs[MAX_OBD_DEVICES]; @@ -97,6 +96,11 @@ int obd_zombie_impexp_init(void); void obd_zombie_impexp_stop(void); void obd_zombie_barrier(void); +int obd_get_request_slot(struct client_obd *cli); +void obd_put_request_slot(struct client_obd *cli); +__u32 obd_get_max_rpcs_in_flight(struct client_obd *cli); +int obd_set_max_rpcs_in_flight(struct client_obd *cli, __u32 max); + struct llog_handle; struct llog_rec_hdr; typedef int (*llog_cb_t)(const struct lu_env *, struct llog_handle *, @@ -265,10 +269,10 @@ static inline int lprocfs_climp_check(struct obd_device *obd) struct inode; struct lu_attr; struct obdo; -void obdo_refresh_inode(struct inode *dst, struct obdo *src, u32 valid); +void obdo_refresh_inode(struct inode *dst, const struct obdo *src, u32 valid); -void obdo_to_ioobj(struct obdo *oa, struct obd_ioobj *ioobj); -void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid); +void obdo_to_ioobj(const struct obdo *oa, struct obd_ioobj *ioobj); +void md_from_obdo(struct md_op_data *op_data, const struct obdo *oa, u32 valid); #define OBT(dev) (dev)->obd_type #define OBP(dev, op) (dev)->obd_type->typ_dt_ops->op @@ -673,15 +677,6 @@ static inline int obd_unpackmd(struct obd_export *exp, return rc; } -/* helper functions */ -static inline int obd_alloc_memmd(struct obd_export *exp, - struct lov_stripe_md **mem_tgt) -{ - LASSERT(mem_tgt); - LASSERT(!*mem_tgt); - return obd_unpackmd(exp, mem_tgt, NULL, 0); -} - static inline int obd_free_memmd(struct obd_export *exp, struct lov_stripe_md **mem_tgt) { @@ -695,29 +690,26 @@ static inline int obd_free_memmd(struct obd_export *exp, } static inline int obd_create(const struct lu_env *env, struct obd_export *exp, - struct obdo *obdo, struct lov_stripe_md **ea, - struct obd_trans_info *oti) + struct obdo *obdo, struct obd_trans_info *oti) { int rc; EXP_CHECK_DT_OP(exp, create); EXP_COUNTER_INCREMENT(exp, create); - rc = OBP(exp->exp_obd, create)(env, exp, obdo, ea, oti); + rc = OBP(exp->exp_obd, create)(env, exp, obdo, oti); return rc; } static inline int obd_destroy(const struct lu_env *env, struct obd_export *exp, - struct obdo *obdo, struct lov_stripe_md *ea, - struct obd_trans_info *oti, - struct obd_export *md_exp) + struct obdo *obdo, struct obd_trans_info *oti) { int rc; EXP_CHECK_DT_OP(exp, destroy); EXP_COUNTER_INCREMENT(exp, destroy); - rc = OBP(exp->exp_obd, destroy)(env, exp, obdo, ea, oti, md_exp); + rc = OBP(exp->exp_obd, destroy)(env, exp, obdo, oti); return rc; } @@ -925,7 +917,8 @@ static inline int obd_fid_fini(struct obd_device *obd) return rc; } -static inline int obd_fid_alloc(struct obd_export *exp, +static inline int obd_fid_alloc(const struct lu_env *env, + struct obd_export *exp, struct lu_fid *fid, struct md_op_data *op_data) { @@ -934,7 +927,7 @@ static inline int obd_fid_alloc(struct obd_export *exp, EXP_CHECK_DT_OP(exp, fid_alloc); EXP_COUNTER_INCREMENT(exp, fid_alloc); - rc = OBP(exp->exp_obd, fid_alloc)(exp, fid, op_data); + rc = OBP(exp->exp_obd, fid_alloc)(env, exp, fid, op_data); return rc; } @@ -1147,19 +1140,6 @@ static inline int obd_commitrw(const struct lu_env *env, int cmd, return rc; } -static inline int obd_adjust_kms(struct obd_export *exp, - struct lov_stripe_md *lsm, u64 size, - int shrink) -{ - int rc; - - EXP_CHECK_DT_OP(exp, adjust_kms); - EXP_COUNTER_INCREMENT(exp, adjust_kms); - - rc = OBP(exp->exp_obd, adjust_kms)(exp, lsm, size, shrink); - return rc; -} - static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void __user *uarg) { @@ -1172,19 +1152,6 @@ static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp, return rc; } -static inline int obd_find_cbdata(struct obd_export *exp, - struct lov_stripe_md *lsm, - ldlm_iterator_t it, void *data) -{ - int rc; - - EXP_CHECK_DT_OP(exp, find_cbdata); - EXP_COUNTER_INCREMENT(exp, find_cbdata); - - rc = OBP(exp->exp_obd, find_cbdata)(exp, lsm, it, data); - return rc; -} - static inline void obd_import_event(struct obd_device *obd, struct obd_import *imp, enum obd_import_event event) @@ -1210,12 +1177,7 @@ static inline int obd_notify(struct obd_device *obd, if (rc) return rc; - /* the check for async_recov is a complete hack - I'm hereby - * overloading the meaning to also mean "this was called from - * mds_postsetup". I know that my mds is able to handle notifies - * by this point, and it needs to get them to execute mds_postrecov. - */ - if (!obd->obd_set_up && !obd->obd_async_recov) { + if (!obd->obd_set_up) { CDEBUG(D_HA, "obd %s not set up\n", obd->obd_name); return -EINVAL; } @@ -1358,18 +1320,6 @@ static inline int md_null_inode(struct obd_export *exp, return rc; } -static inline int md_find_cbdata(struct obd_export *exp, - const struct lu_fid *fid, - ldlm_iterator_t it, void *data) -{ - int rc; - - EXP_CHECK_MD_OP(exp, find_cbdata); - EXP_MD_COUNTER_INCREMENT(exp, find_cbdata); - rc = MDP(exp->exp_obd, find_cbdata)(exp, fid, it, data); - return rc; -} - static inline int md_close(struct obd_export *exp, struct md_op_data *op_data, struct md_open_data *mod, struct ptlrpc_request **request) @@ -1383,9 +1333,9 @@ static inline int md_close(struct obd_export *exp, struct md_op_data *op_data, } static inline int md_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, - __u32 gid, cfs_cap_t cap_effective, __u64 rdev, - struct ptlrpc_request **request) + const void *data, size_t datalen, umode_t mode, + uid_t uid, gid_t gid, cfs_cap_t cap_effective, + __u64 rdev, struct ptlrpc_request **request) { int rc; @@ -1410,19 +1360,18 @@ static inline int md_done_writing(struct obd_export *exp, static inline int md_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, + const ldlm_policy_data_t *policy, struct lookup_intent *it, struct md_op_data *op_data, struct lustre_handle *lockh, - void *lmm, int lmmsize, - struct ptlrpc_request **req, __u64 extra_lock_flags) { int rc; EXP_CHECK_MD_OP(exp, enqueue); EXP_MD_COUNTER_INCREMENT(exp, enqueue); - rc = MDP(exp->exp_obd, enqueue)(exp, einfo, it, op_data, lockh, - lmm, lmmsize, req, extra_lock_flags); + rc = MDP(exp->exp_obd, enqueue)(exp, einfo, policy, it, op_data, lockh, + extra_lock_flags); return rc; } @@ -1439,9 +1388,9 @@ static inline int md_getattr_name(struct obd_export *exp, } static inline int md_intent_lock(struct obd_export *exp, - struct md_op_data *op_data, void *lmm, - int lmmsize, struct lookup_intent *it, - int lookup_flags, struct ptlrpc_request **reqp, + struct md_op_data *op_data, + struct lookup_intent *it, + struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { @@ -1449,9 +1398,8 @@ static inline int md_intent_lock(struct obd_export *exp, EXP_CHECK_MD_OP(exp, intent_lock); EXP_MD_COUNTER_INCREMENT(exp, intent_lock); - rc = MDP(exp->exp_obd, intent_lock)(exp, op_data, lmm, lmmsize, - it, lookup_flags, reqp, cb_blocking, - extra_lock_flags); + rc = MDP(exp->exp_obd, intent_lock)(exp, op_data, it, reqp, + cb_blocking, extra_lock_flags); return rc; } @@ -1467,8 +1415,8 @@ static inline int md_link(struct obd_export *exp, struct md_op_data *op_data, } static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, - int newlen, struct ptlrpc_request **request) + const char *old, size_t oldlen, const char *new, + size_t newlen, struct ptlrpc_request **request) { int rc; @@ -1479,21 +1427,8 @@ static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data, return rc; } -static inline int md_is_subdir(struct obd_export *exp, - const struct lu_fid *pfid, - const struct lu_fid *cfid, - struct ptlrpc_request **request) -{ - int rc; - - EXP_CHECK_MD_OP(exp, is_subdir); - EXP_MD_COUNTER_INCREMENT(exp, is_subdir); - rc = MDP(exp->exp_obd, is_subdir)(exp, pfid, cfid, request); - return rc; -} - static inline int md_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len, + void *ea, size_t ealen, void *ea2, size_t ea2len, struct ptlrpc_request **request, struct md_open_data **mod) { @@ -1517,15 +1452,18 @@ static inline int md_sync(struct obd_export *exp, const struct lu_fid *fid, return rc; } -static inline int md_readpage(struct obd_export *exp, struct md_op_data *opdata, - struct page **pages, - struct ptlrpc_request **request) +static inline int md_read_page(struct obd_export *exp, + struct md_op_data *op_data, + struct md_callback *cb_op, + __u64 hash_offset, + struct page **ppage) { int rc; - EXP_CHECK_MD_OP(exp, readpage); - EXP_MD_COUNTER_INCREMENT(exp, readpage); - rc = MDP(exp->exp_obd, readpage)(exp, opdata, pages, request); + EXP_CHECK_MD_OP(exp, read_page); + EXP_MD_COUNTER_INCREMENT(exp, read_page); + rc = MDP(exp->exp_obd, read_page)(exp, op_data, cb_op, hash_offset, + ppage); return rc; } @@ -1559,6 +1497,16 @@ static inline int md_free_lustre_md(struct obd_export *exp, return MDP(exp->exp_obd, free_lustre_md)(exp, md); } +static inline int md_merge_attr(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + struct cl_attr *attr, + ldlm_blocking_callback cb) +{ + EXP_CHECK_MD_OP(exp, merge_attr); + EXP_MD_COUNTER_INCREMENT(exp, merge_attr); + return MDP(exp->exp_obd, merge_attr)(exp, lsm, attr, cb); +} + static inline int md_setxattr(struct obd_export *exp, const struct lu_fid *fid, u64 valid, const char *name, const char *input, int input_size, @@ -1603,7 +1551,8 @@ static inline int md_clear_open_replay_data(struct obd_export *exp, } static inline int md_set_lock_data(struct obd_export *exp, - __u64 *lockh, void *data, __u64 *bits) + const struct lustre_handle *lockh, + void *data, __u64 *bits) { EXP_CHECK_MD_OP(exp, set_lock_data); EXP_MD_COUNTER_INCREMENT(exp, set_lock_data); @@ -1674,6 +1623,19 @@ static inline int md_revalidate_lock(struct obd_export *exp, return rc; } +static inline int md_get_fid_from_lsm(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + const char *name, int namelen, + struct lu_fid *fid) +{ + int rc; + + EXP_CHECK_MD_OP(exp, get_fid_from_lsm); + EXP_MD_COUNTER_INCREMENT(exp, get_fid_from_lsm); + rc = MDP(exp->exp_obd, get_fid_from_lsm)(exp, lsm, name, namelen, fid); + return rc; +} + /* OBD Metadata Support */ int obd_init_caches(void); @@ -1682,16 +1644,6 @@ void obd_cleanup_caches(void); /* support routines */ extern struct kmem_cache *obdo_cachep; -static inline void obdo2fid(struct obdo *oa, struct lu_fid *fid) -{ - /* something here */ -} - -static inline void fid2obdo(struct lu_fid *fid, struct obdo *oa) -{ - /* something here */ -} - typedef int (*register_lwp_cb)(void *data); struct lwp_register_item { @@ -1710,6 +1662,9 @@ struct lwp_register_item { extern int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c); /* obd_mount.c */ +int lustre_unregister_fs(void); +int lustre_register_fs(void); +int lustre_check_exclusion(struct super_block *sb, char *svname); /* sysctl.c */ int obd_sysctl_init(void); @@ -1730,8 +1685,24 @@ void class_exit_uuidlist(void); extern char obd_jobid_node[]; extern struct miscdevice obd_psdev; extern spinlock_t obd_types_lock; +int class_procfs_init(void); +int class_procfs_clean(void); /* prng.c */ #define ll_generate_random_uuid(uuid_out) cfs_get_random_bytes(uuid_out, sizeof(class_uuid_t)) +/* statfs_pack.c */ +struct kstatfs; +void statfs_pack(struct obd_statfs *osfs, struct kstatfs *sfs); +void statfs_unpack(struct kstatfs *sfs, struct obd_statfs *osfs); + +/* root squash info */ +struct rw_semaphore; +struct root_squash_info { + uid_t rsi_uid; + gid_t rsi_gid; + struct list_head rsi_nosquash_nids; + struct rw_semaphore rsi_sem; +}; + #endif /* __LINUX_OBD_CLASS_H */ diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 845e64a56c21..b346a7f10aa4 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -35,7 +35,7 @@ #include #include "../../include/linux/libcfs/libcfs.h" -#include "linux/lustre_compat25.h" +#include "lustre_compat.h" #include "lprocfs_status.h" /* global variables */ @@ -52,11 +52,9 @@ extern unsigned int at_max; extern unsigned int at_history; extern int at_early_margin; extern int at_extra; -extern unsigned int obd_sync_filter; -extern unsigned int obd_max_dirty_pages; -extern atomic_t obd_unstable_pages; -extern atomic_t obd_dirty_pages; -extern atomic_t obd_dirty_transit_pages; +extern unsigned long obd_max_dirty_pages; +extern atomic_long_t obd_dirty_pages; +extern atomic_long_t obd_dirty_transit_pages; extern char obd_jobid_var[]; /* Some hash init argument constants */ @@ -117,17 +115,17 @@ extern char obd_jobid_var[]; * running on a backup server. (If it's too low, import_select_connection * will increase the timeout anyhow.) */ -#define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN, obd_timeout/20) +#define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN, obd_timeout / 20) /* The max delay between connects is SWITCH_MAX + SWITCH_INC + INITIAL */ #define RECONNECT_DELAY_MAX (CONNECTION_SWITCH_MAX + CONNECTION_SWITCH_INC + \ INITIAL_CONNECT_TIMEOUT) /* The min time a target should wait for clients to reconnect in recovery */ -#define OBD_RECOVERY_TIME_MIN (2*RECONNECT_DELAY_MAX) +#define OBD_RECOVERY_TIME_MIN (2 * RECONNECT_DELAY_MAX) #define OBD_IR_FACTOR_MIN 1 #define OBD_IR_FACTOR_MAX 10 -#define OBD_IR_FACTOR_DEFAULT (OBD_IR_FACTOR_MAX/2) +#define OBD_IR_FACTOR_DEFAULT (OBD_IR_FACTOR_MAX / 2) /* default timeout for the MGS to become IR_FULL */ -#define OBD_IR_MGS_TIMEOUT (4*obd_timeout) +#define OBD_IR_MGS_TIMEOUT (4 * obd_timeout) #define LONG_UNLINK 300 /* Unlink should happen before now */ /** @@ -318,6 +316,10 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LDLM_AGL_NOLOCK 0x31b #define OBD_FAIL_LDLM_OST_LVB 0x31c #define OBD_FAIL_LDLM_ENQUEUE_HANG 0x31d +#define OBD_FAIL_LDLM_CP_CB_WAIT2 0x320 +#define OBD_FAIL_LDLM_CP_CB_WAIT3 0x321 +#define OBD_FAIL_LDLM_CP_CB_WAIT4 0x322 +#define OBD_FAIL_LDLM_CP_CB_WAIT5 0x323 /* LOCKLESS IO */ #define OBD_FAIL_LDLM_SET_CONTENTION 0x385 @@ -400,6 +402,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_MDC_GETATTR_ENQUEUE 0x803 #define OBD_FAIL_MDC_RPCS_SEM 0x804 #define OBD_FAIL_MDC_LIGHTWEIGHT 0x805 +#define OBD_FAIL_MDC_CLOSE 0x806 #define OBD_FAIL_MGS 0x900 #define OBD_FAIL_MGS_ALL_REQUEST_NET 0x901 @@ -455,6 +458,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LOV_INIT 0x1403 #define OBD_FAIL_GLIMPSE_DELAY 0x1404 #define OBD_FAIL_LLITE_XATTR_ENOMEM 0x1405 +#define OBD_FAIL_GETATTR_DELAY 0x1409 #define OBD_FAIL_FID_INDIR 0x1501 #define OBD_FAIL_FID_INLMA 0x1502 @@ -474,11 +478,16 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LFSCK_CRASH 0x160a #define OBD_FAIL_LFSCK_NO_AUTO 0x160b #define OBD_FAIL_LFSCK_NO_DOUBLESCAN 0x160c +#define OBD_FAIL_LFSCK_INVALID_PFID 0x1619 +#define OBD_FAIL_LFSCK_BAD_NAME_HASH 0x1628 /* UPDATE */ #define OBD_FAIL_UPDATE_OBJ_NET 0x1700 #define OBD_FAIL_UPDATE_OBJ_NET_REP 0x1701 +/* LMV */ +#define OBD_FAIL_UNKNOWN_LMV_STRIPE 0x1901 + /* Assign references to moved code to reduce code changes */ #define OBD_FAIL_PRECHECK(id) CFS_FAIL_PRECHECK(id) #define OBD_FAIL_CHECK(id) CFS_FAIL_CHECK(id) @@ -520,7 +529,8 @@ do { \ POISON_PTR(ptr); \ } while (0) -#define KEY_IS(str) \ - (keylen >= (sizeof(str)-1) && memcmp(key, str, (sizeof(str)-1)) == 0) +#define KEY_IS(str) \ + (keylen >= (sizeof(str) - 1) && \ + memcmp(key, str, (sizeof(str) - 1)) == 0) #endif diff --git a/drivers/staging/lustre/lustre/ldlm/interval_tree.c b/drivers/staging/lustre/lustre/ldlm/interval_tree.c index f4a70ebddeaf..e134ecd21bb2 100644 --- a/drivers/staging/lustre/lustre/ldlm/interval_tree.c +++ b/drivers/staging/lustre/lustre/ldlm/interval_tree.c @@ -90,6 +90,17 @@ static inline int extent_equal(struct interval_node_extent *e1, return (e1->start == e2->start) && (e1->end == e2->end); } +static inline int extent_overlapped(struct interval_node_extent *e1, + struct interval_node_extent *e2) +{ + return (e1->start <= e2->end) && (e2->start <= e1->end); +} + +static inline int node_equal(struct interval_node *n1, struct interval_node *n2) +{ + return extent_equal(&n1->in_extent, &n2->in_extent); +} + static inline __u64 max_u64(__u64 x, __u64 y) { return x > y ? x : y; @@ -262,7 +273,7 @@ struct interval_node *interval_insert(struct interval_node *node, p = root; while (*p) { parent = *p; - if (extent_equal(&parent->in_extent, &node->in_extent)) + if (node_equal(parent, node)) return parent; /* max_high field must be updated after each iteration */ @@ -463,3 +474,90 @@ color: interval_erase_color(child, parent, root); } EXPORT_SYMBOL(interval_erase); + +static inline int interval_may_overlap(struct interval_node *node, + struct interval_node_extent *ext) +{ + return (ext->start <= node->in_max_high && + ext->end >= interval_low(node)); +} + +/* + * This function finds all intervals that overlap interval ext, + * and calls func to handle resulted intervals one by one. + * in lustre, this function will find all conflicting locks in + * the granted queue and add these locks to the ast work list. + * + * { + * if (!node) + * return 0; + * if (ext->end < interval_low(node)) { + * interval_search(node->in_left, ext, func, data); + * } else if (interval_may_overlap(node, ext)) { + * if (extent_overlapped(ext, &node->in_extent)) + * func(node, data); + * interval_search(node->in_left, ext, func, data); + * interval_search(node->in_right, ext, func, data); + * } + * return 0; + * } + * + */ +enum interval_iter interval_search(struct interval_node *node, + struct interval_node_extent *ext, + interval_callback_t func, + void *data) +{ + enum interval_iter rc = INTERVAL_ITER_CONT; + struct interval_node *parent; + + LASSERT(ext); + LASSERT(func); + + while (node) { + if (ext->end < interval_low(node)) { + if (node->in_left) { + node = node->in_left; + continue; + } + } else if (interval_may_overlap(node, ext)) { + if (extent_overlapped(ext, &node->in_extent)) { + rc = func(node, data); + if (rc == INTERVAL_ITER_STOP) + break; + } + + if (node->in_left) { + node = node->in_left; + continue; + } + if (node->in_right) { + node = node->in_right; + continue; + } + } + + parent = node->in_parent; + while (parent) { + if (node_is_left_child(node) && + parent->in_right) { + /* + * If we ever got the left, it means that the + * parent met ext->endin_right; + break; + } + node = parent; + parent = parent->in_parent; + } + if (!parent || !interval_may_overlap(parent, ext)) + break; + } + + return rc; +} +EXPORT_SYMBOL(interval_search); diff --git a/drivers/staging/lustre/lustre/ldlm/l_lock.c b/drivers/staging/lustre/lustre/ldlm/l_lock.c index ea8840cb9056..3845f386f1db 100644 --- a/drivers/staging/lustre/lustre/ldlm/l_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/l_lock.c @@ -45,6 +45,8 @@ * being an atomic operation. */ struct ldlm_resource *lock_res_and_lock(struct ldlm_lock *lock) + __acquires(&lock->l_lock) + __acquires(&lock->l_resource->lr_lock) { spin_lock(&lock->l_lock); @@ -59,6 +61,8 @@ EXPORT_SYMBOL(lock_res_and_lock); * Unlock a lock and its resource previously locked with lock_res_and_lock */ void unlock_res_and_lock(struct ldlm_lock *lock) + __releases(&lock->l_resource->lr_lock) + __releases(&lock->l_lock) { /* on server-side resource of lock doesn't change */ ldlm_clear_res_locked(lock); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c index f5023d9b78f5..ecf472e4813d 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c @@ -221,7 +221,7 @@ void ldlm_extent_unlink_lock(struct ldlm_lock *lock) } void ldlm_extent_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy) + ldlm_policy_data_t *lpolicy) { memset(lpolicy, 0, sizeof(*lpolicy)); lpolicy->l_extent.start = wpolicy->l_extent.start; @@ -230,7 +230,7 @@ void ldlm_extent_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, } void ldlm_extent_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, - ldlm_wire_policy_data_t *wpolicy) + ldlm_wire_policy_data_t *wpolicy) { memset(wpolicy, 0, sizeof(*wpolicy)); wpolicy->l_extent.start = lpolicy->l_extent.start; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index d6b61bc39135..861f36f039b5 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -97,7 +97,7 @@ ldlm_flock_destroy(struct ldlm_lock *lock, enum ldlm_mode mode, __u64 flags) LASSERT(hlist_unhashed(&lock->l_exp_flock_hash)); list_del_init(&lock->l_res_link); - if (flags == LDLM_FL_WAIT_NOREPROC && !ldlm_is_failed(lock)) { + if (flags == LDLM_FL_WAIT_NOREPROC) { /* client side - set a flag to prevent sending a CANCEL */ lock->l_flags |= LDLM_FL_LOCAL_ONLY | LDLM_FL_CBPENDING; @@ -166,7 +166,7 @@ reprocess: */ list_for_each(tmp, &res->lr_granted) { lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + l_res_link); if (ldlm_same_flock_owner(lock, req)) { ownlocks = tmp; break; @@ -182,7 +182,7 @@ reprocess: */ list_for_each(tmp, &res->lr_granted) { lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + l_res_link); if (ldlm_same_flock_owner(lock, req)) { if (!ownlocks) @@ -339,10 +339,10 @@ reprocess: lock->l_granted_mode, &null_cbs, NULL, 0, LVB_T_NONE); lock_res_and_lock(req); - if (!new2) { + if (IS_ERR(new2)) { ldlm_flock_destroy(req, lock->l_granted_mode, *flags); - *err = -ENOLCK; + *err = PTR_ERR(new2); return LDLM_ITER_STOP; } goto reprocess; @@ -455,29 +455,22 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) enum ldlm_error err; int rc = 0; + OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT2, 4); + if (OBD_FAIL_PRECHECK(OBD_FAIL_LDLM_CP_CB_WAIT3)) { + lock_res_and_lock(lock); + lock->l_flags |= LDLM_FL_FAIL_LOC; + unlock_res_and_lock(lock); + OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT3, 4); + } CDEBUG(D_DLMTRACE, "flags: 0x%llx data: %p getlk: %p\n", flags, data, getlk); - /* Import invalidation. We need to actually release the lock - * references being held, so that it can go away. No point in - * holding the lock even if app still believes it has it, since - * server already dropped it anyway. Only for granted locks too. - */ - if ((lock->l_flags & (LDLM_FL_FAILED|LDLM_FL_LOCAL_ONLY)) == - (LDLM_FL_FAILED|LDLM_FL_LOCAL_ONLY)) { - if (lock->l_req_mode == lock->l_granted_mode && - lock->l_granted_mode != LCK_NL && !data) - ldlm_lock_decref_internal(lock, lock->l_req_mode); - - /* Need to wake up the waiter if we were evicted */ - wake_up(&lock->l_waitq); - return 0; - } - LASSERT(flags != LDLM_FL_WAIT_NOREPROC); - if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) { + if (flags & LDLM_FL_FAILED) + goto granted; + + if (!(flags & LDLM_FL_BLOCKED_MASK)) { if (!data) /* mds granted the lock in the reply */ goto granted; @@ -514,12 +507,21 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) granted: OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT, 10); - if (ldlm_is_failed(lock)) { - LDLM_DEBUG(lock, "client-side enqueue waking up: failed"); - return -EIO; + if (OBD_FAIL_PRECHECK(OBD_FAIL_LDLM_CP_CB_WAIT4)) { + lock_res_and_lock(lock); + /* DEADLOCK is always set with CBPENDING */ + lock->l_flags |= LDLM_FL_FLOCK_DEADLOCK | LDLM_FL_CBPENDING; + unlock_res_and_lock(lock); + OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT4, 4); + } + if (OBD_FAIL_PRECHECK(OBD_FAIL_LDLM_CP_CB_WAIT5)) { + lock_res_and_lock(lock); + /* DEADLOCK is always set with CBPENDING */ + lock->l_flags |= LDLM_FL_FAIL_LOC | + LDLM_FL_FLOCK_DEADLOCK | LDLM_FL_CBPENDING; + unlock_res_and_lock(lock); + OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT5, 4); } - - LDLM_DEBUG(lock, "client-side enqueue granted"); lock_res_and_lock(lock); @@ -530,20 +532,59 @@ granted: if (ldlm_is_destroyed(lock)) { unlock_res_and_lock(lock); LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed"); - return 0; + /* + * An error is still to be returned, to propagate it up to + * ldlm_cli_enqueue_fini() caller. + */ + return -EIO; } /* ldlm_lock_enqueue() has already placed lock on the granted list. */ - list_del_init(&lock->l_res_link); + ldlm_resource_unlink_lock(lock); - if (ldlm_is_flock_deadlock(lock)) { - LDLM_DEBUG(lock, "client-side enqueue deadlock received"); - rc = -EDEADLK; - } else if (flags & LDLM_FL_TEST_LOCK) { + /* + * Import invalidation. We need to actually release the lock + * references being held, so that it can go away. No point in + * holding the lock even if app still believes it has it, since + * server already dropped it anyway. Only for granted locks too. + */ + /* Do the same for DEADLOCK'ed locks. */ + if (ldlm_is_failed(lock) || ldlm_is_flock_deadlock(lock)) { + int mode; + + if (flags & LDLM_FL_TEST_LOCK) + LASSERT(ldlm_is_test_lock(lock)); + + if (ldlm_is_test_lock(lock) || ldlm_is_flock_deadlock(lock)) + mode = getlk->fl_type; + else + mode = lock->l_granted_mode; + + if (ldlm_is_flock_deadlock(lock)) { + LDLM_DEBUG(lock, "client-side enqueue deadlock received"); + rc = -EDEADLK; + } + ldlm_flock_destroy(lock, mode, LDLM_FL_WAIT_NOREPROC); + unlock_res_and_lock(lock); + + /* Need to wake up the waiter if we were evicted */ + wake_up(&lock->l_waitq); + + /* + * An error is still to be returned, to propagate it up to + * ldlm_cli_enqueue_fini() caller. + */ + return rc ? : -EIO; + } + + LDLM_DEBUG(lock, "client-side enqueue granted"); + + if (flags & LDLM_FL_TEST_LOCK) { /* fcntl(F_GETLK) request */ /* The old mode was saved in getlk->fl_type so that if the mode * in the lock changes we can decref the appropriate refcount. */ + LASSERT(ldlm_is_test_lock(lock)); ldlm_flock_destroy(lock, getlk->fl_type, LDLM_FL_WAIT_NOREPROC); switch (lock->l_granted_mode) { case LCK_PR: diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index e4cf65d2d3b1..5e82cfc245b2 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -100,9 +100,10 @@ enum { int ldlm_cancel_lru(struct ldlm_namespace *ns, int nr, enum ldlm_cancel_flags sync, int flags); int ldlm_cancel_lru_local(struct ldlm_namespace *ns, - struct list_head *cancels, int count, int max, - enum ldlm_cancel_flags cancel_flags, int flags); -extern int ldlm_enqueue_min; + struct list_head *cancels, int count, int max, + enum ldlm_cancel_flags cancel_flags, int flags); +extern unsigned int ldlm_enqueue_min; +extern unsigned int ldlm_cancel_unused_locks_before_replay; /* ldlm_resource.c */ int ldlm_resource_putref_locked(struct ldlm_resource *res); @@ -200,8 +201,7 @@ ldlm_interval_extent(struct ldlm_interval *node) LASSERT(!list_empty(&node->li_group)); - lock = list_entry(node->li_group.next, struct ldlm_lock, - l_sl_policy); + lock = list_entry(node->li_group.next, struct ldlm_lock, l_sl_policy); return &lock->l_policy_data.l_extent; } @@ -302,7 +302,7 @@ static inline int is_granted_or_cancelled(struct ldlm_lock *lock) lock_res_and_lock(lock); if ((lock->l_req_mode == lock->l_granted_mode) && - !ldlm_is_cp_reqd(lock)) + !ldlm_is_cp_reqd(lock)) ret = 1; else if (ldlm_is_failed(lock) || ldlm_is_cancel(lock)) ret = 1; @@ -326,13 +326,13 @@ void ldlm_ibits_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, void ldlm_ibits_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, ldlm_wire_policy_data_t *wpolicy); void ldlm_extent_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy); + ldlm_policy_data_t *lpolicy); void ldlm_extent_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, - ldlm_wire_policy_data_t *wpolicy); + ldlm_wire_policy_data_t *wpolicy); void ldlm_flock_policy_wire18_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy); + ldlm_policy_data_t *lpolicy); void ldlm_flock_policy_wire21_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy); + ldlm_policy_data_t *lpolicy); void ldlm_flock_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, ldlm_wire_policy_data_t *wpolicy); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 7c832aae7d5e..153e990c494e 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -82,7 +82,7 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid, if (priority) { list_del(&item->oic_item); list_add(&item->oic_item, - &imp->imp_conn_list); + &imp->imp_conn_list); item->oic_last_attempt = 0; } CDEBUG(D_HA, "imp %p@%s: found existing conn %s%s\n", @@ -102,7 +102,7 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid, list_add(&imp_conn->oic_item, &imp->imp_conn_list); else list_add_tail(&imp_conn->oic_item, - &imp->imp_conn_list); + &imp->imp_conn_list); CDEBUG(D_HA, "imp %p@%s: add connection %s at %s\n", imp, imp->imp_obd->obd_name, uuid->uuid, (priority ? "head" : "tail")); @@ -299,12 +299,14 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) min_t(unsigned int, LUSTRE_CFG_BUFLEN(lcfg, 2), sizeof(server_uuid))); - cli->cl_dirty = 0; + cli->cl_dirty_pages = 0; cli->cl_avail_grant = 0; - /* FIXME: Should limit this for the sum of all cl_dirty_max. */ - cli->cl_dirty_max = OSC_MAX_DIRTY_DEFAULT * 1024 * 1024; - if (cli->cl_dirty_max >> PAGE_SHIFT > totalram_pages / 8) - cli->cl_dirty_max = totalram_pages << (PAGE_SHIFT - 3); + /* FIXME: Should limit this for the sum of all cl_dirty_max_pages. */ + /* + * cl_dirty_max_pages may be changed at connect time in + * ptlrpc_connect_interpret(). + */ + client_adjust_max_dirty(cli); INIT_LIST_HEAD(&cli->cl_cache_waiters); INIT_LIST_HEAD(&cli->cl_loi_ready_list); INIT_LIST_HEAD(&cli->cl_loi_hp_ready_list); @@ -326,11 +328,11 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) /* lru for osc. */ INIT_LIST_HEAD(&cli->cl_lru_osc); atomic_set(&cli->cl_lru_shrinkers, 0); - atomic_set(&cli->cl_lru_busy, 0); - atomic_set(&cli->cl_lru_in_list, 0); + atomic_long_set(&cli->cl_lru_busy, 0); + atomic_long_set(&cli->cl_lru_in_list, 0); INIT_LIST_HEAD(&cli->cl_lru_list); spin_lock_init(&cli->cl_lru_list_lock); - atomic_set(&cli->cl_unstable_count, 0); + atomic_long_set(&cli->cl_unstable_count, 0); init_waitqueue_head(&cli->cl_destroy_waitq); atomic_set(&cli->cl_destroy_in_flight, 0); @@ -360,7 +362,7 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) cli->cl_chunkbits = PAGE_SHIFT; if (!strcmp(name, LUSTRE_MDC_NAME)) { - cli->cl_max_rpcs_in_flight = MDC_MAX_RIF_DEFAULT; + cli->cl_max_rpcs_in_flight = OBD_MAX_RIF_DEFAULT; } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 128 /* MB */) { cli->cl_max_rpcs_in_flight = 2; } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 256 /* MB */) { @@ -368,7 +370,7 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 512 /* MB */) { cli->cl_max_rpcs_in_flight = 4; } else { - cli->cl_max_rpcs_in_flight = OSC_MAX_RIF_DEFAULT; + cli->cl_max_rpcs_in_flight = OBD_MAX_RIF_DEFAULT; } rc = ldlm_get_ref(); if (rc) { @@ -534,7 +536,7 @@ int client_disconnect_export(struct obd_export *exp) imp = cli->cl_import; down_write(&cli->cl_sem); - CDEBUG(D_INFO, "disconnect %s - %d\n", obd->obd_name, + CDEBUG(D_INFO, "disconnect %s - %zu\n", obd->obd_name, cli->cl_conn_count); if (!cli->cl_conn_count) { @@ -690,7 +692,7 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id) if (rs->rs_transno > exp->exp_last_committed) { /* not committed already */ list_add_tail(&rs->rs_obd_list, - &exp->exp_uncommitted_replies); + &exp->exp_uncommitted_replies); } spin_unlock(&exp->exp_uncommitted_replies_lock); @@ -795,7 +797,7 @@ void ldlm_dump_export_locks(struct obd_export *exp) CERROR("dumping locks for export %p,ignore if the unmount doesn't hang\n", exp); list_for_each_entry(lock, &exp->exp_locks_list, - l_exp_refs_link) + l_exp_refs_link) LDLM_ERROR(lock, "lock:"); } spin_unlock(&exp->exp_locks_list_guard); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index a5993f745ebe..3c48b4fb96f1 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -481,8 +481,8 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock, unlock_res_and_lock(lock); newres = ldlm_resource_get(ns, NULL, new_resid, type, 1); - if (!newres) - return -ENOMEM; + if (IS_ERR(newres)) + return PTR_ERR(newres); lu_ref_add(&newres->lr_reference, "lock", lock); /* @@ -542,7 +542,7 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle, LASSERT(handle); - lock = class_handle2object(handle->cookie); + lock = class_handle2object(handle->cookie, NULL); if (!lock) return NULL; @@ -937,7 +937,7 @@ static void search_granted_lock(struct list_head *queue, /* go to next policy group within mode group */ tmp = policy_end->l_res_link.next; lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + l_res_link); } /* loop over policy groups within the mode group */ /* insert point is last lock of the mode group, @@ -1028,15 +1028,28 @@ void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list) check_res_locked(res); lock->l_granted_mode = lock->l_req_mode; + + if (work_list && lock->l_completion_ast) + ldlm_add_ast_work_item(lock, NULL, work_list); + if (res->lr_type == LDLM_PLAIN || res->lr_type == LDLM_IBITS) ldlm_grant_lock_with_skiplist(lock); else if (res->lr_type == LDLM_EXTENT) ldlm_extent_add_lock(res, lock); - else + else if (res->lr_type == LDLM_FLOCK) { + /* + * We should not add locks to granted list in the following cases: + * - this is an UNLOCK but not a real lock; + * - this is a TEST lock; + * - this is a F_CANCELLK lock (async flock has req_mode == 0) + * - this is a deadlock (flock cannot be granted) + */ + if (!lock->l_req_mode || lock->l_req_mode == LCK_NL || + ldlm_is_test_lock(lock) || ldlm_is_flock_deadlock(lock)) + return; ldlm_resource_add_lock(res, &res->lr_granted, lock); - - if (work_list && lock->l_completion_ast) - ldlm_add_ast_work_item(lock, NULL, work_list); + } else + LBUG(); ldlm_pool_add(&ldlm_res_to_ns(res)->ns_pool, lock); } @@ -1103,7 +1116,7 @@ static struct ldlm_lock *search_queue(struct list_head *queue, * of bits. */ if (lock->l_resource->lr_type == LDLM_IBITS && - ((lock->l_policy_data.l_inodebits.bits & + ((lock->l_policy_data.l_inodebits.bits & policy->l_inodebits.bits) != policy->l_inodebits.bits)) continue; @@ -1214,7 +1227,7 @@ enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, } res = ldlm_resource_get(ns, NULL, res_id, type, 0); - if (!res) { + if (IS_ERR(res)) { LASSERT(!old_lock); return 0; } @@ -1363,12 +1376,12 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill, if (size == sizeof(struct ost_lvb)) { if (loc == RCL_CLIENT) lvb = req_capsule_client_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_ost_lvb); + &RMF_DLM_LVB, + lustre_swab_ost_lvb); else lvb = req_capsule_server_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_ost_lvb); + &RMF_DLM_LVB, + lustre_swab_ost_lvb); if (unlikely(!lvb)) { LDLM_ERROR(lock, "no LVB"); return -EPROTO; @@ -1380,8 +1393,8 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill, if (loc == RCL_CLIENT) lvb = req_capsule_client_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_ost_lvb_v1); + &RMF_DLM_LVB, + lustre_swab_ost_lvb_v1); else lvb = req_capsule_server_sized_swab_get(pill, &RMF_DLM_LVB, size, @@ -1405,12 +1418,12 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill, if (size == sizeof(struct lquota_lvb)) { if (loc == RCL_CLIENT) lvb = req_capsule_client_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_lquota_lvb); + &RMF_DLM_LVB, + lustre_swab_lquota_lvb); else lvb = req_capsule_server_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_lquota_lvb); + &RMF_DLM_LVB, + lustre_swab_lquota_lvb); if (unlikely(!lvb)) { LDLM_ERROR(lock, "no LVB"); return -EPROTO; @@ -1462,15 +1475,15 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns, { struct ldlm_lock *lock; struct ldlm_resource *res; + int rc; res = ldlm_resource_get(ns, NULL, res_id, type, 1); - if (!res) - return NULL; + if (IS_ERR(res)) + return ERR_CAST(res); lock = ldlm_lock_new(res); - if (!lock) - return NULL; + return ERR_PTR(-ENOMEM); lock->l_req_mode = mode; lock->l_ast_data = data; @@ -1484,27 +1497,33 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns, lock->l_tree_node = NULL; /* if this is the extent lock, allocate the interval tree node */ if (type == LDLM_EXTENT) { - if (!ldlm_interval_alloc(lock)) + if (!ldlm_interval_alloc(lock)) { + rc = -ENOMEM; goto out; + } } if (lvb_len) { lock->l_lvb_len = lvb_len; lock->l_lvb_data = kzalloc(lvb_len, GFP_NOFS); - if (!lock->l_lvb_data) + if (!lock->l_lvb_data) { + rc = -ENOMEM; goto out; + } } lock->l_lvb_type = lvb_type; - if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_NEW_LOCK)) + if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_NEW_LOCK)) { + rc = -ENOENT; goto out; + } return lock; out: ldlm_lock_destroy(lock); LDLM_LOCK_RELEASE(lock); - return NULL; + return ERR_PTR(rc); } /** @@ -1522,16 +1541,13 @@ enum ldlm_error ldlm_lock_enqueue(struct ldlm_namespace *ns, struct ldlm_lock *lock = *lockp; struct ldlm_resource *res = lock->l_resource; - lock->l_last_activity = ktime_get_real_seconds(); - lock_res_and_lock(lock); if (lock->l_req_mode == lock->l_granted_mode) { /* The server returned a blocked lock, but it was granted * before we got a chance to actually enqueue it. We don't * need to do anything else. */ - *flags &= ~(LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV | LDLM_FL_BLOCK_WAIT); + *flags &= ~LDLM_FL_BLOCKED_MASK; goto out; } @@ -1546,6 +1562,8 @@ enum ldlm_error ldlm_lock_enqueue(struct ldlm_namespace *ns, */ if (*flags & LDLM_FL_AST_DISCARD_DATA) ldlm_set_ast_discard_data(lock); + if (*flags & LDLM_FL_TEST_LOCK) + ldlm_set_test_lock(lock); /* * This distinction between local lock trees is very important; a client @@ -1688,7 +1706,7 @@ static int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) return -ENOENT; gl_work = list_entry(arg->list->next, struct ldlm_glimpse_work, - gl_list); + gl_list); list_del_init(&gl_work->gl_list); lock = gl_work->gl_lock; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index 821939ff2e6b..fde697ebaadc 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -559,8 +559,11 @@ static int ldlm_callback_handler(struct ptlrpc_request *req) switch (lustre_msg_get_opc(req->rq_reqmsg)) { case LDLM_BL_CALLBACK: - if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) + if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) { + if (cfs_fail_err) + ldlm_callback_reply(req, -(int)cfs_fail_err); return 0; + } break; case LDLM_CP_CALLBACK: if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CP_CALLBACK_NET)) @@ -706,12 +709,12 @@ static struct ldlm_bl_work_item *ldlm_bl_get_work(struct ldlm_bl_pool *blp) if (!list_empty(&blp->blp_list) && (list_empty(&blp->blp_prio_list) || num_bl == 0)) blwi = list_entry(blp->blp_list.next, - struct ldlm_bl_work_item, blwi_entry); + struct ldlm_bl_work_item, blwi_entry); else if (!list_empty(&blp->blp_prio_list)) blwi = list_entry(blp->blp_prio_list.next, - struct ldlm_bl_work_item, - blwi_entry); + struct ldlm_bl_work_item, + blwi_entry); if (blwi) { if (++num_bl >= atomic_read(&blp->blp_num_threads)) @@ -741,7 +744,7 @@ static int ldlm_bl_thread_start(struct ldlm_bl_pool *blp) init_completion(&bltd.bltd_comp); bltd.bltd_num = atomic_read(&blp->blp_num_threads); snprintf(bltd.bltd_name, sizeof(bltd.bltd_name), - "ldlm_bl_%02d", bltd.bltd_num); + "ldlm_bl_%02d", bltd.bltd_num); task = kthread_run(ldlm_bl_thread_main, &bltd, "%s", bltd.bltd_name); if (IS_ERR(task)) { CERROR("cannot start LDLM thread ldlm_bl_%02d: rc %ld\n", @@ -786,8 +789,8 @@ static int ldlm_bl_thread_main(void *arg) if (!blwi) { atomic_dec(&blp->blp_busy_threads); l_wait_event_exclusive(blp->blp_waitq, - (blwi = ldlm_bl_get_work(blp)), - &lwi); + (blwi = ldlm_bl_get_work(blp)), + &lwi); busy = atomic_inc_return(&blp->blp_busy_threads); } else { busy = atomic_read(&blp->blp_busy_threads); @@ -874,8 +877,6 @@ void ldlm_put_ref(void) } EXPORT_SYMBOL(ldlm_put_ref); -extern unsigned int ldlm_cancel_unused_locks_before_replay; - static ssize_t cancel_unused_locks_before_replay_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -1094,16 +1095,17 @@ int ldlm_init(void) return -ENOMEM; ldlm_lock_slab = kmem_cache_create("ldlm_locks", - sizeof(struct ldlm_lock), 0, - SLAB_HWCACHE_ALIGN | SLAB_DESTROY_BY_RCU, NULL); + sizeof(struct ldlm_lock), 0, + SLAB_HWCACHE_ALIGN | + SLAB_DESTROY_BY_RCU, NULL); if (!ldlm_lock_slab) { kmem_cache_destroy(ldlm_resource_slab); return -ENOMEM; } ldlm_interval_slab = kmem_cache_create("interval_node", - sizeof(struct ldlm_interval), - 0, SLAB_HWCACHE_ALIGN, NULL); + sizeof(struct ldlm_interval), + 0, SLAB_HWCACHE_ALIGN, NULL); if (!ldlm_interval_slab) { kmem_cache_destroy(ldlm_resource_slab); kmem_cache_destroy(ldlm_lock_slab); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 657ed4012776..9a1136e32dfc 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -357,38 +357,40 @@ static int ldlm_pool_recalc(struct ldlm_pool *pl) int count; recalc_interval_sec = ktime_get_seconds() - pl->pl_recalc_time; - if (recalc_interval_sec <= 0) - goto recalc; - - spin_lock(&pl->pl_lock); if (recalc_interval_sec > 0) { - /* - * Update pool statistics every 1s. - */ - ldlm_pool_recalc_stats(pl); + spin_lock(&pl->pl_lock); + recalc_interval_sec = ktime_get_seconds() - pl->pl_recalc_time; - /* - * Zero out all rates and speed for the last period. - */ - atomic_set(&pl->pl_grant_rate, 0); - atomic_set(&pl->pl_cancel_rate, 0); + if (recalc_interval_sec > 0) { + /* + * Update pool statistics every 1s. + */ + ldlm_pool_recalc_stats(pl); + + /* + * Zero out all rates and speed for the last period. + */ + atomic_set(&pl->pl_grant_rate, 0); + atomic_set(&pl->pl_cancel_rate, 0); + } + spin_unlock(&pl->pl_lock); } - spin_unlock(&pl->pl_lock); - recalc: if (pl->pl_ops->po_recalc) { count = pl->pl_ops->po_recalc(pl); lprocfs_counter_add(pl->pl_stats, LDLM_POOL_RECALC_STAT, count); } + recalc_interval_sec = pl->pl_recalc_time - ktime_get_seconds() + pl->pl_recalc_period; if (recalc_interval_sec <= 0) { + /* DEBUG: should be re-removed after LU-4536 is fixed */ + CDEBUG(D_DLMTRACE, "%s: Negative interval(%ld), too short period(%ld)\n", + pl->pl_name, (long)recalc_interval_sec, + (long)pl->pl_recalc_period); + /* Prevent too frequent recalculation. */ - CDEBUG(D_DLMTRACE, - "Negative interval(%d), too short period(%lld)", - recalc_interval_sec, - (s64)pl->pl_recalc_period); recalc_interval_sec = 1; } @@ -792,7 +794,8 @@ static struct completion ldlm_pools_comp; */ static unsigned long ldlm_pools_count(ldlm_side_t client, gfp_t gfp_mask) { - int total = 0, nr_ns; + unsigned long total = 0; + int nr_ns; struct ldlm_namespace *ns; struct ldlm_namespace *ns_old = NULL; /* loop detection */ void *cookie; @@ -995,7 +998,7 @@ static int ldlm_pools_thread_main(void *arg) wake_up(&thread->t_ctl_waitq); CDEBUG(D_DLMTRACE, "%s: pool thread starting, process %d\n", - "ldlm_poold", current_pid()); + "ldlm_poold", current_pid()); while (1) { struct l_wait_info lwi; @@ -1025,7 +1028,7 @@ static int ldlm_pools_thread_main(void *arg) wake_up(&thread->t_ctl_waitq); CDEBUG(D_DLMTRACE, "%s: pool thread exiting, process %d\n", - "ldlm_poold", current_pid()); + "ldlm_poold", current_pid()); complete_and_exit(&ldlm_pools_comp, 0); } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index af487f9937f4..35ba6f14d95f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -63,8 +63,8 @@ #include "ldlm_internal.h" -int ldlm_enqueue_min = OBD_TIMEOUT_DEFAULT; -module_param(ldlm_enqueue_min, int, 0644); +unsigned int ldlm_enqueue_min = OBD_TIMEOUT_DEFAULT; +module_param(ldlm_enqueue_min, uint, 0644); MODULE_PARM_DESC(ldlm_enqueue_min, "lock enqueue timeout minimum"); /* in client side, whether the cached locks will be canceled before replay */ @@ -123,44 +123,56 @@ static int ldlm_expired_completion_wait(void *data) return 0; } +/** + * Calculate the Completion timeout (covering enqueue, BL AST, data flush, + * lock cancel, and their replies). Used for lock completion timeout on the + * client side. + * + * \param[in] lock lock which is waiting the completion callback + * + * \retval timeout in seconds to wait for the server reply + */ /* We use the same basis for both server side and client side functions * from a single node. */ -static int ldlm_get_enq_timeout(struct ldlm_lock *lock) +static unsigned int ldlm_cp_timeout(struct ldlm_lock *lock) { - int timeout = at_get(ldlm_lock_to_ns_at(lock)); + unsigned int timeout; if (AT_OFF) - return obd_timeout / 2; - /* Since these are non-updating timeouts, we should be conservative. - * It would be nice to have some kind of "early reply" mechanism for - * lock callbacks too... + return obd_timeout; + + /* + * Wait a long time for enqueue - server may have to callback a + * lock from another client. Server will evict the other client if it + * doesn't respond reasonably, and then give us the lock. */ - timeout = min_t(int, at_max, timeout + (timeout >> 1)); /* 150% */ - return max(timeout, ldlm_enqueue_min); + timeout = at_get(ldlm_lock_to_ns_at(lock)); + return max(3 * timeout, ldlm_enqueue_min); } /** * Helper function for ldlm_completion_ast(), updating timings when lock is * actually granted. */ -static int ldlm_completion_tail(struct ldlm_lock *lock) +static int ldlm_completion_tail(struct ldlm_lock *lock, void *data) { long delay; - int result; + int result = 0; if (ldlm_is_destroyed(lock) || ldlm_is_failed(lock)) { LDLM_DEBUG(lock, "client-side enqueue: destroyed"); result = -EIO; + } else if (!data) { + LDLM_DEBUG(lock, "client-side enqueue: granted"); } else { + /* Take into AT only CP RPC, not immediately granted locks */ delay = ktime_get_real_seconds() - lock->l_last_activity; LDLM_DEBUG(lock, "client-side enqueue: granted after %lds", delay); /* Update our time estimate */ - at_measured(ldlm_lock_to_ns_at(lock), - delay); - result = 0; + at_measured(ldlm_lock_to_ns_at(lock), delay); } return result; } @@ -177,10 +189,9 @@ int ldlm_completion_ast_async(struct ldlm_lock *lock, __u64 flags, void *data) return 0; } - if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) { + if (!(flags & LDLM_FL_BLOCKED_MASK)) { wake_up(&lock->l_waitq); - return ldlm_completion_tail(lock); + return ldlm_completion_tail(lock, data); } LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, going forward"); @@ -224,8 +235,7 @@ int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) goto noreproc; } - if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) { + if (!(flags & LDLM_FL_BLOCKED_MASK)) { wake_up(&lock->l_waitq); return 0; } @@ -240,13 +250,10 @@ noreproc: if (obd) imp = obd->u.cli.cl_import; - /* Wait a long time for enqueue - server may have to callback a - * lock from another client. Server will evict the other client if it - * doesn't respond reasonably, and then give us the lock. - */ - timeout = ldlm_get_enq_timeout(lock) * 2; + timeout = ldlm_cp_timeout(lock); lwd.lwd_lock = lock; + lock->l_last_activity = ktime_get_real_seconds(); if (ldlm_is_no_timeout(lock)) { LDLM_DEBUG(lock, "waiting indefinitely because of NO_TIMEOUT"); @@ -279,7 +286,7 @@ noreproc: return rc; } - return ldlm_completion_tail(lock); + return ldlm_completion_tail(lock, data); } EXPORT_SYMBOL(ldlm_completion_ast); @@ -309,8 +316,6 @@ static void failed_lock_cleanup(struct ldlm_namespace *ns, else LDLM_DEBUG(lock, "lock was granted or failed in race"); - ldlm_lock_decref_internal(lock, mode); - /* XXX - HACK because we shouldn't call ldlm_lock_destroy() * from llite/file.c/ll_file_flock(). */ @@ -321,9 +326,14 @@ static void failed_lock_cleanup(struct ldlm_namespace *ns, */ if (lock->l_resource->lr_type == LDLM_FLOCK) { lock_res_and_lock(lock); - ldlm_resource_unlink_lock(lock); - ldlm_lock_destroy_nolock(lock); + if (!ldlm_is_destroyed(lock)) { + ldlm_resource_unlink_lock(lock); + ldlm_lock_decref_internal_nolock(lock, mode); + ldlm_lock_destroy_nolock(lock); + } unlock_res_and_lock(lock); + } else { + ldlm_lock_decref_internal(lock, mode); } } @@ -418,11 +428,6 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, *flags = ldlm_flags_from_wire(reply->lock_flags); lock->l_flags |= ldlm_flags_from_wire(reply->lock_flags & LDLM_FL_INHERIT_MASK); - /* move NO_TIMEOUT flag to the lock to force ldlm_lock_match() - * to wait with no timeout as well - */ - lock->l_flags |= ldlm_flags_from_wire(reply->lock_flags & - LDLM_FL_NO_TIMEOUT); unlock_res_and_lock(lock); CDEBUG(D_INFO, "local: %p, remote cookie: %#llx, flags: 0x%llx\n", @@ -556,7 +561,7 @@ static inline int ldlm_capsule_handles_avail(struct req_capsule *pill, enum req_location loc, int off) { - int size = req_capsule_msg_size(pill, loc); + u32 size = req_capsule_msg_size(pill, loc); return ldlm_req_handles_avail(size, off); } @@ -565,7 +570,7 @@ static inline int ldlm_format_handles_avail(struct obd_import *imp, const struct req_format *fmt, enum req_location loc, int off) { - int size = req_capsule_fmt_size(imp->imp_msg_magic, fmt, loc); + u32 size = req_capsule_fmt_size(imp->imp_msg_magic, fmt, loc); return ldlm_req_handles_avail(size, off); } @@ -696,8 +701,8 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp, lock = ldlm_lock_create(ns, res_id, einfo->ei_type, einfo->ei_mode, &cbs, einfo->ei_cbdata, lvb_len, lvb_type); - if (!lock) - return -ENOMEM; + if (IS_ERR(lock)) + return PTR_ERR(lock); /* for the local lock, add the reference */ ldlm_lock_addref_internal(lock, einfo->ei_mode); ldlm_lock2handle(lock, lockh); @@ -719,6 +724,7 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp, lock->l_export = NULL; lock->l_blocking_ast = einfo->ei_cb_bl; lock->l_flags |= (*flags & (LDLM_FL_NO_LRU | LDLM_FL_EXCL)); + lock->l_last_activity = ktime_get_real_seconds(); /* lock not sent to server yet */ @@ -819,7 +825,7 @@ static __u64 ldlm_cli_cancel_local(struct ldlm_lock *lock) lock_res_and_lock(lock); ldlm_set_cbpending(lock); local_only = !!(lock->l_flags & - (LDLM_FL_LOCAL_ONLY|LDLM_FL_CANCEL_ON_BLOCK)); + (LDLM_FL_LOCAL_ONLY | LDLM_FL_CANCEL_ON_BLOCK)); ldlm_cancel_callback(lock); rc = ldlm_is_bl_ast(lock) ? LDLM_FL_BL_AST : LDLM_FL_CANCELING; unlock_res_and_lock(lock); @@ -1180,8 +1186,7 @@ static enum ldlm_policy_res ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, slv = ldlm_pool_get_slv(pl); lvf = ldlm_pool_get_lvf(pl); - la = cfs_duration_sec(cfs_time_sub(cur, - lock->l_last_used)); + la = cfs_duration_sec(cfs_time_sub(cur, lock->l_last_used)); lv = lvf * la * unused; /* Inform pool about current CLV to see it via debugfs. */ @@ -1193,9 +1198,6 @@ static enum ldlm_policy_res ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, if (slv == 0 || lv < slv) return LDLM_POLICY_KEEP_LOCK; - if (ns->ns_cancel && ns->ns_cancel(lock) == 0) - return LDLM_POLICY_KEEP_LOCK; - return LDLM_POLICY_CANCEL_LOCK; } @@ -1239,9 +1241,6 @@ static enum ldlm_policy_res ldlm_cancel_aged_policy(struct ldlm_namespace *ns, cfs_time_add(lock->l_last_used, ns->ns_max_age))) return LDLM_POLICY_KEEP_LOCK; - if (ns->ns_cancel && ns->ns_cancel(lock) == 0) - return LDLM_POLICY_KEEP_LOCK; - return LDLM_POLICY_CANCEL_LOCK; } @@ -1374,7 +1373,7 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, break; list_for_each_entry_safe(lock, next, &ns->ns_unused_list, - l_lru) { + l_lru) { /* No locks which got blocking requests. */ LASSERT(!ldlm_is_bl_ast(lock)); @@ -1413,7 +1412,8 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, * That is, for shrinker policy we drop only * old locks, but additionally choose them by * their weight. Big extent locks will stay in - * the cache. */ + * the cache. + */ result = pf(ns, lock, unused, added, count); if (result == LDLM_POLICY_KEEP_LOCK) { lu_ref_del(&lock->l_reference, @@ -1610,8 +1610,7 @@ int ldlm_cli_cancel_list(struct list_head *cancels, int count, */ while (count > 0) { LASSERT(!list_empty(cancels)); - lock = list_entry(cancels->next, struct ldlm_lock, - l_bl_ast); + lock = list_entry(cancels->next, struct ldlm_lock, l_bl_ast); LASSERT(lock->l_conn_export); if (exp_connect_cancelset(lock->l_conn_export)) { @@ -1660,7 +1659,7 @@ int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns, int rc; res = ldlm_resource_get(ns, NULL, res_id, 0, 0); - if (!res) { + if (IS_ERR(res)) { /* This is not a problem. */ CDEBUG(D_INFO, "No resource %llu\n", res_id->name[0]); return 0; @@ -1704,7 +1703,8 @@ static int ldlm_cli_hash_cancel_unused(struct cfs_hash *hs, * that have 0 readers/writers. * * If flags & LCF_LOCAL, throw the locks away without trying - * to notify the server. */ + * to notify the server. + */ int ldlm_cli_cancel_unused(struct ldlm_namespace *ns, const struct ldlm_res_id *res_id, enum ldlm_cancel_flags flags, void *opaque) @@ -1811,13 +1811,10 @@ int ldlm_resource_iterate(struct ldlm_namespace *ns, struct ldlm_resource *res; int rc; - if (!ns) { - CERROR("must pass in namespace\n"); - LBUG(); - } + LASSERTF(ns, "must pass in namespace\n"); res = ldlm_resource_get(ns, NULL, res_id, 0, 0); - if (!res) + if (IS_ERR(res)) return 0; LDLM_RESOURCE_ADDREF(res); @@ -1843,7 +1840,7 @@ static int ldlm_chain_lock_for_replay(struct ldlm_lock *lock, void *closure) * bug 17614: locks being actively cancelled. Get a reference * on a lock so that it does not disappear under us (e.g. due to cancel) */ - if (!(lock->l_flags & (LDLM_FL_FAILED|LDLM_FL_CANCELING))) { + if (!(lock->l_flags & (LDLM_FL_FAILED | LDLM_FL_CANCELING))) { list_add(&lock->l_pending_chain, list); LDLM_LOCK_GET(lock); } @@ -2013,7 +2010,7 @@ static void ldlm_cancel_unused_locks_for_replay(struct ldlm_namespace *ns) LCF_LOCAL, LDLM_CANCEL_NO_WAIT); CDEBUG(D_DLMTRACE, "Canceled %d unused locks from namespace %s\n", - canceled, ldlm_ns_name(ns)); + canceled, ldlm_ns_name(ns)); } int ldlm_replay_locks(struct obd_import *imp) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 51a28d96af39..a09c25aea698 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -449,8 +449,8 @@ static unsigned ldlm_res_hop_hash(struct cfs_hash *hs, const void *key, unsigned mask) { const struct ldlm_res_id *id = key; - unsigned val = 0; - unsigned i; + unsigned int val = 0; + unsigned int i; for (i = 0; i < RES_NAME_SIZE; i++) val += id->name[i]; @@ -561,9 +561,9 @@ static struct cfs_hash_ops ldlm_ns_fid_hash_ops = { struct ldlm_ns_hash_def { enum ldlm_ns_type nsd_type; /** hash bucket bits */ - unsigned nsd_bkt_bits; + unsigned int nsd_bkt_bits; /** hash bits */ - unsigned nsd_all_bits; + unsigned int nsd_all_bits; /** hash operations */ struct cfs_hash_ops *nsd_hops; }; @@ -758,8 +758,7 @@ static void cleanup_resource(struct ldlm_resource *res, struct list_head *q, */ lock_res(res); list_for_each(tmp, q) { - lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + lock = list_entry(tmp, struct ldlm_lock, l_res_link); if (ldlm_is_cleaned(lock)) { lock = NULL; continue; @@ -793,8 +792,14 @@ static void cleanup_resource(struct ldlm_resource *res, struct list_head *q, */ unlock_res(res); LDLM_DEBUG(lock, "setting FL_LOCAL_ONLY"); + if (lock->l_flags & LDLM_FL_FAIL_LOC) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cfs_time_seconds(4)); + set_current_state(TASK_RUNNING); + } if (lock->l_completion_ast) - lock->l_completion_ast(lock, 0, NULL); + lock->l_completion_ast(lock, LDLM_FL_FAILED, + NULL); LDLM_LOCK_RELEASE(lock); continue; } @@ -875,7 +880,8 @@ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force) ldlm_ns_name(ns), atomic_read(&ns->ns_bref)); force_wait: if (force) - lwi = LWI_TIMEOUT(obd_timeout * HZ / 4, NULL, NULL); + lwi = LWI_TIMEOUT(msecs_to_jiffies(obd_timeout * + MSEC_PER_SEC) / 4, NULL, NULL); rc = l_wait_event(ns->ns_waitq, atomic_read(&ns->ns_bref) == 0, &lwi); @@ -1082,10 +1088,11 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, int create) { struct hlist_node *hnode; - struct ldlm_resource *res; + struct ldlm_resource *res = NULL; struct cfs_hash_bd bd; __u64 version; int ns_refcount = 0; + int rc; LASSERT(!parent); LASSERT(ns->ns_rs_hash); @@ -1095,31 +1102,20 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, hnode = cfs_hash_bd_lookup_locked(ns->ns_rs_hash, &bd, (void *)name); if (hnode) { cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 0); - res = hlist_entry(hnode, struct ldlm_resource, lr_hash); - /* Synchronize with regard to resource creation. */ - if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) { - mutex_lock(&res->lr_lvb_mutex); - mutex_unlock(&res->lr_lvb_mutex); - } - - if (unlikely(res->lr_lvb_len < 0)) { - ldlm_resource_putref(res); - res = NULL; - } - return res; + goto lvbo_init; } version = cfs_hash_bd_version_get(&bd); cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 0); if (create == 0) - return NULL; + return ERR_PTR(-ENOENT); LASSERTF(type >= LDLM_MIN_TYPE && type < LDLM_MAX_TYPE, "type: %d\n", type); res = ldlm_resource_new(); if (!res) - return NULL; + return ERR_PTR(-ENOMEM); res->lr_ns_bucket = cfs_hash_bd_extra_get(ns->ns_rs_hash, &bd); res->lr_name = *name; @@ -1137,7 +1133,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, /* We have taken lr_lvb_mutex. Drop it. */ mutex_unlock(&res->lr_lvb_mutex); kmem_cache_free(ldlm_resource_slab, res); - +lvbo_init: res = hlist_entry(hnode, struct ldlm_resource, lr_hash); /* Synchronize with regard to resource creation. */ if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) { @@ -1146,8 +1142,9 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, } if (unlikely(res->lr_lvb_len < 0)) { + rc = res->lr_lvb_len; ldlm_resource_putref(res); - res = NULL; + res = ERR_PTR(rc); } return res; } @@ -1158,8 +1155,6 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1); if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) { - int rc; - OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2); rc = ns->ns_lvbo->lvbo_init(res); if (rc < 0) { @@ -1169,7 +1164,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, res->lr_lvb_len = rc; mutex_unlock(&res->lr_lvb_mutex); ldlm_resource_putref(res); - return NULL; + return ERR_PTR(rc); } } @@ -1386,7 +1381,7 @@ void ldlm_resource_dump(int level, struct ldlm_resource *res) if (!list_empty(&res->lr_granted)) { CDEBUG(level, "Granted locks (in reverse order):\n"); list_for_each_entry_reverse(lock, &res->lr_granted, - l_res_link) { + l_res_link) { LDLM_DEBUG_LIMIT(level, lock, "###"); if (!(level & D_CANTMASK) && ++granted > ldlm_dump_granted_max) { diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index 2cbb1b80bd41..1ac0940bd8df 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_LUSTRE_FS) += lustre.o lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \ - rw.o namei.o symlink.o llite_mmap.o \ + rw.o namei.o symlink.o llite_mmap.o range_lock.o \ xattr.o xattr_cache.o rw26.o super25.o statahead.o \ glimpse.o lcommon_cl.o lcommon_misc.o \ vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o vvp_req.o \ diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 463b1a360733..0e45d8fc4d7c 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -37,7 +37,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "../include/lustre/lustre_idl.h" #include "../include/lustre_dlm.h" @@ -102,39 +101,6 @@ static int ll_dcompare(const struct dentry *dentry, return 0; } -static inline int return_if_equal(struct ldlm_lock *lock, void *data) -{ - return (ldlm_is_canceling(lock) && ldlm_is_discard_data(lock)) ? - LDLM_ITER_CONTINUE : LDLM_ITER_STOP; -} - -/* find any ldlm lock of the inode in mdc and lov - * return 0 not find - * 1 find one - * < 0 error - */ -static int find_cbdata(struct inode *inode) -{ - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct lov_stripe_md *lsm; - int rc = 0; - - LASSERT(inode); - rc = md_find_cbdata(sbi->ll_md_exp, ll_inode2fid(inode), - return_if_equal, NULL); - if (rc != 0) - return rc; - - lsm = ccc_inode_lsm_get(inode); - if (!lsm) - return rc; - - rc = obd_find_cbdata(sbi->ll_dt_exp, lsm, return_if_equal, NULL); - ccc_inode_lsm_put(inode, lsm); - - return rc; -} - /** * Called when last reference to a dentry is dropped and dcache wants to know * whether or not it should cache it: @@ -155,19 +121,6 @@ static int ll_ddelete(const struct dentry *de) /* kernel >= 2.6.38 last refcount is decreased after this function. */ LASSERT(d_count(de) == 1); - /* Disable this piece of code temporarily because this is called - * inside dcache_lock so it's not appropriate to do lots of work - * here. ATTENTION: Before this piece of code enabling, LU-2487 must be - * resolved. - */ -#if 0 - /* if not ldlm lock for this inode, set i_nlink to 0 so that - * this inode can be recycled later b=20433 - */ - if (d_really_is_positive(de) && !find_cbdata(d_inode(de))) - clear_nlink(d_inode(de)); -#endif - if (d_lustre_invalid((struct dentry *)de)) return 1; return 0; @@ -325,14 +278,13 @@ static int ll_revalidate_dentry(struct dentry *dentry, if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE)) return 1; - if (d_need_statahead(dir, dentry) <= 0) + if (!dentry_may_statahead(dir, dentry)) return 1; if (lookup_flags & LOOKUP_RCU) return -ECHILD; - do_statahead_enter(dir, &dentry, !d_inode(dentry)); - ll_statahead_mark(dir, dentry); + ll_statahead(dir, &dentry, !d_inode(dentry)); return 1; } @@ -347,18 +299,9 @@ static int ll_revalidate_nd(struct dentry *dentry, unsigned int flags) return ll_revalidate_dentry(dentry, flags); } -static void ll_d_iput(struct dentry *de, struct inode *inode) -{ - LASSERT(inode); - if (!find_cbdata(inode)) - clear_nlink(inode); - iput(inode); -} - const struct dentry_operations ll_d_ops = { .d_revalidate = ll_revalidate_nd, .d_release = ll_release, .d_delete = ll_ddelete, - .d_iput = ll_d_iput, .d_compare = ll_dcompare, }; diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 5b381779c827..7f32a539d260 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -46,9 +46,8 @@ #include "../include/obd_support.h" #include "../include/obd_class.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_lib.h" -#include "../include/lustre/lustre_idl.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_fid.h" #include "../include/lustre_kernelcomm.h" @@ -134,111 +133,35 @@ * for this integrated page will be adjusted. See lmv_adjust_dirpages(). * */ - -/* returns the page unlocked, but with a reference */ -static int ll_dir_filler(void *_hash, struct page *page0) +struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, + __u64 offset) { - struct inode *inode = page0->mapping->host; - int hash64 = ll_i2sbi(inode)->ll_flags & LL_SBI_64BIT_HASH; - struct obd_export *exp = ll_i2sbi(inode)->ll_md_exp; - struct ptlrpc_request *request; - struct mdt_body *body; - struct md_op_data *op_data; - __u64 hash = *((__u64 *)_hash); - struct page **page_pool; + struct md_callback cb_op; struct page *page; - struct lu_dirpage *dp; - int max_pages = ll_i2sbi(inode)->ll_md_brw_size >> PAGE_SHIFT; - int nrdpgs = 0; /* number of pages read actually */ - int npages; - int i; int rc; - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) hash %llu\n", - PFID(ll_inode2fid(inode)), inode, hash); + cb_op.md_blocking_ast = ll_md_blocking_ast; + rc = md_read_page(ll_i2mdexp(dir), op_data, &cb_op, offset, &page); + if (rc) + return ERR_PTR(rc); - LASSERT(max_pages > 0 && max_pages <= MD_MAX_BRW_PAGES); - - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - return PTR_ERR(op_data); - - page_pool = kcalloc(max_pages, sizeof(page), GFP_NOFS); - if (page_pool) { - page_pool[0] = page0; - } else { - page_pool = &page0; - max_pages = 1; - } - for (npages = 1; npages < max_pages; npages++) { - page = page_cache_alloc_cold(inode->i_mapping); - if (!page) - break; - page_pool[npages] = page; - } - - op_data->op_npages = npages; - op_data->op_offset = hash; - rc = md_readpage(exp, op_data, page_pool, &request); - ll_finish_md_op_data(op_data); - if (rc < 0) { - /* page0 is special, which was added into page cache early */ - delete_from_page_cache(page0); - } else if (rc == 0) { - body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); - /* Checked by mdc_readpage() */ - if (body->valid & OBD_MD_FLSIZE) - i_size_write(inode, body->size); - - nrdpgs = (request->rq_bulk->bd_nob_transferred+PAGE_SIZE-1) - >> PAGE_SHIFT; - SetPageUptodate(page0); - } - unlock_page(page0); - ptlrpc_req_finished(request); - - CDEBUG(D_VFSTRACE, "read %d/%d pages\n", nrdpgs, npages); - - for (i = 1; i < npages; i++) { - unsigned long offset; - int ret; - - page = page_pool[i]; - - if (rc < 0 || i >= nrdpgs) { - put_page(page); - continue; - } - - SetPageUptodate(page); - - dp = kmap(page); - hash = le64_to_cpu(dp->ldp_hash_start); - kunmap(page); - - offset = hash_x_index(hash, hash64); - - prefetchw(&page->flags); - ret = add_to_page_cache_lru(page, inode->i_mapping, offset, - GFP_NOFS); - if (ret == 0) { - unlock_page(page); - } else { - CDEBUG(D_VFSTRACE, "page %lu add to page cache failed: %d\n", - offset, ret); - } - put_page(page); - } - - if (page_pool != &page0) - kfree(page_pool); - return rc; + return page; } -void ll_release_page(struct page *page, int remove) +void ll_release_page(struct inode *inode, struct page *page, bool remove) { kunmap(page); + + /* + * Always remove the page for striped dir, because the page is + * built from temporarily in LMV layer + */ + if (inode && S_ISDIR(inode->i_mode) && + ll_i2info(inode)->lli_lsm_md) { + __free_page(page); + return; + } + if (remove) { lock_page(page); if (likely(page->mapping)) @@ -248,225 +171,6 @@ void ll_release_page(struct page *page, int remove) put_page(page); } -/* - * Find, kmap and return page that contains given hash. - */ -static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, - __u64 *start, __u64 *end) -{ - int hash64 = ll_i2sbi(dir)->ll_flags & LL_SBI_64BIT_HASH; - struct address_space *mapping = dir->i_mapping; - /* - * Complement of hash is used as an index so that - * radix_tree_gang_lookup() can be used to find a page with starting - * hash _smaller_ than one we are looking for. - */ - unsigned long offset = hash_x_index(*hash, hash64); - struct page *page; - int found; - - spin_lock_irq(&mapping->tree_lock); - found = radix_tree_gang_lookup(&mapping->page_tree, - (void **)&page, offset, 1); - if (found > 0 && !radix_tree_exceptional_entry(page)) { - struct lu_dirpage *dp; - - get_page(page); - spin_unlock_irq(&mapping->tree_lock); - /* - * In contrast to find_lock_page() we are sure that directory - * page cannot be truncated (while DLM lock is held) and, - * hence, can avoid restart. - * - * In fact, page cannot be locked here at all, because - * ll_dir_filler() does synchronous io. - */ - wait_on_page_locked(page); - if (PageUptodate(page)) { - dp = kmap(page); - if (BITS_PER_LONG == 32 && hash64) { - *start = le64_to_cpu(dp->ldp_hash_start) >> 32; - *end = le64_to_cpu(dp->ldp_hash_end) >> 32; - *hash = *hash >> 32; - } else { - *start = le64_to_cpu(dp->ldp_hash_start); - *end = le64_to_cpu(dp->ldp_hash_end); - } - LASSERTF(*start <= *hash, "start = %#llx,end = %#llx,hash = %#llx\n", - *start, *end, *hash); - CDEBUG(D_VFSTRACE, "page %lu [%llu %llu], hash %llu\n", - offset, *start, *end, *hash); - if (*hash > *end) { - ll_release_page(page, 0); - page = NULL; - } else if (*end != *start && *hash == *end) { - /* - * upon hash collision, remove this page, - * otherwise put page reference, and - * ll_get_dir_page() will issue RPC to fetch - * the page we want. - */ - ll_release_page(page, - le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - page = NULL; - } - } else { - put_page(page); - page = ERR_PTR(-EIO); - } - - } else { - spin_unlock_irq(&mapping->tree_lock); - page = NULL; - } - return page; -} - -struct page *ll_get_dir_page(struct inode *dir, __u64 hash, - struct ll_dir_chain *chain) -{ - ldlm_policy_data_t policy = {.l_inodebits = {MDS_INODELOCK_UPDATE} }; - struct address_space *mapping = dir->i_mapping; - struct lustre_handle lockh; - struct lu_dirpage *dp; - struct page *page; - enum ldlm_mode mode; - int rc; - __u64 start = 0; - __u64 end = 0; - __u64 lhash = hash; - struct ll_inode_info *lli = ll_i2info(dir); - int hash64 = ll_i2sbi(dir)->ll_flags & LL_SBI_64BIT_HASH; - - mode = LCK_PR; - rc = md_lock_match(ll_i2sbi(dir)->ll_md_exp, LDLM_FL_BLOCK_GRANTED, - ll_inode2fid(dir), LDLM_IBITS, &policy, mode, &lockh); - if (!rc) { - struct ldlm_enqueue_info einfo = { - .ei_type = LDLM_IBITS, - .ei_mode = mode, - .ei_cb_bl = ll_md_blocking_ast, - .ei_cb_cp = ldlm_completion_ast, - }; - struct lookup_intent it = { .it_op = IT_READDIR }; - struct ptlrpc_request *request; - struct md_op_data *op_data; - - op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - return (void *)op_data; - - rc = md_enqueue(ll_i2sbi(dir)->ll_md_exp, &einfo, &it, - op_data, &lockh, NULL, 0, NULL, 0); - - ll_finish_md_op_data(op_data); - - request = (struct ptlrpc_request *)it.it_request; - if (request) - ptlrpc_req_finished(request); - if (rc < 0) { - CERROR("lock enqueue: " DFID " at %llu: rc %d\n", - PFID(ll_inode2fid(dir)), hash, rc); - return ERR_PTR(rc); - } - - CDEBUG(D_INODE, "setting lr_lvb_inode to inode "DFID"(%p)\n", - PFID(ll_inode2fid(dir)), dir); - md_set_lock_data(ll_i2sbi(dir)->ll_md_exp, - &it.it_lock_handle, dir, NULL); - } else { - /* for cross-ref object, l_ast_data of the lock may not be set, - * we reset it here - */ - md_set_lock_data(ll_i2sbi(dir)->ll_md_exp, &lockh.cookie, - dir, NULL); - } - ldlm_lock_dump_handle(D_OTHER, &lockh); - - mutex_lock(&lli->lli_readdir_mutex); - page = ll_dir_page_locate(dir, &lhash, &start, &end); - if (IS_ERR(page)) { - CERROR("dir page locate: "DFID" at %llu: rc %ld\n", - PFID(ll_inode2fid(dir)), lhash, PTR_ERR(page)); - goto out_unlock; - } else if (page) { - /* - * XXX nikita: not entirely correct handling of a corner case: - * suppose hash chain of entries with hash value HASH crosses - * border between pages P0 and P1. First both P0 and P1 are - * cached, seekdir() is called for some entry from the P0 part - * of the chain. Later P0 goes out of cache. telldir(HASH) - * happens and finds P1, as it starts with matching hash - * value. Remaining entries from P0 part of the chain are - * skipped. (Is that really a bug?) - * - * Possible solutions: 0. don't cache P1 is such case, handle - * it as an "overflow" page. 1. invalidate all pages at - * once. 2. use HASH|1 as an index for P1. - */ - goto hash_collision; - } - - page = read_cache_page(mapping, hash_x_index(hash, hash64), - ll_dir_filler, &lhash); - if (IS_ERR(page)) { - CERROR("read cache page: "DFID" at %llu: rc %ld\n", - PFID(ll_inode2fid(dir)), hash, PTR_ERR(page)); - goto out_unlock; - } - - wait_on_page_locked(page); - (void)kmap(page); - if (!PageUptodate(page)) { - CERROR("page not updated: "DFID" at %llu: rc %d\n", - PFID(ll_inode2fid(dir)), hash, -5); - goto fail; - } - if (!PageChecked(page)) - /* XXX: check page format later */ - SetPageChecked(page); - if (PageError(page)) { - CERROR("page error: "DFID" at %llu: rc %d\n", - PFID(ll_inode2fid(dir)), hash, -5); - goto fail; - } -hash_collision: - dp = page_address(page); - if (BITS_PER_LONG == 32 && hash64) { - start = le64_to_cpu(dp->ldp_hash_start) >> 32; - end = le64_to_cpu(dp->ldp_hash_end) >> 32; - lhash = hash >> 32; - } else { - start = le64_to_cpu(dp->ldp_hash_start); - end = le64_to_cpu(dp->ldp_hash_end); - lhash = hash; - } - if (end == start) { - LASSERT(start == lhash); - CWARN("Page-wide hash collision: %llu\n", end); - if (BITS_PER_LONG == 32 && hash64) - CWARN("Real page-wide hash collision at [%llu %llu] with hash %llu\n", - le64_to_cpu(dp->ldp_hash_start), - le64_to_cpu(dp->ldp_hash_end), hash); - /* - * Fetch whole overflow chain... - * - * XXX not yet. - */ - goto fail; - } -out_unlock: - mutex_unlock(&lli->lli_readdir_mutex); - ldlm_lock_decref(&lockh, mode); - return page; - -fail: - ll_release_page(page, 1); - page = ERR_PTR(-EIO); - goto out_unlock; -} - /** * return IF_* type for given lu_dirent entry. * IF_* flag shld be converted to particular OS file type in @@ -489,119 +193,100 @@ static __u16 ll_dirent_type_get(struct lu_dirent *ent) return type; } -int ll_dir_read(struct inode *inode, struct dir_context *ctx) +int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, + struct dir_context *ctx) { - struct ll_inode_info *info = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); - __u64 pos = ctx->pos; - int api32 = ll_need_32bit_api(sbi); - int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; + __u64 pos = *ppos; + int is_api32 = ll_need_32bit_api(sbi); + int is_hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; struct page *page; - struct ll_dir_chain chain; - int done = 0; + bool done = false; int rc = 0; - ll_dir_chain_init(&chain); - - page = ll_get_dir_page(inode, pos, &chain); + page = ll_get_dir_page(inode, op_data, pos); while (rc == 0 && !done) { struct lu_dirpage *dp; struct lu_dirent *ent; + __u64 hash; + __u64 next; - if (!IS_ERR(page)) { - /* - * If page is empty (end of directory is reached), - * use this value. - */ - __u64 hash = MDS_DIR_END_OFF; - __u64 next; - - dp = page_address(page); - for (ent = lu_dirent_start(dp); ent && !done; - ent = lu_dirent_next(ent)) { - __u16 type; - int namelen; - struct lu_fid fid; - __u64 lhash; - __u64 ino; - - /* - * XXX: implement correct swabbing here. - */ - - hash = le64_to_cpu(ent->lde_hash); - if (hash < pos) - /* - * Skip until we find target hash - * value. - */ - continue; - - namelen = le16_to_cpu(ent->lde_namelen); - if (namelen == 0) - /* - * Skip dummy record. - */ - continue; - - if (api32 && hash64) - lhash = hash >> 32; - else - lhash = hash; - fid_le_to_cpu(&fid, &ent->lde_fid); - ino = cl_fid_build_ino(&fid, api32); - type = ll_dirent_type_get(ent); - ctx->pos = lhash; - /* For 'll_nfs_get_name_filldir()', it will try - * to access the 'ent' through its 'lde_name', - * so the parameter 'name' for 'ctx->actor()' - * must be part of the 'ent'. - */ - done = !dir_emit(ctx, ent->lde_name, - namelen, ino, type); - } - next = le64_to_cpu(dp->ldp_hash_end); - if (!done) { - pos = next; - if (pos == MDS_DIR_END_OFF) { - /* - * End of directory reached. - */ - done = 1; - ll_release_page(page, 0); - } else if (1 /* chain is exhausted*/) { - /* - * Normal case: continue to the next - * page. - */ - ll_release_page(page, - le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - next = pos; - page = ll_get_dir_page(inode, pos, - &chain); - } else { - /* - * go into overflow page. - */ - LASSERT(le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - ll_release_page(page, 1); - } - } else { - pos = hash; - ll_release_page(page, 0); - } - } else { + if (IS_ERR(page)) { rc = PTR_ERR(page); - CERROR("error reading dir "DFID" at %lu: rc %d\n", - PFID(&info->lli_fid), (unsigned long)pos, rc); + break; + } + + hash = MDS_DIR_END_OFF; + dp = page_address(page); + for (ent = lu_dirent_start(dp); ent && !done; + ent = lu_dirent_next(ent)) { + __u16 type; + int namelen; + struct lu_fid fid; + __u64 lhash; + __u64 ino; + + hash = le64_to_cpu(ent->lde_hash); + if (hash < pos) + /* + * Skip until we find target hash + * value. + */ + continue; + + namelen = le16_to_cpu(ent->lde_namelen); + if (namelen == 0) + /* + * Skip dummy record. + */ + continue; + + if (is_api32 && is_hash64) + lhash = hash >> 32; + else + lhash = hash; + fid_le_to_cpu(&fid, &ent->lde_fid); + ino = cl_fid_build_ino(&fid, is_api32); + type = ll_dirent_type_get(ent); + ctx->pos = lhash; + /* For 'll_nfs_get_name_filldir()', it will try + * to access the 'ent' through its 'lde_name', + * so the parameter 'name' for 'ctx->actor()' + * must be part of the 'ent'. + */ + done = !dir_emit(ctx, ent->lde_name, + namelen, ino, type); + } + + if (done) { + pos = hash; + ll_release_page(inode, page, false); + break; + } + + next = le64_to_cpu(dp->ldp_hash_end); + pos = next; + if (pos == MDS_DIR_END_OFF) { + /* + * End of directory reached. + */ + done = 1; + ll_release_page(inode, page, false); + } else { + /* + * Normal case: continue to the next + * page. + */ + ll_release_page(inode, page, + le32_to_cpu(dp->ldp_flags) & + LDF_COLLIDE); + next = pos; + page = ll_get_dir_page(inode, op_data, pos); } } ctx->pos = pos; - ll_dir_chain_fini(&chain); return rc; } @@ -613,9 +298,10 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) __u64 pos = lfd ? lfd->lfd_pos : 0; int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; int api32 = ll_need_32bit_api(sbi); + struct md_op_data *op_data; int rc; - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) pos %lu/%llu 32bit_api %d\n", + CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) pos/size %lu/%llu 32bit_api %d\n", PFID(ll_inode2fid(inode)), inode, (unsigned long)pos, i_size_read(inode), api32); @@ -627,19 +313,58 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) goto out; } + op_data = ll_prep_md_op_data(NULL, inode, inode, NULL, 0, 0, + LUSTRE_OPC_ANY, inode); + if (IS_ERR(op_data)) { + rc = PTR_ERR(op_data); + goto out; + } + + if (unlikely(op_data->op_mea1)) { + /* + * This is only needed for striped dir to fill .., + * see lmv_read_page + */ + if (file_dentry(filp)->d_parent && + file_dentry(filp)->d_parent->d_inode) { + __u64 ibits = MDS_INODELOCK_UPDATE; + struct inode *parent; + + parent = file_dentry(filp)->d_parent->d_inode; + if (ll_have_md_lock(parent, &ibits, LCK_MINMODE)) + op_data->op_fid3 = *ll_inode2fid(parent); + } + + /* + * If it can not find in cache, do lookup .. on the master + * object + */ + if (fid_is_zero(&op_data->op_fid3)) { + rc = ll_dir_get_parent_fid(inode, &op_data->op_fid3); + if (rc) { + ll_finish_md_op_data(op_data); + return rc; + } + } + } + op_data->op_max_pages = sbi->ll_md_brw_pages; ctx->pos = pos; - rc = ll_dir_read(inode, ctx); + rc = ll_dir_read(inode, &pos, op_data, ctx); + pos = ctx->pos; if (lfd) - lfd->lfd_pos = ctx->pos; - if (ctx->pos == MDS_DIR_END_OFF) { + lfd->lfd_pos = pos; + + if (pos == MDS_DIR_END_OFF) { if (api32) - ctx->pos = LL_DIR_END_OFF_32BIT; + pos = LL_DIR_END_OFF_32BIT; else - ctx->pos = LL_DIR_END_OFF; + pos = LL_DIR_END_OFF; } else { if (api32 && hash64) - ctx->pos >>= 32; + pos >>= 32; } + ctx->pos = pos; + ll_finish_md_op_data(op_data); filp->f_version = inode->i_version; out: @@ -668,18 +393,40 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) return rc; } -static int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, - char *filename) +/** + * Create striped directory with specified stripe(@lump) + * + * param[in] parent the parent of the directory. + * param[in] lump the specified stripes. + * param[in] dirname the name of the directory. + * param[in] mode the specified mode of the directory. + * + * retval =0 if striped directory is being created successfully. + * <0 if the creation is failed. + */ +static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, + const char *dirname, umode_t mode) { struct ptlrpc_request *request = NULL; struct md_op_data *op_data; - struct ll_sb_info *sbi = ll_i2sbi(dir); - int mode; + struct ll_sb_info *sbi = ll_i2sbi(parent); int err; - mode = (~current_umask() & 0755) | S_IFDIR; - op_data = ll_prep_md_op_data(NULL, dir, NULL, filename, - strlen(filename), mode, LUSTRE_OPC_MKDIR, + if (unlikely(lump->lum_magic != LMV_USER_MAGIC)) + return -EINVAL; + + CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) name %s stripe_offset %d, stripe_count: %u\n", + PFID(ll_inode2fid(parent)), parent, dirname, + (int)lump->lum_stripe_offset, lump->lum_stripe_count); + + if (lump->lum_magic != cpu_to_le32(LMV_USER_MAGIC)) + lustre_swab_lmv_user_md(lump); + + if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent))) + mode &= ~current_umask(); + mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; + op_data = ll_prep_md_op_data(NULL, parent, NULL, dirname, + strlen(dirname), mode, LUSTRE_OPC_MKDIR, lump); if (IS_ERR(op_data)) { err = PTR_ERR(op_data); @@ -730,6 +477,13 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, lum_size = sizeof(struct lov_user_md_v3); break; } + case LMV_USER_MAGIC: { + if (lump->lmm_magic != cpu_to_le32(LMV_USER_MAGIC)) + lustre_swab_lmv_user_md( + (struct lmv_user_md *)lump); + lum_size = sizeof(struct lmv_user_md); + break; + } default: { CDEBUG(D_IOCTL, "bad userland LOV MAGIC: %#08x != %#08x nor %#08x\n", lump->lmm_magic, LOV_USER_MAGIC_V1, @@ -746,9 +500,6 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, if (IS_ERR(op_data)) return PTR_ERR(op_data); - if (lump && lump->lmm_magic == cpu_to_le32(LMV_USER_MAGIC)) - op_data->op_cli_flags |= CLI_SET_MEA; - /* swabbing is done in lov_setstripe() on server side */ rc = md_setattr(sbi->ll_md_exp, op_data, lump, lum_size, NULL, 0, &req, NULL); @@ -803,8 +554,16 @@ end: return rc; } -int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, - int *lmm_size, struct ptlrpc_request **request) +/** + * This function will be used to get default LOV/LMV/Default LMV + * @valid will be used to indicate which stripe it will retrieve + * OBD_MD_MEA LMV stripe EA + * OBD_MD_DEFAULT_MEA Default LMV stripe EA + * otherwise Default LOV EA. + * Each time, it can only retrieve 1 stripe EA + **/ +int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, + struct ptlrpc_request **request, u64 valid) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct mdt_body *body; @@ -813,7 +572,7 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, int rc, lmmsize; struct md_op_data *op_data; - rc = ll_get_default_mdsize(sbi, &lmmsize); + rc = ll_get_max_mdsize(sbi, &lmmsize); if (rc) return rc; @@ -834,9 +593,9 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - lmmsize = body->eadatasize; + lmmsize = body->mbo_eadatasize; - if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || + if (!(body->mbo_valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || lmmsize == 0) { rc = -ENODATA; goto out; @@ -844,6 +603,7 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, lmm = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD, lmmsize); + LASSERT(lmm); /* * This is coming from the MDS, so is probably in @@ -860,40 +620,51 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); break; + case LMV_MAGIC_V1: + if (cpu_to_le32(LMV_MAGIC) != LMV_MAGIC) + lustre_swab_lmv_mds_md((union lmv_mds_md *)lmm); + break; + case LMV_USER_MAGIC: + if (cpu_to_le32(LMV_USER_MAGIC) != LMV_USER_MAGIC) + lustre_swab_lmv_user_md((struct lmv_user_md *)lmm); + break; default: CERROR("unknown magic: %lX\n", (unsigned long)lmm->lmm_magic); rc = -EPROTO; } out: - *lmmp = lmm; - *lmm_size = lmmsize; + *plmm = lmm; + *plmm_size = lmmsize; *request = req; return rc; } +int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, const struct lu_fid *fid) +{ + struct md_op_data *op_data; + int mdt_index, rc; + + op_data = kzalloc(sizeof(*op_data), GFP_NOFS); + if (!op_data) + return -ENOMEM; + + op_data->op_flags |= MF_GET_MDT_IDX; + op_data->op_fid1 = *fid; + rc = md_getattr(sbi->ll_md_exp, op_data, NULL); + mdt_index = op_data->op_mds; + kvfree(op_data); + if (rc < 0) + return rc; + + return mdt_index; +} + /* * Get MDT index for the inode. */ int ll_get_mdt_idx(struct inode *inode) { - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct md_op_data *op_data; - int rc, mdtidx; - - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, - 0, LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - return PTR_ERR(op_data); - - op_data->op_flags |= MF_GET_MDT_IDX; - rc = md_getattr(sbi->ll_md_exp, op_data, NULL); - mdtidx = op_data->op_mds; - ll_finish_md_op_data(op_data); - if (rc < 0) { - CDEBUG(D_INFO, "md_getattr_name: %d\n", rc); - return rc; - } - return mdtidx; + return ll_get_mdt_idx_by_fid(ll_i2sbi(inode), ll_inode2fid(inode)); } /** @@ -1288,11 +1059,9 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } case IOC_MDC_LOOKUP: { - struct ptlrpc_request *request = NULL; int namelen, len = 0; char *buf = NULL; char *filename; - struct md_op_data *op_data; rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); if (rc) @@ -1308,21 +1077,13 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto out_free; } - op_data = ll_prep_md_op_data(NULL, inode, NULL, filename, namelen, - 0, LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) { - rc = PTR_ERR(op_data); - goto out_free; - } - - op_data->op_valid = OBD_MD_FLID; - rc = md_getattr_name(sbi->ll_md_exp, op_data, &request); - ll_finish_md_op_data(op_data); + rc = ll_get_fid_by_name(inode, filename, namelen, NULL); if (rc < 0) { - CDEBUG(D_INFO, "md_getattr_name: %d\n", rc); + CERROR("%s: lookup %.*s failed: rc = %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), namelen, + filename, rc); goto out_free; } - ptlrpc_req_finished(request); out_free: obd_ioctl_freedata(buf, len); return rc; @@ -1333,6 +1094,7 @@ out_free: char *filename; int namelen = 0; int lumlen = 0; + umode_t mode; int len; int rc; @@ -1366,15 +1128,32 @@ out_free: goto lmv_out_free; } - /** - * ll_dir_setdirstripe will be used to set dir stripe - * mdc_create--->mdt_reint_create (with dirstripe) - */ - rc = ll_dir_setdirstripe(inode, lum, filename); +#if OBD_OCD_VERSION(2, 9, 50, 0) > LUSTRE_VERSION_CODE + mode = data->ioc_type != 0 ? data->ioc_type : S_IRWXUGO; +#else + mode = data->ioc_type; +#endif + rc = ll_dir_setdirstripe(inode, lum, filename, mode); lmv_out_free: obd_ioctl_freedata(buf, len); return rc; } + case LL_IOC_LMV_SET_DEFAULT_STRIPE: { + struct lmv_user_md __user *ulump; + struct lmv_user_md lum; + int rc; + + ulump = (struct lmv_user_md __user *)arg; + if (copy_from_user(&lum, ulump, sizeof(lum))) + return -EFAULT; + + if (lum.lum_magic != LMV_USER_MAGIC) + return -EINVAL; + + rc = ll_dir_setstripe(inode, (struct lov_user_md *)&lum, 0); + + return rc; + } case LL_IOC_LOV_SETSTRIPE: { struct lov_user_md_v3 lumv3; struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; @@ -1404,50 +1183,100 @@ lmv_out_free: return rc; } case LL_IOC_LMV_GETSTRIPE: { - struct lmv_user_md __user *lump = (void __user *)arg; + struct lmv_user_md __user *ulmv; struct lmv_user_md lum; - struct lmv_user_md *tmp; + struct ptlrpc_request *request = NULL; + struct lmv_user_md *tmp = NULL; + union lmv_mds_md *lmm = NULL; + u64 valid = 0; + int stripe_count; + int mdt_index; int lum_size; - int rc = 0; - int mdtindex; + int lmmsize; + int rc; + int i; - if (copy_from_user(&lum, lump, sizeof(struct lmv_user_md))) + ulmv = (struct lmv_user_md __user *)arg; + if (copy_from_user(&lum, ulmv, sizeof(*ulmv))) return -EFAULT; - if (lum.lum_magic != LMV_MAGIC_V1) + /* + * lum_magic will indicate which stripe the ioctl will like + * to get, LMV_MAGIC_V1 is for normal LMV stripe, LMV_USER_MAGIC + * is for default LMV stripe + */ + if (lum.lum_magic == LMV_MAGIC_V1) + valid |= OBD_MD_MEA; + else if (lum.lum_magic == LMV_USER_MAGIC) + valid |= OBD_MD_DEFAULT_MEA; + else return -EINVAL; - lum_size = lmv_user_md_size(1, LMV_MAGIC_V1); + rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, &request, + valid); + if (rc) + goto finish_req; + + /* Get default LMV EA */ + if (lum.lum_magic == LMV_USER_MAGIC) { + if (rc) + goto finish_req; + + if (lmmsize > sizeof(*ulmv)) { + rc = -EINVAL; + goto finish_req; + } + + if (copy_to_user(ulmv, lmm, lmmsize)) + rc = -EFAULT; + + goto finish_req; + } + + stripe_count = lmv_mds_md_stripe_count_get(lmm); + lum_size = lmv_user_md_size(stripe_count, LMV_MAGIC_V1); tmp = kzalloc(lum_size, GFP_NOFS); if (!tmp) { rc = -ENOMEM; - goto free_lmv; + goto finish_req; } - *tmp = lum; - tmp->lum_type = LMV_STRIPE_TYPE; - tmp->lum_stripe_count = 1; - mdtindex = ll_get_mdt_idx(inode); - if (mdtindex < 0) { + mdt_index = ll_get_mdt_idx(inode); + if (mdt_index < 0) { rc = -ENOMEM; - goto free_lmv; + goto out_tmp; + } + tmp->lum_magic = LMV_MAGIC_V1; + tmp->lum_stripe_count = 0; + tmp->lum_stripe_offset = mdt_index; + for (i = 0; i < stripe_count; i++) { + struct lu_fid fid; + + fid_le_to_cpu(&fid, &lmm->lmv_md_v1.lmv_stripe_fids[i]); + mdt_index = ll_get_mdt_idx_by_fid(sbi, &fid); + if (mdt_index < 0) { + rc = mdt_index; + goto out_tmp; + } + tmp->lum_objects[i].lum_mds = mdt_index; + tmp->lum_objects[i].lum_fid = fid; + tmp->lum_stripe_count++; } - tmp->lum_stripe_offset = mdtindex; - tmp->lum_objects[0].lum_mds = mdtindex; - memcpy(&tmp->lum_objects[0].lum_fid, ll_inode2fid(inode), - sizeof(struct lu_fid)); - if (copy_to_user((void __user *)arg, tmp, lum_size)) { + if (copy_to_user(ulmv, tmp, lum_size)) { rc = -EFAULT; - goto free_lmv; + goto out_tmp; } -free_lmv: +out_tmp: kfree(tmp); +finish_req: + ptlrpc_req_finished(request); return rc; } + case LL_IOC_LOV_SWAP_LAYOUTS: return -EPERM; - case LL_IOC_OBD_STATFS: + case IOC_OBD_STATFS: return ll_obd_statfs(inode, (void __user *)arg); case LL_IOC_LOV_GETSTRIPE: case LL_IOC_MDC_GETINFO: @@ -1469,7 +1298,8 @@ free_lmv: rc = ll_lov_getstripe_ea_info(inode, filename, &lmm, &lmmsize, &request); } else { - rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request); + rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, + &request, 0); } if (request) { @@ -1512,18 +1342,18 @@ skip_lmm: lstat_t st = { 0 }; st.st_dev = inode->i_sb->s_dev; - st.st_mode = body->mode; - st.st_nlink = body->nlink; - st.st_uid = body->uid; - st.st_gid = body->gid; - st.st_rdev = body->rdev; - st.st_size = body->size; + st.st_mode = body->mbo_mode; + st.st_nlink = body->mbo_nlink; + st.st_uid = body->mbo_uid; + st.st_gid = body->mbo_gid; + st.st_rdev = body->mbo_rdev; + st.st_size = body->mbo_size; st.st_blksize = PAGE_SIZE; - st.st_blocks = body->blocks; - st.st_atime = body->atime; - st.st_mtime = body->mtime; - st.st_ctime = body->ctime; - st.st_ino = cl_fid_build_ino(&body->fid1, + st.st_blocks = body->mbo_blocks; + st.st_atime = body->mbo_atime; + st.st_mtime = body->mbo_mtime; + st.st_ctime = body->mbo_ctime; + st.st_ino = cl_fid_build_ino(&body->mbo_fid1, sbi->ll_flags & LL_SBI_32BIT_API); @@ -1611,9 +1441,6 @@ free_lmm: kvfree(lmm); return rc; } - case OBD_IOC_LLOG_CATINFO: { - return -EOPNOTSUPP; - } case OBD_IOC_QUOTACHECK: { struct obd_quotactl *oqctl; int error = 0; @@ -1671,7 +1498,7 @@ out_poll: kfree(check); return rc; } - case LL_IOC_QUOTACTL: { + case OBD_IOC_QUOTACTL: { struct if_quotactl *qctl; qctl = kzalloc(sizeof(*qctl), GFP_NOFS); @@ -1739,6 +1566,25 @@ out_quotactl: return rc; case OBD_IOC_FID2PATH: return ll_fid2path(inode, (void __user *)arg); + case LL_IOC_GETPARENT: + return ll_getparent(file, (void __user *)arg); + case LL_IOC_FID2MDTIDX: { + struct obd_export *exp = ll_i2mdexp(inode); + struct lu_fid fid; + __u32 index; + + if (copy_from_user(&fid, (const struct lu_fid __user *)arg, + sizeof(fid))) + return -EFAULT; + + /* Call mdc_iocontrol */ + rc = obd_iocontrol(LL_IOC_FID2MDTIDX, exp, sizeof(fid), &fid, + &index); + if (rc) + return rc; + + return index; + } case LL_IOC_HSM_REQUEST: { struct hsm_user_request *hur; ssize_t totalsize; @@ -1853,6 +1699,45 @@ out_quotactl: kfree(copy); return rc; } + case LL_IOC_MIGRATE: { + char *buf = NULL; + const char *filename; + int namelen = 0; + int len; + int rc; + int mdtidx; + + rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); + if (rc < 0) + return rc; + + data = (struct obd_ioctl_data *)buf; + if (!data->ioc_inlbuf1 || !data->ioc_inlbuf2 || + !data->ioc_inllen1 || !data->ioc_inllen2) { + rc = -EINVAL; + goto migrate_free; + } + + filename = data->ioc_inlbuf1; + namelen = data->ioc_inllen1; + if (namelen < 1 || namelen != strlen(filename) + 1) { + rc = -EINVAL; + goto migrate_free; + } + + if (data->ioc_inllen2 != sizeof(mdtidx)) { + rc = -EINVAL; + goto migrate_free; + } + mdtidx = *(int *)data->ioc_inlbuf2; + + rc = ll_migrate(inode, file, mdtidx, filename, namelen - 1); +migrate_free: + obd_ioctl_freedata(buf, len); + + return rc; + } + default: return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, (void __user *)arg); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 57281b9e31ff..6e3a188baaae 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -38,14 +38,15 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/lustre_dlm.h" -#include "../include/lustre_lite.h" #include #include +#include #include -#include "llite_internal.h" #include "../include/lustre/ll_fiemap.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/cl_object.h" +#include "llite_internal.h" static int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg); @@ -188,17 +189,11 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, spin_unlock(&lli->lli_lock); } - if (rc == 0) { - rc = ll_objects_destroy(req, inode); - if (rc) - CERROR("inode %lu ll_objects destroy: rc = %d\n", - inode->i_ino, rc); - } if (rc == 0 && op_data->op_bias & MDS_HSM_RELEASE) { struct mdt_body *body; body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - if (!(body->valid & OBD_MD_FLRELEASED)) + if (!(body->mbo_valid & OBD_MD_FLRELEASED)) rc = -EBUSY; } @@ -349,13 +344,11 @@ int ll_file_release(struct inode *inode, struct file *file) fd = LUSTRE_FPRIVATE(file); LASSERT(fd); - /* The last ref on @file, maybe not be the owner pid of statahead. - * Different processes can open the same dir, "ll_opendir_key" means: - * it is me that should stop the statahead thread. + /* The last ref on @file, maybe not be the owner pid of statahead, + * because parent and child process can share the same file handle. */ - if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd && - lli->lli_opendir_pid != 0) - ll_stop_statahead(inode, lli->lli_opendir_key); + if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd) + ll_deauthorize_statahead(inode, fd); if (is_root_inode(inode)) { LUSTRE_FPRIVATE(file) = NULL; @@ -364,7 +357,8 @@ int ll_file_release(struct inode *inode, struct file *file) } if (!S_ISDIR(inode->i_mode)) { - lov_read_and_clear_async_rc(lli->lli_clob); + if (lli->lli_clob) + lov_read_and_clear_async_rc(lli->lli_clob); lli->lli_async_rc = 0; } @@ -376,55 +370,39 @@ int ll_file_release(struct inode *inode, struct file *file) return rc; } -static int ll_intent_file_open(struct dentry *dentry, void *lmm, - int lmmsize, struct lookup_intent *itp) +static int ll_intent_file_open(struct dentry *de, void *lmm, int lmmsize, + struct lookup_intent *itp) { - struct inode *inode = d_inode(dentry); + struct inode *inode = d_inode(de); struct ll_sb_info *sbi = ll_i2sbi(inode); - struct dentry *parent = dentry->d_parent; - const char *name = dentry->d_name.name; - const int len = dentry->d_name.len; + struct dentry *parent = de->d_parent; + const char *name = NULL; struct md_op_data *op_data; - struct ptlrpc_request *req; - __u32 opc = LUSTRE_OPC_ANY; - int rc; + struct ptlrpc_request *req = NULL; + int len = 0, rc; - /* Usually we come here only for NFSD, and we want open lock. */ - /* We can also get here if there was cached open handle in revalidate_it - * but it disappeared while we were getting from there to ll_file_open. - * But this means this file was closed and immediately opened which - * makes a good candidate for using OPEN lock + LASSERT(parent); + LASSERT(itp->it_flags & MDS_OPEN_BY_FID); + + /* + * if server supports open-by-fid, or file name is invalid, don't pack + * name in open request */ - /* If lmmsize & lmm are not 0, we are just setting stripe info - * parameters. No need for the open lock - */ - if (!lmm && lmmsize == 0) { - struct ll_dentry_data *ldd = ll_d2d(dentry); - /* - * If we came via ll_iget_for_nfs, then we need to request - * struct ll_dentry_data *ldd = ll_d2d(file->f_dentry); - * - * NB: when ldd is NULL, it must have come via normal - * lookup path only, since ll_iget_for_nfs always calls - * ll_d_init(). - */ - if (ldd && ldd->lld_nfs_dentry) { - ldd->lld_nfs_dentry = 0; - itp->it_flags |= MDS_OPEN_LOCK; - } - if (itp->it_flags & FMODE_WRITE) - opc = LUSTRE_OPC_CREATE; + if (!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_OPEN_BY_FID) && + lu_name_is_valid_2(de->d_name.name, de->d_name.len)) { + name = de->d_name.name; + len = de->d_name.len; } - op_data = ll_prep_md_op_data(NULL, d_inode(parent), - inode, name, len, - O_RDWR, opc, NULL); + op_data = ll_prep_md_op_data(NULL, d_inode(parent), inode, name, len, + O_RDWR, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) return PTR_ERR(op_data); + op_data->op_data = lmm; + op_data->op_data_size = lmmsize; - itp->it_flags |= MDS_OPEN_BY_FID; - rc = md_intent_lock(sbi->ll_md_exp, op_data, lmm, lmmsize, itp, - 0 /*unused */, &req, ll_md_blocking_ast, 0); + rc = md_intent_lock(sbi->ll_md_exp, op_data, itp, &req, + &ll_md_blocking_ast, 0); ll_finish_md_op_data(op_data); if (rc == -ESTALE) { /* reason for keep own exit path - don`t flood log @@ -479,8 +457,8 @@ static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it, struct mdt_body *body; body = req_capsule_server_get(&it->it_request->rq_pill, &RMF_MDT_BODY); - och->och_fh = body->handle; - och->och_fid = body->fid1; + och->och_fh = body->mbo_handle; + och->och_fid = body->mbo_fid1; och->och_lease_handle.cookie = it->it_lock_handle; och->och_magic = OBD_CLIENT_HANDLE_MAGIC; och->och_flags = it->it_flags; @@ -508,7 +486,7 @@ static int ll_local_open(struct file *file, struct lookup_intent *it, body = req_capsule_server_get(&it->it_request->rq_pill, &RMF_MDT_BODY); - ll_ioepoch_open(lli, body->ioepoch); + ll_ioepoch_open(lli, body->mbo_ioepoch); } LUSTRE_FPRIVATE(file) = fd; @@ -543,7 +521,7 @@ int ll_file_open(struct inode *inode, struct file *file) struct obd_client_handle **och_p = NULL; __u64 *och_usecount = NULL; struct ll_file_data *fd; - int rc = 0, opendir_set = 0; + int rc = 0; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), flags %o\n", PFID(ll_inode2fid(inode)), inode, file->f_flags); @@ -558,16 +536,8 @@ int ll_file_open(struct inode *inode, struct file *file) } fd->fd_file = file; - if (S_ISDIR(inode->i_mode)) { - spin_lock(&lli->lli_sa_lock); - if (!lli->lli_opendir_key && !lli->lli_sai && - lli->lli_opendir_pid == 0) { - lli->lli_opendir_key = fd; - lli->lli_opendir_pid = current_pid(); - opendir_set = 1; - } - spin_unlock(&lli->lli_sa_lock); - } + if (S_ISDIR(inode->i_mode)) + ll_authorize_statahead(inode, fd); if (is_root_inode(inode)) { LUSTRE_FPRIVATE(file) = fd; @@ -615,7 +585,7 @@ restart: } else if (it->it_flags & FMODE_EXEC) { och_p = &lli->lli_mds_exec_och; och_usecount = &lli->lli_open_fd_exec_count; - } else { + } else { och_p = &lli->lli_mds_read_och; och_usecount = &lli->lli_open_fd_read_count; } @@ -652,9 +622,19 @@ restart: * result in a deadlock */ mutex_unlock(&lli->lli_och_mutex); - it->it_create_mode |= M_CHECK_STALE; + /* + * Normally called under two situations: + * 1. NFS export. + * 2. revalidate with IT_OPEN (revalidate doesn't + * execute this intent any more). + * + * Always fetch MDS_OPEN_LOCK if this is not setstripe. + * + * Always specify MDS_OPEN_BY_FID because we don't want + * to get file with different fid. + */ + it->it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID; rc = ll_intent_file_open(file->f_path.dentry, NULL, 0, it); - it->it_create_mode &= ~M_CHECK_STALE; if (rc) goto out_openerr; @@ -716,9 +696,10 @@ out_och_free: mutex_unlock(&lli->lli_och_mutex); out_openerr: - if (opendir_set != 0) - ll_stop_statahead(inode, lli->lli_opendir_key); - ll_file_data_put(fd); + if (lli->lli_opendir_key == fd) + ll_deauthorize_statahead(inode, fd); + if (fd) + ll_file_data_put(fd); } else { ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1); } @@ -764,7 +745,7 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, struct lookup_intent it = { .it_op = IT_OPEN }; struct ll_sb_info *sbi = ll_i2sbi(inode); struct md_op_data *op_data; - struct ptlrpc_request *req; + struct ptlrpc_request *req = NULL; struct lustre_handle old_handle = { 0 }; struct obd_client_handle *och = NULL; int rc; @@ -831,8 +812,8 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, it.it_flags = fmode | open_flags; it.it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID | MDS_OPEN_LEASE; - rc = md_intent_lock(sbi->ll_md_exp, op_data, NULL, 0, &it, 0, &req, - ll_md_blocking_lease_ast, + rc = md_intent_lock(sbi->ll_md_exp, op_data, &it, &req, + &ll_md_blocking_lease_ast, /* LDLM_FL_NO_LRU: To not put the lease lock into LRU list, otherwise * it can be cancelled which may mislead applications that the lease is * broken; @@ -840,7 +821,7 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, * open in ll_md_blocking_ast(). Otherwise as ll_md_blocking_lease_ast * doesn't deal with openhandle, so normal openhandle will be leaked. */ - LDLM_FL_NO_LRU | LDLM_FL_EXCL); + LDLM_FL_NO_LRU | LDLM_FL_EXCL); ll_finish_md_op_data(op_data); ptlrpc_req_finished(req); if (rc < 0) @@ -908,7 +889,6 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, { struct ldlm_lock *lock; bool cancelled = true; - int rc; lock = ldlm_handle2lock(&och->och_lease_handle); if (lock) { @@ -926,9 +906,8 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, if (lease_broken) *lease_broken = cancelled; - rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och, - NULL); - return rc; + return ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, + inode, och, NULL); } /* Fills the obdo with the attributes for the lsm */ @@ -1138,10 +1117,11 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, { struct ll_inode_info *lli = ll_i2info(file_inode(file)); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + struct range_lock range; struct cl_io *io; ssize_t result; - CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: %llu, count: %zd\n", + CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: %llu, count: %zu\n", file->f_path.dentry->d_name.name, iot, *ppos, count); restart: @@ -1150,7 +1130,12 @@ restart: if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) { struct vvp_io *vio = vvp_env_io(env); - int write_mutex_locked = 0; + bool range_locked = false; + + if (file->f_flags & O_APPEND) + range_lock_init(&range, 0, LUSTRE_EOF); + else + range_lock_init(&range, *ppos, *ppos + count - 1); vio->vui_fd = LUSTRE_FPRIVATE(file); vio->vui_io_subtype = args->via_io_subtype; @@ -1159,14 +1144,23 @@ restart: case IO_NORMAL: vio->vui_iter = args->u.normal.via_iter; vio->vui_iocb = args->u.normal.via_iocb; - if ((iot == CIT_WRITE) && + /* + * Direct IO reads must also take range lock, + * or multiple reads will try to work on the same pages + * See LU-6227 for details. + */ + if (((iot == CIT_WRITE) || + (iot == CIT_READ && (file->f_flags & O_DIRECT))) && !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { - if (mutex_lock_interruptible(&lli-> - lli_write_mutex)) { - result = -ERESTARTSYS; + CDEBUG(D_VFSTRACE, "Range lock [%llu, %llu]\n", + range.rl_node.in_extent.start, + range.rl_node.in_extent.end); + result = range_lock(&lli->lli_write_tree, + &range); + if (result < 0) goto out; - } - write_mutex_locked = 1; + + range_locked = true; } down_read(&lli->lli_trunc_sem); break; @@ -1183,8 +1177,12 @@ restart: ll_cl_remove(file, env); if (args->via_io_subtype == IO_NORMAL) up_read(&lli->lli_trunc_sem); - if (write_mutex_locked) - mutex_unlock(&lli->lli_write_mutex); + if (range_locked) { + CDEBUG(D_VFSTRACE, "Range unlock [%llu, %llu]\n", + range.rl_node.in_extent.start, + range.rl_node.in_extent.end); + range_unlock(&lli->lli_write_tree, &range); + } } else { /* cl_io_rw_init() handled IO */ result = io->ci_result; @@ -1201,7 +1199,7 @@ out: * short read/write instead of restart io. */ if ((result == 0 || result == -ENODATA) && io->ci_need_restart) { - CDEBUG(D_VFSTRACE, "Restart %s on %pD from %lld, count:%zd\n", + CDEBUG(D_VFSTRACE, "Restart %s on %pD from %lld, count:%zu\n", iot == CIT_READ ? "read" : "write", file, *ppos, count); LASSERTF(io->ci_nob == 0, "%zd\n", io->ci_nob); @@ -1296,94 +1294,15 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos, return result; } -static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, u32 ost_idx) -{ - struct obd_export *exp = ll_i2dtexp(inode); - struct obd_trans_info oti = { 0 }; - struct obdo *oa = NULL; - int lsm_size; - int rc = 0; - struct lov_stripe_md *lsm = NULL, *lsm2; - - oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!oa) - return -ENOMEM; - - lsm = ccc_inode_lsm_get(inode); - if (!lsm_has_objects(lsm)) { - rc = -ENOENT; - goto out; - } - - lsm_size = sizeof(*lsm) + (sizeof(struct lov_oinfo) * - (lsm->lsm_stripe_count)); - - lsm2 = libcfs_kvzalloc(lsm_size, GFP_NOFS); - if (!lsm2) { - rc = -ENOMEM; - goto out; - } - - oa->o_oi = *oi; - oa->o_nlink = ost_idx; - oa->o_flags |= OBD_FL_RECREATE_OBJS; - oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS | OBD_MD_FLGROUP; - obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME | - OBD_MD_FLMTIME | OBD_MD_FLCTIME); - obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); - memcpy(lsm2, lsm, lsm_size); - ll_inode_size_lock(inode); - rc = obd_create(NULL, exp, oa, &lsm2, &oti); - ll_inode_size_unlock(inode); - - kvfree(lsm2); - goto out; -out: - ccc_inode_lsm_put(inode, lsm); - kmem_cache_free(obdo_cachep, oa); - return rc; -} - -static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg) -{ - struct ll_recreate_obj ucreat; - struct ost_id oi; - - if (!capable(CFS_CAP_SYS_ADMIN)) - return -EPERM; - - if (copy_from_user(&ucreat, (struct ll_recreate_obj __user *)arg, - sizeof(ucreat))) - return -EFAULT; - - ostid_set_seq_mdt0(&oi); - ostid_set_id(&oi, ucreat.lrc_id); - return ll_lov_recreate(inode, &oi, ucreat.lrc_ost_idx); -} - -static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg) -{ - struct lu_fid fid; - struct ost_id oi; - u32 ost_idx; - - if (!capable(CFS_CAP_SYS_ADMIN)) - return -EPERM; - - if (copy_from_user(&fid, (struct lu_fid __user *)arg, sizeof(fid))) - return -EFAULT; - - fid_to_ostid(&fid, &oi); - ost_idx = (fid_seq(&fid) >> 16) & 0xffff; - return ll_lov_recreate(inode, &oi, ost_idx); -} - int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, __u64 flags, struct lov_user_md *lum, int lum_size) { struct lov_stripe_md *lsm = NULL; - struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags}; + struct lookup_intent oit = { + .it_op = IT_OPEN, + .it_flags = flags | MDS_OPEN_BY_FID, + }; int rc = 0; lsm = ccc_inode_lsm_get(inode); @@ -1397,11 +1316,11 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, ll_inode_size_lock(inode); rc = ll_intent_file_open(dentry, lum, lum_size, &oit); - if (rc) + if (rc < 0) goto out_unlock; rc = oit.it_status; if (rc < 0) - goto out_req_free; + goto out_unlock; ll_release_openhandle(inode, &oit); @@ -1411,9 +1330,6 @@ out_unlock: ccc_inode_lsm_put(inode, lsm); out: return rc; -out_req_free: - ptlrpc_req_finished((struct ptlrpc_request *)oit.it_request); - goto out; } int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, @@ -1448,9 +1364,9 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - lmmsize = body->eadatasize; + lmmsize = body->mbo_eadatasize; - if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || + if (!(body->mbo_valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || lmmsize == 0) { rc = -ENODATA; goto out; @@ -1481,13 +1397,13 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, */ if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) { lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lmm); - if (S_ISREG(body->mode)) + if (S_ISREG(body->mbo_mode)) lustre_swab_lov_user_md_objects( ((struct lov_user_md_v1 *)lmm)->lmm_objects, stripe_count); } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) { lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); - if (S_ISREG(body->mode)) + if (S_ISREG(body->mbo_mode)) lustre_swab_lov_user_md_objects( ((struct lov_user_md_v3 *)lmm)->lmm_objects, stripe_count); @@ -1530,55 +1446,48 @@ static int ll_lov_setea(struct inode *inode, struct file *file, return rc; } -static int ll_lov_setstripe(struct inode *inode, struct file *file, - unsigned long arg) +static int ll_file_getstripe(struct inode *inode, + struct lov_user_md __user *lum) { - struct lov_user_md_v3 lumv3; - struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; - struct lov_user_md_v1 __user *lumv1p = (void __user *)arg; - struct lov_user_md_v3 __user *lumv3p = (void __user *)arg; - int lum_size, rc; - __u64 flags = FMODE_WRITE; + struct lu_env *env; + int refcheck; + int rc; - /* first try with v1 which is smaller than v3 */ - lum_size = sizeof(struct lov_user_md_v1); - if (copy_from_user(lumv1, lumv1p, lum_size)) - return -EFAULT; + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + return PTR_ERR(env); - if (lumv1->lmm_magic == LOV_USER_MAGIC_V3) { - lum_size = sizeof(struct lov_user_md_v3); - if (copy_from_user(&lumv3, lumv3p, lum_size)) - return -EFAULT; - } - - rc = ll_lov_setstripe_ea_info(inode, file->f_path.dentry, flags, lumv1, - lum_size); - cl_lov_delay_create_clear(&file->f_flags); - if (rc == 0) { - struct lov_stripe_md *lsm; - __u32 gen; - - put_user(0, &lumv1p->lmm_stripe_count); - - ll_layout_refresh(inode, &gen); - lsm = ccc_inode_lsm_get(inode); - rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), - 0, lsm, (void __user *)arg); - ccc_inode_lsm_put(inode, lsm); - } + rc = cl_object_getstripe(env, ll_i2info(inode)->lli_clob, lum); + cl_env_put(env, &refcheck); return rc; } -static int ll_lov_getstripe(struct inode *inode, unsigned long arg) +static int ll_lov_setstripe(struct inode *inode, struct file *file, + unsigned long arg) { - struct lov_stripe_md *lsm; - int rc = -ENODATA; + struct lov_user_md __user *lum = (struct lov_user_md __user *)arg; + struct lov_user_md *klum; + int lum_size, rc; + __u64 flags = FMODE_WRITE; - lsm = ccc_inode_lsm_get(inode); - if (lsm) - rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), 0, - lsm, (void __user *)arg); - ccc_inode_lsm_put(inode, lsm); + rc = ll_copy_user_md(lum, &klum); + if (rc < 0) + return rc; + + lum_size = rc; + rc = ll_lov_setstripe_ea_info(inode, file->f_path.dentry, flags, klum, + lum_size); + cl_lov_delay_create_clear(&file->f_flags); + if (rc == 0) { + __u32 gen; + + put_user(0, &lum->lmm_stripe_count); + + ll_layout_refresh(inode, &gen); + rc = ll_file_getstripe(inode, (struct lov_user_md __user *)arg); + } + + kfree(klum); return rc; } @@ -2247,6 +2156,12 @@ free_hss: return rc; } +static inline long ll_lease_type_from_fmode(fmode_t fmode) +{ + return ((fmode & FMODE_READ) ? LL_LEASE_RDLCK : 0) | + ((fmode & FMODE_WRITE) ? LL_LEASE_WRLCK : 0); +} + static long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -2314,11 +2229,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return rc; } case LL_IOC_LOV_GETSTRIPE: - return ll_lov_getstripe(inode, arg); - case LL_IOC_RECREATE_OBJ: - return ll_lov_recreate_obj(inode, arg); - case LL_IOC_RECREATE_FID: - return ll_lov_recreate_fid(inode, arg); + return ll_file_getstripe(inode, + (struct lov_user_md __user *)arg); case FSFILT_IOC_FIEMAP: return ll_ioctl_fiemap(inode, arg); case FSFILT_IOC_GETFLAGS: @@ -2349,6 +2261,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } + case LL_IOC_GETPARENT: + return ll_getparent(file, (struct getparent __user *)arg); case OBD_IOC_FID2PATH: return ll_fid2path(inode, (void __user *)arg); case LL_IOC_DATA_VERSION: { @@ -2451,20 +2365,20 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct ll_inode_info *lli = ll_i2info(inode); struct obd_client_handle *och = NULL; bool lease_broken; - fmode_t mode = 0; + fmode_t fmode; switch (arg) { - case F_WRLCK: + case LL_LEASE_WRLCK: if (!(file->f_mode & FMODE_WRITE)) return -EPERM; - mode = FMODE_WRITE; + fmode = FMODE_WRITE; break; - case F_RDLCK: + case LL_LEASE_RDLCK: if (!(file->f_mode & FMODE_READ)) return -EPERM; - mode = FMODE_READ; + fmode = FMODE_READ; break; - case F_UNLCK: + case LL_LEASE_UNLCK: mutex_lock(&lli->lli_och_mutex); if (fd->fd_lease_och) { och = fd->fd_lease_och; @@ -2472,26 +2386,26 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } mutex_unlock(&lli->lli_och_mutex); - if (och) { - mode = och->och_flags & - (FMODE_READ|FMODE_WRITE); - rc = ll_lease_close(och, inode, &lease_broken); - if (rc == 0 && lease_broken) - mode = 0; - } else { - rc = -ENOLCK; - } + if (!och) + return -ENOLCK; - /* return the type of lease or error */ - return rc < 0 ? rc : (int)mode; + fmode = och->och_flags; + rc = ll_lease_close(och, inode, &lease_broken); + if (rc < 0) + return rc; + + if (lease_broken) + fmode = 0; + + return ll_lease_type_from_fmode(fmode); default: return -EINVAL; } - CDEBUG(D_INODE, "Set lease with mode %d\n", mode); + CDEBUG(D_INODE, "Set lease with mode %u\n", fmode); /* apply for lease */ - och = ll_lease_open(inode, file, mode, 0); + och = ll_lease_open(inode, file, fmode, 0); if (IS_ERR(och)) return PTR_ERR(och); @@ -2512,8 +2426,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_GET_LEASE: { struct ll_inode_info *lli = ll_i2info(inode); struct ldlm_lock *lock = NULL; + fmode_t fmode = 0; - rc = 0; mutex_lock(&lli->lli_och_mutex); if (fd->fd_lease_och) { struct obd_client_handle *och = fd->fd_lease_och; @@ -2522,14 +2436,13 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (lock) { lock_res_and_lock(lock); if (!ldlm_is_cancel(lock)) - rc = och->och_flags & - (FMODE_READ | FMODE_WRITE); + fmode = och->och_flags; unlock_res_and_lock(lock); LDLM_LOCK_PUT(lock); } } mutex_unlock(&lli->lli_och_mutex); - return rc; + return ll_lease_type_from_fmode(fmode); } case LL_IOC_HSM_IMPORT: { struct hsm_user_import *hui; @@ -2574,9 +2487,8 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin) eof = i_size_read(inode); } - retval = generic_file_llseek_size(file, offset, origin, - ll_file_maxbytes(inode), eof); - return retval; + return generic_file_llseek_size(file, offset, origin, + ll_file_maxbytes(inode), eof); } static int ll_flush(struct file *file, fl_owner_t id) @@ -2593,9 +2505,11 @@ static int ll_flush(struct file *file, fl_owner_t id) */ rc = lli->lli_async_rc; lli->lli_async_rc = 0; - err = lov_read_and_clear_async_rc(lli->lli_clob); - if (rc == 0) - rc = err; + if (lli->lli_clob) { + err = lov_read_and_clear_async_rc(lli->lli_clob); + if (!rc) + rc = err; + } /* The application has been told about write failure already. * Do not report failure again. @@ -2714,6 +2628,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) struct md_op_data *op_data; struct lustre_handle lockh = {0}; ldlm_policy_data_t flock = { {0} }; + int fl_type = file_lock->fl_type; __u64 flags = 0; int rc; int rc2 = 0; @@ -2744,7 +2659,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) if (file_lock->fl_lmops && file_lock->fl_lmops->lm_compare_owner) flock.l_flock.owner = (unsigned long)file_lock->fl_pid; - switch (file_lock->fl_type) { + switch (fl_type) { case F_RDLCK: einfo.ei_mode = LCK_PR; break; @@ -2764,8 +2679,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) einfo.ei_mode = LCK_PW; break; default: - CDEBUG(D_INFO, "Unknown fcntl lock type: %d\n", - file_lock->fl_type); + CDEBUG(D_INFO, "Unknown fcntl lock type: %d\n", fl_type); return -ENOTSUPP; } @@ -2787,16 +2701,18 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) case F_GETLK64: #endif flags = LDLM_FL_TEST_LOCK; - /* Save the old mode so that if the mode in the lock changes we - * can decrement the appropriate reader or writer refcount. - */ - file_lock->fl_type = einfo.ei_mode; break; default: CERROR("unknown fcntl lock command: %d\n", cmd); return -EINVAL; } + /* + * Save the old mode so that if the mode in the lock changes we + * can decrement the appropriate reader or writer refcount. + */ + file_lock->fl_type = einfo.ei_mode; + op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) @@ -2806,8 +2722,12 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) PFID(ll_inode2fid(inode)), flock.l_flock.pid, flags, einfo.ei_mode, flock.l_flock.start, flock.l_flock.end); - rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL, - op_data, &lockh, &flock, 0, NULL /* req */, flags); + rc = md_enqueue(sbi->ll_md_exp, &einfo, &flock, NULL, op_data, &lockh, + flags); + + /* Restore the file lock type if not TEST lock. */ + if (!(flags & LDLM_FL_TEST_LOCK)) + file_lock->fl_type = fl_type; if ((rc == 0 || file_lock->fl_type == F_UNLCK) && !(flags & LDLM_FL_TEST_LOCK)) @@ -2815,8 +2735,8 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) if (rc2 && file_lock->fl_type != F_UNLCK) { einfo.ei_mode = LCK_NL; - md_enqueue(sbi->ll_md_exp, &einfo, NULL, - op_data, &lockh, &flock, 0, NULL /* req */, flags); + md_enqueue(sbi->ll_md_exp, &einfo, &flock, NULL, op_data, + &lockh, flags); rc = rc2; } @@ -2825,6 +2745,117 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) return rc; } +int ll_get_fid_by_name(struct inode *parent, const char *name, + int namelen, struct lu_fid *fid) +{ + struct md_op_data *op_data = NULL; + struct ptlrpc_request *req; + struct mdt_body *body; + int rc; + + op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + return PTR_ERR(op_data); + + op_data->op_valid = OBD_MD_FLID; + rc = md_getattr_name(ll_i2sbi(parent)->ll_md_exp, op_data, &req); + ll_finish_md_op_data(op_data); + if (rc < 0) + return rc; + + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + if (!body) { + rc = -EFAULT; + goto out_req; + } + if (fid) + *fid = body->mbo_fid1; +out_req: + ptlrpc_req_finished(req); + return rc; +} + +int ll_migrate(struct inode *parent, struct file *file, int mdtidx, + const char *name, int namelen) +{ + struct ptlrpc_request *request = NULL; + struct inode *child_inode = NULL; + struct dentry *dchild = NULL; + struct md_op_data *op_data; + struct qstr qstr; + int rc; + + CDEBUG(D_VFSTRACE, "migrate %s under "DFID" to MDT%d\n", + name, PFID(ll_inode2fid(parent)), mdtidx); + + op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen, + 0, LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + return PTR_ERR(op_data); + + /* Get child FID first */ + qstr.hash = full_name_hash(parent, name, namelen); + qstr.name = name; + qstr.len = namelen; + dchild = d_lookup(file_dentry(file), &qstr); + if (dchild) { + op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); + if (dchild->d_inode) { + child_inode = igrab(dchild->d_inode); + if (child_inode) { + inode_lock(child_inode); + op_data->op_fid3 = *ll_inode2fid(child_inode); + ll_invalidate_aliases(child_inode); + } + } + dput(dchild); + } else { + rc = ll_get_fid_by_name(parent, name, namelen, + &op_data->op_fid3); + if (rc) + goto out_free; + } + + if (!fid_is_sane(&op_data->op_fid3)) { + CERROR("%s: migrate %s, but fid "DFID" is insane\n", + ll_get_fsname(parent->i_sb, NULL, 0), name, + PFID(&op_data->op_fid3)); + rc = -EINVAL; + goto out_free; + } + + rc = ll_get_mdt_idx_by_fid(ll_i2sbi(parent), &op_data->op_fid3); + if (rc < 0) + goto out_free; + + if (rc == mdtidx) { + CDEBUG(D_INFO, "%s:"DFID" is already on MDT%d.\n", name, + PFID(&op_data->op_fid3), mdtidx); + rc = 0; + goto out_free; + } + + op_data->op_mds = mdtidx; + op_data->op_cli_flags = CLI_MIGRATE; + rc = md_rename(ll_i2sbi(parent)->ll_md_exp, op_data, name, + namelen, name, namelen, &request); + if (!rc) + ll_update_times(request, parent); + + ptlrpc_req_finished(request); + +out_free: + if (child_inode) { + clear_nlink(child_inode); + inode_unlock(child_inode); + iput(child_inode); + } + + ll_finish_md_op_data(op_data); + return rc; +} + static int ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock) { @@ -2847,7 +2878,7 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, struct lustre_handle lockh; ldlm_policy_data_t policy; enum ldlm_mode mode = (l_req_mode == LCK_MINMODE) ? - (LCK_CR|LCK_CW|LCK_PR|LCK_PW) : l_req_mode; + (LCK_CR | LCK_CW | LCK_PR | LCK_PW) : l_req_mode; struct lu_fid *fid; __u64 flags; int i; @@ -2888,15 +2919,12 @@ enum ldlm_mode ll_take_md_lock(struct inode *inode, __u64 bits, { ldlm_policy_data_t policy = { .l_inodebits = {bits} }; struct lu_fid *fid; - enum ldlm_mode rc; fid = &ll_i2info(inode)->lli_fid; CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid)); - rc = md_lock_match(ll_i2mdexp(inode), flags | LDLM_FL_BLOCK_GRANTED, - fid, LDLM_IBITS, &policy, mode, lockh); - - return rc; + return md_lock_match(ll_i2mdexp(inode), flags | LDLM_FL_BLOCK_GRANTED, + fid, LDLM_IBITS, &policy, mode, lockh); } static int ll_inode_revalidate_fini(struct inode *inode, int rc) @@ -2949,15 +2977,9 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits) if (IS_ERR(op_data)) return PTR_ERR(op_data); - oit.it_create_mode |= M_CHECK_STALE; - rc = md_intent_lock(exp, op_data, NULL, 0, - /* we are not interested in name - * based lookup - */ - &oit, 0, &req, - ll_md_blocking_ast, 0); + rc = md_intent_lock(exp, op_data, &oit, &req, + &ll_md_blocking_ast, 0); ll_finish_md_op_data(op_data); - oit.it_create_mode &= ~M_CHECK_STALE; if (rc < 0) { rc = ll_inode_revalidate_fini(inode, rc); goto out; @@ -3003,10 +3025,8 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits) op_data->op_valid = valid; rc = md_getattr(sbi->ll_md_exp, op_data, &req); ll_finish_md_op_data(op_data); - if (rc) { - rc = ll_inode_revalidate_fini(inode, rc); - return rc; - } + if (rc) + return ll_inode_revalidate_fini(inode, rc); rc = ll_prep_inode(&inode, req, NULL, NULL); } @@ -3015,6 +3035,28 @@ out: return rc; } +static int ll_merge_md_attr(struct inode *inode) +{ + struct cl_attr attr = { 0 }; + int rc; + + LASSERT(ll_i2info(inode)->lli_lsm_md); + rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, + &attr, ll_md_blocking_ast); + if (rc) + return rc; + + set_nlink(inode, attr.cat_nlink); + inode->i_blocks = attr.cat_blocks; + i_size_write(inode, attr.cat_size); + + ll_i2info(inode)->lli_atime = attr.cat_atime; + ll_i2info(inode)->lli_mtime = attr.cat_mtime; + ll_i2info(inode)->lli_ctime = attr.cat_ctime; + + return 0; +} + static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits) { struct inode *inode = d_inode(dentry); @@ -3026,6 +3068,13 @@ static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits) /* if object isn't regular file, don't validate size */ if (!S_ISREG(inode->i_mode)) { + if (S_ISDIR(inode->i_mode) && + ll_i2info(inode)->lli_lsm_md) { + rc = ll_merge_md_attr(inode); + if (rc) + return rc; + } + LTIME_S(inode->i_atime) = ll_i2info(inode)->lli_atime; LTIME_S(inode->i_mtime) = ll_i2info(inode)->lli_mtime; LTIME_S(inode->i_ctime) = ll_i2info(inode)->lli_ctime; @@ -3057,13 +3106,14 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) if (res) return res; + OBD_FAIL_TIMEOUT(OBD_FAIL_GETATTR_DELAY, 30); + stat->dev = inode->i_sb->s_dev; if (ll_need_32bit_api(sbi)) stat->ino = cl_fid_build_ino(&lli->lli_fid, 1); else stat->ino = inode->i_ino; stat->mode = inode->i_mode; - stat->nlink = inode->i_nlink; stat->uid = inode->i_uid; stat->gid = inode->i_gid; stat->rdev = inode->i_rdev; @@ -3072,6 +3122,7 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) stat->ctime = inode->i_ctime; stat->blksize = 1 << inode->i_blkbits; + stat->nlink = inode->i_nlink; stat->size = i_size_read(inode); stat->blocks = inode->i_blocks; @@ -3139,6 +3190,12 @@ struct posix_acl *ll_get_acl(struct inode *inode, int type) int ll_inode_permission(struct inode *inode, int mask) { + struct ll_sb_info *sbi; + struct root_squash_info *squash; + const struct cred *old_cred = NULL; + struct cred *cred = NULL; + bool squash_id = false; + cfs_cap_t cap; int rc = 0; if (mask & MAY_NOT_BLOCK) @@ -3158,9 +3215,46 @@ int ll_inode_permission(struct inode *inode, int mask) CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n", PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask); + /* squash fsuid/fsgid if needed */ + sbi = ll_i2sbi(inode); + squash = &sbi->ll_squash; + if (unlikely(squash->rsi_uid && + uid_eq(current_fsuid(), GLOBAL_ROOT_UID) && + !(sbi->ll_flags & LL_SBI_NOROOTSQUASH))) { + squash_id = true; + } + + if (squash_id) { + CDEBUG(D_OTHER, "squash creds (%d:%d)=>(%d:%d)\n", + __kuid_val(current_fsuid()), __kgid_val(current_fsgid()), + squash->rsi_uid, squash->rsi_gid); + + /* + * update current process's credentials + * and FS capability + */ + cred = prepare_creds(); + if (!cred) + return -ENOMEM; + + cred->fsuid = make_kuid(&init_user_ns, squash->rsi_uid); + cred->fsgid = make_kgid(&init_user_ns, squash->rsi_gid); + for (cap = 0; cap < sizeof(cfs_cap_t) * 8; cap++) { + if ((1 << cap) & CFS_CAP_FS_MASK) + cap_lower(cred->cap_effective, cap); + } + old_cred = override_creds(cred); + } + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_INODE_PERM, 1); rc = generic_permission(inode, mask); + /* restore current process's credentials and FS capability */ + if (squash_id) { + revert_creds(old_cred); + put_cred(cred); + } + return rc; } @@ -3213,10 +3307,10 @@ const struct inode_operations ll_file_inode_operations = { .setattr = ll_setattr, .getattr = ll_getattr, .permission = ll_inode_permission, - .setxattr = ll_setxattr, - .getxattr = ll_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ll_listxattr, - .removexattr = ll_removexattr, + .removexattr = generic_removexattr, .fiemap = ll_fiemap, .get_acl = ll_get_acl, }; @@ -3251,7 +3345,6 @@ void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd) if (!in_data) return NULL; - memset(in_data, 0, sizeof(*in_data)); in_data->iocd_size = size; in_data->iocd_cb = cb; in_data->iocd_count = count; @@ -3389,7 +3482,7 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) goto out; } - lmmsize = body->eadatasize; + lmmsize = body->mbo_eadatasize; if (lmmsize == 0) /* empty layout */ { rc = 0; goto out; @@ -3447,7 +3540,7 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode, PFID(&lli->lli_fid), inode, reconf); /* in case this is a caching lock and reinstate with new inode */ - md_set_lock_data(sbi->ll_md_exp, &lockh->cookie, inode, NULL); + md_set_lock_data(sbi->ll_md_exp, lockh, inode, NULL); lock_res_and_lock(lock); lvb_ready = ldlm_is_lvb_ready(lock); @@ -3557,8 +3650,8 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS, .ei_mode = LCK_CR, - .ei_cb_bl = ll_md_blocking_ast, - .ei_cb_cp = ldlm_completion_ast, + .ei_cb_bl = &ll_md_blocking_ast, + .ei_cb_cp = &ldlm_completion_ast, }; int rc; @@ -3604,8 +3697,7 @@ again: ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), inode); - rc = md_enqueue(sbi->ll_md_exp, &einfo, &it, op_data, &lockh, - NULL, 0, NULL, 0); + rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL, &it, op_data, &lockh, 0); ptlrpc_req_finished(it.it_request); it.it_request = NULL; diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index 92004a05f9ee..22507b9c6d69 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -42,7 +42,6 @@ #include "../include/obd.h" #include "../include/lustre_dlm.h" -#include "../include/lustre_lite.h" #include "../include/lustre_mdc.h" #include #include diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 396e4e4f0715..084330d08f7a 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -49,7 +49,6 @@ #include "../include/obd.h" #include "../include/obd_support.h" #include "../include/lustre_fid.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_ver.h" #include "../include/lustre_mdc.h" @@ -100,6 +99,7 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) io->u.ci_setattr.sa_attr.lvb_ctime = LTIME_S(attr->ia_ctime); io->u.ci_setattr.sa_attr.lvb_size = attr->ia_size; io->u.ci_setattr.sa_valid = attr->ia_valid; + io->u.ci_setattr.sa_parent_fid = ll_inode2fid(inode); again: if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) { @@ -154,7 +154,7 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md) int result = 0; int refcheck; - LASSERT(md->body->valid & OBD_MD_FLID); + LASSERT(md->body->mbo_valid & OBD_MD_FLID); LASSERT(S_ISREG(inode->i_mode)); env = cl_env_get(&refcheck); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index f6be105eeef7..fb346c12dad2 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -38,7 +38,6 @@ #include "../include/obd.h" #include "../include/cl_object.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" /* Initialize the default and maximum LOV EA and cookie sizes. This allows diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c index 2326b40a0870..8644631bf2ba 100644 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ b/drivers/staging/lustre/lustre/llite/llite_close.c @@ -38,7 +38,6 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" /** records that a write is in flight */ diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 4d6d589a1677..3e98bd685061 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -36,14 +36,21 @@ #include "../include/lustre_ver.h" #include "../include/lustre_disk.h" /* for s2sbi */ #include "../include/lustre_eacl.h" +#include "../include/lustre_linkea.h" /* for struct cl_lock_descr and struct cl_io */ +#include "../include/lustre_patchless_compat.h" +#include "../include/lustre_compat.h" #include "../include/cl_object.h" +#include "../include/lustre_lmv.h" #include "../include/lustre_mdc.h" #include "../include/lustre_intent.h" #include +#include +#include #include #include "vvp_internal.h" +#include "range_lock.h" #ifndef FMODE_EXEC #define FMODE_EXEC 0 @@ -57,6 +64,9 @@ #define LL_DIR_END_OFF 0x7fffffffffffffffULL #define LL_DIR_END_OFF_32BIT 0x7fffffffUL +/* 4UL * 1024 * 1024 */ +#define LL_MAX_BLKSIZE_BITS 22 + #define LL_IT2STR(it) ((it) ? ldlm_it2str((it)->it_op) : "0") #define LUSTRE_FPRIVATE(file) ((file)->private_data) @@ -116,9 +126,7 @@ struct ll_inode_info { /* identifying fields for both metadata and data stacks. */ struct lu_fid lli_fid; - /* Parent fid for accessing default stripe data on parent directory - * for allocating OST objects after a mknod() and later open-by-FID. - */ + /* master inode fid for stripe directory */ struct lu_fid lli_pfid; struct list_head lli_close_list; @@ -156,7 +164,7 @@ struct ll_inode_info { /* for directory */ struct { /* serialize normal readdir and statahead-readdir. */ - struct mutex d_readdir_mutex; + struct mutex lli_readdir_mutex; /* metadata statahead */ /* since parent-child threads can share the same @file @@ -164,27 +172,39 @@ struct ll_inode_info { * case of parent exit before child -- it is me should * cleanup the dir readahead. */ - void *d_opendir_key; - struct ll_statahead_info *d_sai; + void *lli_opendir_key; + struct ll_statahead_info *lli_sai; /* protect statahead stuff. */ - spinlock_t d_sa_lock; + spinlock_t lli_sa_lock; /* "opendir_pid" is the token when lookup/revalidate * -- I am the owner of dir statahead. */ - pid_t d_opendir_pid; - } d; - -#define lli_readdir_mutex u.d.d_readdir_mutex -#define lli_opendir_key u.d.d_opendir_key -#define lli_sai u.d.d_sai -#define lli_sa_lock u.d.d_sa_lock -#define lli_opendir_pid u.d.d_opendir_pid + pid_t lli_opendir_pid; + /* stat will try to access statahead entries or start + * statahead if this flag is set, and this flag will be + * set upon dir open, and cleared when dir is closed, + * statahead hit ratio is too low, or start statahead + * thread failed. + */ + unsigned int lli_sa_enabled:1; + /* generation for statahead */ + unsigned int lli_sa_generation; + /* directory stripe information */ + struct lmv_stripe_md *lli_lsm_md; + /* default directory stripe offset. This is extracted + * from the "dmv" xattr in order to decide which MDT to + * create a subdirectory on. The MDS itself fetches + * "dmv" and gets the rest of the default layout itself + * (count, hash, etc). + */ + __u32 lli_def_stripe_offset; + }; /* for non-directory */ struct { - struct mutex f_size_mutex; - char *f_symlink_name; - __u64 f_maxbytes; + struct mutex lli_size_mutex; + char *lli_symlink_name; + __u64 lli_maxbytes; /* * struct rw_semaphore { * signed long count; // align d.d_def_acl @@ -192,16 +212,16 @@ struct ll_inode_info { * struct list_head wait_list; * } */ - struct rw_semaphore f_trunc_sem; - struct mutex f_write_mutex; + struct rw_semaphore lli_trunc_sem; + struct range_lock_tree lli_write_tree; - struct rw_semaphore f_glimpse_sem; - unsigned long f_glimpse_time; - struct list_head f_agl_list; - __u64 f_agl_index; + struct rw_semaphore lli_glimpse_sem; + unsigned long lli_glimpse_time; + struct list_head lli_agl_list; + __u64 lli_agl_index; /* for writepage() only to communicate to fsync */ - int f_async_rc; + int lli_async_rc; /* * whenever a process try to read/write the file, the @@ -211,22 +231,9 @@ struct ll_inode_info { * so the read/write statistics for jobid will not be * accurate if the file is shared by different jobs. */ - char f_jobid[JOBSTATS_JOBID_SIZE]; - } f; - -#define lli_size_mutex u.f.f_size_mutex -#define lli_symlink_name u.f.f_symlink_name -#define lli_maxbytes u.f.f_maxbytes -#define lli_trunc_sem u.f.f_trunc_sem -#define lli_write_mutex u.f.f_write_mutex -#define lli_glimpse_sem u.f.f_glimpse_sem -#define lli_glimpse_time u.f.f_glimpse_time -#define lli_agl_list u.f.f_agl_list -#define lli_agl_index u.f.f_agl_index -#define lli_async_rc u.f.f_async_rc -#define lli_jobid u.f.f_jobid - - } u; + char lli_jobid[LUSTRE_JOBID_SIZE]; + }; + }; /* XXX: For following frequent used members, although they maybe special * used for non-directory object, it is some time-wasting to check @@ -401,12 +408,13 @@ enum stats_track_type { #define LL_SBI_LAYOUT_LOCK 0x20000 /* layout lock support */ #define LL_SBI_USER_FID2PATH 0x40000 /* allow fid2path by unprivileged users */ #define LL_SBI_XATTR_CACHE 0x80000 /* support for xattr cache */ +#define LL_SBI_NOROOTSQUASH 0x100000 /* do not apply root squash */ #define LL_SBI_FLAGS { \ "nolck", \ "checksum", \ "flock", \ - "xattr", \ + "user_xattr", \ "acl", \ "???", \ "???", \ @@ -422,9 +430,27 @@ enum stats_track_type { "verbose", \ "layout", \ "user_fid2path",\ - "xattr", \ + "xattr_cache", \ + "norootsquash", \ } +/* + * This is embedded into llite super-blocks to keep track of connect + * flags (capabilities) supported by all imports given mount is + * connected to. + */ +struct lustre_client_ocd { + /* + * This is conjunction of connect_flags across all imports + * (LOVs) this mount is connected to. This field is updated by + * cl_ocd_update() under ->lco_lock. + */ + __u64 lco_flags; + struct mutex lco_lock; + struct obd_export *lco_md_exp; + struct obd_export *lco_dt_exp; +}; + struct ll_sb_info { /* this protects pglist and ra_info. It isn't safe to * grab from interrupt contexts @@ -461,7 +487,7 @@ struct ll_sb_info { unsigned int ll_namelen; struct file_operations *ll_fop; - unsigned int ll_md_brw_size; /* used by readdir */ + unsigned int ll_md_brw_pages; /* readdir pages per RPC */ struct lu_site *ll_site; struct cl_device *ll_cl; @@ -484,11 +510,17 @@ struct ll_sb_info { atomic_t ll_sa_wrong; /* statahead thread stopped for * low hit ratio */ + atomic_t ll_sa_running; /* running statahead thread + * count + */ atomic_t ll_agl_total; /* AGL thread started count */ dev_t ll_sdev_orig; /* save s_dev before assign for * clustered nfs */ + /* root squash */ + struct root_squash_info ll_squash; + __kernel_fsid_t ll_fsid; struct kobject ll_kobj; /* sysfs object */ struct super_block *ll_sb; /* struct super_block (for sysfs code)*/ @@ -643,25 +675,66 @@ void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, struct ll_file_data *file, loff_t pos, size_t count, int rw); +enum { + LPROC_LL_DIRTY_HITS, + LPROC_LL_DIRTY_MISSES, + LPROC_LL_READ_BYTES, + LPROC_LL_WRITE_BYTES, + LPROC_LL_BRW_READ, + LPROC_LL_BRW_WRITE, + LPROC_LL_OSC_READ, + LPROC_LL_OSC_WRITE, + LPROC_LL_IOCTL, + LPROC_LL_OPEN, + LPROC_LL_RELEASE, + LPROC_LL_MAP, + LPROC_LL_LLSEEK, + LPROC_LL_FSYNC, + LPROC_LL_READDIR, + LPROC_LL_SETATTR, + LPROC_LL_TRUNC, + LPROC_LL_FLOCK, + LPROC_LL_GETATTR, + LPROC_LL_CREATE, + LPROC_LL_LINK, + LPROC_LL_UNLINK, + LPROC_LL_SYMLINK, + LPROC_LL_MKDIR, + LPROC_LL_RMDIR, + LPROC_LL_MKNOD, + LPROC_LL_RENAME, + LPROC_LL_STAFS, + LPROC_LL_ALLOC_INODE, + LPROC_LL_SETXATTR, + LPROC_LL_GETXATTR, + LPROC_LL_GETXATTR_HITS, + LPROC_LL_LISTXATTR, + LPROC_LL_REMOVEXATTR, + LPROC_LL_INODE_PERM, + LPROC_LL_FILE_OPCODES +}; + /* llite/dir.c */ -void ll_release_page(struct page *page, int remove); extern const struct file_operations ll_dir_operations; extern const struct inode_operations ll_dir_inode_operations; -struct page *ll_get_dir_page(struct inode *dir, __u64 hash, - struct ll_dir_chain *chain); -int ll_dir_read(struct inode *inode, struct dir_context *ctx); - +int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, + struct dir_context *ctx); int ll_get_mdt_idx(struct inode *inode); +int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, const struct lu_fid *fid); +struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, + __u64 offset); +void ll_release_page(struct inode *inode, struct page *page, bool remove); + /* llite/namei.c */ extern const struct inode_operations ll_special_inode_operations; -int ll_objects_destroy(struct ptlrpc_request *request, - struct inode *dir); struct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *lic); +int ll_test_inode_by_fid(struct inode *inode, void *opaque); int ll_md_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *, void *data, int flag); struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de); +void ll_update_times(struct ptlrpc_request *request, struct inode *inode); /* llite/rw.c */ int ll_writepage(struct page *page, struct writeback_control *wbc); @@ -704,7 +777,10 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, struct lustre_handle *fh); int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat); struct posix_acl *ll_get_acl(struct inode *inode, int type); - +int ll_migrate(struct inode *parent, struct file *file, int mdtidx, + const char *name, int namelen); +int ll_get_fid_by_name(struct inode *parent, const char *name, + int namelen, struct lu_fid *fid); int ll_inode_permission(struct inode *inode, int mask); int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, @@ -715,8 +791,8 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, struct ptlrpc_request **request); int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, int set_default); -int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, - int *lmm_size, struct ptlrpc_request **request); +int ll_dir_getstripe(struct inode *inode, void **lmmp, int *lmm_size, + struct ptlrpc_request **request, u64 valid); int ll_fsync(struct file *file, loff_t start, loff_t end, int data); int ll_merge_attr(const struct lu_env *env, struct inode *inode); int ll_fid2path(struct inode *inode, void __user *arg); @@ -748,8 +824,8 @@ int ll_setattr(struct dentry *de, struct iattr *attr); int ll_statfs(struct dentry *de, struct kstatfs *sfs); int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, __u64 max_age, __u32 flags); -void ll_update_inode(struct inode *inode, struct lustre_md *md); -void ll_read_inode2(struct inode *inode, void *opaque); +int ll_update_inode(struct inode *inode, struct lustre_md *md); +int ll_read_inode2(struct inode *inode, void *opaque); void ll_delete_inode(struct inode *inode); int ll_iocontrol(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); @@ -763,15 +839,46 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, int ll_obd_statfs(struct inode *inode, void __user *arg); int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize); int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize); +int ll_set_default_mdsize(struct ll_sb_info *sbi, int default_mdsize); int ll_process_config(struct lustre_cfg *lcfg); + +enum { + LUSTRE_OPC_MKDIR = 0, + LUSTRE_OPC_SYMLINK = 1, + LUSTRE_OPC_MKNOD = 2, + LUSTRE_OPC_CREATE = 3, + LUSTRE_OPC_ANY = 5, +}; + struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, struct inode *i1, struct inode *i2, - const char *name, int namelen, - int mode, __u32 opc, void *data); + const char *name, size_t namelen, + u32 mode, __u32 opc, void *data); void ll_finish_md_op_data(struct md_op_data *op_data); int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg); char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); +void ll_compute_rootsquash_state(struct ll_sb_info *sbi); void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req); +ssize_t ll_copy_user_md(const struct lov_user_md __user *md, + struct lov_user_md **kbuf); + +/* Compute expected user md size when passing in a md from user space */ +static inline ssize_t ll_lov_user_md_size(const struct lov_user_md *lum) +{ + switch (lum->lmm_magic) { + case LOV_USER_MAGIC_V1: + return sizeof(struct lov_user_md_v1); + case LOV_USER_MAGIC_V3: + return sizeof(struct lov_user_md_v3); + case LOV_USER_MAGIC_SPECIFIC: + if (lum->lmm_stripe_count > LOV_MAX_STRIPE_COUNT) + return -EINVAL; + + return lov_user_md_size(lum->lmm_stripe_count, + LOV_USER_MAGIC_SPECIFIC); + } + return -EINVAL; +} /* llite/llite_nfs.c */ extern const struct export_operations lustre_export_operations; @@ -779,6 +886,7 @@ __u32 get_uuid2int(const char *name, int len); void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid); struct inode *search_inode_for_lustre(struct super_block *sb, const struct lu_fid *fid); +int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid); /* llite/symlink.c */ extern const struct inode_operations ll_fast_symlink_inode_operations; @@ -933,12 +1041,19 @@ static inline __u64 ll_file_maxbytes(struct inode *inode) } /* llite/xattr.c */ -int ll_setxattr(struct dentry *dentry, struct inode *inode, - const char *name, const void *value, size_t size, int flags); -ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *buffer, size_t size); +extern const struct xattr_handler *ll_xattr_handlers[]; + +#define XATTR_USER_T 1 +#define XATTR_TRUSTED_T 2 +#define XATTR_SECURITY_T 3 +#define XATTR_ACL_ACCESS_T 4 +#define XATTR_ACL_DEFAULT_T 5 +#define XATTR_LUSTRE_T 6 +#define XATTR_OTHER_T 7 + ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size); -int ll_removexattr(struct dentry *dentry, const char *name); +int ll_xattr_list(struct inode *inode, const char *name, int type, + void *buffer, size_t size, __u64 valid); /** * Common IO arguments for various VFS I/O interfaces. @@ -964,11 +1079,10 @@ void ll_ra_stats_inc(struct inode *inode, enum ra_stat which); /* per inode struct, for dir only */ struct ll_statahead_info { - struct inode *sai_inode; + struct dentry *sai_dentry; atomic_t sai_refcount; /* when access this struct, hold * refcount */ - unsigned int sai_generation; /* generation for statahead */ unsigned int sai_max; /* max ahead of lookup */ __u64 sai_sent; /* stat requests sent count */ __u64 sai_replied; /* stat requests which received @@ -995,22 +1109,25 @@ struct ll_statahead_info { unsigned int sai_ls_all:1, /* "ls -al", do stat-ahead for * hidden entries */ - sai_agl_valid:1;/* AGL is valid for the dir */ + sai_agl_valid:1,/* AGL is valid for the dir */ + sai_in_readpage:1;/* statahead is in readdir() */ wait_queue_head_t sai_waitq; /* stat-ahead wait queue */ struct ptlrpc_thread sai_thread; /* stat-ahead thread */ struct ptlrpc_thread sai_agl_thread; /* AGL thread */ - struct list_head sai_entries; /* entry list */ - struct list_head sai_entries_received; /* entries returned */ - struct list_head sai_entries_stated; /* entries stated */ - struct list_head sai_entries_agl; /* AGL entries to be sent */ + struct list_head sai_interim_entries; /* entries which got async + * stat reply, but not + * instantiated + */ + struct list_head sai_entries; /* completed entries */ + struct list_head sai_agls; /* AGLs to be sent */ struct list_head sai_cache[LL_SA_CACHE_SIZE]; spinlock_t sai_cache_lock[LL_SA_CACHE_SIZE]; atomic_t sai_cache_count; /* entry count in cache */ }; -int do_statahead_enter(struct inode *dir, struct dentry **dentry, - int only_unplug); -void ll_stop_statahead(struct inode *dir, void *key); +int ll_statahead(struct inode *dir, struct dentry **dentry, bool unplug); +void ll_authorize_statahead(struct inode *dir, void *key); +void ll_deauthorize_statahead(struct inode *dir, void *key); blkcnt_t dirty_cnt(struct inode *inode); @@ -1040,73 +1157,53 @@ static inline int ll_glimpse_size(struct inode *inode) return rc; } -static inline void -ll_statahead_mark(struct inode *dir, struct dentry *dentry) -{ - struct ll_inode_info *lli = ll_i2info(dir); - struct ll_statahead_info *sai = lli->lli_sai; - struct ll_dentry_data *ldd = ll_d2d(dentry); - - /* not the same process, don't mark */ - if (lli->lli_opendir_pid != current_pid()) - return; - - LASSERT(ldd); - if (sai) - ldd->lld_sa_generation = sai->sai_generation; -} - -static inline int -d_need_statahead(struct inode *dir, struct dentry *dentryp) +/* + * dentry may statahead when statahead is enabled and current process has opened + * parent directory, and this dentry hasn't accessed statahead cache before + */ +static inline bool +dentry_may_statahead(struct inode *dir, struct dentry *dentry) { struct ll_inode_info *lli; struct ll_dentry_data *ldd; if (ll_i2sbi(dir)->ll_sa_max == 0) - return -EAGAIN; + return false; lli = ll_i2info(dir); + + /* + * statahead is not allowed for this dir, there may be three causes: + * 1. dir is not opened. + * 2. statahead hit ratio is too low. + * 3. previous stat started statahead thread failed. + */ + if (!lli->lli_sa_enabled) + return false; + /* not the same process, don't statahead */ if (lli->lli_opendir_pid != current_pid()) - return -EAGAIN; + return false; - /* statahead has been stopped */ - if (!lli->lli_opendir_key) - return -EAGAIN; - - ldd = ll_d2d(dentryp); /* - * When stats a dentry, the system trigger more than once "revalidate" - * or "lookup", for "getattr", for "getxattr", and maybe for others. - * Under patchless client mode, the operation intent is not accurate, - * which maybe misguide the statahead thread. For example: - * The "revalidate" call for "getattr" and "getxattr" of a dentry maybe - * have the same operation intent -- "IT_GETATTR". - * In fact, one dentry should has only one chance to interact with the - * statahead thread, otherwise the statahead windows will be confused. + * When stating a dentry, kernel may trigger 'revalidate' or 'lookup' + * multiple times, eg. for 'getattr', 'getxattr' and etc. + * For patchless client, lookup intent is not accurate, which may + * misguide statahead. For example: + * The 'revalidate' call for 'getattr' and 'getxattr' of a dentry will + * have the same intent -- IT_GETATTR, while one dentry should access + * statahead cache once, otherwise statahead windows is messed up. * The solution is as following: - * Assign "lld_sa_generation" with "sai_generation" when a dentry - * "IT_GETATTR" for the first time, and the subsequent "IT_GETATTR" - * will bypass interacting with statahead thread for checking: - * "lld_sa_generation == lli_sai->sai_generation" + * Assign 'lld_sa_generation' with 'lli_sa_generation' when a dentry + * IT_GETATTR for the first time, and subsequent IT_GETATTR will + * bypass interacting with statahead cache by checking + * 'lld_sa_generation == lli->lli_sa_generation'. */ - if (ldd && lli->lli_sai && - ldd->lld_sa_generation == lli->lli_sai->sai_generation) - return -EAGAIN; + ldd = ll_d2d(dentry); + if (ldd && ldd->lld_sa_generation == lli->lli_sa_generation) + return false; - return 1; -} - -static inline int -ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug) -{ - int ret; - - ret = d_need_statahead(dir, *dentryp); - if (ret <= 0) - return ret; - - return do_statahead_enter(dir, dentryp, only_unplug); + return true; } /* llite ioctl register support routine */ @@ -1213,7 +1310,7 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode, CDEBUG(D_DLMTRACE, "setting l_data to inode "DFID"%p for remote lock %#llx\n", PFID(ll_inode2fid(inode)), inode, handle.cookie); - md_set_lock_data(exp, &handle.cookie, inode, NULL); + md_set_lock_data(exp, &handle, inode, NULL); } handle.cookie = it->it_lock_handle; @@ -1221,8 +1318,7 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode, CDEBUG(D_DLMTRACE, "setting l_data to inode "DFID"%p for lock %#llx\n", PFID(ll_inode2fid(inode)), inode, handle.cookie); - md_set_lock_data(exp, &handle.cookie, inode, - &it->it_lock_bits); + md_set_lock_data(exp, &handle, inode, &it->it_lock_bits); it->it_lock_set = 1; } @@ -1295,6 +1391,8 @@ void ll_xattr_fini(void); int ll_page_sync_io(const struct lu_env *env, struct cl_io *io, struct cl_page *page, enum cl_req_type crt); +int ll_getparent(struct file *file, struct getparent __user *arg); + /* lcommon_cl.c */ int cl_setattr_ost(struct inode *inode, const struct iattr *attr); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 546063e728db..6bb41b09172e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -41,7 +41,7 @@ #include #include -#include "../include/lustre_lite.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_ha.h" #include "../include/lustre_dlm.h" #include "../include/lprocfs_status.h" @@ -115,9 +115,16 @@ static struct ll_sb_info *ll_init_sbi(struct super_block *sb) sbi->ll_sa_max = LL_SA_RPC_DEF; atomic_set(&sbi->ll_sa_total, 0); atomic_set(&sbi->ll_sa_wrong, 0); + atomic_set(&sbi->ll_sa_running, 0); atomic_set(&sbi->ll_agl_total, 0); sbi->ll_flags |= LL_SBI_AGL_ENABLED; + /* root squash */ + sbi->ll_squash.rsi_uid = 0; + sbi->ll_squash.rsi_gid = 0; + INIT_LIST_HEAD(&sbi->ll_squash.rsi_nosquash_nids); + init_rwsem(&sbi->ll_squash.rsi_sem); + sbi->ll_sb = sb; return sbi; @@ -128,6 +135,8 @@ static void ll_free_sbi(struct super_block *sb) struct ll_sb_info *sbi = ll_s2sbi(sb); if (sbi->ll_cache) { + if (!list_empty(&sbi->ll_squash.rsi_nosquash_nids)) + cfs_free_nidlist(&sbi->ll_squash.rsi_nosquash_nids); cl_cache_decref(sbi->ll_cache); sbi->ll_cache = NULL; } @@ -180,7 +189,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE | OBD_CONNECT_FLOCK_DEAD | - OBD_CONNECT_DISP_STRIPE; + OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK | + OBD_CONNECT_OPEN_BY_FID | + OBD_CONNECT_DIR_STRIPE; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -310,9 +321,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_flags |= LL_SBI_64BIT_HASH; if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) - sbi->ll_md_brw_size = data->ocd_brw_size; + sbi->ll_md_brw_pages = data->ocd_brw_size >> PAGE_SHIFT; else - sbi->ll_md_brw_size = PAGE_SIZE; + sbi->ll_md_brw_pages = 1; if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; @@ -418,6 +429,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); sb->s_op = &lustre_super_operations; + sb->s_xattr = ll_xattr_handlers; #if THREAD_SIZE >= 8192 /*b=17630*/ sb->s_export_op = &lustre_export_operations; #endif @@ -462,7 +474,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, md_free_lustre_md(sbi->ll_md_exp, &lmd); ptlrpc_req_finished(request); - if (!(root)) { + if (IS_ERR(root)) { if (lmd.lsm) obd_free_memmd(sbi->ll_dt_exp, &lmd.lsm); #ifdef CONFIG_FS_POSIX_ACL @@ -486,11 +498,21 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM), KEY_CHECKSUM, sizeof(checksum), &checksum, NULL); + if (err) { + CERROR("%s: Set checksum failed: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, err); + goto out_root; + } cl_sb_init(sb); err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CACHE_SET), KEY_CACHE_SET, sizeof(*sbi->ll_cache), sbi->ll_cache, NULL); + if (err) { + CERROR("%s: Set cache_set failed: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, err); + goto out_root; + } sb->s_root = d_make_root(root); if (!sb->s_root) { @@ -560,6 +582,17 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize) return rc; } +/** + * Get the value of the default_easize parameter. + * + * \see client_obd::cl_default_mds_easize + * + * \param[in] sbi superblock info for this filesystem + * \param[out] lmmsize pointer to storage location for value + * + * \retval 0 on success + * \retval negative negated errno on failure + */ int ll_get_default_mdsize(struct ll_sb_info *sbi, int *lmmsize) { int size, rc; @@ -573,6 +606,29 @@ int ll_get_default_mdsize(struct ll_sb_info *sbi, int *lmmsize) return rc; } +/** + * Set the default_easize parameter to the given value. + * + * \see client_obd::cl_default_mds_easize + * + * \param[in] sbi superblock info for this filesystem + * \param[in] lmmsize the size to set + * + * \retval 0 on success + * \retval negative negated errno on failure + */ +int ll_set_default_mdsize(struct ll_sb_info *sbi, int lmmsize) +{ + if (lmmsize < sizeof(struct lov_mds_md) || + lmmsize > OBD_MAX_DEFAULT_EA_SIZE) + return -EINVAL; + + return obd_set_info_async(NULL, sbi->ll_md_exp, + sizeof(KEY_DEFAULT_EASIZE), + KEY_DEFAULT_EASIZE, + sizeof(int), &lmmsize, NULL); +} + static void client_common_put_super(struct super_block *sb) { struct ll_sb_info *sbi = ll_s2sbi(sb); @@ -608,6 +664,12 @@ void ll_kill_super(struct super_block *sb) if (sbi) { sb->s_dev = sbi->ll_sdev_orig; sbi->ll_umounting = 1; + + /* wait running statahead threads to quit */ + while (atomic_read(&sbi->ll_sa_running) > 0) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC >> 3)); + } } } @@ -647,7 +709,8 @@ static int ll_options(char *options, int *flags) *flags |= tmp; goto next; } - tmp = ll_set_opt("noflock", s1, LL_SBI_FLOCK|LL_SBI_LOCALFLOCK); + tmp = ll_set_opt("noflock", s1, + LL_SBI_FLOCK | LL_SBI_LOCALFLOCK); if (tmp) { *flags &= ~tmp; goto next; @@ -772,11 +835,13 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_sai = NULL; spin_lock_init(&lli->lli_sa_lock); lli->lli_opendir_pid = 0; + lli->lli_sa_enabled = 0; + lli->lli_def_stripe_offset = -1; } else { mutex_init(&lli->lli_size_mutex); lli->lli_symlink_name = NULL; init_rwsem(&lli->lli_trunc_sem); - mutex_init(&lli->lli_write_mutex); + range_lock_tree_init(&lli->lli_write_tree); init_rwsem(&lli->lli_glimpse_sem); lli->lli_glimpse_time = 0; INIT_LIST_HEAD(&lli->lli_agl_list); @@ -896,7 +961,8 @@ void ll_put_super(struct super_block *sb) struct lustre_sb_info *lsi = s2lsi(sb); struct ll_sb_info *sbi = ll_s2sbi(sb); char *profilenm = get_profile_name(sb); - int ccc_count, next, force = 1, rc = 0; + int next, force = 1, rc = 0; + long ccc_count; CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm); @@ -917,13 +983,13 @@ void ll_put_super(struct super_block *sb) struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); rc = l_wait_event(sbi->ll_cache->ccc_unstable_waitq, - !atomic_read(&sbi->ll_cache->ccc_unstable_nr), + !atomic_long_read(&sbi->ll_cache->ccc_unstable_nr), &lwi); } - ccc_count = atomic_read(&sbi->ll_cache->ccc_unstable_nr); + ccc_count = atomic_long_read(&sbi->ll_cache->ccc_unstable_nr); if (!force && rc != -EINTR) - LASSERTF(!ccc_count, "count: %i\n", ccc_count); + LASSERTF(!ccc_count, "count: %li\n", ccc_count); /* We need to set force before the lov_disconnect in * lustre_common_put_super, since l_d cleans up osc's as well. @@ -991,6 +1057,206 @@ struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock) return inode; } +static void ll_dir_clear_lsm_md(struct inode *inode) +{ + struct ll_inode_info *lli = ll_i2info(inode); + + LASSERT(S_ISDIR(inode->i_mode)); + + if (lli->lli_lsm_md) { + lmv_free_memmd(lli->lli_lsm_md); + lli->lli_lsm_md = NULL; + } +} + +static struct inode *ll_iget_anon_dir(struct super_block *sb, + const struct lu_fid *fid, + struct lustre_md *md) +{ + struct ll_sb_info *sbi = ll_s2sbi(sb); + struct mdt_body *body = md->body; + struct inode *inode; + ino_t ino; + + ino = cl_fid_build_ino(fid, sbi->ll_flags & LL_SBI_32BIT_API); + inode = iget_locked(sb, ino); + if (!inode) { + CERROR("%s: failed get simple inode "DFID": rc = -ENOENT\n", + ll_get_fsname(sb, NULL, 0), PFID(fid)); + return ERR_PTR(-ENOENT); + } + + if (inode->i_state & I_NEW) { + struct ll_inode_info *lli = ll_i2info(inode); + struct lmv_stripe_md *lsm = md->lmv; + + inode->i_mode = (inode->i_mode & ~S_IFMT) | + (body->mbo_mode & S_IFMT); + LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode "DFID"\n", + PFID(fid)); + + LTIME_S(inode->i_mtime) = 0; + LTIME_S(inode->i_atime) = 0; + LTIME_S(inode->i_ctime) = 0; + inode->i_rdev = 0; + + inode->i_op = &ll_dir_inode_operations; + inode->i_fop = &ll_dir_operations; + lli->lli_fid = *fid; + ll_lli_init(lli); + + LASSERT(lsm); + /* master object FID */ + lli->lli_pfid = body->mbo_fid1; + CDEBUG(D_INODE, "lli %p slave "DFID" master "DFID"\n", + lli, PFID(fid), PFID(&lli->lli_pfid)); + unlock_new_inode(inode); + } + + return inode; +} + +static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) +{ + struct lmv_stripe_md *lsm = md->lmv; + struct lu_fid *fid; + int i; + + LASSERT(lsm); + /* + * XXX sigh, this lsm_root initialization should be in + * LMV layer, but it needs ll_iget right now, so we + * put this here right now. + */ + for (i = 0; i < lsm->lsm_md_stripe_count; i++) { + fid = &lsm->lsm_md_oinfo[i].lmo_fid; + LASSERT(!lsm->lsm_md_oinfo[i].lmo_root); + /* Unfortunately ll_iget will call ll_update_inode, + * where the initialization of slave inode is slightly + * different, so it reset lsm_md to NULL to avoid + * initializing lsm for slave inode. + */ + /* For migrating inode, master stripe and master object will + * be same, so we only need assign this inode + */ + if (lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION && !i) + lsm->lsm_md_oinfo[i].lmo_root = inode; + else + lsm->lsm_md_oinfo[i].lmo_root = + ll_iget_anon_dir(inode->i_sb, fid, md); + if (IS_ERR(lsm->lsm_md_oinfo[i].lmo_root)) { + int rc = PTR_ERR(lsm->lsm_md_oinfo[i].lmo_root); + + lsm->lsm_md_oinfo[i].lmo_root = NULL; + return rc; + } + } + + return 0; +} + +static inline int lli_lsm_md_eq(const struct lmv_stripe_md *lsm_md1, + const struct lmv_stripe_md *lsm_md2) +{ + return lsm_md1->lsm_md_magic == lsm_md2->lsm_md_magic && + lsm_md1->lsm_md_stripe_count == lsm_md2->lsm_md_stripe_count && + lsm_md1->lsm_md_master_mdt_index == + lsm_md2->lsm_md_master_mdt_index && + lsm_md1->lsm_md_hash_type == lsm_md2->lsm_md_hash_type && + lsm_md1->lsm_md_layout_version == + lsm_md2->lsm_md_layout_version && + !strcmp(lsm_md1->lsm_md_pool_name, + lsm_md2->lsm_md_pool_name); +} + +static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) +{ + struct ll_inode_info *lli = ll_i2info(inode); + struct lmv_stripe_md *lsm = md->lmv; + int rc; + + LASSERT(S_ISDIR(inode->i_mode)); + CDEBUG(D_INODE, "update lsm %p of "DFID"\n", lli->lli_lsm_md, + PFID(ll_inode2fid(inode))); + + /* no striped information from request. */ + if (!lsm) { + if (!lli->lli_lsm_md) { + return 0; + } else if (lli->lli_lsm_md->lsm_md_hash_type & + LMV_HASH_FLAG_MIGRATION) { + /* + * migration is done, the temporay MIGRATE layout has + * been removed + */ + CDEBUG(D_INODE, DFID" finish migration.\n", + PFID(ll_inode2fid(inode))); + lmv_free_memmd(lli->lli_lsm_md); + lli->lli_lsm_md = NULL; + return 0; + } else { + /* + * The lustre_md from req does not include stripeEA, + * see ll_md_setattr + */ + return 0; + } + } + + /* set the directory layout */ + if (!lli->lli_lsm_md) { + rc = ll_init_lsm_md(inode, md); + if (rc) + return rc; + + lli->lli_lsm_md = lsm; + /* + * set lsm_md to NULL, so the following free lustre_md + * will not free this lsm + */ + md->lmv = NULL; + CDEBUG(D_INODE, "Set lsm %p magic %x to "DFID"\n", lsm, + lsm->lsm_md_magic, PFID(ll_inode2fid(inode))); + return 0; + } + + /* Compare the old and new stripe information */ + if (!lsm_md_eq(lli->lli_lsm_md, lsm)) { + struct lmv_stripe_md *old_lsm = lli->lli_lsm_md; + int idx; + + CERROR("%s: inode "DFID"(%p)'s lmv layout mismatch (%p)/(%p) magic:0x%x/0x%x stripe count: %d/%d master_mdt: %d/%d hash_type:0x%x/0x%x layout: 0x%x/0x%x pool:%s/%s\n", + ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), + inode, lsm, old_lsm, + lsm->lsm_md_magic, old_lsm->lsm_md_magic, + lsm->lsm_md_stripe_count, + old_lsm->lsm_md_stripe_count, + lsm->lsm_md_master_mdt_index, + old_lsm->lsm_md_master_mdt_index, + lsm->lsm_md_hash_type, old_lsm->lsm_md_hash_type, + lsm->lsm_md_layout_version, + old_lsm->lsm_md_layout_version, + lsm->lsm_md_pool_name, + old_lsm->lsm_md_pool_name); + + for (idx = 0; idx < old_lsm->lsm_md_stripe_count; idx++) { + CERROR("%s: sub FIDs in old lsm idx %d, old: "DFID"\n", + ll_get_fsname(inode->i_sb, NULL, 0), idx, + PFID(&old_lsm->lsm_md_oinfo[idx].lmo_fid)); + } + + for (idx = 0; idx < lsm->lsm_md_stripe_count; idx++) { + CERROR("%s: sub FIDs in new lsm idx %d, new: "DFID"\n", + ll_get_fsname(inode->i_sb, NULL, 0), idx, + PFID(&lsm->lsm_md_oinfo[idx].lmo_fid)); + } + + return -EIO; + } + + return 0; +} + void ll_clear_inode(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); @@ -1031,14 +1297,15 @@ void ll_clear_inode(struct inode *inode) #ifdef CONFIG_FS_POSIX_ACL if (lli->lli_posix_acl) { - LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) == 1); posix_acl_release(lli->lli_posix_acl); lli->lli_posix_acl = NULL; } #endif lli->lli_inode_magic = LLI_INODE_DEAD; - if (!S_ISDIR(inode->i_mode)) + if (S_ISDIR(inode->i_mode)) + ll_dir_clear_lsm_md(inode); + if (S_ISREG(inode->i_mode) && !is_bad_inode(inode)) LASSERT(list_empty(&lli->lli_agl_list)); /* @@ -1103,10 +1370,10 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, op_data->op_attr.ia_valid = ia_valid; /* Extract epoch data if obtained. */ - op_data->op_handle = md.body->handle; - op_data->op_ioepoch = md.body->ioepoch; + op_data->op_handle = md.body->mbo_handle; + op_data->op_ioepoch = md.body->mbo_ioepoch; - ll_update_inode(inode, &md); + rc = ll_update_inode(inode, &md); ptlrpc_req_finished(request); return rc; @@ -1138,8 +1405,8 @@ static int ll_setattr_done_writing(struct inode *inode, rc = ll_som_update(inode, op_data); else if (rc) { CERROR("%s: inode "DFID" mdc truncate failed: rc = %d\n", - ll_i2sbi(inode)->ll_md_exp->exp_obd->obd_name, - PFID(ll_inode2fid(inode)), rc); + ll_i2sbi(inode)->ll_md_exp->exp_obd->obd_name, + PFID(ll_inode2fid(inode)), rc); } return rc; } @@ -1331,14 +1598,14 @@ int ll_setattr(struct dentry *de, struct iattr *attr) { int mode = d_inode(de)->i_mode; - if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) == - (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) + if ((attr->ia_valid & (ATTR_CTIME | ATTR_SIZE | ATTR_MODE)) == + (ATTR_CTIME | ATTR_SIZE | ATTR_MODE)) attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; - if (((attr->ia_valid & (ATTR_MODE|ATTR_FORCE|ATTR_SIZE)) == - (ATTR_SIZE|ATTR_MODE)) && + if (((attr->ia_valid & (ATTR_MODE | ATTR_FORCE | ATTR_SIZE)) == + (ATTR_SIZE | ATTR_MODE)) && (((mode & S_ISUID) && !(attr->ia_mode & S_ISUID)) || - (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && + (((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) && !(attr->ia_mode & S_ISGID)))) attr->ia_valid |= ATTR_FORCE; @@ -1349,7 +1616,7 @@ int ll_setattr(struct dentry *de, struct iattr *attr) attr->ia_valid |= ATTR_KILL_SUID; if ((attr->ia_valid & ATTR_MODE) && - ((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && + ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) && !(attr->ia_mode & S_ISGID) && !(attr->ia_valid & ATTR_KILL_SGID)) attr->ia_valid |= ATTR_KILL_SGID; @@ -1465,14 +1732,14 @@ void ll_inode_size_unlock(struct inode *inode) mutex_unlock(&lli->lli_size_mutex); } -void ll_update_inode(struct inode *inode, struct lustre_md *md) +int ll_update_inode(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); struct mdt_body *body = md->body; struct lov_stripe_md *lsm = md->lsm; struct ll_sb_info *sbi = ll_i2sbi(inode); - LASSERT((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0)); + LASSERT((lsm != NULL) == ((body->mbo_valid & OBD_MD_FLEASIZE) != 0)); if (lsm) { if (!lli->lli_has_smd && !(sbi->ll_flags & LL_SBI_LAYOUT_LOCK)) @@ -1483,8 +1750,16 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) lli->lli_maxbytes = MAX_LFS_FILESIZE; } + if (S_ISDIR(inode->i_mode)) { + int rc; + + rc = ll_update_lsm_md(inode, md); + if (rc) + return rc; + } + #ifdef CONFIG_FS_POSIX_ACL - if (body->valid & OBD_MD_FLACL) { + if (body->mbo_valid & OBD_MD_FLACL) { spin_lock(&lli->lli_lock); if (lli->lli_posix_acl) posix_acl_release(lli->lli_posix_acl); @@ -1492,65 +1767,67 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) spin_unlock(&lli->lli_lock); } #endif - inode->i_ino = cl_fid_build_ino(&body->fid1, + inode->i_ino = cl_fid_build_ino(&body->mbo_fid1, sbi->ll_flags & LL_SBI_32BIT_API); - inode->i_generation = cl_fid_build_gen(&body->fid1); + inode->i_generation = cl_fid_build_gen(&body->mbo_fid1); - if (body->valid & OBD_MD_FLATIME) { - if (body->atime > LTIME_S(inode->i_atime)) - LTIME_S(inode->i_atime) = body->atime; - lli->lli_atime = body->atime; + if (body->mbo_valid & OBD_MD_FLATIME) { + if (body->mbo_atime > LTIME_S(inode->i_atime)) + LTIME_S(inode->i_atime) = body->mbo_atime; + lli->lli_atime = body->mbo_atime; } - if (body->valid & OBD_MD_FLMTIME) { - if (body->mtime > LTIME_S(inode->i_mtime)) { + if (body->mbo_valid & OBD_MD_FLMTIME) { + if (body->mbo_mtime > LTIME_S(inode->i_mtime)) { CDEBUG(D_INODE, "setting ino %lu mtime from %lu to %llu\n", inode->i_ino, LTIME_S(inode->i_mtime), - body->mtime); - LTIME_S(inode->i_mtime) = body->mtime; + body->mbo_mtime); + LTIME_S(inode->i_mtime) = body->mbo_mtime; } - lli->lli_mtime = body->mtime; + lli->lli_mtime = body->mbo_mtime; } - if (body->valid & OBD_MD_FLCTIME) { - if (body->ctime > LTIME_S(inode->i_ctime)) - LTIME_S(inode->i_ctime) = body->ctime; - lli->lli_ctime = body->ctime; + if (body->mbo_valid & OBD_MD_FLCTIME) { + if (body->mbo_ctime > LTIME_S(inode->i_ctime)) + LTIME_S(inode->i_ctime) = body->mbo_ctime; + lli->lli_ctime = body->mbo_ctime; } - if (body->valid & OBD_MD_FLMODE) - inode->i_mode = (inode->i_mode & S_IFMT)|(body->mode & ~S_IFMT); - if (body->valid & OBD_MD_FLTYPE) - inode->i_mode = (inode->i_mode & ~S_IFMT)|(body->mode & S_IFMT); + if (body->mbo_valid & OBD_MD_FLMODE) + inode->i_mode = (inode->i_mode & S_IFMT) | + (body->mbo_mode & ~S_IFMT); + if (body->mbo_valid & OBD_MD_FLTYPE) + inode->i_mode = (inode->i_mode & ~S_IFMT) | + (body->mbo_mode & S_IFMT); LASSERT(inode->i_mode != 0); if (S_ISREG(inode->i_mode)) inode->i_blkbits = min(PTLRPC_MAX_BRW_BITS + 1, LL_MAX_BLKSIZE_BITS); else inode->i_blkbits = inode->i_sb->s_blocksize_bits; - if (body->valid & OBD_MD_FLUID) - inode->i_uid = make_kuid(&init_user_ns, body->uid); - if (body->valid & OBD_MD_FLGID) - inode->i_gid = make_kgid(&init_user_ns, body->gid); - if (body->valid & OBD_MD_FLFLAGS) - inode->i_flags = ll_ext_to_inode_flags(body->flags); - if (body->valid & OBD_MD_FLNLINK) - set_nlink(inode, body->nlink); - if (body->valid & OBD_MD_FLRDEV) - inode->i_rdev = old_decode_dev(body->rdev); + if (body->mbo_valid & OBD_MD_FLUID) + inode->i_uid = make_kuid(&init_user_ns, body->mbo_uid); + if (body->mbo_valid & OBD_MD_FLGID) + inode->i_gid = make_kgid(&init_user_ns, body->mbo_gid); + if (body->mbo_valid & OBD_MD_FLFLAGS) + inode->i_flags = ll_ext_to_inode_flags(body->mbo_flags); + if (body->mbo_valid & OBD_MD_FLNLINK) + set_nlink(inode, body->mbo_nlink); + if (body->mbo_valid & OBD_MD_FLRDEV) + inode->i_rdev = old_decode_dev(body->mbo_rdev); - if (body->valid & OBD_MD_FLID) { + if (body->mbo_valid & OBD_MD_FLID) { /* FID shouldn't be changed! */ if (fid_is_sane(&lli->lli_fid)) { - LASSERTF(lu_fid_eq(&lli->lli_fid, &body->fid1), + LASSERTF(lu_fid_eq(&lli->lli_fid, &body->mbo_fid1), "Trying to change FID "DFID" to the "DFID", inode "DFID"(%p)\n", - PFID(&lli->lli_fid), PFID(&body->fid1), + PFID(&lli->lli_fid), PFID(&body->mbo_fid1), PFID(ll_inode2fid(inode)), inode); } else { - lli->lli_fid = body->fid1; + lli->lli_fid = body->mbo_fid1; } } LASSERT(fid_seq(&lli->lli_fid) != 0); - if (body->valid & OBD_MD_FLSIZE) { + if (body->mbo_valid & OBD_MD_FLSIZE) { if (exp_connect_som(ll_i2mdexp(inode)) && S_ISREG(inode->i_mode)) { struct lustre_handle lockh; @@ -1577,7 +1854,7 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) /* Use old size assignment to avoid * deadlock bz14138 & bz14326 */ - i_size_write(inode, body->size); + i_size_write(inode, body->mbo_size); spin_lock(&lli->lli_lock); lli->lli_flags |= LLIF_MDS_SIZE_LOCK; spin_unlock(&lli->lli_lock); @@ -1588,26 +1865,29 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) /* Use old size assignment to avoid * deadlock bz14138 & bz14326 */ - i_size_write(inode, body->size); + i_size_write(inode, body->mbo_size); CDEBUG(D_VFSTRACE, "inode=%lu, updating i_size %llu\n", - inode->i_ino, (unsigned long long)body->size); + inode->i_ino, (unsigned long long)body->mbo_size); } - if (body->valid & OBD_MD_FLBLOCKS) - inode->i_blocks = body->blocks; + if (body->mbo_valid & OBD_MD_FLBLOCKS) + inode->i_blocks = body->mbo_blocks; } - if (body->valid & OBD_MD_TSTATE) { - if (body->t_state & MS_RESTORE) + if (body->mbo_valid & OBD_MD_TSTATE) { + if (body->mbo_t_state & MS_RESTORE) lli->lli_flags |= LLIF_FILE_RESTORING; } + + return 0; } -void ll_read_inode2(struct inode *inode, void *opaque) +int ll_read_inode2(struct inode *inode, void *opaque) { struct lustre_md *md = opaque; struct ll_inode_info *lli = ll_i2info(inode); + int rc; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", PFID(&lli->lli_fid), inode); @@ -1623,7 +1903,9 @@ void ll_read_inode2(struct inode *inode, void *opaque) LTIME_S(inode->i_atime) = 0; LTIME_S(inode->i_ctime) = 0; inode->i_rdev = 0; - ll_update_inode(inode, md); + rc = ll_update_inode(inode, md); + if (rc) + return rc; /* OIDEBUG(inode); */ @@ -1644,6 +1926,8 @@ void ll_read_inode2(struct inode *inode, void *opaque) init_special_inode(inode, inode->i_mode, inode->i_rdev); } + + return 0; } void ll_delete_inode(struct inode *inode) @@ -1655,20 +1939,13 @@ void ll_delete_inode(struct inode *inode) * osc_extent implementation at LU-1030. */ cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, - CL_FSYNC_DISCARD, 1); + CL_FSYNC_LOCAL, 1); truncate_inode_pages_final(&inode->i_data); - /* Workaround for LU-118 */ - if (inode->i_data.nrpages) { - spin_lock_irq(&inode->i_data.tree_lock); - spin_unlock_irq(&inode->i_data.tree_lock); - LASSERTF(inode->i_data.nrpages == 0, - "inode="DFID"(%p) nrpages=%lu, see http://jira.whamcloud.com/browse/LU-118\n", - PFID(ll_inode2fid(inode)), inode, - inode->i_data.nrpages); - } - /* Workaround end */ + LASSERTF(!inode->i_data.nrpages, + "inode=" DFID "(%p) nrpages=%lu, see http://jira.whamcloud.com/browse/LU-118\n", + PFID(ll_inode2fid(inode)), inode, inode->i_data.nrpages); ll_clear_inode(inode); clear_inode(inode); @@ -1704,7 +1981,7 @@ int ll_iocontrol(struct inode *inode, struct file *file, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - flags = body->flags; + flags = body->mbo_flags; ptlrpc_req_finished(req); @@ -1886,9 +2163,9 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req) if (!op_data) return; - op_data->op_fid1 = body->fid1; - op_data->op_ioepoch = body->ioepoch; - op_data->op_handle = body->handle; + op_data->op_fid1 = body->mbo_fid1; + op_data->op_ioepoch = body->mbo_ioepoch; + op_data->op_handle = body->mbo_handle; op_data->op_mod_time = get_seconds(); md_close(exp, op_data, NULL, &close_req); ptlrpc_req_finished(close_req); @@ -1910,7 +2187,9 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, goto cleanup; if (*inode) { - ll_update_inode(*inode, &md); + rc = ll_update_inode(*inode, &md); + if (rc) + goto out; } else { LASSERT(sb); @@ -1918,18 +2197,18 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, * At this point server returns to client's same fid as client * generated for creating. So using ->fid1 is okay here. */ - if (!fid_is_sane(&md.body->fid1)) { + if (!fid_is_sane(&md.body->mbo_fid1)) { CERROR("%s: Fid is insane " DFID "\n", ll_get_fsname(sb, NULL, 0), - PFID(&md.body->fid1)); + PFID(&md.body->mbo_fid1)); rc = -EINVAL; goto out; } - *inode = ll_iget(sb, cl_fid_build_ino(&md.body->fid1, + *inode = ll_iget(sb, cl_fid_build_ino(&md.body->mbo_fid1, sbi->ll_flags & LL_SBI_32BIT_API), &md); - if (!*inode) { + if (IS_ERR(*inode)) { #ifdef CONFIG_FS_POSIX_ACL if (md.posix_acl) { posix_acl_release(md.posix_acl); @@ -2075,11 +2354,20 @@ int ll_process_config(struct lustre_cfg *lcfg) /* this function prepares md_op_data hint for passing ot down to MD stack. */ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, struct inode *i1, struct inode *i2, - const char *name, int namelen, - int mode, __u32 opc, void *data) + const char *name, size_t namelen, + u32 mode, __u32 opc, void *data) { - if (namelen > ll_i2sbi(i1)->ll_namelen) - return ERR_PTR(-ENAMETOOLONG); + if (!name) { + /* Do not reuse namelen for something else. */ + if (namelen) + return ERR_PTR(-EINVAL); + } else { + if (namelen > ll_i2sbi(i1)->ll_namelen) + return ERR_PTR(-ENAMETOOLONG); + + if (!lu_name_is_valid_2(name, namelen)) + return ERR_PTR(-EINVAL); + } if (!op_data) op_data = kzalloc(sizeof(*op_data), GFP_NOFS); @@ -2089,11 +2377,26 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, ll_i2gids(op_data->op_suppgids, i1, i2); op_data->op_fid1 = *ll_inode2fid(i1); + op_data->op_default_stripe_offset = -1; + if (S_ISDIR(i1->i_mode)) { + op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md; + op_data->op_default_stripe_offset = + ll_i2info(i1)->lli_def_stripe_offset; + } - if (i2) + if (i2) { op_data->op_fid2 = *ll_inode2fid(i2); - else + if (S_ISDIR(i2->i_mode)) + op_data->op_mea2 = ll_i2info(i2)->lli_lsm_md; + } else { fid_zero(&op_data->op_fid2); + } + + if (ll_i2sbi(i1)->ll_flags & LL_SBI_64BIT_HASH) + op_data->op_cli_flags |= CLI_HASH64; + + if (ll_need_32bit_api(ll_i2sbi(i1))) + op_data->op_cli_flags |= CLI_API32; op_data->op_name = name; op_data->op_namelen = namelen; @@ -2105,26 +2408,12 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, op_data->op_bias = 0; op_data->op_cli_flags = 0; if ((opc == LUSTRE_OPC_CREATE) && name && - filename_is_volatile(name, namelen, NULL)) + filename_is_volatile(name, namelen, &op_data->op_mds)) op_data->op_bias |= MDS_CREATE_VOLATILE; - op_data->op_opc = opc; - op_data->op_mds = 0; + else + op_data->op_mds = 0; op_data->op_data = data; - /* If the file is being opened after mknod() (normally due to NFS) - * try to use the default stripe data from parent directory for - * allocating OST objects. Try to pass the parent FID to MDS. - */ - if (opc == LUSTRE_OPC_CREATE && i1 == i2 && S_ISREG(i2->i_mode) && - !ll_i2info(i2)->lli_has_smd) { - struct ll_inode_info *lli = ll_i2info(i2); - - spin_lock(&lli->lli_lock); - if (likely(!lli->lli_has_smd && !fid_is_zero(&lli->lli_pfid))) - op_data->op_fid1 = lli->lli_pfid; - spin_unlock(&lli->lli_lock); - } - /* When called by ll_setattr_raw, file is i1. */ if (ll_i2info(i1)->lli_flags & LLIF_DATA_MODIFIED) op_data->op_bias |= MDS_DATA_MODIFIED; @@ -2251,3 +2540,197 @@ void ll_dirty_page_discard_warn(struct page *page, int ioret) if (buf) free_page((unsigned long)buf); } + +ssize_t ll_copy_user_md(const struct lov_user_md __user *md, + struct lov_user_md **kbuf) +{ + struct lov_user_md lum; + ssize_t lum_size; + + if (copy_from_user(&lum, md, sizeof(lum))) { + lum_size = -EFAULT; + goto no_kbuf; + } + + lum_size = ll_lov_user_md_size(&lum); + if (lum_size < 0) + goto no_kbuf; + + *kbuf = kzalloc(lum_size, GFP_NOFS); + if (!*kbuf) { + lum_size = -ENOMEM; + goto no_kbuf; + } + + if (copy_from_user(*kbuf, md, lum_size) != 0) { + kfree(*kbuf); + *kbuf = NULL; + lum_size = -EFAULT; + } +no_kbuf: + return lum_size; +} + +/* + * Compute llite root squash state after a change of root squash + * configuration setting or add/remove of a lnet nid + */ +void ll_compute_rootsquash_state(struct ll_sb_info *sbi) +{ + struct root_squash_info *squash = &sbi->ll_squash; + lnet_process_id_t id; + bool matched; + int i; + + /* Update norootsquash flag */ + down_write(&squash->rsi_sem); + if (list_empty(&squash->rsi_nosquash_nids)) { + sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH; + } else { + /* + * Do not apply root squash as soon as one of our NIDs is + * in the nosquash_nids list + */ + matched = false; + i = 0; + + while (LNetGetId(i++, &id) != -ENOENT) { + if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND) + continue; + if (cfs_match_nid(id.nid, &squash->rsi_nosquash_nids)) { + matched = true; + break; + } + } + if (matched) + sbi->ll_flags |= LL_SBI_NOROOTSQUASH; + else + sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH; + } + up_write(&squash->rsi_sem); +} + +/** + * Parse linkea content to extract information about a given hardlink + * + * \param[in] ldata - Initialized linkea data + * \param[in] linkno - Link identifier + * \param[out] parent_fid - The entry's parent FID + * \param[in] size - Entry name destination buffer + * + * \retval 0 on success + * \retval Appropriate negative error code on failure + */ +static int ll_linkea_decode(struct linkea_data *ldata, unsigned int linkno, + struct lu_fid *parent_fid, struct lu_name *ln) +{ + unsigned int idx; + int rc; + + rc = linkea_init(ldata); + if (rc < 0) + return rc; + + if (linkno >= ldata->ld_leh->leh_reccount) + /* beyond last link */ + return -ENODATA; + + linkea_first_entry(ldata); + for (idx = 0; ldata->ld_lee; idx++) { + linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, ln, + parent_fid); + if (idx == linkno) + break; + + linkea_next_entry(ldata); + } + + if (idx < linkno) + return -ENODATA; + + return 0; +} + +/** + * Get parent FID and name of an identified link. Operation is performed for + * a given link number, letting the caller iterate over linkno to list one or + * all links of an entry. + * + * \param[in] file - File descriptor against which to perform the operation + * \param[in,out] arg - User-filled structure containing the linkno to operate + * on and the available size. It is eventually filled with + * the requested information or left untouched on error + * + * \retval - 0 on success + * \retval - Appropriate negative error code on failure + */ +int ll_getparent(struct file *file, struct getparent __user *arg) +{ + struct inode *inode = file_inode(file); + struct linkea_data *ldata; + struct lu_fid parent_fid; + struct lu_buf buf = { + .lb_buf = NULL, + .lb_len = 0 + }; + struct lu_name ln; + u32 name_size; + u32 linkno; + int rc; + + if (!capable(CFS_CAP_DAC_READ_SEARCH) && + !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH)) + return -EPERM; + + if (get_user(name_size, &arg->gp_name_size)) + return -EFAULT; + + if (get_user(linkno, &arg->gp_linkno)) + return -EFAULT; + + if (name_size > PATH_MAX) + return -EINVAL; + + ldata = kzalloc(sizeof(*ldata), GFP_NOFS); + if (!ldata) + return -ENOMEM; + + rc = linkea_data_new(ldata, &buf); + if (rc < 0) + goto ldata_free; + + rc = ll_xattr_list(inode, XATTR_NAME_LINK, XATTR_TRUSTED_T, buf.lb_buf, + buf.lb_len, OBD_MD_FLXATTR); + if (rc < 0) + goto lb_free; + + rc = ll_linkea_decode(ldata, linkno, &parent_fid, &ln); + if (rc < 0) + goto lb_free; + + if (ln.ln_namelen >= name_size) { + rc = -EOVERFLOW; + goto lb_free; + } + + if (copy_to_user(&arg->gp_fid, &parent_fid, sizeof(arg->gp_fid))) { + rc = -EFAULT; + goto lb_free; + } + + if (copy_to_user(&arg->gp_name, ln.ln_name, ln.ln_namelen)) { + rc = -EFAULT; + goto lb_free; + } + + if (put_user('\0', arg->gp_name + ln.ln_namelen)) { + rc = -EFAULT; + goto lb_free; + } + +lb_free: + lu_buf_free(&buf); +ldata_free: + kfree(ldata); + return rc; +} diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 66ee5db5fce8..436691814a5e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -43,9 +43,7 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" -#include "../include/linux/lustre_compat25.h" static const struct vm_operations_struct ll_file_vm_ops; @@ -126,7 +124,7 @@ restart: fio = &io->u.ci_fault; fio->ft_index = index; - fio->ft_executable = vma->vm_flags&VM_EXEC; + fio->ft_executable = vma->vm_flags & VM_EXEC; /* * disable VM_SEQ_READ and use VM_RAND_READ to make sure that @@ -134,7 +132,7 @@ restart: * filemap_nopage. we do our readahead in ll_readpage. */ if (ra_flags) - *ra_flags = vma->vm_flags & (VM_RAND_READ|VM_SEQ_READ); + *ra_flags = vma->vm_flags & (VM_RAND_READ | VM_SEQ_READ); vma->vm_flags &= ~VM_SEQ_READ; vma->vm_flags |= VM_RAND_READ; @@ -429,7 +427,6 @@ static void ll_vm_open(struct vm_area_struct *vma) struct inode *inode = file_inode(vma->vm_file); struct vvp_object *vob = cl_inode2vvp(inode); - LASSERT(vma->vm_file); LASSERT(atomic_read(&vob->vob_mmap_cnt) >= 0); atomic_inc(&vob->vob_mmap_cnt); } @@ -442,7 +439,6 @@ static void ll_vm_close(struct vm_area_struct *vma) struct inode *inode = file_inode(vma->vm_file); struct vvp_object *vob = cl_inode2vvp(inode); - LASSERT(vma->vm_file); atomic_dec(&vob->vob_mmap_cnt); LASSERT(atomic_read(&vob->vob_mmap_cnt) >= 0); } diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 65972c892731..709230571b4b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -38,7 +38,6 @@ */ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" #include @@ -73,11 +72,6 @@ void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid) fsid->val[1] = key >> 32; } -static int ll_nfs_test_inode(struct inode *inode, void *opaque) -{ - return lu_fid_eq(&ll_i2info(inode)->lli_fid, opaque); -} - struct inode *search_inode_for_lustre(struct super_block *sb, const struct lu_fid *fid) { @@ -92,7 +86,7 @@ struct inode *search_inode_for_lustre(struct super_block *sb, CDEBUG(D_INFO, "searching inode for:(%lu,"DFID")\n", hash, PFID(fid)); - inode = ilookup5(sb, hash, ll_nfs_test_inode, (void *)fid); + inode = ilookup5(sb, hash, ll_test_inode_by_fid, (void *)fid); if (inode) return inode; @@ -153,12 +147,18 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren return ERR_PTR(-ESTALE); } + result = d_obtain_alias(inode); + if (IS_ERR(result)) { + iput(inode); + return result; + } + /** - * It is an anonymous dentry without OST objects created yet. - * We have to find the parent to tell MDS how to init lov objects. + * In case d_obtain_alias() found a disconnected dentry, always update + * lli_pfid to allow later operation (normally open) have parent fid, + * which may be used by MDS to create data. */ - if (S_ISREG(inode->i_mode) && !ll_i2info(inode)->lli_has_smd && - parent && !fid_is_zero(parent)) { + if (parent) { struct ll_inode_info *lli = ll_i2info(inode); spin_lock(&lli->lli_lock); @@ -255,6 +255,8 @@ static int ll_get_name(struct dentry *dentry, char *name, .lgd_fid = ll_i2info(d_inode(child))->lli_fid, .ctx.actor = ll_nfs_get_name_filldir, }; + struct md_op_data *op_data; + __u64 pos = 0; if (!dir || !S_ISDIR(dir->i_mode)) { rc = -ENOTDIR; @@ -266,9 +268,18 @@ static int ll_get_name(struct dentry *dentry, char *name, goto out; } + op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, + LUSTRE_OPC_ANY, dir); + if (IS_ERR(op_data)) { + rc = PTR_ERR(op_data); + goto out; + } + + op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; inode_lock(dir); - rc = ll_dir_read(dir, &lgd.ctx); + rc = ll_dir_read(dir, &pos, op_data, &lgd.ctx); inode_unlock(dir); + ll_finish_md_op_data(op_data); if (!rc && !lgd.lgd_found) rc = -ENOENT; out: @@ -297,14 +308,12 @@ static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid, return ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL); } -static struct dentry *ll_get_parent(struct dentry *dchild) +int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid) { struct ptlrpc_request *req = NULL; - struct inode *dir = d_inode(dchild); struct ll_sb_info *sbi; - struct dentry *result = NULL; struct mdt_body *body; - static char dotdot[] = ".."; + static const char dotdot[] = ".."; struct md_op_data *op_data; int rc; int lmmsize; @@ -319,13 +328,13 @@ static struct dentry *ll_get_parent(struct dentry *dchild) rc = ll_get_default_mdsize(sbi, &lmmsize); if (rc != 0) - return ERR_PTR(rc); + return rc; op_data = ll_prep_md_op_data(NULL, dir, NULL, dotdot, strlen(dotdot), lmmsize, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) - return (void *)op_data; + return PTR_ERR(op_data); rc = md_getattr_name(sbi->ll_md_exp, op_data, &req); ll_finish_md_op_data(op_data); @@ -333,21 +342,36 @@ static struct dentry *ll_get_parent(struct dentry *dchild) CERROR("%s: failure inode "DFID" get parent: rc = %d\n", ll_get_fsname(dir->i_sb, NULL, 0), PFID(ll_inode2fid(dir)), rc); - return ERR_PTR(rc); + return rc; } body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); /* * LU-3952: MDT may lost the FID of its parent, we should not crash * the NFS server, ll_iget_for_nfs() will handle the error. */ - if (body->valid & OBD_MD_FLID) { + if (body->mbo_valid & OBD_MD_FLID) { CDEBUG(D_INFO, "parent for " DFID " is " DFID "\n", - PFID(ll_inode2fid(dir)), PFID(&body->fid1)); + PFID(ll_inode2fid(dir)), PFID(&body->mbo_fid1)); + *parent_fid = body->mbo_fid1; } - result = ll_iget_for_nfs(dir->i_sb, &body->fid1, NULL); ptlrpc_req_finished(req); - return result; + return 0; +} + +static struct dentry *ll_get_parent(struct dentry *dchild) +{ + struct lu_fid parent_fid = { 0 }; + struct dentry *dentry; + int rc; + + rc = ll_dir_get_parent_fid(dchild->d_inode, &parent_fid); + if (rc) + return ERR_PTR(rc); + + dentry = ll_iget_for_nfs(dchild->d_inode->i_sb, &parent_fid, NULL); + + return dentry; } const struct export_operations lustre_export_operations = { diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index e86bf3c53be3..6eae60595905 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -31,7 +31,6 @@ */ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "../include/lprocfs_status.h" #include #include "../include/obd_support.h" @@ -358,16 +357,16 @@ static int ll_max_cached_mb_seq_show(struct seq_file *m, void *v) struct ll_sb_info *sbi = ll_s2sbi(sb); struct cl_client_cache *cache = sbi->ll_cache; int shift = 20 - PAGE_SHIFT; - int max_cached_mb; - int unused_mb; + long max_cached_mb; + long unused_mb; max_cached_mb = cache->ccc_lru_max >> shift; - unused_mb = atomic_read(&cache->ccc_lru_left) >> shift; + unused_mb = atomic_long_read(&cache->ccc_lru_left) >> shift; seq_printf(m, "users: %d\n" - "max_cached_mb: %d\n" - "used_mb: %d\n" - "unused_mb: %d\n" + "max_cached_mb: %ld\n" + "used_mb: %ld\n" + "unused_mb: %ld\n" "reclaim_count: %u\n", atomic_read(&cache->ccc_users), max_cached_mb, @@ -385,10 +384,13 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, struct ll_sb_info *sbi = ll_s2sbi(sb); struct cl_client_cache *cache = sbi->ll_cache; struct lu_env *env; + long diff = 0; + long nrpages = 0; int refcheck; - int mult, rc, pages_number; - int diff = 0; - int nrpages = 0; + long pages_number; + int mult; + long rc; + u64 val; char kernbuf[128]; if (count >= sizeof(kernbuf)) @@ -401,10 +403,14 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, mult = 1 << (20 - PAGE_SHIFT); buffer += lprocfs_find_named_value(kernbuf, "max_cached_mb:", &count) - kernbuf; - rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult); + rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult); if (rc) return rc; + if (val > LONG_MAX) + return -ERANGE; + pages_number = (long)val; + if (pages_number < 0 || pages_number > totalram_pages) { CERROR("%s: can't set max cache more than %lu MB\n", ll_get_fsname(sb, NULL, 0), @@ -418,7 +424,7 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, /* easy - add more LRU slots. */ if (diff >= 0) { - atomic_add(diff, &cache->ccc_lru_left); + atomic_long_add(diff, &cache->ccc_lru_left); rc = 0; goto out; } @@ -429,18 +435,18 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, diff = -diff; while (diff > 0) { - int tmp; + long tmp; /* reduce LRU budget from free slots. */ do { - int ov, nv; + long ov, nv; - ov = atomic_read(&cache->ccc_lru_left); + ov = atomic_long_read(&cache->ccc_lru_left); if (ov == 0) break; nv = ov > diff ? ov - diff : 0; - rc = atomic_cmpxchg(&cache->ccc_lru_left, ov, nv); + rc = atomic_long_cmpxchg(&cache->ccc_lru_left, ov, nv); if (likely(ov == rc)) { diff -= ov - nv; nrpages += ov - nv; @@ -474,7 +480,7 @@ out: spin_unlock(&sbi->ll_lock); rc = count; } else { - atomic_add(nrpages, &cache->ccc_lru_left); + atomic_long_add(nrpages, &cache->ccc_lru_left); } return rc; } @@ -738,6 +744,18 @@ static ssize_t max_easize_show(struct kobject *kobj, } LUSTRE_RO_ATTR(max_easize); +/** + * Get default_easize. + * + * \see client_obd::cl_default_mds_easize + * + * \param[in] kobj kernel object for sysfs tree + * \param[in] attr attribute of this kernel object + * \param[in] buf buffer to write data into + * + * \retval positive \a count on success + * \retval negative negated errno on failure + */ static ssize_t default_easize_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -753,7 +771,44 @@ static ssize_t default_easize_show(struct kobject *kobj, return sprintf(buf, "%u\n", ealen); } -LUSTRE_RO_ATTR(default_easize); + +/** + * Set default_easize. + * + * Range checking on the passed value is handled by + * ll_set_default_mdsize(). + * + * \see client_obd::cl_default_mds_easize + * + * \param[in] kobj kernel object for sysfs tree + * \param[in] attr attribute of this kernel object + * \param[in] buffer string passed from user space + * \param[in] count \a buffer length + * + * \retval positive \a count on success + * \retval negative negated errno on failure + */ +static ssize_t default_easize_store(struct kobject *kobj, + struct attribute *attr, + const char *buffer, + size_t count) +{ + struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, + ll_kobj); + unsigned long val; + int rc; + + rc = kstrtoul(buffer, 10, &val); + if (rc) + return rc; + + rc = ll_set_default_mdsize(sbi, val); + if (rc) + return rc; + + return count; +} +LUSTRE_RW_ATTR(default_easize); static int ll_sbi_flags_seq_show(struct seq_file *m, void *v) { @@ -774,7 +829,7 @@ static int ll_sbi_flags_seq_show(struct seq_file *m, void *v) flags >>= 1; ++i; } - seq_printf(m, "\b\n"); + seq_puts(m, "\b\n"); return 0; } @@ -823,15 +878,116 @@ static ssize_t unstable_stats_show(struct kobject *kobj, struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, ll_kobj); struct cl_client_cache *cache = sbi->ll_cache; - int pages, mb; + long pages; + int mb; - pages = atomic_read(&cache->ccc_unstable_nr); + pages = atomic_long_read(&cache->ccc_unstable_nr); mb = (pages * PAGE_SIZE) >> 20; - return sprintf(buf, "unstable_pages: %8d\n" - "unstable_mb: %8d\n", pages, mb); + return sprintf(buf, "unstable_check: %8d\n" + "unstable_pages: %12ld\n" + "unstable_mb: %8d\n", + cache->ccc_unstable_check, pages, mb); } -LUSTRE_RO_ATTR(unstable_stats); + +static ssize_t unstable_stats_store(struct kobject *kobj, + struct attribute *attr, + const char *buffer, + size_t count) +{ + struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, + ll_kobj); + char kernbuf[128]; + int val, rc; + + if (!count) + return 0; + if (count >= sizeof(kernbuf)) + return -EINVAL; + + if (copy_from_user(kernbuf, buffer, count)) + return -EFAULT; + kernbuf[count] = 0; + + buffer += lprocfs_find_named_value(kernbuf, "unstable_check:", &count) - + kernbuf; + rc = lprocfs_write_helper(buffer, count, &val); + if (rc < 0) + return rc; + + /* borrow lru lock to set the value */ + spin_lock(&sbi->ll_cache->ccc_lru_lock); + sbi->ll_cache->ccc_unstable_check = !!val; + spin_unlock(&sbi->ll_cache->ccc_lru_lock); + + return count; +} +LUSTRE_RW_ATTR(unstable_stats); + +static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, + ll_kobj); + struct root_squash_info *squash = &sbi->ll_squash; + + return sprintf(buf, "%u:%u\n", squash->rsi_uid, squash->rsi_gid); +} + +static ssize_t root_squash_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, + ll_kobj); + struct root_squash_info *squash = &sbi->ll_squash; + + return lprocfs_wr_root_squash(buffer, count, squash, + ll_get_fsname(sbi->ll_sb, NULL, 0)); +} +LUSTRE_RW_ATTR(root_squash); + +static int ll_nosquash_nids_seq_show(struct seq_file *m, void *v) +{ + struct super_block *sb = m->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); + struct root_squash_info *squash = &sbi->ll_squash; + int len; + + down_read(&squash->rsi_sem); + if (!list_empty(&squash->rsi_nosquash_nids)) { + len = cfs_print_nidlist(m->buf + m->count, m->size - m->count, + &squash->rsi_nosquash_nids); + m->count += len; + seq_puts(m, "\n"); + } else { + seq_puts(m, "NONE\n"); + } + up_read(&squash->rsi_sem); + + return 0; +} + +static ssize_t ll_nosquash_nids_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) +{ + struct seq_file *m = file->private_data; + struct super_block *sb = m->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); + struct root_squash_info *squash = &sbi->ll_squash; + int rc; + + rc = lprocfs_wr_nosquash_nids(buffer, count, squash, + ll_get_fsname(sb, NULL, 0)); + if (rc < 0) + return rc; + + ll_compute_rootsquash_state(sbi); + + return rc; +} + +LPROC_SEQ_FOPS(ll_nosquash_nids); static struct lprocfs_vars lprocfs_llite_obd_vars[] = { /* { "mntpt_path", ll_rd_path, 0, 0 }, */ @@ -840,6 +996,8 @@ static struct lprocfs_vars lprocfs_llite_obd_vars[] = { { "max_cached_mb", &ll_max_cached_mb_fops, NULL }, { "statahead_stats", &ll_statahead_stats_fops, NULL, 0 }, { "sbi_flags", &ll_sbi_flags_fops, NULL, 0 }, + { .name = "nosquash_nids", + .fops = &ll_nosquash_nids_fops }, { NULL } }; @@ -869,6 +1027,7 @@ static struct attribute *llite_attrs[] = { &lustre_attr_default_easize.attr, &lustre_attr_xattr_cache.attr, &lustre_attr_unstable_stats.attr, + &lustre_attr_root_squash.attr, NULL, }; @@ -893,17 +1052,17 @@ static const struct llite_file_opcode { /* file operation */ { LPROC_LL_DIRTY_HITS, LPROCFS_TYPE_REGS, "dirty_pages_hits" }, { LPROC_LL_DIRTY_MISSES, LPROCFS_TYPE_REGS, "dirty_pages_misses" }, - { LPROC_LL_READ_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES, + { LPROC_LL_READ_BYTES, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES, "read_bytes" }, - { LPROC_LL_WRITE_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES, + { LPROC_LL_WRITE_BYTES, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES, "write_bytes" }, - { LPROC_LL_BRW_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES, + { LPROC_LL_BRW_READ, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES, "brw_read" }, - { LPROC_LL_BRW_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES, + { LPROC_LL_BRW_WRITE, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES, "brw_write" }, - { LPROC_LL_OSC_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES, + { LPROC_LL_OSC_READ, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES, "osc_read" }, - { LPROC_LL_OSC_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES, + { LPROC_LL_OSC_WRITE, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES, "osc_write" }, { LPROC_LL_IOCTL, LPROCFS_TYPE_REGS, "ioctl" }, { LPROC_LL_OPEN, LPROCFS_TYPE_REGS, "open" }, @@ -1150,7 +1309,7 @@ static void ll_display_extents_info(struct ll_rw_extents_info *io_extents, r, pct(r, read_tot), pct(read_cum, read_tot), w, pct(w, write_tot), pct(write_cum, write_tot)); start = end; - if (start == 1<<10) { + if (start == 1 << 10) { start = 1; units += 10; unitp++; diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 2c4dc69731e8..dfa36d34c645 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -42,13 +42,12 @@ #include "../include/obd_support.h" #include "../include/lustre_fid.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_ver.h" #include "llite_internal.h" -static int ll_create_it(struct inode *, struct dentry *, - int, struct lookup_intent *); +static int ll_create_it(struct inode *dir, struct dentry *dentry, + struct lookup_intent *it); /* called from iget5_locked->find_inode() under inode_hash_lock spinlock */ static int ll_test_inode(struct inode *inode, void *opaque) @@ -56,12 +55,12 @@ static int ll_test_inode(struct inode *inode, void *opaque) struct ll_inode_info *lli = ll_i2info(inode); struct lustre_md *md = opaque; - if (unlikely(!(md->body->valid & OBD_MD_FLID))) { + if (unlikely(!(md->body->mbo_valid & OBD_MD_FLID))) { CERROR("MDS body missing FID\n"); return 0; } - if (!lu_fid_eq(&lli->lli_fid, &md->body->fid1)) + if (!lu_fid_eq(&lli->lli_fid, &md->body->mbo_fid1)) return 0; return 1; @@ -72,20 +71,20 @@ static int ll_set_inode(struct inode *inode, void *opaque) struct ll_inode_info *lli = ll_i2info(inode); struct mdt_body *body = ((struct lustre_md *)opaque)->body; - if (unlikely(!(body->valid & OBD_MD_FLID))) { + if (unlikely(!(body->mbo_valid & OBD_MD_FLID))) { CERROR("MDS body missing FID\n"); return -EINVAL; } - lli->lli_fid = body->fid1; - if (unlikely(!(body->valid & OBD_MD_FLTYPE))) { + lli->lli_fid = body->mbo_fid1; + if (unlikely(!(body->mbo_valid & OBD_MD_FLTYPE))) { CERROR("Can not initialize inode " DFID " without object type: valid = %#llx\n", - PFID(&lli->lli_fid), body->valid); + PFID(&lli->lli_fid), body->mbo_valid); return -EINVAL; } - inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mode & S_IFMT); + inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mbo_mode & S_IFMT); if (unlikely(inode->i_mode == 0)) { CERROR("Invalid inode "DFID" type\n", PFID(&lli->lli_fid)); return -EINVAL; @@ -96,41 +95,45 @@ static int ll_set_inode(struct inode *inode, void *opaque) return 0; } -/* - * Get an inode by inode number (already instantiated by the intent lookup). - * Returns inode or NULL +/** + * Get an inode by inode number(@hash), which is already instantiated by + * the intent lookup). */ struct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *md) { struct inode *inode; + int rc = 0; LASSERT(hash != 0); inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md); + if (!inode) + return ERR_PTR(-ENOMEM); - if (inode) { - if (inode->i_state & I_NEW) { - int rc = 0; - - ll_read_inode2(inode, md); - if (S_ISREG(inode->i_mode) && - !ll_i2info(inode)->lli_clob) { - CDEBUG(D_INODE, - "%s: apply lsm %p to inode " DFID ".\n", - ll_get_fsname(sb, NULL, 0), md->lsm, - PFID(ll_inode2fid(inode))); - rc = cl_file_inode_init(inode, md); - } - if (rc != 0) { - iget_failed(inode); - inode = NULL; - } else { - unlock_new_inode(inode); - } - } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) { - ll_update_inode(inode, md); - CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p)\n", - PFID(&md->body->fid1), inode); + if (inode->i_state & I_NEW) { + rc = ll_read_inode2(inode, md); + if (!rc && S_ISREG(inode->i_mode) && + !ll_i2info(inode)->lli_clob) { + CDEBUG(D_INODE, "%s: apply lsm %p to inode "DFID"\n", + ll_get_fsname(sb, NULL, 0), md->lsm, + PFID(ll_inode2fid(inode))); + rc = cl_file_inode_init(inode, md); + } + if (rc) { + make_bad_inode(inode); + unlock_new_inode(inode); + iput(inode); + inode = ERR_PTR(rc); + } else { + unlock_new_inode(inode); + } + } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) { + rc = ll_update_inode(inode, md); + CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p): rc = %d\n", + PFID(&md->body->mbo_fid1), inode, rc); + if (rc) { + iput(inode); + inode = ERR_PTR(rc); } } return inode; @@ -158,6 +161,11 @@ static void ll_invalidate_negative_children(struct inode *dir) spin_unlock(&dir->i_lock); } +int ll_test_inode_by_fid(struct inode *inode, void *opaque) +{ + return lu_fid_eq(&ll_i2info(inode)->lli_fid, opaque); +} + int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, void *data, int flag) { @@ -196,6 +204,8 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, } if (bits & MDS_INODELOCK_XATTR) { + if (S_ISDIR(inode->i_mode)) + ll_i2info(inode)->lli_def_stripe_offset = -1; ll_xattr_cache_destroy(inode); bits &= ~MDS_INODELOCK_XATTR; } @@ -253,10 +263,41 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, } if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) { - CDEBUG(D_INODE, "invalidating inode "DFID"\n", - PFID(ll_inode2fid(inode))); + struct ll_inode_info *lli = ll_i2info(inode); + + CDEBUG(D_INODE, "invalidating inode "DFID" lli = %p, pfid = "DFID"\n", + PFID(ll_inode2fid(inode)), lli, + PFID(&lli->lli_pfid)); + truncate_inode_pages(inode->i_mapping, 0); - ll_invalidate_negative_children(inode); + + if (unlikely(!fid_is_zero(&lli->lli_pfid))) { + struct inode *master_inode = NULL; + unsigned long hash; + + /* + * This is slave inode, since all of the child + * dentry is connected on the master inode, so + * we have to invalidate the negative children + * on master inode + */ + CDEBUG(D_INODE, "Invalidate s"DFID" m"DFID"\n", + PFID(ll_inode2fid(inode)), + PFID(&lli->lli_pfid)); + + hash = cl_fid_build_ino(&lli->lli_pfid, + ll_need_32bit_api(ll_i2sbi(inode))); + + master_inode = ilookup5(inode->i_sb, hash, + ll_test_inode_by_fid, + (void *)&lli->lli_pfid); + if (master_inode && !IS_ERR(master_inode)) { + ll_invalidate_negative_children(master_inode); + iput(master_inode); + } + } else { + ll_invalidate_negative_children(inode); + } } if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) && @@ -322,7 +363,8 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) LASSERT(alias != dentry); spin_lock(&alias->d_lock); - if (alias->d_flags & DCACHE_DISCONNECTED) + if ((alias->d_flags & DCACHE_DISCONNECTED) && + S_ISDIR(inode->i_mode)) /* LASSERT(last_discon == NULL); LU-405, bz 20055 */ discon_alias = alias; else if (alias->d_parent == dentry->d_parent && @@ -433,9 +475,20 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request, struct lookup_intent parent_it = { .it_op = IT_GETATTR, .it_lock_handle = 0 }; + struct lu_fid fid = ll_i2info(parent)->lli_fid; - if (md_revalidate_lock(ll_i2mdexp(parent), &parent_it, - &ll_i2info(parent)->lli_fid, NULL)) { + /* If it is striped directory, get the real stripe parent */ + if (unlikely(ll_i2info(parent)->lli_lsm_md)) { + rc = md_get_fid_from_lsm(ll_i2mdexp(parent), + ll_i2info(parent)->lli_lsm_md, + (*de)->d_name.name, + (*de)->d_name.len, &fid); + if (rc) + return rc; + } + + if (md_revalidate_lock(ll_i2mdexp(parent), &parent_it, &fid, + NULL)) { d_lustre_revalidate(*de); ll_intent_release(&parent_it); } @@ -449,13 +502,13 @@ out: } static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, - struct lookup_intent *it, int lookup_flags) + struct lookup_intent *it) { struct lookup_intent lookup_it = { .it_op = IT_LOOKUP }; struct dentry *save = dentry, *retval; struct ptlrpc_request *req = NULL; + struct md_op_data *op_data = NULL; struct inode *inode; - struct md_op_data *op_data; __u32 opc; int rc; @@ -471,8 +524,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, if (!it || it->it_op == IT_GETXATTR) it = &lookup_it; - if (it->it_op == IT_GETATTR) { - rc = ll_statahead_enter(parent, &dentry, 0); + if (it->it_op == IT_GETATTR && dentry_may_statahead(parent, dentry)) { + rc = ll_statahead(parent, &dentry, 0); if (rc == 1) { if (dentry == save) retval = NULL; @@ -488,8 +541,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, opc = LUSTRE_OPC_ANY; op_data = ll_prep_md_op_data(NULL, parent, NULL, dentry->d_name.name, - dentry->d_name.len, lookup_flags, opc, - NULL); + dentry->d_name.len, 0, opc, NULL); if (IS_ERR(op_data)) return (void *)op_data; @@ -497,9 +549,38 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent))) it->it_create_mode &= ~current_umask(); - rc = md_intent_lock(ll_i2mdexp(parent), op_data, NULL, 0, it, - lookup_flags, &req, ll_md_blocking_ast, 0); - ll_finish_md_op_data(op_data); + rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req, + &ll_md_blocking_ast, 0); + /* + * If the MDS allows the client to chgrp (CFS_SETGRP_PERM), but the + * client does not know which suppgid should be sent to the MDS, or + * some other(s) changed the target file's GID after this RPC sent + * to the MDS with the suppgid as the original GID, then we should + * try again with right suppgid. + */ + if (rc == -EACCES && it->it_op & IT_OPEN && + it_disposition(it, DISP_OPEN_DENY)) { + struct mdt_body *body; + + LASSERT(req); + + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + if (op_data->op_suppgids[0] == body->mbo_gid || + op_data->op_suppgids[1] == body->mbo_gid || + !in_group_p(make_kgid(&init_user_ns, body->mbo_gid))) { + retval = ERR_PTR(-EACCES); + goto out; + } + + fid_zero(&op_data->op_fid2); + op_data->op_suppgids[1] = body->mbo_gid; + ptlrpc_req_finished(req); + req = NULL; + ll_intent_release(it); + rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req, + ll_md_blocking_ast, 0); + } + if (rc < 0) { retval = ERR_PTR(rc); goto out; @@ -524,11 +605,11 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, retval = NULL; else retval = dentry; - out: - if (req) - ptlrpc_req_finished(req); - if (it->it_op == IT_GETATTR && (!retval || retval == dentry)) - ll_statahead_mark(parent, dentry); +out: + if (op_data && !IS_ERR(op_data)) + ll_finish_md_op_data(op_data); + + ptlrpc_req_finished(req); return retval; } @@ -541,15 +622,19 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),flags=%u\n", dentry, PFID(ll_inode2fid(parent)), parent, flags); - /* Optimize away (CREATE && !OPEN). Let .create handle the race. */ - if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN)) + /* Optimize away (CREATE && !OPEN). Let .create handle the race. + * but only if we have write permissions there, otherwise we need + * to proceed with lookup. LU-4185 + */ + if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN) && + (inode_permission(parent, MAY_WRITE | MAY_EXEC) == 0)) return NULL; - if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) + if (flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE)) itp = NULL; else itp = ⁢ - de = ll_lookup_it(parent, dentry, itp, 0); + de = ll_lookup_it(parent, dentry, itp); if (itp) ll_intent_release(itp); @@ -567,7 +652,6 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, { struct lookup_intent *it; struct dentry *de; - long long lookup_flags = LOOKUP_OPEN; int rc = 0; CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),file %p,open_flags %x,mode %x opened %d\n", @@ -597,15 +681,14 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, return -ENOMEM; it->it_op = IT_OPEN; - if (open_flags & O_CREAT) { + if (open_flags & O_CREAT) it->it_op |= IT_CREAT; - lookup_flags |= LOOKUP_CREATE; - } it->it_create_mode = (mode & S_IALLUGO) | S_IFREG; it->it_flags = (open_flags & ~O_ACCMODE) | OPEN_FMODE(open_flags); + it->it_flags &= ~MDS_OPEN_FL_INTERNAL; /* Dentry added to dcache tree in ll_lookup_it */ - de = ll_lookup_it(dir, dentry, it, lookup_flags); + de = ll_lookup_it(dir, dentry, it); if (IS_ERR(de)) rc = PTR_ERR(de); else if (de) @@ -614,7 +697,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, if (!rc) { if (it_disposition(it, DISP_OPEN_CREATE)) { /* Dentry instantiated in ll_create_it. */ - rc = ll_create_it(dir, dentry, mode, it); + rc = ll_create_it(dir, dentry, it); if (rc) { /* We dget in ll_splice_alias. */ if (de) @@ -700,7 +783,7 @@ static struct inode *ll_create_node(struct inode *dir, struct lookup_intent *it) * If the create succeeds, we fill in the inode information * with d_instantiate(). */ -static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode, +static int ll_create_it(struct inode *dir, struct dentry *dentry, struct lookup_intent *it) { struct inode *inode; @@ -721,27 +804,26 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode, return 0; } -static void ll_update_times(struct ptlrpc_request *request, - struct inode *inode) +void ll_update_times(struct ptlrpc_request *request, struct inode *inode) { struct mdt_body *body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); LASSERT(body); - if (body->valid & OBD_MD_FLMTIME && - body->mtime > LTIME_S(inode->i_mtime)) { + if (body->mbo_valid & OBD_MD_FLMTIME && + body->mbo_mtime > LTIME_S(inode->i_mtime)) { CDEBUG(D_INODE, "setting fid "DFID" mtime from %lu to %llu\n", PFID(ll_inode2fid(inode)), LTIME_S(inode->i_mtime), - body->mtime); - LTIME_S(inode->i_mtime) = body->mtime; + body->mbo_mtime); + LTIME_S(inode->i_mtime) = body->mbo_mtime; } - if (body->valid & OBD_MD_FLCTIME && - body->ctime > LTIME_S(inode->i_ctime)) - LTIME_S(inode->i_ctime) = body->ctime; + if (body->mbo_valid & OBD_MD_FLCTIME && + body->mbo_ctime > LTIME_S(inode->i_ctime)) + LTIME_S(inode->i_ctime) = body->mbo_ctime; } static int ll_new_node(struct inode *dir, struct dentry *dentry, - const char *tgt, int mode, int rdev, + const char *tgt, umode_t mode, int rdev, __u32 opc) { struct ptlrpc_request *request = NULL; @@ -753,7 +835,7 @@ static int ll_new_node(struct inode *dir, struct dentry *dentry, if (unlikely(tgt)) tgt_len = strlen(tgt) + 1; - +again: op_data = ll_prep_md_op_data(NULL, dir, NULL, dentry->d_name.name, dentry->d_name.len, @@ -768,9 +850,45 @@ static int ll_new_node(struct inode *dir, struct dentry *dentry, from_kgid(&init_user_ns, current_fsgid()), cfs_curproc_cap_pack(), rdev, &request); ll_finish_md_op_data(op_data); - if (err) + if (err < 0 && err != -EREMOTE) goto err_exit; + /* + * If the client doesn't know where to create a subdirectory (or + * in case of a race that sends the RPC to the wrong MDS), the + * MDS will return -EREMOTE and the client will fetch the layout + * of the directory, then create the directory on the right MDT. + */ + if (unlikely(err == -EREMOTE)) { + struct ll_inode_info *lli = ll_i2info(dir); + struct lmv_user_md *lum; + int lumsize, err2; + + ptlrpc_req_finished(request); + request = NULL; + + err2 = ll_dir_getstripe(dir, (void **)&lum, &lumsize, &request, + OBD_MD_DEFAULT_MEA); + if (!err2) { + /* Update stripe_offset and retry */ + lli->lli_def_stripe_offset = lum->lum_stripe_offset; + } else if (err2 == -ENODATA && + lli->lli_def_stripe_offset != -1) { + /* + * If there are no default stripe EA on the MDT, but the + * client has default stripe, then it probably means + * default stripe EA has just been deleted. + */ + lli->lli_def_stripe_offset = -1; + } else { + goto err_exit; + } + + ptlrpc_req_finished(request); + request = NULL; + goto again; + } + ll_update_times(request, dir); err = ll_prep_inode(&inode, request, dir->i_sb, NULL); @@ -779,7 +897,8 @@ static int ll_new_node(struct inode *dir, struct dentry *dentry, d_instantiate(dentry, inode); err_exit: - ptlrpc_req_finished(request); + if (request) + ptlrpc_req_finished(request); return err; } @@ -842,77 +961,6 @@ static int ll_create_nd(struct inode *dir, struct dentry *dentry, return rc; } -int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) -{ - struct mdt_body *body; - struct lov_mds_md *eadata; - struct lov_stripe_md *lsm = NULL; - struct obd_trans_info oti = { 0 }; - struct obdo *oa; - int rc; - - /* req is swabbed so this is safe */ - body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); - if (!(body->valid & OBD_MD_FLEASIZE)) - return 0; - - if (body->eadatasize == 0) { - CERROR("OBD_MD_FLEASIZE set but eadatasize zero\n"); - rc = -EPROTO; - goto out; - } - - /* The MDS sent back the EA because we unlinked the last reference - * to this file. Use this EA to unlink the objects on the OST. - * It's opaque so we don't swab here; we leave it to obd_unpackmd() to - * check it is complete and sensible. - */ - eadata = req_capsule_server_sized_get(&request->rq_pill, &RMF_MDT_MD, - body->eadatasize); - LASSERT(eadata); - - rc = obd_unpackmd(ll_i2dtexp(dir), &lsm, eadata, body->eadatasize); - if (rc < 0) { - CERROR("obd_unpackmd: %d\n", rc); - goto out; - } - LASSERT(rc >= sizeof(*lsm)); - - oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!oa) { - rc = -ENOMEM; - goto out_free_memmd; - } - - oa->o_oi = lsm->lsm_oi; - oa->o_mode = body->mode & S_IFMT; - oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP; - - if (body->valid & OBD_MD_FLCOOKIE) { - oa->o_valid |= OBD_MD_FLCOOKIE; - oti.oti_logcookies = - req_capsule_server_sized_get(&request->rq_pill, - &RMF_LOGCOOKIES, - sizeof(struct llog_cookie) * - lsm->lsm_stripe_count); - if (!oti.oti_logcookies) { - oa->o_valid &= ~OBD_MD_FLCOOKIE; - body->valid &= ~OBD_MD_FLCOOKIE; - } - } - - rc = obd_destroy(NULL, ll_i2dtexp(dir), oa, lsm, &oti, - ll_i2mdexp(dir)); - if (rc) - CERROR("obd destroy objid "DOSTID" error %d\n", - POSTID(&lsm->lsm_oi), rc); -out_free_memmd: - obd_free_memmd(ll_i2dtexp(dir), &lsm); - kmem_cache_free(obdo_cachep, oa); -out: - return rc; -} - /* ll_unlink() doesn't update the inode with the new link count. * Instead, ll_ddelete() and ll_d_iput() will update it based upon if there * is any lock existing. They will recycle dentries and inodes based upon locks @@ -934,7 +982,7 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild) if (IS_ERR(op_data)) return PTR_ERR(op_data); - if (dchild && dchild->d_inode) + if (dchild->d_inode) op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); op_data->op_fid2 = op_data->op_fid3; @@ -946,7 +994,6 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild) ll_update_times(request, dir); ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_UNLINK, 1); - rc = ll_objects_destroy(request, dir); out: ptlrpc_req_finished(request); return rc; @@ -961,9 +1008,9 @@ static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir))) mode &= ~current_umask(); - mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR; - err = ll_new_node(dir, dentry, NULL, mode, 0, LUSTRE_OPC_MKDIR); + mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; + err = ll_new_node(dir, dentry, NULL, mode, 0, LUSTRE_OPC_MKDIR); if (!err) ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKDIR, 1); @@ -986,7 +1033,7 @@ static int ll_rmdir(struct inode *dir, struct dentry *dchild) if (IS_ERR(op_data)) return PTR_ERR(op_data); - if (dchild && dchild->d_inode) + if (dchild->d_inode) op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); op_data->op_fid2 = op_data->op_fid3; @@ -1067,9 +1114,9 @@ static int ll_rename(struct inode *src, struct dentry *src_dchild, if (IS_ERR(op_data)) return PTR_ERR(op_data); - if (src_dchild && src_dchild->d_inode) + if (src_dchild->d_inode) op_data->op_fid3 = *ll_inode2fid(src_dchild->d_inode); - if (tgt_dchild && tgt_dchild->d_inode) + if (tgt_dchild->d_inode) op_data->op_fid4 = *ll_inode2fid(tgt_dchild->d_inode); err = md_rename(sbi->ll_md_exp, op_data, @@ -1082,7 +1129,6 @@ static int ll_rename(struct inode *src, struct dentry *src_dchild, ll_update_times(request, src); ll_update_times(request, tgt); ll_stats_ops_tally(sbi, LPROC_LL_RENAME, 1); - err = ll_objects_destroy(request, src); } ptlrpc_req_finished(request); @@ -1106,10 +1152,10 @@ const struct inode_operations ll_dir_inode_operations = { .setattr = ll_setattr, .getattr = ll_getattr, .permission = ll_inode_permission, - .setxattr = ll_setxattr, - .getxattr = ll_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ll_listxattr, - .removexattr = ll_removexattr, + .removexattr = generic_removexattr, .get_acl = ll_get_acl, }; @@ -1117,9 +1163,9 @@ const struct inode_operations ll_special_inode_operations = { .setattr = ll_setattr, .getattr = ll_getattr, .permission = ll_inode_permission, - .setxattr = ll_setxattr, - .getxattr = ll_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ll_listxattr, - .removexattr = ll_removexattr, + .removexattr = generic_removexattr, .get_acl = ll_get_acl, }; diff --git a/drivers/staging/lustre/lustre/llite/range_lock.c b/drivers/staging/lustre/lustre/llite/range_lock.c new file mode 100644 index 000000000000..94c818f1478b --- /dev/null +++ b/drivers/staging/lustre/lustre/llite/range_lock.c @@ -0,0 +1,233 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Range lock is used to allow multiple threads writing a single shared + * file given each thread is writing to a non-overlapping portion of the + * file. + * + * Refer to the possible upstream kernel version of range lock by + * Jan Kara : https://lkml.org/lkml/2013/1/31/480 + * + * This file could later replaced by the upstream kernel version. + */ +/* + * Author: Prakash Surya + * Author: Bobi Jam + */ +#include "range_lock.h" +#include "../include/lustre/lustre_user.h" + +/** + * Initialize a range lock tree + * + * \param tree [in] an empty range lock tree + * + * Pre: Caller should have allocated the range lock tree. + * Post: The range lock tree is ready to function. + */ +void range_lock_tree_init(struct range_lock_tree *tree) +{ + tree->rlt_root = NULL; + tree->rlt_sequence = 0; + spin_lock_init(&tree->rlt_lock); +} + +/** + * Initialize a range lock node + * + * \param lock [in] an empty range lock node + * \param start [in] start of the covering region + * \param end [in] end of the covering region + * + * Pre: Caller should have allocated the range lock node. + * Post: The range lock node is meant to cover [start, end] region + */ +void range_lock_init(struct range_lock *lock, __u64 start, __u64 end) +{ + memset(&lock->rl_node, 0, sizeof(lock->rl_node)); + if (end != LUSTRE_EOF) + end >>= PAGE_SHIFT; + interval_set(&lock->rl_node, start >> PAGE_SHIFT, end); + INIT_LIST_HEAD(&lock->rl_next_lock); + lock->rl_task = NULL; + lock->rl_lock_count = 0; + lock->rl_blocking_ranges = 0; + lock->rl_sequence = 0; +} + +static inline struct range_lock *next_lock(struct range_lock *lock) +{ + return list_entry(lock->rl_next_lock.next, typeof(*lock), rl_next_lock); +} + +/** + * Helper function of range_unlock() + * + * \param node [in] a range lock found overlapped during interval node + * search + * \param arg [in] the range lock to be tested + * + * \retval INTERVAL_ITER_CONT indicate to continue the search for next + * overlapping range node + * \retval INTERVAL_ITER_STOP indicate to stop the search + */ +static enum interval_iter range_unlock_cb(struct interval_node *node, void *arg) +{ + struct range_lock *lock = arg; + struct range_lock *overlap = node2rangelock(node); + struct range_lock *iter; + + list_for_each_entry(iter, &overlap->rl_next_lock, rl_next_lock) { + if (iter->rl_sequence > lock->rl_sequence) { + --iter->rl_blocking_ranges; + LASSERT(iter->rl_blocking_ranges > 0); + } + } + if (overlap->rl_sequence > lock->rl_sequence) { + --overlap->rl_blocking_ranges; + if (overlap->rl_blocking_ranges == 0) + wake_up_process(overlap->rl_task); + } + return INTERVAL_ITER_CONT; +} + +/** + * Unlock a range lock, wake up locks blocked by this lock. + * + * \param tree [in] range lock tree + * \param lock [in] range lock to be deleted + * + * If this lock has been granted, relase it; if not, just delete it from + * the tree or the same region lock list. Wake up those locks only blocked + * by this lock through range_unlock_cb(). + */ +void range_unlock(struct range_lock_tree *tree, struct range_lock *lock) +{ + spin_lock(&tree->rlt_lock); + if (!list_empty(&lock->rl_next_lock)) { + struct range_lock *next; + + if (interval_is_intree(&lock->rl_node)) { /* first lock */ + /* Insert the next same range lock into the tree */ + next = next_lock(lock); + next->rl_lock_count = lock->rl_lock_count - 1; + interval_erase(&lock->rl_node, &tree->rlt_root); + interval_insert(&next->rl_node, &tree->rlt_root); + } else { + /* find the first lock in tree */ + list_for_each_entry(next, &lock->rl_next_lock, + rl_next_lock) { + if (!interval_is_intree(&next->rl_node)) + continue; + + LASSERT(next->rl_lock_count > 0); + next->rl_lock_count--; + break; + } + } + list_del_init(&lock->rl_next_lock); + } else { + LASSERT(interval_is_intree(&lock->rl_node)); + interval_erase(&lock->rl_node, &tree->rlt_root); + } + + interval_search(tree->rlt_root, &lock->rl_node.in_extent, + range_unlock_cb, lock); + spin_unlock(&tree->rlt_lock); +} + +/** + * Helper function of range_lock() + * + * \param node [in] a range lock found overlapped during interval node + * search + * \param arg [in] the range lock to be tested + * + * \retval INTERVAL_ITER_CONT indicate to continue the search for next + * overlapping range node + * \retval INTERVAL_ITER_STOP indicate to stop the search + */ +static enum interval_iter range_lock_cb(struct interval_node *node, void *arg) +{ + struct range_lock *lock = (struct range_lock *)arg; + struct range_lock *overlap = node2rangelock(node); + + lock->rl_blocking_ranges += overlap->rl_lock_count + 1; + return INTERVAL_ITER_CONT; +} + +/** + * Lock a region + * + * \param tree [in] range lock tree + * \param lock [in] range lock node containing the region span + * + * \retval 0 get the range lock + * \retval <0 error code while not getting the range lock + * + * If there exists overlapping range lock, the new lock will wait and + * retry, if later it find that it is not the chosen one to wake up, + * it wait again. + */ +int range_lock(struct range_lock_tree *tree, struct range_lock *lock) +{ + struct interval_node *node; + int rc = 0; + + spin_lock(&tree->rlt_lock); + /* + * We need to check for all conflicting intervals + * already in the tree. + */ + interval_search(tree->rlt_root, &lock->rl_node.in_extent, + range_lock_cb, lock); + /* + * Insert to the tree if I am unique, otherwise I've been linked to + * the rl_next_lock of another lock which has the same range as mine + * in range_lock_cb(). + */ + node = interval_insert(&lock->rl_node, &tree->rlt_root); + if (node) { + struct range_lock *tmp = node2rangelock(node); + + list_add_tail(&lock->rl_next_lock, &tmp->rl_next_lock); + tmp->rl_lock_count++; + } + lock->rl_sequence = ++tree->rlt_sequence; + + while (lock->rl_blocking_ranges > 0) { + lock->rl_task = current; + __set_current_state(TASK_INTERRUPTIBLE); + spin_unlock(&tree->rlt_lock); + schedule(); + + if (signal_pending(current)) { + range_unlock(tree, lock); + rc = -EINTR; + goto out; + } + spin_lock(&tree->rlt_lock); + } + spin_unlock(&tree->rlt_lock); +out: + return rc; +} diff --git a/drivers/staging/lustre/lustre/llite/range_lock.h b/drivers/staging/lustre/lustre/llite/range_lock.h new file mode 100644 index 000000000000..c6d04a6f99fd --- /dev/null +++ b/drivers/staging/lustre/lustre/llite/range_lock.h @@ -0,0 +1,82 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Range lock is used to allow multiple threads writing a single shared + * file given each thread is writing to a non-overlapping portion of the + * file. + * + * Refer to the possible upstream kernel version of range lock by + * Jan Kara : https://lkml.org/lkml/2013/1/31/480 + * + * This file could later replaced by the upstream kernel version. + */ +/* + * Author: Prakash Surya + * Author: Bobi Jam + */ +#ifndef _RANGE_LOCK_H +#define _RANGE_LOCK_H + +#include "../../include/linux/libcfs/libcfs.h" +#include "../include/interval_tree.h" + +struct range_lock { + struct interval_node rl_node; + /** + * Process to enqueue this lock. + */ + struct task_struct *rl_task; + /** + * List of locks with the same range. + */ + struct list_head rl_next_lock; + /** + * Number of locks in the list rl_next_lock + */ + unsigned int rl_lock_count; + /** + * Number of ranges which are blocking acquisition of the lock + */ + unsigned int rl_blocking_ranges; + /** + * Sequence number of range lock. This number is used to get to know + * the order the locks are queued; this is required for range_cancel(). + */ + __u64 rl_sequence; +}; + +static inline struct range_lock *node2rangelock(const struct interval_node *n) +{ + return container_of(n, struct range_lock, rl_node); +} + +struct range_lock_tree { + struct interval_node *rlt_root; + spinlock_t rlt_lock; /* protect range lock tree */ + __u64 rlt_sequence; +}; + +void range_lock_tree_init(struct range_lock_tree *tree); +void range_lock_init(struct range_lock *lock, __u64 start, __u64 end); +int range_lock(struct range_lock_tree *tree, struct range_lock *lock); +void range_unlock(struct range_lock_tree *tree, struct range_lock *lock); +#endif diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 87393c4bd51e..50c0152ba022 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -50,10 +50,8 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "../include/obd_cksum.h" #include "llite_internal.h" -#include "../include/linux/lustre_compat25.h" static void ll_ra_stats_inc_sbi(struct ll_sb_info *sbi, enum ra_stat which); @@ -413,7 +411,7 @@ static int ll_read_ahead_pages(const struct lu_env *env, * forward read-ahead, it will be fixed when backward * read-ahead is implemented */ - LASSERTF(page_idx > ria->ria_stoff, "Invalid page_idx %lu rs %lu re %lu ro %lu rl %lu rp %lu\n", + LASSERTF(page_idx >= ria->ria_stoff, "Invalid page_idx %lu rs %lu re %lu ro %lu rl %lu rp %lu\n", page_idx, ria->ria_start, ria->ria_end, ria->ria_stoff, ria->ria_length, ria->ria_pages); @@ -474,10 +472,22 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, } /* Reserve a part of the read-ahead window that we'll be issuing */ - if (ras->ras_window_len) { - start = ras->ras_next_readahead; + if (ras->ras_window_len > 0) { + /* + * Note: other thread might rollback the ras_next_readahead, + * if it can not get the full size of prepared pages, see the + * end of this function. For stride read ahead, it needs to + * make sure the offset is no less than ras_stride_offset, + * so that stride read ahead can work correctly. + */ + if (stride_io_mode(ras)) + start = max(ras->ras_next_readahead, + ras->ras_stride_offset); + else + start = ras->ras_next_readahead; end = ras->ras_window_start + ras->ras_window_len - 1; } + if (end != 0) { unsigned long rpc_boundary; /* @@ -648,10 +658,11 @@ static void ras_update_stride_detector(struct ll_readahead_state *ras, { unsigned long stride_gap = index - ras->ras_last_readpage - 1; - if (!stride_io_mode(ras) && (stride_gap != 0 || - ras->ras_consecutive_stride_requests == 0)) { + if ((stride_gap != 0 || ras->ras_consecutive_stride_requests == 0) && + !stride_io_mode(ras)) { ras->ras_stride_pages = ras->ras_consecutive_pages; - ras->ras_stride_length = stride_gap+ras->ras_consecutive_pages; + ras->ras_stride_length = ras->ras_consecutive_pages + + stride_gap; } LASSERT(ras->ras_request_index == 0); LASSERT(ras->ras_consecutive_stride_requests == 0); @@ -663,10 +674,9 @@ static void ras_update_stride_detector(struct ll_readahead_state *ras, } ras->ras_stride_pages = ras->ras_consecutive_pages; - ras->ras_stride_length = stride_gap+ras->ras_consecutive_pages; + ras->ras_stride_length = stride_gap + ras->ras_consecutive_pages; RAS_CDEBUG(ras); - return; } /* Stride Read-ahead window will be increased inc_len according to @@ -882,7 +892,6 @@ out_unlock: RAS_CDEBUG(ras); ras->ras_request_index++; spin_unlock(&ras->ras_lock); - return; } int ll_writepage(struct page *vmpage, struct writeback_control *wbc) @@ -1015,11 +1024,15 @@ int ll_writepages(struct address_space *mapping, struct writeback_control *wbc) * is called later on. */ ignore_layout = 1; + + if (!ll_i2info(inode)->lli_clob) + return 0; + result = cl_sync_file_range(inode, start, end, mode, ignore_layout); if (result > 0) { wbc->nr_to_write -= result; result = 0; - } + } if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) { if (end == OBD_OBJECT_EOF) diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index d98c7acc0832..26f3a37873a7 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -51,9 +51,7 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" -#include "../include/linux/lustre_compat25.h" /** * Implements Linux VM address_space::invalidatepage() method. This method is @@ -161,7 +159,7 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask) return result; } -#define MAX_DIRECTIO_SIZE (2*1024*1024*1024UL) +#define MAX_DIRECTIO_SIZE (2 * 1024 * 1024 * 1024UL) static inline int ll_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages, @@ -214,10 +212,10 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, int i; ssize_t rc = 0; loff_t file_offset = pv->ldp_start_offset; - long size = pv->ldp_size; + size_t size = pv->ldp_size; int page_count = pv->ldp_nr; struct page **pages = pv->ldp_pages; - long page_size = cl_page_size(obj); + size_t page_size = cl_page_size(obj); bool do_io; int io_pages = 0; @@ -346,7 +344,6 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) struct cl_io *io; struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - struct vvp_object *obj = cl_inode2vvp(inode); loff_t file_offset = iocb->ki_pos; ssize_t count = iov_iter_count(iter); ssize_t tot_bytes = 0, result = 0; @@ -375,14 +372,6 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) io = vvp_env_io(env)->vui_cl.cis_io; LASSERT(io); - /* 0. Need locking between buffered and direct access. and race with - * size changing by concurrent truncates and writes. - * 1. Need inode mutex to operate transient pages. - */ - if (iov_iter_rw(iter) == READ) - inode_lock(inode); - - LASSERT(obj->vob_transient_pages == 0); while (iov_iter_count(iter)) { struct page **pages; size_t offs; @@ -430,10 +419,6 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) file_offset += result; } out: - LASSERT(obj->vob_transient_pages == 0); - if (iov_iter_rw(iter) == READ) - inode_unlock(inode); - if (tot_bytes > 0) { struct vvp_io *vio = vvp_env_io(env); @@ -616,6 +601,13 @@ static int ll_write_end(struct file *file, struct address_space *mapping, LASSERT(from == 0); vio->u.write.vui_to = from + copied; + /* + * To address the deadlock in balance_dirty_pages() where + * this dirty page may be written back in the same thread. + */ + if (PageDirty(vmpage)) + unplug = true; + /* We may have one full RPC, commit it soon */ if (plist->pl_nr >= PTLRPC_MAX_BRW_PAGES) unplug = true; diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index c1cb6b19e724..0677513476ec 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -39,7 +39,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "llite_internal.h" @@ -50,24 +49,26 @@ enum se_stat { SA_ENTRY_INIT = 0, /** init entry */ SA_ENTRY_SUCC = 1, /** stat succeed */ SA_ENTRY_INVA = 2, /** invalid entry */ - SA_ENTRY_DEST = 3, /** entry to be destroyed */ }; -struct ll_sa_entry { - /* link into sai->sai_entries */ - struct list_head se_link; - /* link into sai->sai_entries_{received,stated} */ +/* + * sa_entry is not refcounted: statahead thread allocates it and do async stat, + * and in async stat callback ll_statahead_interpret() will add it into + * sai_interim_entries, later statahead thread will call sa_handle_callback() to + * instantiate entry and move it into sai_entries, and then only scanner process + * can access and free it. + */ +struct sa_entry { + /* link into sai_interim_entries or sai_entries */ struct list_head se_list; /* link into sai hash table locally */ struct list_head se_hash; - /* entry reference count */ - atomic_t se_refcount; /* entry index in the sai */ __u64 se_index; /* low layer ldlm lock handle */ __u64 se_handle; /* entry status */ - enum se_stat se_stat; + enum se_stat se_state; /* entry size, contains name */ int se_size; /* pointer to async getattr enqueue info */ @@ -83,27 +84,24 @@ struct ll_sa_entry { static unsigned int sai_generation; static DEFINE_SPINLOCK(sai_generation_lock); -/* - * The entry only can be released by the caller, it is necessary to hold lock. - */ -static inline int ll_sa_entry_stated(struct ll_sa_entry *entry) +/* sa_entry is ready to use */ +static inline int sa_ready(struct sa_entry *entry) { smp_rmb(); - return (entry->se_stat != SA_ENTRY_INIT); + return (entry->se_state != SA_ENTRY_INIT); } -static inline int ll_sa_entry_hash(int val) +/* hash value to put in sai_cache */ +static inline int sa_hash(int val) { return val & LL_SA_CACHE_MASK; } -/* - * Insert entry to hash SA table. - */ +/* hash entry into sai_cache */ static inline void -ll_sa_entry_enhash(struct ll_statahead_info *sai, struct ll_sa_entry *entry) +sa_rehash(struct ll_statahead_info *sai, struct sa_entry *entry) { - int i = ll_sa_entry_hash(entry->se_qstr.hash); + int i = sa_hash(entry->se_qstr.hash); spin_lock(&sai->sai_cache_lock[i]); list_add_tail(&entry->se_hash, &sai->sai_cache[i]); @@ -114,9 +112,9 @@ ll_sa_entry_enhash(struct ll_statahead_info *sai, struct ll_sa_entry *entry) * Remove entry from SA table. */ static inline void -ll_sa_entry_unhash(struct ll_statahead_info *sai, struct ll_sa_entry *entry) +sa_unhash(struct ll_statahead_info *sai, struct sa_entry *entry) { - int i = ll_sa_entry_hash(entry->se_qstr.hash); + int i = sa_hash(entry->se_qstr.hash); spin_lock(&sai->sai_cache_lock[i]); list_del_init(&entry->se_hash); @@ -129,19 +127,21 @@ static inline int agl_should_run(struct ll_statahead_info *sai, return (inode && S_ISREG(inode->i_mode) && sai->sai_agl_valid); } +/* statahead window is full */ static inline int sa_sent_full(struct ll_statahead_info *sai) { return atomic_read(&sai->sai_cache_count) >= sai->sai_max; } -static inline int sa_received_empty(struct ll_statahead_info *sai) +/* got async stat replies */ +static inline int sa_has_callback(struct ll_statahead_info *sai) { - return list_empty(&sai->sai_entries_received); + return !list_empty(&sai->sai_interim_entries); } static inline int agl_list_empty(struct ll_statahead_info *sai) { - return list_empty(&sai->sai_entries_agl); + return list_empty(&sai->sai_agls); } /** @@ -157,7 +157,7 @@ static inline int sa_low_hit(struct ll_statahead_info *sai) } /* - * If the given index is behind of statahead window more than + * if the given index is behind of statahead window more than * SA_OMITTED_ENTRY_MAX, then it is old. */ static inline int is_omitted_entry(struct ll_statahead_info *sai, __u64 index) @@ -166,20 +166,17 @@ static inline int is_omitted_entry(struct ll_statahead_info *sai, __u64 index) sai->sai_index); } -/* - * Insert it into sai_entries tail when init. - */ -static struct ll_sa_entry * -ll_sa_entry_alloc(struct dentry *parent, - struct ll_statahead_info *sai, __u64 index, - const char *name, int len) +/* allocate sa_entry and hash it to allow scanner process to find it */ +static struct sa_entry * +sa_alloc(struct dentry *parent, struct ll_statahead_info *sai, __u64 index, + const char *name, int len) { struct ll_inode_info *lli; - struct ll_sa_entry *entry; + struct sa_entry *entry; int entry_size; char *dname; - entry_size = sizeof(struct ll_sa_entry) + (len & ~3) + 4; + entry_size = sizeof(struct sa_entry) + (len & ~3) + 4; entry = kzalloc(entry_size, GFP_NOFS); if (unlikely(!entry)) return ERR_PTR(-ENOMEM); @@ -188,34 +185,9 @@ ll_sa_entry_alloc(struct dentry *parent, len, name, entry, index); entry->se_index = index; - - /* - * Statahead entry reference rules: - * - * 1) When statahead entry is initialized, its reference is set as 2. - * One reference is used by the directory scanner. When the scanner - * searches the statahead cache for the given name, it can perform - * lockless hash lookup (only the scanner can remove entry from hash - * list), and once found, it needn't to call "atomic_inc()" for the - * entry reference. So the performance is improved. After using the - * statahead entry, the scanner will call "atomic_dec()" to drop the - * reference held when initialization. If it is the last reference, - * the statahead entry will be freed. - * - * 2) All other threads, including statahead thread and ptlrpcd thread, - * when they process the statahead entry, the reference for target - * should be held to guarantee the entry will not be released by the - * directory scanner. After processing the entry, these threads will - * drop the entry reference. If it is the last reference, the entry - * will be freed. - * - * The second reference when initializes the statahead entry is used - * by the statahead thread, following the rule 2). - */ - atomic_set(&entry->se_refcount, 2); - entry->se_stat = SA_ENTRY_INIT; + entry->se_state = SA_ENTRY_INIT; entry->se_size = entry_size; - dname = (char *)entry + sizeof(struct ll_sa_entry); + dname = (char *)entry + sizeof(struct sa_entry); memcpy(dname, name, len); dname[len] = 0; @@ -223,11 +195,10 @@ ll_sa_entry_alloc(struct dentry *parent, entry->se_qstr.len = len; entry->se_qstr.name = dname; - lli = ll_i2info(sai->sai_inode); + lli = ll_i2info(sai->sai_dentry->d_inode); spin_lock(&lli->lli_sa_lock); - list_add_tail(&entry->se_link, &sai->sai_entries); INIT_LIST_HEAD(&entry->se_list); - ll_sa_entry_enhash(sai, entry); + sa_rehash(sai, entry); spin_unlock(&lli->lli_sa_lock); atomic_inc(&sai->sai_cache_count); @@ -235,18 +206,29 @@ ll_sa_entry_alloc(struct dentry *parent, return entry; } -/* - * Used by the directory scanner to search entry with name. - * - * Only the caller can remove the entry from hash, so it is unnecessary to hold - * hash lock. It is caller's duty to release the init refcount on the entry, so - * it is also unnecessary to increase refcount on the entry. - */ -static struct ll_sa_entry * -ll_sa_entry_get_byname(struct ll_statahead_info *sai, const struct qstr *qstr) +/* free sa_entry, which should have been unhashed and not in any list */ +static void sa_free(struct ll_statahead_info *sai, struct sa_entry *entry) { - struct ll_sa_entry *entry; - int i = ll_sa_entry_hash(qstr->hash); + CDEBUG(D_READA, "free sa entry %.*s(%p) index %llu\n", + entry->se_qstr.len, entry->se_qstr.name, entry, + entry->se_index); + + LASSERT(list_empty(&entry->se_list)); + LASSERT(list_empty(&entry->se_hash)); + + kfree(entry); + atomic_dec(&sai->sai_cache_count); +} + +/* + * find sa_entry by name, used by directory scanner, lock is not needed because + * only scanner can remove the entry from cache. + */ +static struct sa_entry * +sa_get(struct ll_statahead_info *sai, const struct qstr *qstr) +{ + struct sa_entry *entry; + int i = sa_hash(qstr->hash); list_for_each_entry(entry, &sai->sai_cache[i], se_hash) { if (entry->se_qstr.hash == qstr->hash && @@ -257,36 +239,100 @@ ll_sa_entry_get_byname(struct ll_statahead_info *sai, const struct qstr *qstr) return NULL; } -/* - * Used by the async getattr request callback to find entry with index. - * - * Inside lli_sa_lock to prevent others to change the list during the search. - * It needs to increase entry refcount before returning to guarantee that the - * entry cannot be freed by others. - */ -static struct ll_sa_entry * -ll_sa_entry_get_byindex(struct ll_statahead_info *sai, __u64 index) +/* unhash and unlink sa_entry, and then free it */ +static inline void +sa_kill(struct ll_statahead_info *sai, struct sa_entry *entry) { - struct ll_sa_entry *entry; + struct ll_inode_info *lli = ll_i2info(sai->sai_dentry->d_inode); - list_for_each_entry(entry, &sai->sai_entries, se_link) { - if (entry->se_index == index) { - LASSERT(atomic_read(&entry->se_refcount) > 0); - atomic_inc(&entry->se_refcount); - return entry; - } - if (entry->se_index > index) - break; - } - return NULL; + LASSERT(!list_empty(&entry->se_hash)); + LASSERT(!list_empty(&entry->se_list)); + LASSERT(sa_ready(entry)); + + sa_unhash(sai, entry); + + spin_lock(&lli->lli_sa_lock); + list_del_init(&entry->se_list); + spin_unlock(&lli->lli_sa_lock); + + if (entry->se_inode) + iput(entry->se_inode); + + sa_free(sai, entry); } -static void ll_sa_entry_cleanup(struct ll_statahead_info *sai, - struct ll_sa_entry *entry) +/* called by scanner after use, sa_entry will be killed */ +static void +sa_put(struct ll_statahead_info *sai, struct sa_entry *entry) { - struct md_enqueue_info *minfo = entry->se_minfo; - struct ptlrpc_request *req = entry->se_req; + struct sa_entry *tmp, *next; + if (entry && entry->se_state == SA_ENTRY_SUCC) { + struct ll_sb_info *sbi = ll_i2sbi(sai->sai_dentry->d_inode); + + sai->sai_hit++; + sai->sai_consecutive_miss = 0; + sai->sai_max = min(2 * sai->sai_max, sbi->ll_sa_max); + } else { + sai->sai_miss++; + sai->sai_consecutive_miss++; + } + + if (entry) + sa_kill(sai, entry); + + /* + * kill old completed entries, only scanner process does this, no need + * to lock + */ + list_for_each_entry_safe(tmp, next, &sai->sai_entries, se_list) { + if (!is_omitted_entry(sai, tmp->se_index)) + break; + sa_kill(sai, tmp); + } + + wake_up(&sai->sai_thread.t_ctl_waitq); +} + +/* + * update state and sort add entry to sai_entries by index, return true if + * scanner is waiting on this entry. + */ +static bool +__sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) +{ + struct list_head *pos = &sai->sai_entries; + __u64 index = entry->se_index; + struct sa_entry *se; + + LASSERT(!sa_ready(entry)); + LASSERT(list_empty(&entry->se_list)); + + list_for_each_entry_reverse(se, &sai->sai_entries, se_list) { + if (se->se_index < entry->se_index) { + pos = &se->se_list; + break; + } + } + list_add(&entry->se_list, pos); + entry->se_state = ret < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC; + + return (index == sai->sai_index_wait); +} + +/* + * release resources used in async stat RPC, update entry state and wakeup if + * scanner process it waiting on this entry. + */ +static void +sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) +{ + struct ll_inode_info *lli = ll_i2info(sai->sai_dentry->d_inode); + struct md_enqueue_info *minfo = entry->se_minfo; + struct ptlrpc_request *req = entry->se_req; + bool wakeup; + + /* release resources used in RPC */ if (minfo) { entry->se_minfo = NULL; ll_intent_release(&minfo->mi_it); @@ -298,123 +344,21 @@ static void ll_sa_entry_cleanup(struct ll_statahead_info *sai, entry->se_req = NULL; ptlrpc_req_finished(req); } -} - -static void ll_sa_entry_put(struct ll_statahead_info *sai, - struct ll_sa_entry *entry) -{ - if (atomic_dec_and_test(&entry->se_refcount)) { - CDEBUG(D_READA, "free sa entry %.*s(%p) index %llu\n", - entry->se_qstr.len, entry->se_qstr.name, entry, - entry->se_index); - - LASSERT(list_empty(&entry->se_link)); - LASSERT(list_empty(&entry->se_list)); - LASSERT(list_empty(&entry->se_hash)); - - ll_sa_entry_cleanup(sai, entry); - iput(entry->se_inode); - - kfree(entry); - atomic_dec(&sai->sai_cache_count); - } -} - -static inline void -do_sa_entry_fini(struct ll_statahead_info *sai, struct ll_sa_entry *entry) -{ - struct ll_inode_info *lli = ll_i2info(sai->sai_inode); - - LASSERT(!list_empty(&entry->se_hash)); - LASSERT(!list_empty(&entry->se_link)); - - ll_sa_entry_unhash(sai, entry); spin_lock(&lli->lli_sa_lock); - entry->se_stat = SA_ENTRY_DEST; - list_del_init(&entry->se_link); - if (likely(!list_empty(&entry->se_list))) - list_del_init(&entry->se_list); + wakeup = __sa_make_ready(sai, entry, ret); spin_unlock(&lli->lli_sa_lock); - ll_sa_entry_put(sai, entry); + if (wakeup) + wake_up(&sai->sai_waitq); } -/* - * Delete it from sai_entries_stated list when fini. - */ -static void -ll_sa_entry_fini(struct ll_statahead_info *sai, struct ll_sa_entry *entry) -{ - struct ll_sa_entry *pos, *next; - - if (entry) - do_sa_entry_fini(sai, entry); - - /* drop old entry, only 'scanner' process does this, no need to lock */ - list_for_each_entry_safe(pos, next, &sai->sai_entries, se_link) { - if (!is_omitted_entry(sai, pos->se_index)) - break; - do_sa_entry_fini(sai, pos); - } -} - -/* - * Inside lli_sa_lock. - */ -static void -do_sa_entry_to_stated(struct ll_statahead_info *sai, - struct ll_sa_entry *entry, enum se_stat stat) -{ - struct ll_sa_entry *se; - struct list_head *pos = &sai->sai_entries_stated; - - if (!list_empty(&entry->se_list)) - list_del_init(&entry->se_list); - - list_for_each_entry_reverse(se, &sai->sai_entries_stated, se_list) { - if (se->se_index < entry->se_index) { - pos = &se->se_list; - break; - } - } - - list_add(&entry->se_list, pos); - entry->se_stat = stat; -} - -/* - * Move entry to sai_entries_stated and sort with the index. - * \retval 1 -- entry to be destroyed. - * \retval 0 -- entry is inserted into stated list. - */ -static int -ll_sa_entry_to_stated(struct ll_statahead_info *sai, - struct ll_sa_entry *entry, enum se_stat stat) -{ - struct ll_inode_info *lli = ll_i2info(sai->sai_inode); - int ret = 1; - - ll_sa_entry_cleanup(sai, entry); - - spin_lock(&lli->lli_sa_lock); - if (likely(entry->se_stat != SA_ENTRY_DEST)) { - do_sa_entry_to_stated(sai, entry, stat); - ret = 0; - } - spin_unlock(&lli->lli_sa_lock); - - return ret; -} - -/* - * Insert inode into the list of sai_entries_agl. - */ +/* Insert inode into the list of sai_agls. */ static void ll_agl_add(struct ll_statahead_info *sai, struct inode *inode, int index) { struct ll_inode_info *child = ll_i2info(inode); - struct ll_inode_info *parent = ll_i2info(sai->sai_inode); + struct ll_inode_info *parent = ll_i2info(sai->sai_dentry->d_inode); int added = 0; spin_lock(&child->lli_agl_lock); @@ -426,9 +370,9 @@ static void ll_agl_add(struct ll_statahead_info *sai, igrab(inode); spin_lock(&parent->lli_agl_lock); - if (list_empty(&sai->sai_entries_agl)) + if (list_empty(&sai->sai_agls)) added = 1; - list_add_tail(&child->lli_agl_list, &sai->sai_entries_agl); + list_add_tail(&child->lli_agl_list, &sai->sai_agls); spin_unlock(&parent->lli_agl_lock); } else { spin_unlock(&child->lli_agl_lock); @@ -438,8 +382,10 @@ static void ll_agl_add(struct ll_statahead_info *sai, wake_up(&sai->sai_agl_thread.t_ctl_waitq); } -static struct ll_statahead_info *ll_sai_alloc(void) +/* allocate sai */ +static struct ll_statahead_info *ll_sai_alloc(struct dentry *dentry) { + struct ll_inode_info *lli = ll_i2info(dentry->d_inode); struct ll_statahead_info *sai; int i; @@ -447,24 +393,18 @@ static struct ll_statahead_info *ll_sai_alloc(void) if (!sai) return NULL; + sai->sai_dentry = dget(dentry); atomic_set(&sai->sai_refcount, 1); - spin_lock(&sai_generation_lock); - sai->sai_generation = ++sai_generation; - if (unlikely(sai_generation == 0)) - sai->sai_generation = ++sai_generation; - spin_unlock(&sai_generation_lock); - sai->sai_max = LL_SA_RPC_MIN; sai->sai_index = 1; init_waitqueue_head(&sai->sai_waitq); init_waitqueue_head(&sai->sai_thread.t_ctl_waitq); init_waitqueue_head(&sai->sai_agl_thread.t_ctl_waitq); + INIT_LIST_HEAD(&sai->sai_interim_entries); INIT_LIST_HEAD(&sai->sai_entries); - INIT_LIST_HEAD(&sai->sai_entries_received); - INIT_LIST_HEAD(&sai->sai_entries_stated); - INIT_LIST_HEAD(&sai->sai_entries_agl); + INIT_LIST_HEAD(&sai->sai_agls); for (i = 0; i < LL_SA_CACHE_SIZE; i++) { INIT_LIST_HEAD(&sai->sai_cache[i]); @@ -472,63 +412,74 @@ static struct ll_statahead_info *ll_sai_alloc(void) } atomic_set(&sai->sai_cache_count, 0); + spin_lock(&sai_generation_lock); + lli->lli_sa_generation = ++sai_generation; + if (unlikely(!sai_generation)) + lli->lli_sa_generation = ++sai_generation; + spin_unlock(&sai_generation_lock); + return sai; } -static inline struct ll_statahead_info * -ll_sai_get(struct ll_statahead_info *sai) +/* free sai */ +static inline void ll_sai_free(struct ll_statahead_info *sai) { - atomic_inc(&sai->sai_refcount); + LASSERT(sai->sai_dentry); + dput(sai->sai_dentry); + kfree(sai); +} + +/* + * take refcount of sai if sai for @dir exists, which means statahead is on for + * this directory. + */ +static inline struct ll_statahead_info *ll_sai_get(struct inode *dir) +{ + struct ll_inode_info *lli = ll_i2info(dir); + struct ll_statahead_info *sai = NULL; + + spin_lock(&lli->lli_sa_lock); + sai = lli->lli_sai; + if (sai) + atomic_inc(&sai->sai_refcount); + spin_unlock(&lli->lli_sa_lock); + return sai; } +/* + * put sai refcount after use, if refcount reaches zero, free sai and sa_entries + * attached to it. + */ static void ll_sai_put(struct ll_statahead_info *sai) { - struct inode *inode = sai->sai_inode; - struct ll_inode_info *lli = ll_i2info(inode); + struct ll_inode_info *lli = ll_i2info(sai->sai_dentry->d_inode); if (atomic_dec_and_lock(&sai->sai_refcount, &lli->lli_sa_lock)) { - struct ll_sa_entry *entry, *next; - - if (unlikely(atomic_read(&sai->sai_refcount) > 0)) { - /* It is race case, the interpret callback just hold - * a reference count - */ - spin_unlock(&lli->lli_sa_lock); - return; - } - - LASSERT(!lli->lli_opendir_key); - LASSERT(thread_is_stopped(&sai->sai_thread)); - LASSERT(thread_is_stopped(&sai->sai_agl_thread)); + struct ll_sb_info *sbi = ll_i2sbi(sai->sai_dentry->d_inode); + struct sa_entry *entry, *next; lli->lli_sai = NULL; - lli->lli_opendir_pid = 0; spin_unlock(&lli->lli_sa_lock); - if (sai->sai_sent > sai->sai_replied) - CDEBUG(D_READA, "statahead for dir "DFID - " does not finish: [sent:%llu] [replied:%llu]\n", - PFID(&lli->lli_fid), - sai->sai_sent, sai->sai_replied); + LASSERT(thread_is_stopped(&sai->sai_thread)); + LASSERT(thread_is_stopped(&sai->sai_agl_thread)); + LASSERT(sai->sai_sent == sai->sai_replied); + LASSERT(!sa_has_callback(sai)); list_for_each_entry_safe(entry, next, &sai->sai_entries, - se_link) - do_sa_entry_fini(sai, entry); - - LASSERT(list_empty(&sai->sai_entries)); - LASSERT(list_empty(&sai->sai_entries_received)); - LASSERT(list_empty(&sai->sai_entries_stated)); + se_list) + sa_kill(sai, entry); LASSERT(atomic_read(&sai->sai_cache_count) == 0); - LASSERT(list_empty(&sai->sai_entries_agl)); + LASSERT(list_empty(&sai->sai_agls)); - iput(inode); - kfree(sai); + ll_sai_free(sai); + atomic_dec(&sbi->ll_sa_running); } } -/* Do NOT forget to drop inode refcount when into sai_entries_agl. */ +/* Do NOT forget to drop inode refcount when into sai_agls. */ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) { struct ll_inode_info *lli = ll_i2info(inode); @@ -588,29 +539,21 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) iput(inode); } -static void ll_post_statahead(struct ll_statahead_info *sai) +/* + * prepare inode for sa entry, add it into agl list, now sa_entry is ready + * to be used by scanner process. + */ +static void sa_instantiate(struct ll_statahead_info *sai, + struct sa_entry *entry) { - struct inode *dir = sai->sai_inode; + struct inode *dir = sai->sai_dentry->d_inode; struct inode *child; - struct ll_inode_info *lli = ll_i2info(dir); - struct ll_sa_entry *entry; struct md_enqueue_info *minfo; struct lookup_intent *it; struct ptlrpc_request *req; struct mdt_body *body; int rc = 0; - spin_lock(&lli->lli_sa_lock); - if (unlikely(list_empty(&sai->sai_entries_received))) { - spin_unlock(&lli->lli_sa_lock); - return; - } - entry = list_entry(sai->sai_entries_received.next, - struct ll_sa_entry, se_list); - atomic_inc(&entry->se_refcount); - list_del_init(&entry->se_list); - spin_unlock(&lli->lli_sa_lock); - LASSERT(entry->se_handle != 0); minfo = entry->se_minfo; @@ -632,7 +575,7 @@ static void ll_post_statahead(struct ll_statahead_info *sai) /* XXX: No fid in reply, this is probably cross-ref case. * SA can't handle it yet. */ - if (body->valid & OBD_MD_MDS) { + if (body->mbo_valid & OBD_MD_MDS) { rc = -EAGAIN; goto out; } @@ -641,7 +584,7 @@ static void ll_post_statahead(struct ll_statahead_info *sai) * revalidate. */ /* unlinked and re-created with the same name */ - if (unlikely(!lu_fid_eq(&minfo->mi_data.op_fid2, &body->fid1))) { + if (unlikely(!lu_fid_eq(&minfo->mi_data.op_fid2, &body->mbo_fid1))) { entry->se_inode = NULL; iput(child); child = NULL; @@ -659,8 +602,9 @@ static void ll_post_statahead(struct ll_statahead_info *sai) if (rc) goto out; - CDEBUG(D_DLMTRACE, "%s: setting l_data to inode "DFID"%p\n", + CDEBUG(D_READA, "%s: setting %.*s" DFID " l_data to inode %p\n", ll_get_fsname(child->i_sb, NULL, 0), + entry->se_qstr.len, entry->se_qstr.name, PFID(ll_inode2fid(child)), child); ll_set_lock_data(ll_i2sbi(dir)->ll_md_exp, child, it, NULL); @@ -670,34 +614,75 @@ static void ll_post_statahead(struct ll_statahead_info *sai) ll_agl_add(sai, child, entry->se_index); out: - /* The "ll_sa_entry_to_stated()" will drop related ldlm ibits lock - * reference count by calling "ll_intent_drop_lock()" in spite of the - * above operations failed or not. Do not worry about calling - * "ll_intent_drop_lock()" more than once. + /* + * sa_make_ready() will drop ldlm ibits lock refcount by calling + * ll_intent_drop_lock() in spite of failures. Do not worry about + * calling ll_intent_drop_lock() more than once. */ - rc = ll_sa_entry_to_stated(sai, entry, - rc < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC); - if (rc == 0 && entry->se_index == sai->sai_index_wait) - wake_up(&sai->sai_waitq); - ll_sa_entry_put(sai, entry); + sa_make_ready(sai, entry, rc); } +/* once there are async stat replies, instantiate sa_entry from replies */ +static void sa_handle_callback(struct ll_statahead_info *sai) +{ + struct ll_inode_info *lli; + + lli = ll_i2info(sai->sai_dentry->d_inode); + + while (sa_has_callback(sai)) { + struct sa_entry *entry; + + spin_lock(&lli->lli_sa_lock); + if (unlikely(!sa_has_callback(sai))) { + spin_unlock(&lli->lli_sa_lock); + break; + } + entry = list_entry(sai->sai_interim_entries.next, + struct sa_entry, se_list); + list_del_init(&entry->se_list); + spin_unlock(&lli->lli_sa_lock); + + sa_instantiate(sai, entry); + } +} + +/* + * callback for async stat, because this is called in ptlrpcd context, we only + * put sa_entry in sai_cb_entries list, and let sa_handle_callback() to really + * prepare inode and instantiate sa_entry later. + */ static int ll_statahead_interpret(struct ptlrpc_request *req, struct md_enqueue_info *minfo, int rc) { struct lookup_intent *it = &minfo->mi_it; struct inode *dir = minfo->mi_dir; struct ll_inode_info *lli = ll_i2info(dir); - struct ll_statahead_info *sai = NULL; - struct ll_sa_entry *entry; - __u64 handle = 0; - int wakeup; + struct ll_statahead_info *sai = lli->lli_sai; + struct sa_entry *entry = (struct sa_entry *)minfo->mi_cbdata; + __u64 handle = 0; + bool wakeup; if (it_disposition(it, DISP_LOOKUP_NEG)) rc = -ENOENT; - if (rc == 0) { - /* release ibits lock ASAP to avoid deadlock when statahead + /* + * because statahead thread will wait for all inflight RPC to finish, + * sai should be always valid, no need to refcount + */ + LASSERT(sai); + LASSERT(!thread_is_stopped(&sai->sai_thread)); + LASSERT(entry); + + CDEBUG(D_READA, "sa_entry %.*s rc %d\n", + entry->se_qstr.len, entry->se_qstr.name, rc); + + if (rc) { + ll_intent_release(it); + iput(dir); + kfree(minfo); + } else { + /* + * release ibits lock ASAP to avoid deadlock when statahead * thread enqueues lock on parent in readdir and another * process enqueues lock on child with parent lock held, eg. * unlink. @@ -707,65 +692,32 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, } spin_lock(&lli->lli_sa_lock); - /* stale entry */ - if (unlikely(!lli->lli_sai || - lli->lli_sai->sai_generation != minfo->mi_generation)) { - spin_unlock(&lli->lli_sa_lock); - rc = -ESTALE; - goto out; + if (rc) { + wakeup = __sa_make_ready(sai, entry, rc); } else { - sai = ll_sai_get(lli->lli_sai); - if (unlikely(!thread_is_running(&sai->sai_thread))) { - sai->sai_replied++; - spin_unlock(&lli->lli_sa_lock); - rc = -EBADFD; - goto out; - } - - entry = ll_sa_entry_get_byindex(sai, minfo->mi_cbdata); - if (!entry) { - sai->sai_replied++; - spin_unlock(&lli->lli_sa_lock); - rc = -EIDRM; - goto out; - } - - if (rc != 0) { - do_sa_entry_to_stated(sai, entry, SA_ENTRY_INVA); - wakeup = (entry->se_index == sai->sai_index_wait); - } else { - entry->se_minfo = minfo; - entry->se_req = ptlrpc_request_addref(req); - /* Release the async ibits lock ASAP to avoid deadlock - * when statahead thread tries to enqueue lock on parent - * for readpage and other tries to enqueue lock on child - * with parent's lock held, for example: unlink. - */ - entry->se_handle = handle; - wakeup = list_empty(&sai->sai_entries_received); - list_add_tail(&entry->se_list, - &sai->sai_entries_received); - } - sai->sai_replied++; - spin_unlock(&lli->lli_sa_lock); - - ll_sa_entry_put(sai, entry); - if (wakeup) - wake_up(&sai->sai_thread.t_ctl_waitq); + entry->se_minfo = minfo; + entry->se_req = ptlrpc_request_addref(req); + /* + * Release the async ibits lock ASAP to avoid deadlock + * when statahead thread tries to enqueue lock on parent + * for readpage and other tries to enqueue lock on child + * with parent's lock held, for example: unlink. + */ + entry->se_handle = handle; + wakeup = !sa_has_callback(sai); + list_add_tail(&entry->se_list, &sai->sai_interim_entries); } + sai->sai_replied++; + + if (wakeup) + wake_up(&sai->sai_thread.t_ctl_waitq); + spin_unlock(&lli->lli_sa_lock); -out: - if (rc != 0) { - ll_intent_release(it); - iput(dir); - kfree(minfo); - } - if (sai) - ll_sai_put(sai); return rc; } -static void sa_args_fini(struct md_enqueue_info *minfo, +/* finish async stat RPC arguments */ +static void sa_fini_data(struct md_enqueue_info *minfo, struct ldlm_enqueue_info *einfo) { LASSERT(minfo && einfo); @@ -777,12 +729,11 @@ static void sa_args_fini(struct md_enqueue_info *minfo, /** * prepare arguments for async stat RPC. */ -static int sa_args_init(struct inode *dir, struct inode *child, - struct ll_sa_entry *entry, struct md_enqueue_info **pmi, +static int sa_prep_data(struct inode *dir, struct inode *child, + struct sa_entry *entry, struct md_enqueue_info **pmi, struct ldlm_enqueue_info **pei) { const struct qstr *qstr = &entry->se_qstr; - struct ll_inode_info *lli = ll_i2info(dir); struct md_enqueue_info *minfo; struct ldlm_enqueue_info *einfo; struct md_op_data *op_data; @@ -808,8 +759,7 @@ static int sa_args_init(struct inode *dir, struct inode *child, minfo->mi_it.it_op = IT_GETATTR; minfo->mi_dir = igrab(dir); minfo->mi_cb = ll_statahead_interpret; - minfo->mi_generation = lli->lli_sai->sai_generation; - minfo->mi_cbdata = entry->se_index; + minfo->mi_cbdata = entry; einfo->ei_type = LDLM_IBITS; einfo->ei_mode = it_to_lock_mode(&minfo->mi_it); @@ -824,31 +774,33 @@ static int sa_args_init(struct inode *dir, struct inode *child, return 0; } -static int do_sa_lookup(struct inode *dir, struct ll_sa_entry *entry) +/* async stat for file not found in dcache */ +static int sa_lookup(struct inode *dir, struct sa_entry *entry) { struct md_enqueue_info *minfo; struct ldlm_enqueue_info *einfo; int rc; - rc = sa_args_init(dir, NULL, entry, &minfo, &einfo); + rc = sa_prep_data(dir, NULL, entry, &minfo, &einfo); if (rc) return rc; rc = md_intent_getattr_async(ll_i2mdexp(dir), minfo, einfo); - if (rc < 0) - sa_args_fini(minfo, einfo); + if (rc) + sa_fini_data(minfo, einfo); return rc; } /** - * similar to ll_revalidate_it(). - * \retval 1 -- dentry valid - * \retval 0 -- will send stat-ahead request - * \retval others -- prepare stat-ahead request failed + * async stat for file found in dcache, similar to .revalidate + * + * \retval 1 dentry valid, no RPC sent + * \retval 0 dentry invalid, will send async stat RPC + * \retval negative number upon error */ -static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, - struct dentry *dentry) +static int sa_revalidate(struct inode *dir, struct sa_entry *entry, + struct dentry *dentry) { struct inode *inode = d_inode(dentry); struct lookup_intent it = { .it_op = IT_GETATTR, @@ -872,7 +824,7 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, return 1; } - rc = sa_args_init(dir, inode, entry, &minfo, &einfo); + rc = sa_prep_data(dir, inode, entry, &minfo, &einfo); if (rc) { entry->se_inode = NULL; iput(inode); @@ -880,56 +832,50 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, } rc = md_intent_getattr_async(ll_i2mdexp(dir), minfo, einfo); - if (rc < 0) { + if (rc) { entry->se_inode = NULL; iput(inode); - sa_args_fini(minfo, einfo); + sa_fini_data(minfo, einfo); } return rc; } -static void ll_statahead_one(struct dentry *parent, const char *entry_name, - int entry_name_len) +/* async stat for file with @name */ +static void sa_statahead(struct dentry *parent, const char *name, int len) { struct inode *dir = d_inode(parent); struct ll_inode_info *lli = ll_i2info(dir); struct ll_statahead_info *sai = lli->lli_sai; struct dentry *dentry = NULL; - struct ll_sa_entry *entry; + struct sa_entry *entry; int rc; - int rc1; - entry = ll_sa_entry_alloc(parent, sai, sai->sai_index, entry_name, - entry_name_len); + entry = sa_alloc(parent, sai, sai->sai_index, name, len); if (IS_ERR(entry)) return; dentry = d_lookup(parent, &entry->se_qstr); if (!dentry) { - rc = do_sa_lookup(dir, entry); + rc = sa_lookup(dir, entry); } else { - rc = do_sa_revalidate(dir, entry, dentry); + rc = sa_revalidate(dir, entry, dentry); if (rc == 1 && agl_should_run(sai, d_inode(dentry))) ll_agl_add(sai, d_inode(dentry), entry->se_index); + } + if (dentry) dput(dentry); - } - if (rc) { - rc1 = ll_sa_entry_to_stated(sai, entry, - rc < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC); - if (rc1 == 0 && entry->se_index == sai->sai_index_wait) - wake_up(&sai->sai_waitq); - } else { + if (rc) + sa_make_ready(sai, entry, rc); + else sai->sai_sent++; - } sai->sai_index++; - /* drop one refcount on entry by ll_sa_entry_alloc */ - ll_sa_entry_put(sai, entry); } +/* async glimpse (agl) thread main function */ static int ll_agl_thread(void *arg) { struct dentry *parent = arg; @@ -937,10 +883,12 @@ static int ll_agl_thread(void *arg) struct ll_inode_info *plli = ll_i2info(dir); struct ll_inode_info *clli; struct ll_sb_info *sbi = ll_i2sbi(dir); - struct ll_statahead_info *sai = ll_sai_get(plli->lli_sai); - struct ptlrpc_thread *thread = &sai->sai_agl_thread; + struct ll_statahead_info *sai; + struct ptlrpc_thread *thread; struct l_wait_info lwi = { 0 }; + sai = ll_sai_get(dir); + thread = &sai->sai_agl_thread; thread->t_pid = current_pid(); CDEBUG(D_READA, "agl thread started: sai %p, parent %pd\n", sai, parent); @@ -959,7 +907,7 @@ static int ll_agl_thread(void *arg) while (1) { l_wait_event(thread->t_ctl_waitq, - !list_empty(&sai->sai_entries_agl) || + !list_empty(&sai->sai_agls) || !thread_is_running(thread), &lwi); @@ -970,8 +918,8 @@ static int ll_agl_thread(void *arg) /* The statahead thread maybe help to process AGL entries, * so check whether list empty again. */ - if (!list_empty(&sai->sai_entries_agl)) { - clli = list_entry(sai->sai_entries_agl.next, + if (!list_empty(&sai->sai_agls)) { + clli = list_entry(sai->sai_agls.next, struct ll_inode_info, lli_agl_list); list_del_init(&clli->lli_agl_list); spin_unlock(&plli->lli_agl_lock); @@ -983,8 +931,8 @@ static int ll_agl_thread(void *arg) spin_lock(&plli->lli_agl_lock); sai->sai_agl_valid = 0; - while (!list_empty(&sai->sai_entries_agl)) { - clli = list_entry(sai->sai_entries_agl.next, + while (!list_empty(&sai->sai_agls)) { + clli = list_entry(sai->sai_agls.next, struct ll_inode_info, lli_agl_list); list_del_init(&clli->lli_agl_list); spin_unlock(&plli->lli_agl_lock); @@ -1001,6 +949,7 @@ static int ll_agl_thread(void *arg) return 0; } +/* start agl thread */ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai) { struct ptlrpc_thread *thread = &sai->sai_agl_thread; @@ -1025,58 +974,71 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai) &lwi); } +/* statahead thread main function */ static int ll_statahead_thread(void *arg) { struct dentry *parent = arg; struct inode *dir = d_inode(parent); - struct ll_inode_info *plli = ll_i2info(dir); - struct ll_inode_info *clli; + struct ll_inode_info *lli = ll_i2info(dir); struct ll_sb_info *sbi = ll_i2sbi(dir); - struct ll_statahead_info *sai = ll_sai_get(plli->lli_sai); - struct ptlrpc_thread *thread = &sai->sai_thread; - struct ptlrpc_thread *agl_thread = &sai->sai_agl_thread; - struct page *page; + struct ll_statahead_info *sai; + struct ptlrpc_thread *sa_thread; + struct ptlrpc_thread *agl_thread; + struct page *page = NULL; __u64 pos = 0; int first = 0; int rc = 0; - struct ll_dir_chain chain; + struct md_op_data *op_data; struct l_wait_info lwi = { 0 }; - thread->t_pid = current_pid(); + sai = ll_sai_get(dir); + sa_thread = &sai->sai_thread; + agl_thread = &sai->sai_agl_thread; + sa_thread->t_pid = current_pid(); CDEBUG(D_READA, "statahead thread starting: sai %p, parent %pd\n", sai, parent); + op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, + LUSTRE_OPC_ANY, dir); + if (IS_ERR(op_data)) { + rc = PTR_ERR(op_data); + goto out; + } + + op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; + if (sbi->ll_flags & LL_SBI_AGL_ENABLED) ll_start_agl(parent, sai); atomic_inc(&sbi->ll_sa_total); - spin_lock(&plli->lli_sa_lock); - if (thread_is_init(thread)) + spin_lock(&lli->lli_sa_lock); + if (thread_is_init(sa_thread)) /* If someone else has changed the thread state * (e.g. already changed to SVC_STOPPING), we can't just * blindly overwrite that setting. */ - thread_set_flags(thread, SVC_RUNNING); - spin_unlock(&plli->lli_sa_lock); - wake_up(&thread->t_ctl_waitq); + thread_set_flags(sa_thread, SVC_RUNNING); + spin_unlock(&lli->lli_sa_lock); + wake_up(&sa_thread->t_ctl_waitq); - ll_dir_chain_init(&chain); - page = ll_get_dir_page(dir, pos, &chain); - - while (1) { + while (pos != MDS_DIR_END_OFF && thread_is_running(sa_thread)) { struct lu_dirpage *dp; struct lu_dirent *ent; + sai->sai_in_readpage = 1; + page = ll_get_dir_page(dir, op_data, pos); + sai->sai_in_readpage = 0; if (IS_ERR(page)) { rc = PTR_ERR(page); - CDEBUG(D_READA, "error reading dir "DFID" at %llu/%llu: [rc %d] [parent %u]\n", + CDEBUG(D_READA, "error reading dir "DFID" at %llu/%llu: opendir_pid = %u: rc = %d\n", PFID(ll_inode2fid(dir)), pos, sai->sai_index, - rc, plli->lli_opendir_pid); - goto out; + lli->lli_opendir_pid, rc); + break; } dp = page_address(page); - for (ent = lu_dirent_start(dp); ent; + for (ent = lu_dirent_start(dp); + ent && thread_is_running(sa_thread) && !sa_low_hit(sai); ent = lu_dirent_next(ent)) { __u64 hash; int namelen; @@ -1123,123 +1085,79 @@ static int ll_statahead_thread(void *arg) if (unlikely(++first == 1)) continue; -keep_it: - l_wait_event(thread->t_ctl_waitq, - !sa_sent_full(sai) || - !list_empty(&sai->sai_entries_received) || - !list_empty(&sai->sai_entries_agl) || - !thread_is_running(thread), - &lwi); + /* wait for spare statahead window */ + do { + l_wait_event(sa_thread->t_ctl_waitq, + !sa_sent_full(sai) || + sa_has_callback(sai) || + !list_empty(&sai->sai_agls) || + !thread_is_running(sa_thread), + &lwi); + sa_handle_callback(sai); -interpret_it: - while (!list_empty(&sai->sai_entries_received)) - ll_post_statahead(sai); + spin_lock(&lli->lli_agl_lock); + while (sa_sent_full(sai) && + !agl_list_empty(sai)) { + struct ll_inode_info *clli; - if (unlikely(!thread_is_running(thread))) { - ll_release_page(page, 0); - rc = 0; - goto out; - } - - /* If no window for metadata statahead, but there are - * some AGL entries to be triggered, then try to help - * to process the AGL entries. - */ - if (sa_sent_full(sai)) { - spin_lock(&plli->lli_agl_lock); - while (!list_empty(&sai->sai_entries_agl)) { - clli = list_entry(sai->sai_entries_agl.next, + clli = list_entry(sai->sai_agls.next, struct ll_inode_info, lli_agl_list); list_del_init(&clli->lli_agl_list); - spin_unlock(&plli->lli_agl_lock); + spin_unlock(&lli->lli_agl_lock); + ll_agl_trigger(&clli->lli_vfs_inode, sai); - if (!list_empty(&sai->sai_entries_received)) - goto interpret_it; - - if (unlikely( - !thread_is_running(thread))) { - ll_release_page(page, 0); - rc = 0; - goto out; - } - - if (!sa_sent_full(sai)) - goto do_it; - - spin_lock(&plli->lli_agl_lock); + spin_lock(&lli->lli_agl_lock); } - spin_unlock(&plli->lli_agl_lock); + spin_unlock(&lli->lli_agl_lock); + } while (sa_sent_full(sai) && + thread_is_running(sa_thread)); - goto keep_it; - } - -do_it: - ll_statahead_one(parent, name, namelen); + sa_statahead(parent, name, namelen); } + pos = le64_to_cpu(dp->ldp_hash_end); - if (pos == MDS_DIR_END_OFF) { - /* - * End of directory reached. - */ - ll_release_page(page, 0); - while (1) { - l_wait_event(thread->t_ctl_waitq, - !list_empty(&sai->sai_entries_received) || - sai->sai_sent == sai->sai_replied || - !thread_is_running(thread), - &lwi); + ll_release_page(dir, page, + le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - while (!list_empty(&sai->sai_entries_received)) - ll_post_statahead(sai); - - if (unlikely(!thread_is_running(thread))) { - rc = 0; - goto out; - } - - if (sai->sai_sent == sai->sai_replied && - list_empty(&sai->sai_entries_received)) - break; - } - - spin_lock(&plli->lli_agl_lock); - while (!list_empty(&sai->sai_entries_agl) && - thread_is_running(thread)) { - clli = list_entry(sai->sai_entries_agl.next, - struct ll_inode_info, lli_agl_list); - list_del_init(&clli->lli_agl_list); - spin_unlock(&plli->lli_agl_lock); - ll_agl_trigger(&clli->lli_vfs_inode, sai); - spin_lock(&plli->lli_agl_lock); - } - spin_unlock(&plli->lli_agl_lock); - - rc = 0; - goto out; - } else if (1) { - /* - * chain is exhausted. - * Normal case: continue to the next page. - */ - ll_release_page(page, le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - page = ll_get_dir_page(dir, pos, &chain); - } else { - LASSERT(le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - ll_release_page(page, 1); - /* - * go into overflow page. - */ + if (sa_low_hit(sai)) { + rc = -EFAULT; + atomic_inc(&sbi->ll_sa_wrong); + CDEBUG(D_READA, "Statahead for dir "DFID" hit ratio too low: hit/miss %llu/%llu, sent/replied %llu/%llu, stopping statahead thread: pid %d\n", + PFID(&lli->lli_fid), sai->sai_hit, + sai->sai_miss, sai->sai_sent, + sai->sai_replied, current_pid()); + break; } } + ll_finish_md_op_data(op_data); + if (rc < 0) { + spin_lock(&lli->lli_sa_lock); + thread_set_flags(sa_thread, SVC_STOPPING); + lli->lli_sa_enabled = 0; + spin_unlock(&lli->lli_sa_lock); + } + + /* + * statahead is finished, but statahead entries need to be cached, wait + * for file release to stop me. + */ + while (thread_is_running(sa_thread)) { + l_wait_event(sa_thread->t_ctl_waitq, + sa_has_callback(sai) || + !agl_list_empty(sai) || + !thread_is_running(sa_thread), + &lwi); + + sa_handle_callback(sai); + } out: if (sai->sai_agl_valid) { - spin_lock(&plli->lli_agl_lock); + spin_lock(&lli->lli_agl_lock); thread_set_flags(agl_thread, SVC_STOPPING); - spin_unlock(&plli->lli_agl_lock); + spin_unlock(&lli->lli_agl_lock); wake_up(&agl_thread->t_ctl_waitq); CDEBUG(D_READA, "stop agl thread: sai %p pid %u\n", @@ -1249,84 +1167,93 @@ out: &lwi); } else { /* Set agl_thread flags anyway. */ - thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED); + thread_set_flags(agl_thread, SVC_STOPPED); } - ll_dir_chain_fini(&chain); - spin_lock(&plli->lli_sa_lock); - if (!list_empty(&sai->sai_entries_received)) { - thread_set_flags(thread, SVC_STOPPING); - spin_unlock(&plli->lli_sa_lock); - /* To release the resources held by received entries. */ - while (!list_empty(&sai->sai_entries_received)) - ll_post_statahead(sai); - - spin_lock(&plli->lli_sa_lock); + /* + * wait for inflight statahead RPCs to finish, and then we can free sai + * safely because statahead RPC will access sai data + */ + while (sai->sai_sent != sai->sai_replied) { + /* in case we're not woken up, timeout wait */ + lwi = LWI_TIMEOUT(msecs_to_jiffies(MSEC_PER_SEC >> 3), + NULL, NULL); + l_wait_event(sa_thread->t_ctl_waitq, + sai->sai_sent == sai->sai_replied, &lwi); } - thread_set_flags(thread, SVC_STOPPED); - spin_unlock(&plli->lli_sa_lock); - wake_up(&sai->sai_waitq); - wake_up(&thread->t_ctl_waitq); - ll_sai_put(sai); - dput(parent); + + /* release resources held by statahead RPCs */ + sa_handle_callback(sai); + + spin_lock(&lli->lli_sa_lock); + thread_set_flags(sa_thread, SVC_STOPPED); + spin_unlock(&lli->lli_sa_lock); + CDEBUG(D_READA, "statahead thread stopped: sai %p, parent %pd\n", sai, parent); + + wake_up(&sai->sai_waitq); + wake_up(&sa_thread->t_ctl_waitq); + ll_sai_put(sai); + return rc; } -/** - * called in ll_file_release(). - */ -void ll_stop_statahead(struct inode *dir, void *key) +/* authorize opened dir handle @key to statahead */ +void ll_authorize_statahead(struct inode *dir, void *key) { struct ll_inode_info *lli = ll_i2info(dir); - if (unlikely(!key)) - return; + spin_lock(&lli->lli_sa_lock); + if (!lli->lli_opendir_key && !lli->lli_sai) { + /* + * if lli_sai is not NULL, it means previous statahead is not + * finished yet, we'd better not start a new statahead for now. + */ + LASSERT(!lli->lli_opendir_pid); + lli->lli_opendir_key = key; + lli->lli_opendir_pid = current_pid(); + lli->lli_sa_enabled = 1; + } + spin_unlock(&lli->lli_sa_lock); +} + +/* + * deauthorize opened dir handle @key to statahead, but statahead thread may + * still be running, notify it to quit. + */ +void ll_deauthorize_statahead(struct inode *dir, void *key) +{ + struct ll_inode_info *lli = ll_i2info(dir); + struct ll_statahead_info *sai; + + LASSERT(lli->lli_opendir_key == key); + LASSERT(lli->lli_opendir_pid); + + CDEBUG(D_READA, "deauthorize statahead for "DFID"\n", + PFID(&lli->lli_fid)); spin_lock(&lli->lli_sa_lock); - if (lli->lli_opendir_key != key || lli->lli_opendir_pid == 0) { - spin_unlock(&lli->lli_sa_lock); - return; - } - lli->lli_opendir_key = NULL; - - if (lli->lli_sai) { - struct l_wait_info lwi = { 0 }; - struct ptlrpc_thread *thread = &lli->lli_sai->sai_thread; - - if (!thread_is_stopped(thread)) { - thread_set_flags(thread, SVC_STOPPING); - spin_unlock(&lli->lli_sa_lock); - wake_up(&thread->t_ctl_waitq); - - CDEBUG(D_READA, "stop statahead thread: sai %p pid %u\n", - lli->lli_sai, (unsigned int)thread->t_pid); - l_wait_event(thread->t_ctl_waitq, - thread_is_stopped(thread), - &lwi); - } else { - spin_unlock(&lli->lli_sa_lock); - } - + lli->lli_opendir_pid = 0; + lli->lli_sa_enabled = 0; + sai = lli->lli_sai; + if (sai && thread_is_running(&sai->sai_thread)) { /* - * Put the ref which was held when first statahead_enter. - * It maybe not the last ref for some statahead requests - * maybe inflight. + * statahead thread may not quit yet because it needs to cache + * entries, now it's time to tell it to quit. */ - ll_sai_put(lli->lli_sai); - } else { - lli->lli_opendir_pid = 0; - spin_unlock(&lli->lli_sa_lock); + thread_set_flags(&sai->sai_thread, SVC_STOPPING); + wake_up(&sai->sai_thread.t_ctl_waitq); } + spin_unlock(&lli->lli_sa_lock); } enum { /** * not first dirent, or is "." */ - LS_NONE_FIRST_DE = 0, + LS_NOT_FIRST_DE = 0, /** * the first non-hidden dirent */ @@ -1337,17 +1264,26 @@ enum { LS_FIRST_DOT_DE }; +/* file is first dirent under @dir */ static int is_first_dirent(struct inode *dir, struct dentry *dentry) { - struct ll_dir_chain chain; const struct qstr *target = &dentry->d_name; + struct md_op_data *op_data; struct page *page; __u64 pos = 0; int dot_de; - int rc = LS_NONE_FIRST_DE; + int rc = LS_NOT_FIRST_DE; - ll_dir_chain_init(&chain); - page = ll_get_dir_page(dir, pos, &chain); + op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, + LUSTRE_OPC_ANY, dir); + if (IS_ERR(op_data)) + return PTR_ERR(op_data); + /** + * FIXME choose the start offset of the readdir + */ + op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; + + page = ll_get_dir_page(dir, op_data, pos); while (1) { struct lu_dirpage *dp; @@ -1357,9 +1293,10 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) struct ll_inode_info *lli = ll_i2info(dir); rc = PTR_ERR(page); - CERROR("error reading dir "DFID" at %llu: [rc %d] [parent %u]\n", + CERROR("%s: error reading dir "DFID" at %llu: opendir_pid = %u : rc = %d\n", + ll_get_fsname(dir->i_sb, NULL, 0), PFID(ll_inode2fid(dir)), pos, - rc, lli->lli_opendir_pid); + lli->lli_opendir_pid, rc); break; } @@ -1411,13 +1348,13 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) if (target->len != namelen || memcmp(target->name, name, namelen) != 0) - rc = LS_NONE_FIRST_DE; + rc = LS_NOT_FIRST_DE; else if (!dot_de) rc = LS_FIRST_DE; else rc = LS_FIRST_DOT_DE; - ll_release_page(page, 0); + ll_release_page(dir, page, false); goto out; } pos = le64_to_cpu(dp->ldp_hash_end); @@ -1425,261 +1362,228 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) /* * End of directory reached. */ - ll_release_page(page, 0); - break; - } else if (1) { + ll_release_page(dir, page, false); + goto out; + } else { /* * chain is exhausted * Normal case: continue to the next page. */ - ll_release_page(page, le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - page = ll_get_dir_page(dir, pos, &chain); - } else { - /* - * go into overflow page. - */ - LASSERT(le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - ll_release_page(page, 1); + ll_release_page(dir, page, + le32_to_cpu(dp->ldp_flags) & + LDF_COLLIDE); + page = ll_get_dir_page(dir, op_data, pos); } } - out: - ll_dir_chain_fini(&chain); + ll_finish_md_op_data(op_data); return rc; } -static void -ll_sai_unplug(struct ll_statahead_info *sai, struct ll_sa_entry *entry) +/** + * revalidate @dentryp from statahead cache + * + * \param[in] dir parent directory + * \param[in] sai sai structure + * \param[out] dentryp pointer to dentry which will be revalidated + * \param[in] unplug unplug statahead window only (normally for negative + * dentry) + * \retval 1 on success, dentry is saved in @dentryp + * \retval 0 if revalidation failed (no proper lock on client) + * \retval negative number upon error + */ +static int revalidate_statahead_dentry(struct inode *dir, + struct ll_statahead_info *sai, + struct dentry **dentryp, + bool unplug) { - struct ptlrpc_thread *thread = &sai->sai_thread; - struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); - int hit; + struct sa_entry *entry = NULL; + struct l_wait_info lwi = { 0 }; + struct ll_dentry_data *ldd; + struct ll_inode_info *lli; + int rc = 0; - if (entry && entry->se_stat == SA_ENTRY_SUCC) - hit = 1; - else - hit = 0; + if ((*dentryp)->d_name.name[0] == '.') { + if (sai->sai_ls_all || + sai->sai_miss_hidden >= sai->sai_skip_hidden) { + /* + * Hidden dentry is the first one, or statahead + * thread does not skip so many hidden dentries + * before "sai_ls_all" enabled as below. + */ + } else { + if (!sai->sai_ls_all) + /* + * It maybe because hidden dentry is not + * the first one, "sai_ls_all" was not + * set, then "ls -al" missed. Enable + * "sai_ls_all" for such case. + */ + sai->sai_ls_all = 1; - ll_sa_entry_fini(sai, entry); - if (hit) { - sai->sai_hit++; - sai->sai_consecutive_miss = 0; - sai->sai_max = min(2 * sai->sai_max, sbi->ll_sa_max); - } else { - struct ll_inode_info *lli = ll_i2info(sai->sai_inode); - - sai->sai_miss++; - sai->sai_consecutive_miss++; - if (sa_low_hit(sai) && thread_is_running(thread)) { - atomic_inc(&sbi->ll_sa_wrong); - CDEBUG(D_READA, "Statahead for dir " DFID " hit ratio too low: hit/miss %llu/%llu, sent/replied %llu/%llu, stopping statahead thread\n", - PFID(&lli->lli_fid), sai->sai_hit, - sai->sai_miss, sai->sai_sent, - sai->sai_replied); - spin_lock(&lli->lli_sa_lock); - if (!thread_is_stopped(thread)) - thread_set_flags(thread, SVC_STOPPING); - spin_unlock(&lli->lli_sa_lock); + /* + * Such "getattr" has been skipped before + * "sai_ls_all" enabled as above. + */ + sai->sai_miss_hidden++; + return -EAGAIN; } } - if (!thread_is_stopped(thread)) - wake_up(&thread->t_ctl_waitq); + if (unplug) { + rc = 1; + goto out_unplug; + } + + entry = sa_get(sai, &(*dentryp)->d_name); + if (!entry) { + rc = -EAGAIN; + goto out_unplug; + } + + /* if statahead is busy in readdir, help it do post-work */ + if (!sa_ready(entry) && sai->sai_in_readpage) + sa_handle_callback(sai); + + if (!sa_ready(entry)) { + sai->sai_index_wait = entry->se_index; + lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(30), NULL, + LWI_ON_SIGNAL_NOOP, NULL); + rc = l_wait_event(sai->sai_waitq, sa_ready(entry), &lwi); + if (rc < 0) { + /* + * entry may not be ready, so it may be used by inflight + * statahead RPC, don't free it. + */ + entry = NULL; + rc = -EAGAIN; + goto out_unplug; + } + } + + if (entry->se_state == SA_ENTRY_SUCC && entry->se_inode) { + struct inode *inode = entry->se_inode; + struct lookup_intent it = { .it_op = IT_GETATTR, + .it_lock_handle = entry->se_handle }; + __u64 bits; + + rc = md_revalidate_lock(ll_i2mdexp(dir), &it, + ll_inode2fid(inode), &bits); + if (rc == 1) { + if (!(*dentryp)->d_inode) { + struct dentry *alias; + + alias = ll_splice_alias(inode, *dentryp); + if (IS_ERR(alias)) { + rc = PTR_ERR(alias); + goto out_unplug; + } + *dentryp = alias; + /** + * statahead prepared this inode, transfer inode + * refcount from sa_entry to dentry + */ + entry->se_inode = NULL; + } else if ((*dentryp)->d_inode != inode) { + /* revalidate, but inode is recreated */ + CDEBUG(D_READA, + "%s: stale dentry %pd inode "DFID", statahead inode "DFID"\n", + ll_get_fsname((*dentryp)->d_inode->i_sb, + NULL, 0), + *dentryp, + PFID(ll_inode2fid((*dentryp)->d_inode)), + PFID(ll_inode2fid(inode))); + rc = -ESTALE; + goto out_unplug; + } + + if ((bits & MDS_INODELOCK_LOOKUP) && + d_lustre_invalid(*dentryp)) + d_lustre_revalidate(*dentryp); + ll_intent_release(&it); + } + } +out_unplug: + /* + * statahead cached sa_entry can be used only once, and will be killed + * right after use, so if lookup/revalidate accessed statahead cache, + * set dentry ldd_sa_generation to parent lli_sa_generation, later if we + * stat this file again, we know we've done statahead before, see + * dentry_may_statahead(). + */ + ldd = ll_d2d(*dentryp); + lli = ll_i2info(dir); + /* ldd can be NULL if llite lookup failed. */ + if (ldd) + ldd->lld_sa_generation = lli->lli_sa_generation; + sa_put(sai, entry); + return rc; } /** - * Start statahead thread if this is the first dir entry. - * Otherwise if a thread is started already, wait it until it is ahead of me. - * \retval 1 -- find entry with lock in cache, the caller needs to do - * nothing. - * \retval 0 -- find entry in cache, but without lock, the caller needs - * refresh from MDS. - * \retval others -- the caller need to process as non-statahead. + * start statahead thread + * + * \param[in] dir parent directory + * \param[in] dentry dentry that triggers statahead, normally the first + * dirent under @dir + * \retval -EAGAIN on success, because when this function is + * called, it's already in lookup call, so client should + * do it itself instead of waiting for statahead thread + * to do it asynchronously. + * \retval negative number upon error */ -int do_statahead_enter(struct inode *dir, struct dentry **dentryp, - int only_unplug) +static int start_statahead_thread(struct inode *dir, struct dentry *dentry) { - struct ll_inode_info *lli = ll_i2info(dir); - struct ll_statahead_info *sai = lli->lli_sai; - struct dentry *parent; - struct ll_sa_entry *entry; - struct ptlrpc_thread *thread; - struct l_wait_info lwi = { 0 }; + struct ll_inode_info *lli = ll_i2info(dir); + struct ll_statahead_info *sai = NULL; + struct l_wait_info lwi = { 0 }; + struct ptlrpc_thread *thread; struct task_struct *task; - int rc = 0; - struct ll_inode_info *plli; - - LASSERT(lli->lli_opendir_pid == current_pid()); - - if (sai) { - thread = &sai->sai_thread; - if (unlikely(thread_is_stopped(thread) && - list_empty(&sai->sai_entries_stated))) { - /* to release resource */ - ll_stop_statahead(dir, lli->lli_opendir_key); - return -EAGAIN; - } - - if ((*dentryp)->d_name.name[0] == '.') { - if (sai->sai_ls_all || - sai->sai_miss_hidden >= sai->sai_skip_hidden) { - /* - * Hidden dentry is the first one, or statahead - * thread does not skip so many hidden dentries - * before "sai_ls_all" enabled as below. - */ - } else { - if (!sai->sai_ls_all) - /* - * It maybe because hidden dentry is not - * the first one, "sai_ls_all" was not - * set, then "ls -al" missed. Enable - * "sai_ls_all" for such case. - */ - sai->sai_ls_all = 1; - - /* - * Such "getattr" has been skipped before - * "sai_ls_all" enabled as above. - */ - sai->sai_miss_hidden++; - return -EAGAIN; - } - } - - entry = ll_sa_entry_get_byname(sai, &(*dentryp)->d_name); - if (!entry || only_unplug) { - ll_sai_unplug(sai, entry); - return entry ? 1 : -EAGAIN; - } - - if (!ll_sa_entry_stated(entry)) { - sai->sai_index_wait = entry->se_index; - lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(30), NULL, - LWI_ON_SIGNAL_NOOP, NULL); - rc = l_wait_event(sai->sai_waitq, - ll_sa_entry_stated(entry) || - thread_is_stopped(thread), - &lwi); - if (rc < 0) { - ll_sai_unplug(sai, entry); - return -EAGAIN; - } - } - - if (entry->se_stat == SA_ENTRY_SUCC && entry->se_inode) { - struct inode *inode = entry->se_inode; - struct lookup_intent it = { .it_op = IT_GETATTR, - .it_lock_handle = - entry->se_handle }; - __u64 bits; - - rc = md_revalidate_lock(ll_i2mdexp(dir), &it, - ll_inode2fid(inode), &bits); - if (rc == 1) { - if (!d_inode(*dentryp)) { - struct dentry *alias; - - alias = ll_splice_alias(inode, - *dentryp); - if (IS_ERR(alias)) { - ll_sai_unplug(sai, entry); - return PTR_ERR(alias); - } - *dentryp = alias; - } else if (d_inode(*dentryp) != inode) { - /* revalidate, but inode is recreated */ - CDEBUG(D_READA, "%s: stale dentry %pd inode "DFID", statahead inode "DFID"\n", - ll_get_fsname(d_inode(*dentryp)->i_sb, NULL, 0), - *dentryp, - PFID(ll_inode2fid(d_inode(*dentryp))), - PFID(ll_inode2fid(inode))); - ll_sai_unplug(sai, entry); - return -ESTALE; - } else { - iput(inode); - } - entry->se_inode = NULL; - - if ((bits & MDS_INODELOCK_LOOKUP) && - d_lustre_invalid(*dentryp)) - d_lustre_revalidate(*dentryp); - ll_intent_release(&it); - } - } - - ll_sai_unplug(sai, entry); - return rc; - } + struct dentry *parent = dentry->d_parent; + int rc; /* I am the "lli_opendir_pid" owner, only me can set "lli_sai". */ - rc = is_first_dirent(dir, *dentryp); - if (rc == LS_NONE_FIRST_DE) { + rc = is_first_dirent(dir, dentry); + if (rc == LS_NOT_FIRST_DE) { /* It is not "ls -{a}l" operation, no need statahead for it. */ - rc = -EAGAIN; + rc = -EFAULT; goto out; } - sai = ll_sai_alloc(); + sai = ll_sai_alloc(parent); if (!sai) { rc = -ENOMEM; goto out; } sai->sai_ls_all = (rc == LS_FIRST_DOT_DE); - sai->sai_inode = igrab(dir); - if (unlikely(!sai->sai_inode)) { - CWARN("Do not start stat ahead on dying inode "DFID"\n", - PFID(&lli->lli_fid)); - rc = -ESTALE; - goto out; - } - - /* get parent reference count here, and put it in ll_statahead_thread */ - parent = dget((*dentryp)->d_parent); - if (unlikely(sai->sai_inode != d_inode(parent))) { - struct ll_inode_info *nlli = ll_i2info(d_inode(parent)); - - CWARN("Race condition, someone changed %pd just now: old parent "DFID", new parent "DFID"\n", - *dentryp, - PFID(&lli->lli_fid), PFID(&nlli->lli_fid)); - dput(parent); - iput(sai->sai_inode); - rc = -EAGAIN; - goto out; - } - - CDEBUG(D_READA, "start statahead thread: sai %p, parent %pd\n", - sai, parent); - - /* The sai buffer already has one reference taken at allocation time, - * but as soon as we expose the sai by attaching it to the lli that - * default reference can be dropped by another thread calling - * ll_stop_statahead. We need to take a local reference to protect - * the sai buffer while we intend to access it. + /* + * if current lli_opendir_key was deauthorized, or dir re-opened by + * another process, don't start statahead, otherwise the newly spawned + * statahead thread won't be notified to quit. */ - ll_sai_get(sai); + spin_lock(&lli->lli_sa_lock); + if (unlikely(lli->lli_sai || lli->lli_opendir_key || + lli->lli_opendir_pid != current->pid)) { + spin_unlock(&lli->lli_sa_lock); + rc = -EPERM; + goto out; + } lli->lli_sai = sai; + spin_unlock(&lli->lli_sa_lock); + + atomic_inc(&ll_i2sbi(parent->d_inode)->ll_sa_running); + + CDEBUG(D_READA, "start statahead thread: [pid %d] [parent %pd]\n", + current_pid(), parent); - plli = ll_i2info(d_inode(parent)); task = kthread_run(ll_statahead_thread, parent, "ll_sa_%u", - plli->lli_opendir_pid); + lli->lli_opendir_pid); thread = &sai->sai_thread; if (IS_ERR(task)) { rc = PTR_ERR(task); - CERROR("can't start ll_sa thread, rc: %d\n", rc); - dput(parent); - lli->lli_opendir_key = NULL; - thread_set_flags(thread, SVC_STOPPED); - thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED); - /* Drop both our own local reference and the default - * reference from allocation time. - */ - ll_sai_put(sai); - ll_sai_put(sai); - LASSERT(!lli->lli_sai); - return -EAGAIN; + CERROR("can't start ll_sa thread, rc : %d\n", rc); + goto out; } l_wait_event(thread->t_ctl_waitq, @@ -1694,10 +1598,47 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, return -EAGAIN; out: - kfree(sai); + /* + * once we start statahead thread failed, disable statahead so + * that subsequent stat won't waste time to try it. + */ spin_lock(&lli->lli_sa_lock); - lli->lli_opendir_key = NULL; - lli->lli_opendir_pid = 0; + lli->lli_sa_enabled = 0; + lli->lli_sai = NULL; spin_unlock(&lli->lli_sa_lock); + if (sai) + ll_sai_free(sai); return rc; } + +/** + * statahead entry function, this is called when client getattr on a file, it + * will start statahead thread if this is the first dir entry, else revalidate + * dentry from statahead cache. + * + * \param[in] dir parent directory + * \param[out] dentryp dentry to getattr + * \param[in] unplug unplug statahead window only (normally for negative + * dentry) + * \retval 1 on success + * \retval 0 revalidation from statahead cache failed, caller needs + * to getattr from server directly + * \retval negative number on error, caller often ignores this and + * then getattr from server + */ +int ll_statahead(struct inode *dir, struct dentry **dentryp, bool unplug) +{ + struct ll_statahead_info *sai; + + sai = ll_sai_get(dir); + if (sai) { + int rc; + + rc = revalidate_statahead_dentry(dir, sai, dentryp, unplug); + CDEBUG(D_READA, "revalidate statahead %pd: %d.\n", + *dentryp, rc); + ll_sai_put(sai); + return rc; + } + return start_statahead_thread(dir, *dentryp); +} diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 3dd7e0eb0b54..106cd00910a7 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -34,7 +34,6 @@ #include #include -#include "../include/lustre_lite.h" #include "../include/lustre_ha.h" #include "../include/lustre_dlm.h" #include @@ -83,8 +82,6 @@ struct super_operations lustre_super_operations = { }; MODULE_ALIAS_FS("lustre"); -void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg)); - static int __init lustre_init(void) { lnet_process_id_t lnet_id; @@ -102,8 +99,8 @@ static int __init lustre_init(void) rc = -ENOMEM; ll_inode_cachep = kmem_cache_create("lustre_inode_cache", - sizeof(struct ll_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT, + sizeof(struct ll_inode_info), 0, + SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT, NULL); if (!ll_inode_cachep) goto out_cache; diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 8c8bdfe1ad71..f8bc7ed59646 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c @@ -35,7 +35,6 @@ #include #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" static int ll_readlink_internal(struct inode *inode, @@ -80,17 +79,17 @@ static int ll_readlink_internal(struct inode *inode, } body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY); - if ((body->valid & OBD_MD_LINKNAME) == 0) { + if ((body->mbo_valid & OBD_MD_LINKNAME) == 0) { CERROR("OBD_MD_LINKNAME not set on reply\n"); rc = -EPROTO; goto failed; } LASSERT(symlen != 0); - if (body->eadatasize != symlen) { + if (body->mbo_eadatasize != symlen) { CERROR("%s: inode "DFID": symlink length %d not expected %d\n", ll_get_fsname(inode->i_sb, NULL, 0), - PFID(ll_inode2fid(inode)), body->eadatasize - 1, + PFID(ll_inode2fid(inode)), body->mbo_eadatasize - 1, symlen - 1); rc = -EPROTO; goto failed; @@ -155,8 +154,8 @@ const struct inode_operations ll_fast_symlink_inode_operations = { .get_link = ll_get_link, .getattr = ll_getattr, .permission = ll_inode_permission, - .setxattr = ll_setxattr, - .getxattr = ll_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ll_listxattr, - .removexattr = ll_removexattr, + .removexattr = generic_removexattr, }; diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index e623216e962d..8aa8ecc09a48 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -38,7 +38,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "vvp_internal.h" @@ -368,12 +367,6 @@ int cl_sb_fini(struct super_block *sb) CERROR("Cannot cleanup cl-stack due to memory shortage.\n"); result = PTR_ERR(env); } - /* - * If mount failed (sbi->ll_cl == NULL), and this there are no other - * mounts, stop device types manually (this usually happens - * automatically when last device is destroyed). - */ - lu_types_stop(); return result; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 79fc428461ed..5802da81cd0e 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -217,11 +217,12 @@ struct vvp_object { struct list_head vob_pending_list; /** - * Access this counter is protected by inode->i_sem. Now that - * the lifetime of transient pages must be covered by inode sem, - * we don't need to hold any lock.. + * Number of transient pages. This is no longer protected by i_sem, + * and needs to be atomic. This is not actually used for anything, + * and can probably be removed. */ - int vob_transient_pages; + atomic_t vob_transient_pages; + /** * Number of outstanding mmaps on this file. * @@ -247,9 +248,9 @@ struct vvp_object { */ struct vvp_page { struct cl_page_slice vpg_cl; - int vpg_defer_uptodate; - int vpg_ra_used; - int vpg_write_queued; + unsigned int vpg_defer_uptodate:1, + vpg_ra_used:1, + vpg_write_queued:1; /** * Non-empty iff this page is already counted in * vvp_object::vob_pending_list. This list is only used as a flag, diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 94916dcc6caa..2ab450359b6d 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -38,7 +38,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "vvp_internal.h" @@ -628,7 +627,7 @@ static int vvp_io_setattr_time(const struct lu_env *env, attr->cat_mtime = io->u.ci_setattr.sa_attr.lvb_mtime; valid |= CAT_MTIME; } - result = cl_object_attr_set(env, obj, attr, valid); + result = cl_object_attr_update(env, obj, attr, valid); cl_object_attr_unlock(obj); return result; @@ -821,7 +820,7 @@ static void write_commit_callback(const struct lu_env *env, struct cl_io *io, cl_page_disown(env, io, page); /* held in ll_cl_init() */ - lu_ref_del(&page->cp_reference, "cl_io", io); + lu_ref_del(&page->cp_reference, "cl_io", cl_io_top(io)); cl_page_put(env, page); } @@ -959,10 +958,30 @@ static int vvp_io_write_start(const struct lu_env *env, CDEBUG(D_VFSTRACE, "write: [%lli, %lli)\n", pos, pos + (long long)cnt); - if (!vio->vui_iter) /* from a temp io in ll_cl_init(). */ + if (!vio->vui_iter) { + /* from a temp io in ll_cl_init(). */ result = 0; - else - result = generic_file_write_iter(vio->vui_iocb, vio->vui_iter); + } else { + /* + * When using the locked AIO function (generic_file_aio_write()) + * testing has shown the inode mutex to be a limiting factor + * with multi-threaded single shared file performance. To get + * around this, we now use the lockless version. To maintain + * consistency, proper locking to protect against writes, + * trucates, etc. is handled in the higher layers of lustre. + */ + bool lock_node = !IS_NOSEC(inode); + + if (lock_node) + inode_lock(inode); + result = __generic_file_write_iter(vio->vui_iocb, + vio->vui_iter); + if (lock_node) + inode_unlock(inode); + + if (result > 0 || result == -EIOCBQUEUED) + result = generic_write_sync(vio->vui_iocb, result); + } if (result > 0) { result = vvp_io_write_commit(env, io); diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c index 64be0c9df35b..07eb26cc43f5 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_lock.c +++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c @@ -37,7 +37,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "vvp_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 2c520b0bf6ca..b57195d15674 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -39,7 +39,6 @@ #include "../../include/linux/libcfs/libcfs.h" #include "../include/obd.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "vvp_internal.h" @@ -68,8 +67,8 @@ static int vvp_object_print(const struct lu_env *env, void *cookie, (*p)(env, cookie, "(%s %d %d) inode: %p ", list_empty(&obj->vob_pending_list) ? "-" : "+", - obj->vob_transient_pages, atomic_read(&obj->vob_mmap_cnt), - inode); + atomic_read(&obj->vob_transient_pages), + atomic_read(&obj->vob_mmap_cnt), inode); if (inode) { lli = ll_i2info(inode); (*p)(env, cookie, "%lu/%u %o %u %d %p "DFID, @@ -102,8 +101,8 @@ static int vvp_attr_get(const struct lu_env *env, struct cl_object *obj, return 0; /* layers below have to fill in the rest */ } -static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid) +static int vvp_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid) { struct inode *inode = vvp_object_inode(obj); @@ -120,7 +119,7 @@ static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj, if (0 && valid & CAT_SIZE) i_size_write(inode, attr->cat_size); /* not currently necessary */ - if (0 && valid & (CAT_UID|CAT_GID|CAT_SIZE)) + if (0 && valid & (CAT_UID | CAT_GID | CAT_SIZE)) mark_inode_dirty(inode); return 0; } @@ -210,7 +209,7 @@ static const struct cl_object_operations vvp_ops = { .coo_lock_init = vvp_lock_init, .coo_io_init = vvp_io_init, .coo_attr_get = vvp_attr_get, - .coo_attr_set = vvp_attr_set, + .coo_attr_update = vvp_attr_update, .coo_conf_set = vvp_conf_set, .coo_prune = vvp_prune, .coo_glimpse = vvp_object_glimpse @@ -221,7 +220,7 @@ static int vvp_object_init0(const struct lu_env *env, const struct cl_object_conf *conf) { vob->vob_inode = conf->coc_inode; - vob->vob_transient_pages = 0; + atomic_set(&vob->vob_transient_pages, 0); cl_object_page_init(&vob->vob_cl, sizeof(struct vvp_page)); return 0; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 2e566d90bb94..5d79efc1aafe 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -44,8 +44,6 @@ #include #include -#include "../include/lustre_lite.h" - #include "llite_internal.h" #include "vvp_internal.h" @@ -249,7 +247,7 @@ static void vvp_vmpage_error(struct inode *inode, struct page *vmpage, int ioret set_bit(AS_EIO, &inode->i_mapping->flags); if ((ioret == -ESHUTDOWN || ioret == -EINTR) && - obj->vob_discard_page_warned == 0) { + obj->vob_discard_page_warned == 0) { obj->vob_discard_page_warned = 1; ll_dirty_page_discard_warn(vmpage, ioret); } @@ -444,18 +442,10 @@ static int vvp_transient_page_prep(const struct lu_env *env, return 0; } -static void vvp_transient_page_verify(const struct cl_page *page) -{ - struct inode *inode = vvp_object_inode(page->cp_obj); - - LASSERT(!inode_trylock(inode)); -} - static int vvp_transient_page_own(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused, int nonblock) { - vvp_transient_page_verify(slice->cpl_page); return 0; } @@ -463,21 +453,18 @@ static void vvp_transient_page_assume(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { - vvp_transient_page_verify(slice->cpl_page); } static void vvp_transient_page_unassume(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { - vvp_transient_page_verify(slice->cpl_page); } static void vvp_transient_page_disown(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { - vvp_transient_page_verify(slice->cpl_page); } static void vvp_transient_page_discard(const struct lu_env *env, @@ -486,8 +473,6 @@ static void vvp_transient_page_discard(const struct lu_env *env, { struct cl_page *page = slice->cpl_page; - vvp_transient_page_verify(slice->cpl_page); - /* * For transient pages, remove it from the radix tree. */ @@ -511,7 +496,6 @@ vvp_transient_page_completion(const struct lu_env *env, const struct cl_page_slice *slice, int ioret) { - vvp_transient_page_verify(slice->cpl_page); } static void vvp_transient_page_fini(const struct lu_env *env, @@ -522,8 +506,7 @@ static void vvp_transient_page_fini(const struct lu_env *env, struct vvp_object *clobj = cl2vvp(clp->cp_obj); vvp_page_fini_common(vpg); - LASSERT(!inode_trylock(clobj->vob_inode)); - clobj->vob_transient_pages--; + atomic_dec(&clobj->vob_transient_pages); } static const struct cl_page_operations vvp_transient_page_ops = { @@ -549,7 +532,7 @@ static const struct cl_page_operations vvp_transient_page_ops = { }; int vvp_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, pgoff_t index) + struct cl_page *page, pgoff_t index) { struct vvp_page *vpg = cl_object_page_slice(obj, page); struct page *vmpage = page->cp_vmpage; @@ -570,10 +553,9 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, } else { struct vvp_object *clobj = cl2vvp(obj); - LASSERT(!inode_trylock(clobj->vob_inode)); cl_page_slice_add(page, &vpg->vpg_cl, obj, index, &vvp_transient_page_ops); - clobj->vob_transient_pages++; + atomic_inc(&clobj->vob_transient_pages); } return 0; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_req.c b/drivers/staging/lustre/lustre/llite/vvp_req.c index 9fe9d6c0a7d1..e3f4c790d646 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_req.c +++ b/drivers/staging/lustre/lustre/llite/vvp_req.c @@ -32,7 +32,6 @@ #include "../include/cl_object.h" #include "../include/obd.h" #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "vvp_internal.h" @@ -83,8 +82,10 @@ static void vvp_req_attr_set(const struct lu_env *env, } obdo_from_inode(oa, inode, valid_flags & flags); obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); + if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_INVALID_PFID)) + oa->o_parent_oid++; memcpy(attr->cra_jobid, ll_i2info(inode)->lli_jobid, - JOBSTATS_JOBID_SIZE); + LUSTRE_JOBID_SIZE); } static void vvp_req_completion(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 98303cf85815..e070adb7a3cc 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -38,21 +38,12 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_ver.h" #include "../include/lustre_eacl.h" #include "llite_internal.h" -#define XATTR_USER_T (1) -#define XATTR_TRUSTED_T (2) -#define XATTR_SECURITY_T (3) -#define XATTR_ACL_ACCESS_T (4) -#define XATTR_ACL_DEFAULT_T (5) -#define XATTR_LUSTRE_T (6) -#define XATTR_OTHER_T (7) - static int get_xattr_type(const char *name) { @@ -99,46 +90,57 @@ int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type) return 0; } -static -int ll_setxattr_common(struct inode *inode, const char *name, - const void *value, size_t size, - int flags, __u64 valid) +static int +ll_xattr_set_common(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) { + char fullname[strlen(handler->prefix) + strlen(name) + 1]; struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req = NULL; - int xattr_type, rc; const char *pv = value; + __u64 valid; + int rc; - xattr_type = get_xattr_type(name); - rc = xattr_type_filter(sbi, xattr_type); + if (flags == XATTR_REPLACE) { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1); + valid = OBD_MD_FLXATTRRM; + } else { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1); + valid = OBD_MD_FLXATTR; + } + + rc = xattr_type_filter(sbi, handler->flags); if (rc) return rc; - if ((xattr_type == XATTR_ACL_ACCESS_T || - xattr_type == XATTR_ACL_DEFAULT_T) && + if ((handler->flags == XATTR_ACL_ACCESS_T || + handler->flags == XATTR_ACL_DEFAULT_T) && !inode_owner_or_capable(inode)) return -EPERM; /* b10667: ignore lustre special xattr for now */ - if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) || - (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0)) + if ((handler->flags == XATTR_TRUSTED_T && !strcmp(name, "lov")) || + (handler->flags == XATTR_LUSTRE_T && !strcmp(name, "lov"))) return 0; /* b15587: ignore security.capability xattr for now */ - if ((xattr_type == XATTR_SECURITY_T && - strcmp(name, "security.capability") == 0)) + if ((handler->flags == XATTR_SECURITY_T && + !strcmp(name, "capability"))) return 0; /* LU-549: Disable security.selinux when selinux is disabled */ - if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && - strcmp(name, "security.selinux") == 0) + if (handler->flags == XATTR_SECURITY_T && !selinux_is_enabled() && + strcmp(name, "selinux") == 0) return -EOPNOTSUPP; + sprintf(fullname, "%s%s\n", handler->prefix, name); rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), - valid, name, pv, size, 0, flags, + valid, fullname, pv, size, 0, flags, ll_i2suppgid(inode), &req); if (rc) { - if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { + if (rc == -EOPNOTSUPP && handler->flags == XATTR_USER_T) { LCONSOLE_INFO("Disabling user_xattr feature because it is not supported on the server\n"); sbi->ll_flags &= ~LL_SBI_USER_XATTR; } @@ -149,8 +151,10 @@ int ll_setxattr_common(struct inode *inode, const char *name, return 0; } -int ll_setxattr(struct dentry *dentry, struct inode *inode, - const char *name, const void *value, size_t size, int flags) +static int ll_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) { LASSERT(inode); LASSERT(name); @@ -158,20 +162,24 @@ int ll_setxattr(struct dentry *dentry, struct inode *inode, CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), xattr %s\n", PFID(ll_inode2fid(inode)), inode, name); - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1); - - if ((strncmp(name, XATTR_TRUSTED_PREFIX, - sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 && - strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) || - (strncmp(name, XATTR_LUSTRE_PREFIX, - sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 && - strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) { + if (!strcmp(name, "lov")) { struct lov_user_md *lump = (struct lov_user_md *)value; + int op_type = flags == XATTR_REPLACE ? LPROC_LL_REMOVEXATTR : + LPROC_LL_SETXATTR; int rc = 0; + ll_stats_ops_tally(ll_i2sbi(inode), op_type, 1); + if (size != 0 && size < sizeof(struct lov_user_md)) return -EINVAL; + /* + * It is possible to set an xattr to a "" value of zero size. + * For this case we are going to treat it as a removal. + */ + if (!size && lump) + lump = NULL; + /* Attributes that are saved via getxattr will always have * the stripe_offset as 0. Instead, the MDS should be * allowed to pick the starting OST index. b=17846 @@ -181,12 +189,15 @@ int ll_setxattr(struct dentry *dentry, struct inode *inode, if (lump && S_ISREG(inode->i_mode)) { __u64 it_flags = FMODE_WRITE; - int lum_size = (lump->lmm_magic == LOV_USER_MAGIC_V1) ? - sizeof(*lump) : sizeof(struct lov_user_md_v3); + int lum_size; + + lum_size = ll_lov_user_md_size(lump); + if (lum_size < 0 || size < lum_size) + return 0; /* b=10667: ignore error */ rc = ll_lov_setstripe_ea_info(inode, dentry, it_flags, lump, lum_size); - /* b10667: rc always be 0 here for now */ + /* b=10667: rc always be 0 here for now */ rc = 0; } else if (S_ISDIR(inode->i_mode)) { rc = ll_dir_setstripe(inode, lump, 0); @@ -194,92 +205,27 @@ int ll_setxattr(struct dentry *dentry, struct inode *inode, return rc; - } else if (strcmp(name, XATTR_NAME_LMA) == 0 || - strcmp(name, XATTR_NAME_LINK) == 0) + } else if (!strcmp(name, "lma") || !strcmp(name, "link")) { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1); return 0; + } - return ll_setxattr_common(inode, name, value, size, flags, - OBD_MD_FLXATTR); + return ll_xattr_set_common(handler, dentry, inode, name, value, size, + flags); } -int ll_removexattr(struct dentry *dentry, const char *name) -{ - struct inode *inode = d_inode(dentry); - - LASSERT(inode); - LASSERT(name); - - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), xattr %s\n", - PFID(ll_inode2fid(inode)), inode, name); - - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1); - return ll_setxattr_common(inode, name, NULL, 0, 0, - OBD_MD_FLXATTRRM); -} - -static -int ll_getxattr_common(struct inode *inode, const char *name, - void *buffer, size_t size, __u64 valid) +int +ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer, + size_t size, __u64 valid) { + struct ll_inode_info *lli = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req = NULL; struct mdt_body *body; - int xattr_type, rc; void *xdata; - struct ll_inode_info *lli = ll_i2info(inode); + int rc; - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", - PFID(ll_inode2fid(inode)), inode); - - /* listxattr have slightly different behavior from of ext3: - * without 'user_xattr' ext3 will list all xattr names but - * filtered out "^user..*"; we list them all for simplicity. - */ - if (!name) { - xattr_type = XATTR_OTHER_T; - goto do_getxattr; - } - - xattr_type = get_xattr_type(name); - rc = xattr_type_filter(sbi, xattr_type); - if (rc) - return rc; - - /* b15587: ignore security.capability xattr for now */ - if ((xattr_type == XATTR_SECURITY_T && - strcmp(name, "security.capability") == 0)) - return -ENODATA; - - /* LU-549: Disable security.selinux when selinux is disabled */ - if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && - strcmp(name, "security.selinux") == 0) - return -EOPNOTSUPP; - -#ifdef CONFIG_FS_POSIX_ACL - /* posix acl is under protection of LOOKUP lock. when calling to this, - * we just have path resolution to the target inode, so we have great - * chance that cached ACL is uptodate. - */ - if (xattr_type == XATTR_ACL_ACCESS_T) { - struct posix_acl *acl; - - spin_lock(&lli->lli_lock); - acl = posix_acl_dup(lli->lli_posix_acl); - spin_unlock(&lli->lli_lock); - - if (!acl) - return -ENODATA; - - rc = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); - posix_acl_release(acl); - return rc; - } - if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode)) - return -ENODATA; -#endif - -do_getxattr: - if (sbi->ll_xattr_cache_enabled && xattr_type != XATTR_ACL_ACCESS_T) { + if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T) { rc = ll_xattr_cache_get(inode, name, buffer, size, valid); if (rc == -EAGAIN) goto getxattr_nocache; @@ -311,36 +257,36 @@ getxattr_nocache: /* only detect the xattr size */ if (size == 0) { - rc = body->eadatasize; + rc = body->mbo_eadatasize; goto out; } - if (size < body->eadatasize) { + if (size < body->mbo_eadatasize) { CERROR("server bug: replied size %u > %u\n", - body->eadatasize, (int)size); + body->mbo_eadatasize, (int)size); rc = -ERANGE; goto out; } - if (body->eadatasize == 0) { + if (body->mbo_eadatasize == 0) { rc = -ENODATA; goto out; } /* do not need swab xattr data */ xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, - body->eadatasize); + body->mbo_eadatasize); if (!xdata) { rc = -EFAULT; goto out; } - memcpy(buffer, xdata, body->eadatasize); - rc = body->eadatasize; + memcpy(buffer, xdata, body->mbo_eadatasize); + rc = body->mbo_eadatasize; } out_xattr: - if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { + if (rc == -EOPNOTSUPP && type == XATTR_USER_T) { LCONSOLE_INFO( "%s: disabling user_xattr feature because it is not supported on the server: rc = %d\n", ll_get_fsname(inode->i_sb, NULL, 0), rc); @@ -351,8 +297,65 @@ out: return rc; } -ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *buffer, size_t size) +static int ll_xattr_get_common(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) +{ + char fullname[strlen(handler->prefix) + strlen(name) + 1]; + struct ll_sb_info *sbi = ll_i2sbi(inode); +#ifdef CONFIG_FS_POSIX_ACL + struct ll_inode_info *lli = ll_i2info(inode); +#endif + int rc; + + CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", + PFID(ll_inode2fid(inode)), inode); + + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); + + rc = xattr_type_filter(sbi, handler->flags); + if (rc) + return rc; + + /* b15587: ignore security.capability xattr for now */ + if ((handler->flags == XATTR_SECURITY_T && !strcmp(name, "capability"))) + return -ENODATA; + + /* LU-549: Disable security.selinux when selinux is disabled */ + if (handler->flags == XATTR_SECURITY_T && !selinux_is_enabled() && + !strcmp(name, "selinux")) + return -EOPNOTSUPP; + +#ifdef CONFIG_FS_POSIX_ACL + /* posix acl is under protection of LOOKUP lock. when calling to this, + * we just have path resolution to the target inode, so we have great + * chance that cached ACL is uptodate. + */ + if (handler->flags == XATTR_ACL_ACCESS_T) { + struct posix_acl *acl; + + spin_lock(&lli->lli_lock); + acl = posix_acl_dup(lli->lli_posix_acl); + spin_unlock(&lli->lli_lock); + + if (!acl) + return -ENODATA; + + rc = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); + posix_acl_release(acl); + return rc; + } + if (handler->flags == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode)) + return -ENODATA; +#endif + sprintf(fullname, "%s%s\n", handler->prefix, name); + return ll_xattr_list(inode, fullname, handler->flags, buffer, size, + OBD_MD_FLXATTR); +} + +static int ll_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { LASSERT(inode); LASSERT(name); @@ -360,36 +363,23 @@ ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), xattr %s\n", PFID(ll_inode2fid(inode)), inode, name); - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); - - if ((strncmp(name, XATTR_TRUSTED_PREFIX, - sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 && - strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) || - (strncmp(name, XATTR_LUSTRE_PREFIX, - sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 && - strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) { + if (!strcmp(name, "lov")) { struct lov_stripe_md *lsm; struct lov_user_md *lump; struct lov_mds_md *lmm = NULL; struct ptlrpc_request *request = NULL; int rc = 0, lmmsize = 0; + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); + if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) return -ENODATA; - if (size == 0 && S_ISDIR(inode->i_mode)) { - /* XXX directory EA is fix for now, optimize to save - * RPC transfer - */ - rc = sizeof(struct lov_user_md); - goto out; - } - lsm = ccc_inode_lsm_get(inode); if (!lsm) { if (S_ISDIR(inode->i_mode)) { - rc = ll_dir_getstripe(inode, &lmm, - &lmmsize, &request); + rc = ll_dir_getstripe(inode, (void **)&lmm, + &lmmsize, &request, 0); } else { rc = -ENODATA; } @@ -439,7 +429,7 @@ out: return rc; } - return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR); + return ll_xattr_get_common(handler, dentry, inode, name, buffer, size); } ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) @@ -457,7 +447,8 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1); - rc = ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS); + rc = ll_xattr_list(inode, NULL, XATTR_OTHER_T, buffer, size, + OBD_MD_FLXATTRLS); if (rc < 0) goto out; @@ -488,7 +479,8 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) if (!ll_i2info(inode)->lli_has_smd) rc2 = -1; } else if (S_ISDIR(inode->i_mode)) { - rc2 = ll_dir_getstripe(inode, &lmm, &lmmsize, &request); + rc2 = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, + &request, 0); } if (rc2 < 0) { @@ -518,3 +510,57 @@ out: return rc; } + +static const struct xattr_handler ll_user_xattr_handler = { + .prefix = XATTR_USER_PREFIX, + .flags = XATTR_USER_T, + .get = ll_xattr_get_common, + .set = ll_xattr_set_common, +}; + +static const struct xattr_handler ll_trusted_xattr_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .flags = XATTR_TRUSTED_T, + .get = ll_xattr_get, + .set = ll_xattr_set, +}; + +static const struct xattr_handler ll_security_xattr_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .flags = XATTR_SECURITY_T, + .get = ll_xattr_get_common, + .set = ll_xattr_set_common, +}; + +static const struct xattr_handler ll_acl_access_xattr_handler = { + .prefix = XATTR_NAME_POSIX_ACL_ACCESS, + .flags = XATTR_ACL_ACCESS_T, + .get = ll_xattr_get_common, + .set = ll_xattr_set_common, +}; + +static const struct xattr_handler ll_acl_default_xattr_handler = { + .prefix = XATTR_NAME_POSIX_ACL_DEFAULT, + .flags = XATTR_ACL_DEFAULT_T, + .get = ll_xattr_get_common, + .set = ll_xattr_set_common, +}; + +static const struct xattr_handler ll_lustre_xattr_handler = { + .prefix = XATTR_LUSTRE_PREFIX, + .flags = XATTR_LUSTRE_T, + .get = ll_xattr_get, + .set = ll_xattr_set, +}; + +const struct xattr_handler *ll_xattr_handlers[] = { + &ll_user_xattr_handler, + &ll_trusted_xattr_handler, + &ll_security_xattr_handler, +#ifdef CONFIG_FS_POSIX_ACL + &ll_acl_access_xattr_handler, + &ll_acl_default_xattr_handler, +#endif + &ll_lustre_xattr_handler, + NULL, +}; diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c index 8089da8143d9..50a19a40bd4e 100644 --- a/drivers/staging/lustre/lustre/llite/xattr_cache.c +++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c @@ -13,7 +13,6 @@ #include #include #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_ver.h" #include "llite_internal.h" @@ -270,10 +269,12 @@ static int ll_xattr_find_get_lock(struct inode *inode, struct lustre_handle lockh = { 0 }; struct md_op_data *op_data; struct ll_inode_info *lli = ll_i2info(inode); - struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS, - .ei_mode = it_to_lock_mode(oit), - .ei_cb_bl = ll_md_blocking_ast, - .ei_cb_cp = ldlm_completion_ast }; + struct ldlm_enqueue_info einfo = { + .ei_type = LDLM_IBITS, + .ei_mode = it_to_lock_mode(oit), + .ei_cb_bl = &ll_md_blocking_ast, + .ei_cb_cp = &ldlm_completion_ast, + }; struct ll_sb_info *sbi = ll_i2sbi(inode); struct obd_export *exp = sbi->ll_md_exp; int rc; @@ -304,7 +305,7 @@ static int ll_xattr_find_get_lock(struct inode *inode, op_data->op_valid = OBD_MD_FLXATTR | OBD_MD_FLXATTRLS; - rc = md_enqueue(exp, &einfo, oit, op_data, &lockh, NULL, 0, NULL, 0); + rc = md_enqueue(exp, &einfo, NULL, oit, op_data, &lockh, 0); ll_finish_md_op_data(op_data); if (rc < 0) { @@ -380,25 +381,25 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit) } /* do not need swab xattr data */ xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, - body->eadatasize); + body->mbo_eadatasize); xval = req_capsule_server_sized_get(&req->rq_pill, &RMF_EAVALS, - body->aclsize); + body->mbo_aclsize); xsizes = req_capsule_server_sized_get(&req->rq_pill, &RMF_EAVALS_LENS, - body->max_mdsize * sizeof(__u32)); + body->mbo_max_mdsize * sizeof(__u32)); if (!xdata || !xval || !xsizes) { CERROR("wrong setxattr reply\n"); rc = -EPROTO; goto out_destroy; } - xtail = xdata + body->eadatasize; - xvtail = xval + body->aclsize; + xtail = xdata + body->mbo_eadatasize; + xvtail = xval + body->mbo_aclsize; CDEBUG(D_CACHE, "caching: xdata=%p xtail=%p\n", xdata, xtail); ll_xattr_cache_init(lli); - for (i = 0; i < body->max_mdsize; i++) { + for (i = 0; i < body->mbo_max_mdsize; i++) { CDEBUG(D_CACHE, "caching [%s]=%.*s\n", xdata, *xsizes, xval); /* Perform consistency checks: attr names and vals in pill */ if (!memchr(xdata, 0, xtail - xdata)) { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_fld.c b/drivers/staging/lustre/lustre/lmv/lmv_fld.c index a3d170aa6fd2..a5265f9b5797 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_fld.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_fld.c @@ -47,18 +47,20 @@ #include "../include/lprocfs_status.h" #include "lmv_internal.h" -int lmv_fld_lookup(struct lmv_obd *lmv, - const struct lu_fid *fid, - u32 *mds) +int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds) { + struct obd_device *obd = lmv2obd_dev(lmv); int rc; - /* FIXME: Currently ZFS still use local seq for ROOT unfortunately, and + /* + * FIXME: Currently ZFS still use local seq for ROOT unfortunately, and * this fid_is_local check should be removed once LU-2240 is fixed */ - LASSERTF((fid_seq_in_fldb(fid_seq(fid)) || - fid_seq_is_local_file(fid_seq(fid))) && - fid_is_sane(fid), DFID" is insane!\n", PFID(fid)); + if (!fid_is_sane(fid) || !(fid_seq_in_fldb(fid_seq(fid)) || + fid_seq_is_local_file(fid_seq(fid)))) { + CERROR("%s: invalid FID " DFID "\n", obd->obd_name, PFID(fid)); + return -EINVAL; + } rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds, LU_SEQ_RANGE_MDT, NULL); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 2f58fdab8d1e..9f4e826bb0af 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -43,13 +43,13 @@ #include "../include/lustre_lib.h" #include "../include/lustre_net.h" #include "../include/lustre_dlm.h" +#include "../include/lustre_mdc.h" #include "../include/obd_class.h" #include "../include/lprocfs_status.h" #include "lmv_internal.h" -static int lmv_intent_remote(struct obd_export *exp, void *lmm, - int lmmsize, struct lookup_intent *it, - const struct lu_fid *parent_fid, int flags, +static int lmv_intent_remote(struct obd_export *exp, struct lookup_intent *it, + const struct lu_fid *parent_fid, struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) @@ -68,7 +68,7 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, if (!body) return -EPROTO; - LASSERT((body->valid & OBD_MD_MDS)); + LASSERT((body->mbo_valid & OBD_MD_MDS)); /* * Unfortunately, we have to lie to MDC/MDS to retrieve @@ -87,9 +87,9 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, it->it_request = NULL; } - LASSERT(fid_is_sane(&body->fid1)); + LASSERT(fid_is_sane(&body->mbo_fid1)); - tgt = lmv_find_target(lmv, &body->fid1); + tgt = lmv_find_target(lmv, &body->mbo_fid1); if (IS_ERR(tgt)) { rc = PTR_ERR(tgt); goto out; @@ -101,7 +101,7 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, goto out; } - op_data->op_fid1 = body->fid1; + op_data->op_fid1 = body->mbo_fid1; /* Sent the parent FID to the remote MDT */ if (parent_fid) { /* The parent fid is only for remote open to @@ -110,18 +110,14 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, */ LASSERT(it->it_op & IT_OPEN); op_data->op_fid2 = *parent_fid; - /* Add object FID to op_fid3, in case it needs to check stale - * (M_CHECK_STALE), see mdc_finish_intent_lock - */ - op_data->op_fid3 = body->fid1; } op_data->op_bias = MDS_CROSS_REF; - CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%d\n", - PFID(&body->fid1), tgt->ltd_idx); + CDEBUG(D_INODE, "REMOTE_INTENT with fid=" DFID " -> mds #%u\n", + PFID(&body->mbo_fid1), tgt->ltd_idx); - rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, - flags, &req, cb_blocking, extra_lock_flags); + rc = md_intent_lock(tgt->ltd_exp, op_data, it, &req, cb_blocking, + extra_lock_flags); if (rc) goto out_free_op_data; @@ -136,8 +132,10 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, it->it_remote_lock_mode = it->it_lock_mode; } - it->it_lock_handle = plock.cookie; - it->it_lock_mode = pmode; + if (pmode) { + it->it_lock_handle = plock.cookie; + it->it_lock_mode = pmode; + } out_free_op_data: kfree(op_data); @@ -150,13 +148,126 @@ out: return rc; } +int lmv_revalidate_slaves(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + ldlm_blocking_callback cb_blocking, + int extra_lock_flags) +{ + struct obd_device *obd = exp->exp_obd; + struct lmv_obd *lmv = &obd->u.lmv; + struct ptlrpc_request *req = NULL; + struct mdt_body *body; + struct md_op_data *op_data; + int rc = 0, i; + + /** + * revalidate slaves has some problems, temporarily return, + * we may not need that + */ + op_data = kzalloc(sizeof(*op_data), GFP_NOFS); + if (!op_data) + return -ENOMEM; + + /** + * Loop over the stripe information, check validity and update them + * from MDS if needed. + */ + for (i = 0; i < lsm->lsm_md_stripe_count; i++) { + struct lookup_intent it = { .it_op = IT_GETATTR }; + struct lustre_handle *lockh = NULL; + struct lmv_tgt_desc *tgt = NULL; + struct inode *inode; + struct lu_fid fid; + + fid = lsm->lsm_md_oinfo[i].lmo_fid; + inode = lsm->lsm_md_oinfo[i].lmo_root; + + /* + * Prepare op_data for revalidating. Note that @fid2 shluld be + * defined otherwise it will go to server and take new lock + * which is not needed here. + */ + memset(op_data, 0, sizeof(*op_data)); + op_data->op_fid1 = fid; + op_data->op_fid2 = fid; + + tgt = lmv_locate_mds(lmv, op_data, &fid); + if (IS_ERR(tgt)) { + rc = PTR_ERR(tgt); + goto cleanup; + } + + CDEBUG(D_INODE, "Revalidate slave " DFID " -> mds #%u\n", + PFID(&fid), tgt->ltd_idx); + + if (req) { + ptlrpc_req_finished(req); + req = NULL; + } + + rc = md_intent_lock(tgt->ltd_exp, op_data, &it, &req, + cb_blocking, extra_lock_flags); + if (rc < 0) + goto cleanup; + + lockh = (struct lustre_handle *)&it.it_lock_handle; + if (rc > 0 && !req) { + /* slave inode is still valid */ + CDEBUG(D_INODE, "slave "DFID" is still valid.\n", + PFID(&fid)); + rc = 0; + } else { + /* refresh slave from server */ + body = req_capsule_server_get(&req->rq_pill, + &RMF_MDT_BODY); + LASSERT(body); + + if (unlikely(body->mbo_nlink < 2)) { + CERROR("%s: nlink %d < 2 corrupt stripe %d "DFID":" DFID"\n", + obd->obd_name, body->mbo_nlink, i, + PFID(&lsm->lsm_md_oinfo[i].lmo_fid), + PFID(&lsm->lsm_md_oinfo[0].lmo_fid)); + + if (it.it_lock_mode && lockh) { + ldlm_lock_decref(lockh, it.it_lock_mode); + it.it_lock_mode = 0; + } + + rc = -EIO; + goto cleanup; + } + + i_size_write(inode, body->mbo_size); + inode->i_blocks = body->mbo_blocks; + set_nlink(inode, body->mbo_nlink); + LTIME_S(inode->i_atime) = body->mbo_atime; + LTIME_S(inode->i_ctime) = body->mbo_ctime; + LTIME_S(inode->i_mtime) = body->mbo_mtime; + } + + md_set_lock_data(tgt->ltd_exp, lockh, inode, NULL); + + if (it.it_lock_mode && lockh) { + ldlm_lock_decref(lockh, it.it_lock_mode); + it.it_lock_mode = 0; + } + } + +cleanup: + if (req) + ptlrpc_req_finished(req); + + kfree(op_data); + return rc; +} + /* * IT_OPEN is intended to open (and create, possible) an object. Parent (pid) * may be split dir. */ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int flags, struct ptlrpc_request **reqp, + struct lookup_intent *it, + struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { @@ -166,35 +277,55 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, struct mdt_body *body; int rc; - tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); + if (it->it_flags & MDS_OPEN_BY_FID) { + LASSERT(fid_is_sane(&op_data->op_fid2)); + + /* + * for striped directory, we can't know parent stripe fid + * without name, but we can set it to child fid, and MDT + * will obtain it from linkea in open in such case. + */ + if (op_data->op_mea1) + op_data->op_fid1 = op_data->op_fid2; + + tgt = lmv_find_target(lmv, &op_data->op_fid2); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + op_data->op_mds = tgt->ltd_idx; + } else { + LASSERT(fid_is_sane(&op_data->op_fid1)); + LASSERT(fid_is_zero(&op_data->op_fid2)); + LASSERT(op_data->op_name); + + tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + } /* If it is ready to open the file by FID, do not need * allocate FID at all, otherwise it will confuse MDT */ - if ((it->it_op & IT_CREAT) && - !(it->it_flags & MDS_OPEN_BY_FID)) { + if ((it->it_op & IT_CREAT) && !(it->it_flags & MDS_OPEN_BY_FID)) { /* - * For open with IT_CREATE and for IT_CREATE cases allocate new - * fid and setup FLD for it. + * For lookup(IT_CREATE) cases allocate new fid and setup FLD + * for it. */ - op_data->op_fid3 = op_data->op_fid2; - rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data); + rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc != 0) return rc; } - CDEBUG(D_INODE, "OPEN_INTENT with fid1=" DFID ", fid2=" DFID ", name='%s' -> mds #%d\n", + CDEBUG(D_INODE, "OPEN_INTENT with fid1=" DFID ", fid2=" DFID ", name='%s' -> mds #%u\n", PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), op_data->op_name, tgt->ltd_idx); - rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, flags, - reqp, cb_blocking, extra_lock_flags); + rc = md_intent_lock(tgt->ltd_exp, op_data, it, reqp, cb_blocking, + extra_lock_flags); if (rc != 0) return rc; /* - * Nothing is found, do not access body->fid1 as it is zero and thus + * Nothing is found, do not access body->mbo_fid1 as it is zero and thus * pointless. */ if ((it->it_disposition & DISP_LOOKUP_NEG) && @@ -205,31 +336,17 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); if (!body) return -EPROTO; - /* - * Not cross-ref case, just get out of here. - */ - if (likely(!(body->valid & OBD_MD_MDS))) - return 0; - /* - * Okay, MDS has returned success. Probably name has been resolved in - * remote inode. - */ - rc = lmv_intent_remote(exp, lmm, lmmsize, it, &op_data->op_fid1, flags, - reqp, cb_blocking, extra_lock_flags); - if (rc != 0) { - LASSERT(rc < 0); - /* - * This is possible, that some userspace application will try to - * open file as directory and we will have -ENOTDIR here. As - * this is normal situation, we should not print error here, - * only debug info. - */ - CDEBUG(D_INODE, "Can't handle remote %s: dir " DFID "(" DFID "):%*s: %d\n", - LL_IT2STR(it), PFID(&op_data->op_fid2), - PFID(&op_data->op_fid1), op_data->op_namelen, - op_data->op_name, rc); - return rc; + /* Not cross-ref case, just get out of here. */ + if (unlikely((body->mbo_valid & OBD_MD_MDS))) { + rc = lmv_intent_remote(exp, it, &op_data->op_fid1, reqp, + cb_blocking, extra_lock_flags); + if (rc != 0) + return rc; + + body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); + if (!body) + return -EPROTO; } return rc; @@ -240,38 +357,103 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, */ static int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int flags, struct ptlrpc_request **reqp, + struct lookup_intent *it, + struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { + struct lmv_stripe_md *lsm = op_data->op_mea1; struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt = NULL; struct mdt_body *body; int rc = 0; + /* + * If it returns ERR_PTR(-EBADFD) then it is an unknown hash type + * it will try all stripes to locate the object + */ tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); - if (IS_ERR(tgt)) + if (IS_ERR(tgt) && (PTR_ERR(tgt) != -EBADFD)) return PTR_ERR(tgt); + /* + * Both migrating dir and unknown hash dir need to try + * all of sub-stripes + */ + if (lsm && !lmv_is_known_hash_type(lsm->lsm_md_hash_type)) { + struct lmv_oinfo *oinfo = &lsm->lsm_md_oinfo[0]; + + op_data->op_fid1 = oinfo->lmo_fid; + op_data->op_mds = oinfo->lmo_mds; + tgt = lmv_get_target(lmv, oinfo->lmo_mds, NULL); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + } + if (!fid_is_sane(&op_data->op_fid2)) fid_zero(&op_data->op_fid2); - CDEBUG(D_INODE, "LOOKUP_INTENT with fid1="DFID", fid2="DFID - ", name='%s' -> mds #%d\n", PFID(&op_data->op_fid1), - PFID(&op_data->op_fid2), + CDEBUG(D_INODE, "LOOKUP_INTENT with fid1=" DFID ", fid2=" DFID ", name='%s' -> mds #%u lsm=%p lsm_magic=%x\n", + PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), op_data->op_name ? op_data->op_name : "", - tgt->ltd_idx); + tgt->ltd_idx, lsm, !lsm ? -1 : lsm->lsm_md_magic); op_data->op_bias &= ~MDS_CROSS_REF; - rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, - flags, reqp, cb_blocking, extra_lock_flags); - - if (rc < 0 || !*reqp) + rc = md_intent_lock(tgt->ltd_exp, op_data, it, reqp, cb_blocking, + extra_lock_flags); + if (rc < 0) return rc; + if (!*reqp) { + /* + * If RPC happens, lsm information will be revalidated + * during update_inode process (see ll_update_lsm_md) + */ + if (op_data->op_mea2) { + rc = lmv_revalidate_slaves(exp, op_data->op_mea2, + cb_blocking, + extra_lock_flags); + if (rc != 0) + return rc; + } + return rc; + } else if (it_disposition(it, DISP_LOOKUP_NEG) && lsm && + lmv_need_try_all_stripes(lsm)) { + /* + * For migrating and unknown hash type directory, it will + * try to target the entry on other stripes + */ + int stripe_index; + + for (stripe_index = 1; + stripe_index < lsm->lsm_md_stripe_count && + it_disposition(it, DISP_LOOKUP_NEG); stripe_index++) { + struct lmv_oinfo *oinfo; + + /* release the previous request */ + ptlrpc_req_finished(*reqp); + it->it_request = NULL; + *reqp = NULL; + + oinfo = &lsm->lsm_md_oinfo[stripe_index]; + tgt = lmv_find_target(lmv, &oinfo->lmo_fid); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + CDEBUG(D_INODE, "Try other stripes " DFID"\n", + PFID(&oinfo->lmo_fid)); + + op_data->op_fid1 = oinfo->lmo_fid; + it->it_disposition &= ~DISP_ENQ_COMPLETE; + rc = md_intent_lock(tgt->ltd_exp, op_data, it, reqp, + cb_blocking, extra_lock_flags); + if (rc) + return rc; + } + } + /* * MDS has returned success. Probably name has been resolved in * remote inode. Let's check this. @@ -279,19 +461,23 @@ static int lmv_intent_lookup(struct obd_export *exp, body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); if (!body) return -EPROTO; - /* Not cross-ref case, just get out of here. */ - if (likely(!(body->valid & OBD_MD_MDS))) - return 0; - rc = lmv_intent_remote(exp, lmm, lmmsize, it, NULL, flags, reqp, - cb_blocking, extra_lock_flags); + /* Not cross-ref case, just get out of here. */ + if (unlikely((body->mbo_valid & OBD_MD_MDS))) { + rc = lmv_intent_remote(exp, it, NULL, reqp, cb_blocking, + extra_lock_flags); + if (rc != 0) + return rc; + body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); + if (!body) + return -EPROTO; + } return rc; } int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int flags, struct ptlrpc_request **reqp, + struct lookup_intent *it, struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { @@ -300,8 +486,9 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, LASSERT(fid_is_sane(&op_data->op_fid1)); - CDEBUG(D_INODE, "INTENT LOCK '%s' for '%*s' on "DFID"\n", - LL_IT2STR(it), op_data->op_namelen, op_data->op_name, + CDEBUG(D_INODE, "INTENT LOCK '%s' for "DFID" '%*s' on "DFID"\n", + LL_IT2STR(it), PFID(&op_data->op_fid2), + (int)op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1)); rc = lmv_check_connect(obd); @@ -309,14 +496,34 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, return rc; if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_LAYOUT)) - rc = lmv_intent_lookup(exp, op_data, lmm, lmmsize, it, - flags, reqp, cb_blocking, + rc = lmv_intent_lookup(exp, op_data, it, reqp, cb_blocking, extra_lock_flags); else if (it->it_op & IT_OPEN) - rc = lmv_intent_open(exp, op_data, lmm, lmmsize, it, - flags, reqp, cb_blocking, + rc = lmv_intent_open(exp, op_data, it, reqp, cb_blocking, extra_lock_flags); else LBUG(); + + if (rc < 0) { + struct lustre_handle lock_handle; + + if (it->it_lock_mode) { + lock_handle.cookie = it->it_lock_handle; + ldlm_lock_decref(&lock_handle, it->it_lock_mode); + } + + it->it_lock_handle = 0; + it->it_lock_mode = 0; + + if (it->it_remote_lock_mode) { + lock_handle.cookie = it->it_remote_lock_handle; + ldlm_lock_decref(&lock_handle, + it->it_remote_lock_mode); + } + + it->it_remote_lock_handle = 0; + it->it_remote_lock_mode = 0; + } + return rc; } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index 0beafc49b8d2..52b03745ac19 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -35,6 +35,7 @@ #include "../include/lustre/lustre_idl.h" #include "../include/obd.h" +#include "../include/lustre_lmv.h" #define LMV_MAX_TGT_COUNT 128 @@ -44,77 +45,116 @@ int lmv_check_connect(struct obd_device *obd); int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int flags, struct ptlrpc_request **reqp, + struct lookup_intent *it, struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags); int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds); int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds); -int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data); +int lmv_fid_alloc(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data); -static inline struct lmv_stripe_md *lmv_get_mea(struct ptlrpc_request *req) +int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, + const union lmv_mds_md *lmm, int stripe_count); + +int lmv_revalidate_slaves(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + ldlm_blocking_callback cb_blocking, + int extra_lock_flags); + +static inline struct obd_device *lmv2obd_dev(struct lmv_obd *lmv) { - struct mdt_body *body; - struct lmv_stripe_md *mea; - - LASSERT(req); - - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - - if (!body || !S_ISDIR(body->mode) || !body->eadatasize) - return NULL; - - mea = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD, - body->eadatasize); - if (mea->mea_count == 0) - return NULL; - if (mea->mea_magic != MEA_MAGIC_LAST_CHAR && - mea->mea_magic != MEA_MAGIC_ALL_CHARS && - mea->mea_magic != MEA_MAGIC_HASH_SEGMENT) - return NULL; - - return mea; -} - -static inline int lmv_get_easize(struct lmv_obd *lmv) -{ - return sizeof(struct lmv_stripe_md) + - lmv->desc.ld_tgt_count * - sizeof(struct lu_fid); + return container_of0(lmv, struct obd_device, u.lmv); } static inline struct lmv_tgt_desc * -lmv_get_target(struct lmv_obd *lmv, u32 mds) +lmv_get_target(struct lmv_obd *lmv, u32 mdt_idx, int *index) { - int count = lmv->desc.ld_tgt_count; int i; - for (i = 0; i < count; i++) { + for (i = 0; i < lmv->desc.ld_tgt_count; i++) { if (!lmv->tgts[i]) continue; - if (lmv->tgts[i]->ltd_idx == mds) + if (lmv->tgts[i]->ltd_idx == mdt_idx) { + if (index) + *index = i; return lmv->tgts[i]; + } } return ERR_PTR(-ENODEV); } +static inline int +lmv_find_target_index(struct lmv_obd *lmv, const struct lu_fid *fid) +{ + struct lmv_tgt_desc *ltd; + u32 mdt_idx = 0; + int index = 0; + + if (lmv->desc.ld_tgt_count > 1) { + int rc; + + rc = lmv_fld_lookup(lmv, fid, &mdt_idx); + if (rc < 0) + return rc; + } + + ltd = lmv_get_target(lmv, mdt_idx, &index); + if (IS_ERR(ltd)) + return PTR_ERR(ltd); + + return index; +} + static inline struct lmv_tgt_desc * lmv_find_target(struct lmv_obd *lmv, const struct lu_fid *fid) { - u32 mds = 0; - int rc; + int index; - if (lmv->desc.ld_tgt_count > 1) { - rc = lmv_fld_lookup(lmv, fid, &mds); - if (rc) - return ERR_PTR(rc); - } + index = lmv_find_target_index(lmv, fid); + if (index < 0) + return ERR_PTR(index); - return lmv_get_target(lmv, mds); + return lmv->tgts[index]; +} + +static inline int lmv_stripe_md_size(int stripe_count) +{ + struct lmv_stripe_md *lsm; + + return sizeof(*lsm) + stripe_count * sizeof(lsm->lsm_md_oinfo[0]); +} + +int lmv_name_to_stripe_index(enum lmv_hash_type hashtype, + unsigned int max_mdt_index, + const char *name, int namelen); + +static inline const struct lmv_oinfo * +lsm_name_to_stripe_info(const struct lmv_stripe_md *lsm, const char *name, + int namelen) +{ + int stripe_index; + + stripe_index = lmv_name_to_stripe_index(lsm->lsm_md_hash_type, + lsm->lsm_md_stripe_count, + name, namelen); + if (stripe_index < 0) + return ERR_PTR(stripe_index); + + LASSERTF(stripe_index < lsm->lsm_md_stripe_count, + "stripe_index = %d, stripe_count = %d hash_type = %x name = %.*s\n", + stripe_index, lsm->lsm_md_stripe_count, + lsm->lsm_md_hash_type, namelen, name); + + return &lsm->lsm_md_oinfo[stripe_index]; +} + +static inline bool lmv_need_try_all_stripes(const struct lmv_stripe_md *lsm) +{ + return !lmv_is_known_hash_type(lsm->lsm_md_hash_type) || + lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION; } struct lmv_tgt_desc @@ -123,6 +163,6 @@ struct lmv_tgt_desc /* lproc_lmv.c */ void lprocfs_lmv_init_vars(struct lprocfs_static_vars *lvars); -extern struct file_operations lmv_proc_target_fops; +extern const struct file_operations lmv_proc_target_fops; #endif diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 0e1588a43187..7dbb2b946acf 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -43,12 +43,13 @@ #include "../include/lustre/lustre_idl.h" #include "../include/obd_support.h" -#include "../include/lustre_lib.h" #include "../include/lustre_net.h" #include "../include/obd_class.h" +#include "../include/lustre_lmv.h" #include "../include/lprocfs_status.h" -#include "../include/lustre_lite.h" +#include "../include/cl_object.h" #include "../include/lustre_fid.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_kernelcomm.h" #include "lmv_internal.h" @@ -70,12 +71,12 @@ static void lmv_activate_target(struct lmv_obd *lmv, * -ENOTCONN: The UUID is found, but the target connection is bad (!) * -EBADF : The UUID is found, but the OBD of the wrong type (!) */ -static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid, +static int lmv_set_mdc_active(struct lmv_obd *lmv, const struct obd_uuid *uuid, int activate) { struct lmv_tgt_desc *uninitialized_var(tgt); struct obd_device *obd; - int i; + u32 i; int rc = 0; CDEBUG(D_INFO, "Searching in lmv %p for uuid %s (activate=%d)\n", @@ -244,36 +245,12 @@ static int lmv_connect(const struct lu_env *env, return rc; } -static void lmv_set_timeouts(struct obd_device *obd) -{ - struct lmv_obd *lmv; - int i; - - lmv = &obd->u.lmv; - if (lmv->server_timeout == 0) - return; - - if (lmv->connected == 0) - return; - - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - struct lmv_tgt_desc *tgt = lmv->tgts[i]; - - tgt = lmv->tgts[i]; - if (!tgt || !tgt->ltd_exp || !tgt->ltd_active) - continue; - - obd_set_info_async(NULL, tgt->ltd_exp, sizeof(KEY_INTERMDS), - KEY_INTERMDS, 0, NULL, NULL); - } -} - -static int lmv_init_ea_size(struct obd_export *exp, int easize, - int def_easize, int cookiesize, int def_cookiesize) +static int lmv_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, + u32 cookiesize, u32 def_cookiesize) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; - int i; + u32 i; int rc = 0; int change = 0; @@ -420,6 +397,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, { struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; + int orig_tgt_count = 0; int rc = 0; CDEBUG(D_CONFIG, "Target uuid: %s. index %d\n", uuidp->uuid, index); @@ -489,14 +467,17 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, tgt->ltd_uuid = *uuidp; tgt->ltd_active = 0; lmv->tgts[index] = tgt; - if (index >= lmv->desc.ld_tgt_count) + if (index >= lmv->desc.ld_tgt_count) { + orig_tgt_count = lmv->desc.ld_tgt_count; lmv->desc.ld_tgt_count = index + 1; + } if (lmv->connected) { rc = lmv_connect_mdc(obd, tgt); if (rc) { spin_lock(&lmv->lmv_lock); - lmv->desc.ld_tgt_count--; + if (lmv->desc.ld_tgt_count == index + 1) + lmv->desc.ld_tgt_count = orig_tgt_count; memset(tgt, 0, sizeof(*tgt)); spin_unlock(&lmv->lmv_lock); } else { @@ -514,7 +495,7 @@ int lmv_check_connect(struct obd_device *obd) { struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; - int i; + u32 i; int rc; int easize; @@ -554,10 +535,9 @@ int lmv_check_connect(struct obd_device *obd) goto out_disc; } - lmv_set_timeouts(obd); class_export_put(lmv->exp); lmv->connected = 1; - easize = lmv_get_easize(lmv); + easize = lmv_mds_md_size(lmv->desc.ld_tgt_count, LMV_MAGIC); lmv_init_ea_size(obd->obd_self_export, easize, 0, 0, 0); mutex_unlock(&lmv->lmv_init_mutex); return 0; @@ -629,7 +609,7 @@ static int lmv_disconnect(struct obd_export *exp) struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; int rc; - int i; + u32 i; if (!lmv->tgts) goto out_local; @@ -758,7 +738,7 @@ static int lmv_hsm_req_count(struct lmv_obd *lmv, const struct hsm_user_request *hur, const struct lmv_tgt_desc *tgt_mds) { - int i, nr = 0; + u32 i, nr = 0; struct lmv_tgt_desc *curr_tgt; /* count how many requests must be sent to the given target */ @@ -885,10 +865,8 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, &kcd, sizeof(kcd)); - if (rc) { - if (filp) - fput(filp); - } + if (rc) + fput(filp); return rc; } @@ -899,10 +877,10 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, struct obd_device *obddev = class_exp2obd(exp); struct lmv_obd *lmv = &obddev->u.lmv; struct lmv_tgt_desc *tgt = NULL; - int i = 0; + u32 i = 0; int rc = 0; int set = 0; - int count = lmv->desc.ld_tgt_count; + u32 count = lmv->desc.ld_tgt_count; if (count == 0) return -ENOTTY; @@ -1011,6 +989,21 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg); break; } + case LL_IOC_FID2MDTIDX: { + struct lu_fid *fid = karg; + int mdt_index; + + rc = lmv_fld_lookup(lmv, fid, &mdt_index); + if (rc) + return rc; + + /* + * Note: this is from llite(see ll_dir_ioctl()), @uarg does not + * point to user space memory for FID2MDTIDX. + */ + *(__u32 *)uarg = mdt_index; + break; + } case OBD_IOC_FID2PATH: { rc = lmv_fid2path(exp, len, karg, uarg); break; @@ -1169,32 +1162,37 @@ static int lmv_placement_policy(struct obd_device *obd, return 0; } + if (op_data->op_default_stripe_offset != -1) { + *mds = op_data->op_default_stripe_offset; + return 0; + } + /** * If stripe_offset is provided during setdirstripe * (setdirstripe -i xx), xx MDS will be chosen. */ - if (op_data->op_cli_flags & CLI_SET_MEA) { + if (op_data->op_cli_flags & CLI_SET_MEA && op_data->op_data) { struct lmv_user_md *lum; - lum = (struct lmv_user_md *)op_data->op_data; - if (lum->lum_type == LMV_STRIPE_TYPE && - lum->lum_stripe_offset != -1) { - if (lum->lum_stripe_offset >= lmv->desc.ld_tgt_count) { - CERROR("%s: Stripe_offset %d > MDT count %d: rc = %d\n", - obd->obd_name, - lum->lum_stripe_offset, - lmv->desc.ld_tgt_count, -ERANGE); - return -ERANGE; - } - *mds = lum->lum_stripe_offset; - return 0; + lum = op_data->op_data; + if (le32_to_cpu(lum->lum_stripe_offset) != (__u32)-1) { + *mds = le32_to_cpu(lum->lum_stripe_offset); + } else { + /* + * -1 means default, which will be in the same MDT with + * the stripe + */ + *mds = op_data->op_mds; + lum->lum_stripe_offset = cpu_to_le32(op_data->op_mds); } + } else { + /* + * Allocate new fid on target according to operation type and + * parent home mds. + */ + *mds = op_data->op_mds; } - /* Allocate new fid on target according to operation type and parent - * home mds. - */ - *mds = op_data->op_mds; return 0; } @@ -1203,7 +1201,7 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds) struct lmv_tgt_desc *tgt; int rc; - tgt = lmv_get_target(lmv, mds); + tgt = lmv_get_target(lmv, mds, NULL); if (IS_ERR(tgt)) return PTR_ERR(tgt); @@ -1221,7 +1219,7 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds) /* * Asking underlaying tgt layer to allocate new fid. */ - rc = obd_fid_alloc(tgt->ltd_exp, fid, NULL); + rc = obd_fid_alloc(NULL, tgt->ltd_exp, fid, NULL); if (rc > 0) { LASSERT(fid_is_sane(fid)); rc = 0; @@ -1232,8 +1230,8 @@ out: return rc; } -int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data) +int lmv_fid_alloc(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data) { struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; @@ -1278,10 +1276,10 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg) return -EINVAL; } - lmv->tgts = kcalloc(32, sizeof(*lmv->tgts), GFP_NOFS); + lmv->tgts_size = 32U; + lmv->tgts = kcalloc(lmv->tgts_size, sizeof(*lmv->tgts), GFP_NOFS); if (!lmv->tgts) return -ENOMEM; - lmv->tgts_size = 32; obd_str2uuid(&lmv->desc.ld_uuid, desc->ld_uuid.uuid); lmv->desc.ld_tgt_count = 0; @@ -1354,7 +1352,7 @@ static int lmv_process_config(struct obd_device *obd, u32 len, void *buf) obd_str2uuid(&obd_uuid, lustre_cfg_buf(lcfg, 1)); - if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) { + if (sscanf(lustre_cfg_buf(lcfg, 2), "%u", &index) != 1) { rc = -EINVAL; goto out; } @@ -1380,7 +1378,7 @@ static int lmv_statfs(const struct lu_env *env, struct obd_export *exp, struct lmv_obd *lmv = &obd->u.lmv; struct obd_statfs *temp; int rc = 0; - int i; + u32 i; rc = lmv_check_connect(obd); if (rc) @@ -1522,7 +1520,7 @@ static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; - int i; + u32 i; int rc; rc = lmv_check_connect(obd); @@ -1545,36 +1543,6 @@ static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid) return 0; } -static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, - ldlm_iterator_t it, void *data) -{ - struct obd_device *obd = exp->exp_obd; - struct lmv_obd *lmv = &obd->u.lmv; - int i; - int rc; - - rc = lmv_check_connect(obd); - if (rc) - return rc; - - CDEBUG(D_INODE, "CBDATA for "DFID"\n", PFID(fid)); - - /* - * With DNE every object can have two locks in different namespaces: - * lookup lock in space of MDT storing direntry and update/open lock in - * space of MDT storing inode. - */ - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - if (!lmv->tgts[i] || !lmv->tgts[i]->ltd_exp) - continue; - rc = md_find_cbdata(lmv->tgts[i]->ltd_exp, fid, it, data); - if (rc) - return rc; - } - - return rc; -} - static int lmv_close(struct obd_export *exp, struct md_op_data *op_data, struct md_open_data *mod, struct ptlrpc_request **request) { @@ -1596,25 +1564,116 @@ static int lmv_close(struct obd_export *exp, struct md_op_data *op_data, return rc; } -struct lmv_tgt_desc -*lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, - struct lu_fid *fid) +/** + * Choosing the MDT by name or FID in @op_data. + * For non-striped directory, it will locate MDT by fid. + * For striped-directory, it will locate MDT by name. And also + * it will reset op_fid1 with the FID of the chosen stripe. + **/ +static struct lmv_tgt_desc * +lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, + const char *name, int namelen, struct lu_fid *fid, + u32 *mds) { + const struct lmv_oinfo *oinfo; struct lmv_tgt_desc *tgt; - tgt = lmv_find_target(lmv, fid); - if (IS_ERR(tgt)) - return tgt; + if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_NAME_HASH)) { + if (cfs_fail_val >= lsm->lsm_md_stripe_count) + return ERR_PTR(-EBADF); + oinfo = &lsm->lsm_md_oinfo[cfs_fail_val]; + } else { + oinfo = lsm_name_to_stripe_info(lsm, name, namelen); + if (IS_ERR(oinfo)) + return ERR_CAST(oinfo); + } - op_data->op_mds = tgt->ltd_idx; + if (fid) + *fid = oinfo->lmo_fid; + if (mds) + *mds = oinfo->lmo_mds; + tgt = lmv_get_target(lmv, oinfo->lmo_mds, NULL); + + CDEBUG(D_INFO, "locate on mds %u " DFID "\n", oinfo->lmo_mds, + PFID(&oinfo->lmo_fid)); return tgt; } +/** + * Locate mds by fid or name + * + * For striped directory (lsm != NULL), it will locate the stripe + * by name hash (see lsm_name_to_stripe_info()). Note: if the hash_type + * is unknown, it will return -EBADFD, and lmv_intent_lookup might need + * walk through all of stripes to locate the entry. + * + * For normal direcotry, it will locate MDS by FID directly. + * \param[in] lmv LMV device + * \param[in] op_data client MD stack parameters, name, namelen + * mds_num etc. + * \param[in] fid object FID used to locate MDS. + * + * retval pointer to the lmv_tgt_desc if succeed. + * ERR_PTR(errno) if failed. + */ +struct lmv_tgt_desc* +lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, + struct lu_fid *fid) +{ + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct lmv_tgt_desc *tgt; + + /* + * During creating VOLATILE file, it should honor the mdt + * index if the file under striped dir is being restored, see + * ct_restore(). + */ + if (op_data->op_bias & MDS_CREATE_VOLATILE && + (int)op_data->op_mds != -1 && lsm) { + int i; + + tgt = lmv_get_target(lmv, op_data->op_mds, NULL); + if (IS_ERR(tgt)) + return tgt; + + /* refill the right parent fid */ + for (i = 0; i < lsm->lsm_md_stripe_count; i++) { + struct lmv_oinfo *oinfo; + + oinfo = &lsm->lsm_md_oinfo[i]; + if (oinfo->lmo_mds == op_data->op_mds) { + *fid = oinfo->lmo_fid; + break; + } + } + + /* Hmm, can not find the stripe by mdt_index(op_mds) */ + if (i == lsm->lsm_md_stripe_count) + tgt = ERR_PTR(-EINVAL); + + return tgt; + } + + if (!lsm || !op_data->op_namelen) { + tgt = lmv_find_target(lmv, fid); + if (IS_ERR(tgt)) + return tgt; + + op_data->op_mds = tgt->ltd_idx; + + return tgt; + } + + return lmv_locate_target_for_name(lmv, lsm, op_data->op_name, + op_data->op_namelen, fid, + &op_data->op_mds); +} + static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, - __u32 gid, cfs_cap_t cap_effective, __u64 rdev, - struct ptlrpc_request **request) + const void *data, size_t datalen, umode_t mode, + uid_t uid, gid_t gid, cfs_cap_t cap_effective, + __u64 rdev, struct ptlrpc_request **request) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -1632,13 +1691,30 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, if (IS_ERR(tgt)) return PTR_ERR(tgt); - rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data); + CDEBUG(D_INODE, "CREATE name '%.*s' on "DFID" -> mds #%x\n", + (int)op_data->op_namelen, op_data->op_name, + PFID(&op_data->op_fid1), op_data->op_mds); + + rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc) return rc; - CDEBUG(D_INODE, "CREATE '%*s' on "DFID" -> mds #%x\n", - op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), - op_data->op_mds); + if (exp_connect_flags(exp) & OBD_CONNECT_DIR_STRIPE) { + /* + * Send the create request to the MDT where the object + * will be located + */ + tgt = lmv_find_target(lmv, &op_data->op_fid2); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + op_data->op_mds = tgt->ltd_idx; + } else { + CDEBUG(D_CONFIG, "Server doesn't support striped dirs\n"); + } + + CDEBUG(D_INODE, "CREATE obj "DFID" -> mds #%x\n", + PFID(&op_data->op_fid1), op_data->op_mds); op_data->op_flags |= MF_MDC_CANCEL_FID1; rc = md_create(tgt->ltd_exp, op_data, data, datalen, mode, uid, gid, @@ -1673,71 +1749,11 @@ static int lmv_done_writing(struct obd_export *exp, return rc; } -static int -lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo, - struct lookup_intent *it, struct md_op_data *op_data, - struct lustre_handle *lockh, void *lmm, int lmmsize, - __u64 extra_lock_flags) -{ - struct ptlrpc_request *req = it->it_request; - struct obd_device *obd = exp->exp_obd; - struct lmv_obd *lmv = &obd->u.lmv; - struct lustre_handle plock; - struct lmv_tgt_desc *tgt; - struct md_op_data *rdata; - struct lu_fid fid1; - struct mdt_body *body; - int rc = 0; - int pmode; - - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - - if (!(body->valid & OBD_MD_MDS)) - return 0; - - CDEBUG(D_INODE, "REMOTE_ENQUEUE '%s' on "DFID" -> "DFID"\n", - LL_IT2STR(it), PFID(&op_data->op_fid1), PFID(&body->fid1)); - - /* - * We got LOOKUP lock, but we really need attrs. - */ - pmode = it->it_lock_mode; - LASSERT(pmode != 0); - memcpy(&plock, lockh, sizeof(plock)); - it->it_lock_mode = 0; - it->it_request = NULL; - fid1 = body->fid1; - - ptlrpc_req_finished(req); - - tgt = lmv_find_target(lmv, &fid1); - if (IS_ERR(tgt)) { - rc = PTR_ERR(tgt); - goto out; - } - - rdata = kzalloc(sizeof(*rdata), GFP_NOFS); - if (!rdata) { - rc = -ENOMEM; - goto out; - } - - rdata->op_fid1 = fid1; - rdata->op_bias = MDS_CROSS_REF; - - rc = md_enqueue(tgt->ltd_exp, einfo, it, rdata, lockh, - lmm, lmmsize, NULL, extra_lock_flags); - kfree(rdata); -out: - ldlm_lock_decref(&plock, pmode); - return rc; -} - static int lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, + const ldlm_policy_data_t *policy, struct lookup_intent *it, struct md_op_data *op_data, - struct lustre_handle *lockh, void *lmm, int lmmsize, - struct ptlrpc_request **req, __u64 extra_lock_flags) + struct lustre_handle *lockh, __u64 extra_lock_flags) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -1755,22 +1771,18 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, if (IS_ERR(tgt)) return PTR_ERR(tgt); - CDEBUG(D_INODE, "ENQUEUE '%s' on "DFID" -> mds #%d\n", + CDEBUG(D_INODE, "ENQUEUE '%s' on " DFID " -> mds #%u\n", LL_IT2STR(it), PFID(&op_data->op_fid1), tgt->ltd_idx); - rc = md_enqueue(tgt->ltd_exp, einfo, it, op_data, lockh, - lmm, lmmsize, req, extra_lock_flags); + rc = md_enqueue(tgt->ltd_exp, einfo, policy, it, op_data, lockh, + extra_lock_flags); - if (rc == 0 && it && it->it_op == IT_OPEN) { - rc = lmv_enqueue_remote(exp, einfo, it, op_data, lockh, - lmm, lmmsize, extra_lock_flags); - } return rc; } static int lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, - struct ptlrpc_request **request) + struct ptlrpc_request **preq) { struct ptlrpc_request *req = NULL; struct obd_device *obd = exp->exp_obd; @@ -1787,26 +1799,25 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, if (IS_ERR(tgt)) return PTR_ERR(tgt); - CDEBUG(D_INODE, "GETATTR_NAME for %*s on "DFID" -> mds #%d\n", - op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), - tgt->ltd_idx); + CDEBUG(D_INODE, "GETATTR_NAME for %*s on " DFID " -> mds #%u\n", + (int)op_data->op_namelen, op_data->op_name, + PFID(&op_data->op_fid1), tgt->ltd_idx); - rc = md_getattr_name(tgt->ltd_exp, op_data, request); + rc = md_getattr_name(tgt->ltd_exp, op_data, preq); if (rc != 0) return rc; - body = req_capsule_server_get(&(*request)->rq_pill, - &RMF_MDT_BODY); - - if (body->valid & OBD_MD_MDS) { - struct lu_fid rid = body->fid1; + body = req_capsule_server_get(&(*preq)->rq_pill, &RMF_MDT_BODY); + if (body->mbo_valid & OBD_MD_MDS) { + struct lu_fid rid = body->mbo_fid1; CDEBUG(D_INODE, "Request attrs for "DFID"\n", PFID(&rid)); tgt = lmv_find_target(lmv, &rid); if (IS_ERR(tgt)) { - ptlrpc_req_finished(*request); + ptlrpc_req_finished(*preq); + *preq = NULL; return PTR_ERR(tgt); } @@ -1815,8 +1826,8 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, op_data->op_namelen = 0; op_data->op_name = NULL; rc = md_getattr_name(tgt->ltd_exp, op_data, &req); - ptlrpc_req_finished(*request); - *request = req; + ptlrpc_req_finished(*preq); + *preq = req; } return rc; @@ -1829,23 +1840,24 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, fl == MF_MDC_CANCEL_FID4 ? &op_data->op_fid4 : \ NULL) -static int lmv_early_cancel(struct obd_export *exp, struct md_op_data *op_data, - int op_tgt, enum ldlm_mode mode, int bits, - int flag) +static int lmv_early_cancel(struct obd_export *exp, struct lmv_tgt_desc *tgt, + struct md_op_data *op_data, int op_tgt, + enum ldlm_mode mode, int bits, int flag) { struct lu_fid *fid = md_op_data_fid(op_data, flag); struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; - struct lmv_tgt_desc *tgt; ldlm_policy_data_t policy = { {0} }; int rc = 0; if (!fid_is_sane(fid)) return 0; - tgt = lmv_find_target(lmv, fid); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); + if (!tgt) { + tgt = lmv_find_target(lmv, fid); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + } if (tgt->ltd_idx != op_tgt) { CDEBUG(D_INODE, "EARLY_CANCEL on "DFID"\n", PFID(fid)); @@ -1882,12 +1894,24 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, LASSERT(op_data->op_namelen != 0); CDEBUG(D_INODE, "LINK "DFID":%*s to "DFID"\n", - PFID(&op_data->op_fid2), op_data->op_namelen, + PFID(&op_data->op_fid2), (int)op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1)); op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); + if (op_data->op_mea2) { + struct lmv_stripe_md *lsm = op_data->op_mea2; + const struct lmv_oinfo *oinfo; + + oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name, + op_data->op_namelen); + if (IS_ERR(oinfo)) + return PTR_ERR(oinfo); + + op_data->op_fid2 = oinfo->lmo_fid; + } + tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2); if (IS_ERR(tgt)) return PTR_ERR(tgt); @@ -1896,7 +1920,7 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, * Cancel UPDATE lock on child (fid1). */ op_data->op_flags |= MF_MDC_CANCEL_FID2; - rc = lmv_early_cancel(exp, op_data, tgt->ltd_idx, LCK_EX, + rc = lmv_early_cancel(exp, NULL, op_data, tgt->ltd_idx, LCK_EX, MDS_INODELOCK_UPDATE, MF_MDC_CANCEL_FID1); if (rc != 0) return rc; @@ -1907,20 +1931,22 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, } static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen, + const char *old, size_t oldlen, + const char *new, size_t newlen, struct ptlrpc_request **request) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *src_tgt; - struct lmv_tgt_desc *tgt_tgt; int rc; LASSERT(oldlen != 0); - CDEBUG(D_INODE, "RENAME %*s in "DFID" to %*s in "DFID"\n", - oldlen, old, PFID(&op_data->op_fid1), - newlen, new, PFID(&op_data->op_fid2)); + CDEBUG(D_INODE, "RENAME %.*s in "DFID":%d to %.*s in "DFID":%d\n", + (int)oldlen, old, PFID(&op_data->op_fid1), + op_data->op_mea1 ? op_data->op_mea1->lsm_md_stripe_count : 0, + (int)newlen, new, PFID(&op_data->op_fid2), + op_data->op_mea2 ? op_data->op_mea2->lsm_md_stripe_count : 0); rc = lmv_check_connect(obd); if (rc) @@ -1929,13 +1955,60 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); - src_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); + + if (op_data->op_cli_flags & CLI_MIGRATE) { + LASSERTF(fid_is_sane(&op_data->op_fid3), "invalid FID "DFID"\n", + PFID(&op_data->op_fid3)); + + if (op_data->op_mea1) { + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct lmv_tgt_desc *tmp; + + /* Fix the parent fid for striped dir */ + tmp = lmv_locate_target_for_name(lmv, lsm, old, + oldlen, + &op_data->op_fid1, + NULL); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + } + + rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); + if (rc) + return rc; + src_tgt = lmv_find_target(lmv, &op_data->op_fid3); + } else { + if (op_data->op_mea1) { + struct lmv_stripe_md *lsm = op_data->op_mea1; + + src_tgt = lmv_locate_target_for_name(lmv, lsm, old, + oldlen, + &op_data->op_fid1, + &op_data->op_mds); + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); + } else { + src_tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); + + op_data->op_mds = src_tgt->ltd_idx; + } + + if (op_data->op_mea2) { + struct lmv_stripe_md *lsm = op_data->op_mea2; + const struct lmv_oinfo *oinfo; + + oinfo = lsm_name_to_stripe_info(lsm, new, newlen); + if (IS_ERR(oinfo)) + return PTR_ERR(oinfo); + + op_data->op_fid2 = oinfo->lmo_fid; + } + } if (IS_ERR(src_tgt)) return PTR_ERR(src_tgt); - tgt_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2); - if (IS_ERR(tgt_tgt)) - return PTR_ERR(tgt_tgt); /* * LOOKUP lock on src child (fid3) should also be cancelled for * src_tgt in mdc_rename. @@ -1946,35 +2019,53 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, * Cancel UPDATE locks on tgt parent (fid2), tgt_tgt is its * own target. */ - rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx, + rc = lmv_early_cancel(exp, NULL, op_data, src_tgt->ltd_idx, LCK_EX, MDS_INODELOCK_UPDATE, MF_MDC_CANCEL_FID2); - + if (rc) + return rc; /* - * Cancel LOOKUP locks on tgt child (fid4) for parent tgt_tgt. + * Cancel LOOKUP locks on source child (fid3) for parent tgt_tgt. */ - if (rc == 0) { - rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx, + if (fid_is_sane(&op_data->op_fid3)) { + struct lmv_tgt_desc *tgt; + + tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + /* Cancel LOOKUP lock on its parent */ + rc = lmv_early_cancel(exp, tgt, op_data, src_tgt->ltd_idx, LCK_EX, MDS_INODELOCK_LOOKUP, - MF_MDC_CANCEL_FID4); + MF_MDC_CANCEL_FID3); + if (rc) + return rc; + + rc = lmv_early_cancel(exp, NULL, op_data, src_tgt->ltd_idx, + LCK_EX, MDS_INODELOCK_FULL, + MF_MDC_CANCEL_FID3); + if (rc) + return rc; } /* * Cancel all the locks on tgt child (fid4). */ - if (rc == 0) - rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx, + if (fid_is_sane(&op_data->op_fid4)) + rc = lmv_early_cancel(exp, NULL, op_data, src_tgt->ltd_idx, LCK_EX, MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID4); - if (rc == 0) - rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen, - new, newlen, request); + CDEBUG(D_INODE, DFID":m%d to "DFID"\n", PFID(&op_data->op_fid1), + op_data->op_mds, PFID(&op_data->op_fid2)); + + rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen, + new, newlen, request); return rc; } static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len, + void *ea, size_t ealen, void *ea2, size_t ea2len, struct ptlrpc_request **request, struct md_open_data **mod) { @@ -2021,169 +2112,419 @@ static int lmv_sync(struct obd_export *exp, const struct lu_fid *fid, return rc; } -/* - * Adjust a set of pages, each page containing an array of lu_dirpages, - * so that each page can be used as a single logical lu_dirpage. +/** + * Get current minimum entry from striped directory * - * A lu_dirpage is laid out as follows, where s = ldp_hash_start, - * e = ldp_hash_end, f = ldp_flags, p = padding, and each "ent" is a - * struct lu_dirent. It has size up to LU_PAGE_SIZE. The ldp_hash_end - * value is used as a cookie to request the next lu_dirpage in a - * directory listing that spans multiple pages (two in this example): - * ________ - * | | - * .|--------v------- -----. - * |s|e|f|p|ent|ent| ... |ent| - * '--|-------------- -----' Each CFS_PAGE contains a single - * '------. lu_dirpage. - * .---------v------- -----. - * |s|e|f|p|ent| 0 | ... | 0 | - * '----------------- -----' + * This function will search the dir entry, whose hash value is the + * closest(>=) to @hash_offset, from all of sub-stripes, and it is + * only being called for striped directory. * - * However, on hosts where the native VM page size (PAGE_SIZE) is - * larger than LU_PAGE_SIZE, a single host page may contain multiple - * lu_dirpages. After reading the lu_dirpages from the MDS, the - * ldp_hash_end of the first lu_dirpage refers to the one immediately - * after it in the same CFS_PAGE (arrows simplified for brevity, but - * in general e0==s1, e1==s2, etc.): + * \param[in] exp export of LMV + * \param[in] op_data parameters transferred beween client MD stack + * stripe_information will be included in this + * parameter + * \param[in] cb_op ldlm callback being used in enqueue in + * mdc_read_page + * \param[in] hash_offset the hash value, which is used to locate + * minum(closet) dir entry + * \param[in|out] stripe_offset the caller use this to indicate the stripe + * index of last entry, so to avoid hash conflict + * between stripes. It will also be used to + * return the stripe index of current dir entry. + * \param[in|out] entp the minum entry and it also is being used + * to input the last dir entry to resolve the + * hash conflict * - * .-------------------- -----. - * |s0|e0|f0|p|ent|ent| ... |ent| - * |---v---------------- -----| - * |s1|e1|f1|p|ent|ent| ... |ent| - * |---v---------------- -----| Here, each CFS_PAGE contains - * ... multiple lu_dirpages. - * |---v---------------- -----| - * |s'|e'|f'|p|ent|ent| ... |ent| - * '---|---------------- -----' - * v - * .----------------------------. - * | next CFS_PAGE | + * \param[out] ppage the page which holds the minum entry * - * This structure is transformed into a single logical lu_dirpage as follows: - * - * - Replace e0 with e' so the request for the next lu_dirpage gets the page - * labeled 'next CFS_PAGE'. - * - * - Copy the LDF_COLLIDE flag from f' to f0 to correctly reflect whether - * a hash collision with the next page exists. - * - * - Adjust the lde_reclen of the ending entry of each lu_dirpage to span - * to the first entry of the next lu_dirpage. + * \retval = 0 get the entry successfully + * negative errno (< 0) does not get the entry */ -#if PAGE_SIZE > LU_PAGE_SIZE -static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs) +static int lmv_get_min_striped_entry(struct obd_export *exp, + struct md_op_data *op_data, + struct md_callback *cb_op, + __u64 hash_offset, int *stripe_offset, + struct lu_dirent **entp, + struct page **ppage) { + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct obd_device *obd = exp->exp_obd; + struct lmv_obd *lmv = &obd->u.lmv; + struct lu_dirent *min_ent = NULL; + struct page *min_page = NULL; + struct lmv_tgt_desc *tgt; + int stripe_count; + int min_idx = 0; + int rc = 0; int i; - for (i = 0; i < ncfspgs; i++) { - struct lu_dirpage *dp = kmap(pages[i]); - struct lu_dirpage *first = dp; - struct lu_dirent *end_dirent = NULL; - struct lu_dirent *ent; - __u64 hash_end = dp->ldp_hash_end; - __u32 flags = dp->ldp_flags; + stripe_count = lsm->lsm_md_stripe_count; + for (i = 0; i < stripe_count; i++) { + __u64 stripe_hash = hash_offset; + struct lu_dirent *ent = NULL; + struct page *page = NULL; + struct lu_dirpage *dp; - while (--nlupgs > 0) { - ent = lu_dirent_start(dp); - for (end_dirent = ent; ent; - end_dirent = ent, ent = lu_dirent_next(ent)) - ; - - /* Advance dp to next lu_dirpage. */ - dp = (struct lu_dirpage *)((char *)dp + LU_PAGE_SIZE); - - /* Check if we've reached the end of the CFS_PAGE. */ - if (!((unsigned long)dp & ~PAGE_MASK)) - break; - - /* Save the hash and flags of this lu_dirpage. */ - hash_end = dp->ldp_hash_end; - flags = dp->ldp_flags; - - /* Check if lu_dirpage contains no entries. */ - if (!end_dirent) - break; - - /* Enlarge the end entry lde_reclen from 0 to - * first entry of next lu_dirpage. - */ - LASSERT(le16_to_cpu(end_dirent->lde_reclen) == 0); - end_dirent->lde_reclen = - cpu_to_le16((char *)(dp->ldp_entries) - - (char *)end_dirent); + tgt = lmv_get_target(lmv, lsm->lsm_md_oinfo[i].lmo_mds, NULL); + if (IS_ERR(tgt)) { + rc = PTR_ERR(tgt); + goto out; } - first->ldp_hash_end = hash_end; - first->ldp_flags &= ~cpu_to_le32(LDF_COLLIDE); - first->ldp_flags |= flags & cpu_to_le32(LDF_COLLIDE); + /* + * op_data will be shared by each stripe, so we need + * reset these value for each stripe + */ + op_data->op_fid1 = lsm->lsm_md_oinfo[i].lmo_fid; + op_data->op_fid2 = lsm->lsm_md_oinfo[i].lmo_fid; + op_data->op_data = lsm->lsm_md_oinfo[i].lmo_root; +next: + rc = md_read_page(tgt->ltd_exp, op_data, cb_op, stripe_hash, + &page); + if (rc) + goto out; - kunmap(pages[i]); + dp = page_address(page); + for (ent = lu_dirent_start(dp); ent; + ent = lu_dirent_next(ent)) { + /* Skip dummy entry */ + if (!le16_to_cpu(ent->lde_namelen)) + continue; + + if (le64_to_cpu(ent->lde_hash) < hash_offset) + continue; + + if (le64_to_cpu(ent->lde_hash) == hash_offset && + (*entp == ent || i < *stripe_offset)) + continue; + + /* skip . and .. for other stripes */ + if (i && (!strncmp(ent->lde_name, ".", + le16_to_cpu(ent->lde_namelen)) || + !strncmp(ent->lde_name, "..", + le16_to_cpu(ent->lde_namelen)))) + continue; + break; + } + + if (!ent) { + stripe_hash = le64_to_cpu(dp->ldp_hash_end); + + kunmap(page); + put_page(page); + page = NULL; + + /* + * reach the end of current stripe, go to next stripe + */ + if (stripe_hash == MDS_DIR_END_OFF) + continue; + else + goto next; + } + + if (min_ent) { + if (le64_to_cpu(min_ent->lde_hash) > + le64_to_cpu(ent->lde_hash)) { + min_ent = ent; + kunmap(min_page); + put_page(min_page); + min_idx = i; + min_page = page; + } else { + kunmap(page); + put_page(page); + page = NULL; + } + } else { + min_ent = ent; + min_page = page; + min_idx = i; + } } - LASSERTF(nlupgs == 0, "left = %d", nlupgs); -} -#else -#define lmv_adjust_dirpages(pages, ncfspgs, nlupgs) do {} while (0) -#endif /* PAGE_SIZE > LU_PAGE_SIZE */ -static int lmv_readpage(struct obd_export *exp, struct md_op_data *op_data, - struct page **pages, struct ptlrpc_request **request) +out: + if (*ppage) { + kunmap(*ppage); + put_page(*ppage); + } + *stripe_offset = min_idx; + *entp = min_ent; + *ppage = min_page; + return rc; +} + +/** + * Build dir entry page from a striped directory + * + * This function gets one entry by @offset from a striped directory. It will + * read entries from all of stripes, and choose one closest to the required + * offset(&offset). A few notes + * 1. skip . and .. for non-zero stripes, because there can only have one . + * and .. in a directory. + * 2. op_data will be shared by all of stripes, instead of allocating new + * one, so need to restore before reusing. + * 3. release the entry page if that is not being chosen. + * + * \param[in] exp obd export refer to LMV + * \param[in] op_data hold those MD parameters of read_entry + * \param[in] cb_op ldlm callback being used in enqueue in mdc_read_entry + * \param[out] ldp the entry being read + * \param[out] ppage the page holding the entry. Note: because the entry + * will be accessed in upper layer, so we need hold the + * page until the usages of entry is finished, see + * ll_dir_entry_next. + * + * retval =0 if get entry successfully + * <0 cannot get entry + */ +static int lmv_read_striped_page(struct obd_export *exp, + struct md_op_data *op_data, + struct md_callback *cb_op, + __u64 offset, struct page **ppage) { - struct obd_device *obd = exp->exp_obd; - struct lmv_obd *lmv = &obd->u.lmv; - __u64 offset = op_data->op_offset; - int rc; - int ncfspgs; /* pages read in PAGE_SIZE */ - int nlupgs; /* pages read in LU_PAGE_SIZE */ - struct lmv_tgt_desc *tgt; + struct inode *master_inode = op_data->op_data; + struct lu_fid master_fid = op_data->op_fid1; + struct obd_device *obd = exp->exp_obd; + __u64 hash_offset = offset; + struct page *min_ent_page = NULL; + struct page *ent_page = NULL; + struct lu_dirent *min_ent = NULL; + struct lu_dirent *last_ent; + struct lu_dirent *ent; + struct lu_dirpage *dp; + size_t left_bytes; + int ent_idx = 0; + void *area; + int rc; rc = lmv_check_connect(obd); if (rc) return rc; - CDEBUG(D_INODE, "READPAGE at %#llx from "DFID"\n", - offset, PFID(&op_data->op_fid1)); + /* + * Allocate a page and read entries from all of stripes and fill + * the page by hash order + */ + ent_page = alloc_page(GFP_KERNEL); + if (!ent_page) + return -ENOMEM; + + /* Initialize the entry page */ + dp = kmap(ent_page); + memset(dp, 0, sizeof(*dp)); + dp->ldp_hash_start = cpu_to_le64(offset); + dp->ldp_flags |= LDF_COLLIDE; + + area = dp + 1; + left_bytes = PAGE_SIZE - sizeof(*dp); + ent = area; + last_ent = ent; + do { + __u16 ent_size; + + /* Find the minum entry from all sub-stripes */ + rc = lmv_get_min_striped_entry(exp, op_data, cb_op, hash_offset, + &ent_idx, &min_ent, + &min_ent_page); + if (rc) + goto out; + + /* + * If it can not get minum entry, it means it already reaches + * the end of this directory + */ + if (!min_ent) { + last_ent->lde_reclen = 0; + hash_offset = MDS_DIR_END_OFF; + goto out; + } + + ent_size = le16_to_cpu(min_ent->lde_reclen); + + /* + * the last entry lde_reclen is 0, but it might not + * the end of this entry of this temporay entry + */ + if (!ent_size) + ent_size = lu_dirent_calc_size( + le16_to_cpu(min_ent->lde_namelen), + le32_to_cpu(min_ent->lde_attrs)); + if (ent_size > left_bytes) { + last_ent->lde_reclen = cpu_to_le16(0); + hash_offset = le64_to_cpu(min_ent->lde_hash); + goto out; + } + + memcpy(ent, min_ent, ent_size); + + /* + * Replace . with master FID and Replace .. with the parent FID + * of master object + */ + if (!strncmp(ent->lde_name, ".", + le16_to_cpu(ent->lde_namelen)) && + le16_to_cpu(ent->lde_namelen) == 1) + fid_cpu_to_le(&ent->lde_fid, &master_fid); + else if (!strncmp(ent->lde_name, "..", + le16_to_cpu(ent->lde_namelen)) && + le16_to_cpu(ent->lde_namelen) == 2) + fid_cpu_to_le(&ent->lde_fid, &op_data->op_fid3); + + left_bytes -= ent_size; + ent->lde_reclen = cpu_to_le16(ent_size); + last_ent = ent; + ent = (void *)ent + ent_size; + hash_offset = le64_to_cpu(min_ent->lde_hash); + if (hash_offset == MDS_DIR_END_OFF) { + last_ent->lde_reclen = 0; + break; + } + } while (1); +out: + if (min_ent_page) { + kunmap(min_ent_page); + put_page(min_ent_page); + } + + if (unlikely(rc)) { + __free_page(ent_page); + ent_page = NULL; + } else { + if (ent == area) + dp->ldp_flags |= LDF_EMPTY; + dp->ldp_flags = cpu_to_le32(dp->ldp_flags); + dp->ldp_hash_end = cpu_to_le64(hash_offset); + } + + /* + * We do not want to allocate md_op_data during each + * dir entry reading, so op_data will be shared by every stripe, + * then we need to restore it back to original value before + * return to the upper layer + */ + op_data->op_fid1 = master_fid; + op_data->op_fid2 = master_fid; + op_data->op_data = master_inode; + + *ppage = ent_page; + + return rc; +} + +static int lmv_read_page(struct obd_export *exp, struct md_op_data *op_data, + struct md_callback *cb_op, __u64 offset, + struct page **ppage) +{ + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct obd_device *obd = exp->exp_obd; + struct lmv_obd *lmv = &obd->u.lmv; + struct lmv_tgt_desc *tgt; + int rc; + + rc = lmv_check_connect(obd); + if (rc) + return rc; + + if (unlikely(lsm)) { + rc = lmv_read_striped_page(exp, op_data, cb_op, offset, ppage); + return rc; + } tgt = lmv_find_target(lmv, &op_data->op_fid1); if (IS_ERR(tgt)) return PTR_ERR(tgt); - rc = md_readpage(tgt->ltd_exp, op_data, pages, request); - if (rc != 0) - return rc; - - ncfspgs = ((*request)->rq_bulk->bd_nob_transferred + PAGE_SIZE - 1) - >> PAGE_SHIFT; - nlupgs = (*request)->rq_bulk->bd_nob_transferred >> LU_PAGE_SHIFT; - LASSERT(!((*request)->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK)); - LASSERT(ncfspgs > 0 && ncfspgs <= op_data->op_npages); - - CDEBUG(D_INODE, "read %d(%d)/%d pages\n", ncfspgs, nlupgs, - op_data->op_npages); - - lmv_adjust_dirpages(pages, ncfspgs, nlupgs); + rc = md_read_page(tgt->ltd_exp, op_data, cb_op, offset, ppage); return rc; } +/** + * Unlink a file/directory + * + * Unlink a file or directory under the parent dir. The unlink request + * usually will be sent to the MDT where the child is located, but if + * the client does not have the child FID then request will be sent to the + * MDT where the parent is located. + * + * If the parent is a striped directory then it also needs to locate which + * stripe the name of the child is located, and replace the parent FID + * (@op->op_fid1) with the stripe FID. Note: if the stripe is unknown, + * it will walk through all of sub-stripes until the child is being + * unlinked finally. + * + * \param[in] exp export refer to LMV + * \param[in] op_data different parameters transferred beween client + * MD stacks, name, namelen, FIDs etc. + * op_fid1 is the parent FID, op_fid2 is the child + * FID. + * \param[out] request point to the request of unlink. + * + * retval 0 if succeed + * negative errno if failed. + */ static int lmv_unlink(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request) { - struct obd_device *obd = exp->exp_obd; + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; + struct lmv_tgt_desc *parent_tgt = NULL; struct lmv_tgt_desc *tgt = NULL; struct mdt_body *body; + int stripe_index = 0; int rc; rc = lmv_check_connect(obd); if (rc) return rc; -retry: +retry_unlink: + /* For striped dir, we need to locate the parent as well */ + if (lsm) { + struct lmv_tgt_desc *tmp; + + LASSERT(op_data->op_name && op_data->op_namelen); + + tmp = lmv_locate_target_for_name(lmv, lsm, + op_data->op_name, + op_data->op_namelen, + &op_data->op_fid1, + &op_data->op_mds); + + /* + * return -EBADFD means unknown hash type, might + * need try all sub-stripe here + */ + if (IS_ERR(tmp) && PTR_ERR(tmp) != -EBADFD) + return PTR_ERR(tmp); + + /* + * Note: both migrating dir and unknown hash dir need to + * try all of sub-stripes, so we need start search the + * name from stripe 0, but migrating dir is already handled + * inside lmv_locate_target_for_name(), so we only check + * unknown hash type directory here + */ + if (!lmv_is_known_hash_type(lsm->lsm_md_hash_type)) { + struct lmv_oinfo *oinfo; + + oinfo = &lsm->lsm_md_oinfo[stripe_index]; + + op_data->op_fid1 = oinfo->lmo_fid; + op_data->op_mds = oinfo->lmo_mds; + } + } + +try_next_stripe: /* Send unlink requests to the MDT where the child is located */ if (likely(!fid_is_zero(&op_data->op_fid2))) - tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2); + tgt = lmv_find_target(lmv, &op_data->op_fid2); + else if (lsm) + tgt = lmv_get_target(lmv, op_data->op_mds, NULL); else tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); + if (IS_ERR(tgt)) return PTR_ERR(tgt); @@ -2203,29 +2544,57 @@ retry: /* * Cancel FULL locks on child (fid3). */ - rc = lmv_early_cancel(exp, op_data, tgt->ltd_idx, LCK_EX, - MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID3); + parent_tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(parent_tgt)) + return PTR_ERR(parent_tgt); + if (parent_tgt != tgt) { + rc = lmv_early_cancel(exp, parent_tgt, op_data, tgt->ltd_idx, + LCK_EX, MDS_INODELOCK_LOOKUP, + MF_MDC_CANCEL_FID3); + } + + rc = lmv_early_cancel(exp, NULL, op_data, tgt->ltd_idx, LCK_EX, + MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID3); if (rc != 0) return rc; - CDEBUG(D_INODE, "unlink with fid="DFID"/"DFID" -> mds #%d\n", + CDEBUG(D_INODE, "unlink with fid=" DFID "/" DFID " -> mds #%u\n", PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), tgt->ltd_idx); rc = md_unlink(tgt->ltd_exp, op_data, request); - if (rc != 0 && rc != -EREMOTE) + if (rc != 0 && rc != -EREMOTE && rc != -ENOENT) return rc; + /* Try next stripe if it is needed. */ + if (rc == -ENOENT && lsm && lmv_need_try_all_stripes(lsm)) { + struct lmv_oinfo *oinfo; + + stripe_index++; + if (stripe_index >= lsm->lsm_md_stripe_count) + return rc; + + oinfo = &lsm->lsm_md_oinfo[stripe_index]; + + op_data->op_fid1 = oinfo->lmo_fid; + op_data->op_mds = oinfo->lmo_mds; + + ptlrpc_req_finished(*request); + *request = NULL; + + goto try_next_stripe; + } + body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY); if (!body) return -EPROTO; /* Not cross-ref case, just get out of here. */ - if (likely(!(body->valid & OBD_MD_MDS))) - return 0; + if (likely(!(body->mbo_valid & OBD_MD_MDS))) + return rc; CDEBUG(D_INODE, "%s: try unlink to another MDT for "DFID"\n", - exp->exp_obd->obd_name, PFID(&body->fid1)); + exp->exp_obd->obd_name, PFID(&body->mbo_fid1)); /* This is a remote object, try remote MDT, Note: it may * try more than 1 time here, Considering following case @@ -2247,11 +2616,11 @@ retry: * In theory, it might try unlimited time here, but it should * be very rare case. */ - op_data->op_fid2 = body->fid1; + op_data->op_fid2 = body->mbo_fid1; ptlrpc_req_finished(*request); *request = NULL; - goto retry; + goto retry_unlink; } static int lmv_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) @@ -2274,6 +2643,22 @@ static int lmv_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) return 0; } +/** + * Get by key a value associated with a LMV device. + * + * Dispatch request to lower-layer devices as needed. + * + * \param[in] env execution environment for this thread + * \param[in] exp export for the LMV device + * \param[in] keylen length of key identifier + * \param[in] key identifier of key to get value for + * \param[in] vallen size of \a val + * \param[out] val pointer to storage location for value + * \param[in] lsm optional striping metadata of object + * + * \retval 0 on success + * \retval negative negated errno on failure + */ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, __u32 keylen, void *key, __u32 *vallen, void *val, struct lov_stripe_md *lsm) @@ -2337,6 +2722,22 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } +/** + * Asynchronously set by key a value associated with a LMV device. + * + * Dispatch request to lower-layer devices as needed. + * + * \param[in] env execution environment for this thread + * \param[in] exp export for the LMV device + * \param[in] keylen length of key identifier + * \param[in] key identifier of key to store value for + * \param[in] vallen size of value to store + * \param[in] val pointer to data to be stored + * \param[in] set optional list of related ptlrpc requests + * + * \retval 0 on success + * \retval negative negated errno on failure + */ static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, u32 keylen, void *key, u32 vallen, void *val, struct ptlrpc_request_set *set) @@ -2354,7 +2755,8 @@ static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, } lmv = &obd->u.lmv; - if (KEY_IS(KEY_READ_ONLY) || KEY_IS(KEY_FLUSH_CTX)) { + if (KEY_IS(KEY_READ_ONLY) || KEY_IS(KEY_FLUSH_CTX) || + KEY_IS(KEY_DEFAULT_EASIZE)) { int i, err = 0; for (i = 0; i < lmv->desc.ld_tgt_count; i++) { @@ -2375,105 +2777,247 @@ static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } -static int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) +static int lmv_pack_md_v1(const struct lmv_stripe_md *lsm, + struct lmv_mds_md_v1 *lmm1) { - struct obd_device *obd = class_exp2obd(exp); - struct lmv_obd *lmv = &obd->u.lmv; - struct lmv_stripe_md *meap; - struct lmv_stripe_md *lsmp; - int mea_size; - int i; + int cplen; + int i; - mea_size = lmv_get_easize(lmv); - if (!lmmp) - return mea_size; + lmm1->lmv_magic = cpu_to_le32(lsm->lsm_md_magic); + lmm1->lmv_stripe_count = cpu_to_le32(lsm->lsm_md_stripe_count); + lmm1->lmv_master_mdt_index = cpu_to_le32(lsm->lsm_md_master_mdt_index); + lmm1->lmv_hash_type = cpu_to_le32(lsm->lsm_md_hash_type); + cplen = strlcpy(lmm1->lmv_pool_name, lsm->lsm_md_pool_name, + sizeof(lmm1->lmv_pool_name)); + if (cplen >= sizeof(lmm1->lmv_pool_name)) + return -E2BIG; + for (i = 0; i < lsm->lsm_md_stripe_count; i++) + fid_cpu_to_le(&lmm1->lmv_stripe_fids[i], + &lsm->lsm_md_oinfo[i].lmo_fid); + return 0; +} + +static int +lmv_pack_md(union lmv_mds_md **lmmp, const struct lmv_stripe_md *lsm, + int stripe_count) +{ + int lmm_size = 0, rc = 0; + bool allocated = false; + + LASSERT(lmmp); + + /* Free lmm */ if (*lmmp && !lsm) { + int stripe_cnt; + + stripe_cnt = lmv_mds_md_stripe_count_get(*lmmp); + lmm_size = lmv_mds_md_size(stripe_cnt, + le32_to_cpu((*lmmp)->lmv_magic)); + if (!lmm_size) + return -EINVAL; kvfree(*lmmp); *lmmp = NULL; return 0; } - if (!*lmmp) { - *lmmp = libcfs_kvzalloc(mea_size, GFP_NOFS); + /* Alloc lmm */ + if (!*lmmp && !lsm) { + lmm_size = lmv_mds_md_size(stripe_count, LMV_MAGIC); + LASSERT(lmm_size > 0); + *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); if (!*lmmp) return -ENOMEM; + lmv_mds_md_stripe_count_set(*lmmp, stripe_count); + (*lmmp)->lmv_magic = cpu_to_le32(LMV_MAGIC); + return lmm_size; } - if (!lsm) - return mea_size; - - lsmp = (struct lmv_stripe_md *)lsm; - meap = (struct lmv_stripe_md *)*lmmp; - - if (lsmp->mea_magic != MEA_MAGIC_LAST_CHAR && - lsmp->mea_magic != MEA_MAGIC_ALL_CHARS) - return -EINVAL; - - meap->mea_magic = cpu_to_le32(lsmp->mea_magic); - meap->mea_count = cpu_to_le32(lsmp->mea_count); - meap->mea_master = cpu_to_le32(lsmp->mea_master); - - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - meap->mea_ids[i] = lsmp->mea_ids[i]; - fid_cpu_to_le(&meap->mea_ids[i], &lsmp->mea_ids[i]); + /* pack lmm */ + LASSERT(lsm); + lmm_size = lmv_mds_md_size(lsm->lsm_md_stripe_count, + lsm->lsm_md_magic); + if (!*lmmp) { + *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); + if (!*lmmp) + return -ENOMEM; + allocated = true; } - return mea_size; + switch (lsm->lsm_md_magic) { + case LMV_MAGIC_V1: + rc = lmv_pack_md_v1(lsm, &(*lmmp)->lmv_md_v1); + break; + default: + rc = -EINVAL; + break; + } + + if (rc && allocated) { + kvfree(*lmmp); + *lmmp = NULL; + } + + return lmm_size; } -static int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int lmm_size) +static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm, + const struct lmv_mds_md_v1 *lmm1) { - struct obd_device *obd = class_exp2obd(exp); - struct lmv_stripe_md **tmea = (struct lmv_stripe_md **)lsmp; - struct lmv_stripe_md *mea = (struct lmv_stripe_md *)lmm; - struct lmv_obd *lmv = &obd->u.lmv; - int mea_size; - int i; - __u32 magic; + struct lmv_obd *lmv = &exp->exp_obd->u.lmv; + int stripe_count; + int rc = 0; + int cplen; + int i; - mea_size = lmv_get_easize(lmv); - if (!lsmp) - return mea_size; + lsm->lsm_md_magic = le32_to_cpu(lmm1->lmv_magic); + lsm->lsm_md_stripe_count = le32_to_cpu(lmm1->lmv_stripe_count); + lsm->lsm_md_master_mdt_index = le32_to_cpu(lmm1->lmv_master_mdt_index); + if (OBD_FAIL_CHECK(OBD_FAIL_UNKNOWN_LMV_STRIPE)) + lsm->lsm_md_hash_type = LMV_HASH_TYPE_UNKNOWN; + else + lsm->lsm_md_hash_type = le32_to_cpu(lmm1->lmv_hash_type); + lsm->lsm_md_layout_version = le32_to_cpu(lmm1->lmv_layout_version); + cplen = strlcpy(lsm->lsm_md_pool_name, lmm1->lmv_pool_name, + sizeof(lsm->lsm_md_pool_name)); - if (*lsmp && !lmm) { - kvfree(*tmea); + if (cplen >= sizeof(lsm->lsm_md_pool_name)) + return -E2BIG; + + CDEBUG(D_INFO, "unpack lsm count %d, master %d hash_type %d layout_version %d\n", + lsm->lsm_md_stripe_count, lsm->lsm_md_master_mdt_index, + lsm->lsm_md_hash_type, lsm->lsm_md_layout_version); + + stripe_count = le32_to_cpu(lmm1->lmv_stripe_count); + for (i = 0; i < stripe_count; i++) { + fid_le_to_cpu(&lsm->lsm_md_oinfo[i].lmo_fid, + &lmm1->lmv_stripe_fids[i]); + rc = lmv_fld_lookup(lmv, &lsm->lsm_md_oinfo[i].lmo_fid, + &lsm->lsm_md_oinfo[i].lmo_mds); + if (rc) + return rc; + CDEBUG(D_INFO, "unpack fid #%d "DFID"\n", i, + PFID(&lsm->lsm_md_oinfo[i].lmo_fid)); + } + + return rc; +} + +int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, + const union lmv_mds_md *lmm, int stripe_count) +{ + struct lmv_stripe_md *lsm; + bool allocated = false; + int lsm_size, rc; + + LASSERT(lsmp); + + lsm = *lsmp; + /* Free memmd */ + if (lsm && !lmm) { + int i; + + for (i = 1; i < lsm->lsm_md_stripe_count; i++) { + /* + * For migrating inode, the master stripe and master + * object will be the same, so do not need iput, see + * ll_update_lsm_md + */ + if (!(lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION && + !i) && lsm->lsm_md_oinfo[i].lmo_root) + iput(lsm->lsm_md_oinfo[i].lmo_root); + } + + kvfree(lsm); *lsmp = NULL; return 0; } - LASSERT(mea_size == lmm_size); + /* Alloc memmd */ + if (!lsm && !lmm) { + lsm_size = lmv_stripe_md_size(stripe_count); + lsm = libcfs_kvzalloc(lsm_size, GFP_NOFS); + if (!lsm) + return -ENOMEM; + lsm->lsm_md_stripe_count = stripe_count; + *lsmp = lsm; + return 0; + } - *tmea = libcfs_kvzalloc(mea_size, GFP_NOFS); - if (!*tmea) - return -ENOMEM; + if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_STRIPE) + return -EPERM; - if (!lmm) - return mea_size; + /* Unpack memmd */ + if (le32_to_cpu(lmm->lmv_magic) != LMV_MAGIC_V1 && + le32_to_cpu(lmm->lmv_magic) != LMV_USER_MAGIC) { + CERROR("%s: invalid lmv magic %x: rc = %d\n", + exp->exp_obd->obd_name, le32_to_cpu(lmm->lmv_magic), + -EIO); + return -EIO; + } - if (mea->mea_magic == MEA_MAGIC_LAST_CHAR || - mea->mea_magic == MEA_MAGIC_ALL_CHARS || - mea->mea_magic == MEA_MAGIC_HASH_SEGMENT) { - magic = le32_to_cpu(mea->mea_magic); - } else { - /* - * Old mea is not handled here. + if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_V1) + lsm_size = lmv_stripe_md_size(lmv_mds_md_stripe_count_get(lmm)); + else + /** + * Unpack default dirstripe(lmv_user_md) to lmv_stripe_md, + * stripecount should be 0 then. */ - CERROR("Old not supportable EA is found\n"); - LBUG(); + lsm_size = lmv_stripe_md_size(0); + + if (!lsm) { + lsm = libcfs_kvzalloc(lsm_size, GFP_NOFS); + if (!lsm) + return -ENOMEM; + allocated = true; + *lsmp = lsm; } - (*tmea)->mea_magic = magic; - (*tmea)->mea_count = le32_to_cpu(mea->mea_count); - (*tmea)->mea_master = le32_to_cpu(mea->mea_master); - - for (i = 0; i < (*tmea)->mea_count; i++) { - (*tmea)->mea_ids[i] = mea->mea_ids[i]; - fid_le_to_cpu(&(*tmea)->mea_ids[i], &(*tmea)->mea_ids[i]); + switch (le32_to_cpu(lmm->lmv_magic)) { + case LMV_MAGIC_V1: + rc = lmv_unpack_md_v1(exp, lsm, &lmm->lmv_md_v1); + break; + default: + CERROR("%s: unrecognized magic %x\n", exp->exp_obd->obd_name, + le32_to_cpu(lmm->lmv_magic)); + rc = -EINVAL; + break; } - return mea_size; + + if (rc && allocated) { + kvfree(lsm); + *lsmp = NULL; + lsm_size = rc; + } + return lsm_size; +} +EXPORT_SYMBOL(lmv_unpack_md); + +static int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_mds_md *lmm, int disk_len) +{ + return lmv_unpack_md(exp, (struct lmv_stripe_md **)lsmp, + (union lmv_mds_md *)lmm, disk_len); +} + +static int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) +{ + const struct lmv_stripe_md *lmv = (struct lmv_stripe_md *)lsm; + struct obd_device *obd = exp->exp_obd; + struct lmv_obd *lmv_obd = &obd->u.lmv; + int stripe_count; + + if (!lmmp) { + if (lsm) + stripe_count = lmv->lsm_md_stripe_count; + else + stripe_count = lmv_obd->desc.ld_tgt_count; + + return lmv_mds_md_size(stripe_count, LMV_MAGIC_V1); + } + + return lmv_pack_md((union lmv_mds_md **)lmmp, lmv, 0); } static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, @@ -2484,7 +3028,7 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, struct lmv_obd *lmv = &obd->u.lmv; int rc = 0; int err; - int i; + u32 i; LASSERT(fid); @@ -2502,8 +3046,9 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, return rc; } -static int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, - __u64 *bits) +static int lmv_set_lock_data(struct obd_export *exp, + const struct lustre_handle *lockh, + void *data, __u64 *bits) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; struct lmv_tgt_desc *tgt = lmv->tgts[0]; @@ -2526,24 +3071,32 @@ static enum ldlm_mode lmv_lock_match(struct obd_export *exp, __u64 flags, struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; enum ldlm_mode rc; - int i; + int tgt; + u32 i; CDEBUG(D_INODE, "Lock match for "DFID"\n", PFID(fid)); /* - * With CMD every object can have two locks in different namespaces: - * lookup lock in space of mds storing direntry and update/open lock in - * space of mds storing inode. Thus we check all targets, not only that - * one fid was created in. + * With DNE every object can have two locks in different namespaces: + * lookup lock in space of MDT storing direntry and update/open lock in + * space of MDT storing inode. Try the MDT that the FID maps to first, + * since this can be easily found, and only try others if that fails. */ - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - struct lmv_tgt_desc *tgt = lmv->tgts[i]; + for (i = 0, tgt = lmv_find_target_index(lmv, fid); + i < lmv->desc.ld_tgt_count; + i++, tgt = (tgt + 1) % lmv->desc.ld_tgt_count) { + if (tgt < 0) { + CDEBUG(D_HA, "%s: "DFID" is inaccessible: rc = %d\n", + obd->obd_name, PFID(fid), tgt); + tgt = 0; + } - if (!tgt || !tgt->ltd_exp || !tgt->ltd_active) + if (!lmv->tgts[tgt] || !lmv->tgts[tgt]->ltd_exp || + !lmv->tgts[tgt]->ltd_active) continue; - rc = md_lock_match(tgt->ltd_exp, flags, fid, type, policy, mode, - lockh); + rc = md_lock_match(lmv->tgts[tgt]->ltd_exp, flags, fid, + type, policy, mode, lockh); if (rc) return rc; } @@ -2571,8 +3124,10 @@ static int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt = lmv->tgts[0]; - if (md->mea) - obd_free_memmd(exp, (void *)&md->mea); + if (md->lmv) { + lmv_free_memmd(md->lmv); + md->lmv = NULL; + } if (!tgt || !tgt->ltd_exp) return -EINVAL; return md_free_lustre_md(tgt->ltd_exp, md); @@ -2621,7 +3176,7 @@ static int lmv_intent_getattr_async(struct obd_export *exp, if (rc) return rc; - tgt = lmv_find_target(lmv, &op_data->op_fid1); + tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); if (IS_ERR(tgt)) return PTR_ERR(tgt); @@ -2649,6 +3204,23 @@ static int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, return rc; } +static int +lmv_get_fid_from_lsm(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + const char *name, int namelen, struct lu_fid *fid) +{ + const struct lmv_oinfo *oinfo; + + LASSERT(lsm); + oinfo = lsm_name_to_stripe_info(lsm, name, namelen); + if (IS_ERR(oinfo)) + return PTR_ERR(oinfo); + + *fid = oinfo->lmo_fid; + + return 0; +} + /** * For lmv, only need to send request to master MDT, and the master MDT will * process with other slave MDTs. The only exception is Q_GETOQUOTA for which @@ -2660,8 +3232,9 @@ static int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt = lmv->tgts[0]; - int rc = 0, i; + int rc = 0; __u64 curspace = 0, curinodes = 0; + u32 i; if (!tgt || !tgt->ltd_exp || !tgt->ltd_active || !lmv->desc.ld_tgt_count) { @@ -2704,7 +3277,8 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; - int i, rc = 0; + int rc = 0; + u32 i; for (i = 0; i < lmv->desc.ld_tgt_count; i++) { int err; @@ -2723,6 +3297,47 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, return rc; } +static int lmv_merge_attr(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + struct cl_attr *attr, + ldlm_blocking_callback cb_blocking) +{ + int rc, i; + + rc = lmv_revalidate_slaves(exp, lsm, cb_blocking, 0); + if (rc < 0) + return rc; + + for (i = 0; i < lsm->lsm_md_stripe_count; i++) { + struct inode *inode = lsm->lsm_md_oinfo[i].lmo_root; + + CDEBUG(D_INFO, ""DFID" size %llu, blocks %llu nlink %u, atime %lu ctime %lu, mtime %lu.\n", + PFID(&lsm->lsm_md_oinfo[i].lmo_fid), + i_size_read(inode), (unsigned long long)inode->i_blocks, + inode->i_nlink, LTIME_S(inode->i_atime), + LTIME_S(inode->i_ctime), LTIME_S(inode->i_mtime)); + + /* for slave stripe, it needs to subtract nlink for . and .. */ + if (i) + attr->cat_nlink += inode->i_nlink - 2; + else + attr->cat_nlink = inode->i_nlink; + + attr->cat_size += i_size_read(inode); + attr->cat_blocks += inode->i_blocks; + + if (attr->cat_atime < LTIME_S(inode->i_atime)) + attr->cat_atime = LTIME_S(inode->i_atime); + + if (attr->cat_ctime < LTIME_S(inode->i_ctime)) + attr->cat_ctime = LTIME_S(inode->i_ctime); + + if (attr->cat_mtime < LTIME_S(inode->i_mtime)) + attr->cat_mtime = LTIME_S(inode->i_mtime); + } + return 0; +} + static struct obd_ops lmv_obd_ops = { .owner = THIS_MODULE, .setup = lmv_setup, @@ -2746,7 +3361,6 @@ static struct obd_ops lmv_obd_ops = { static struct md_ops lmv_md_ops = { .getstatus = lmv_getstatus, .null_inode = lmv_null_inode, - .find_cbdata = lmv_find_cbdata, .close = lmv_close, .create = lmv_create, .done_writing = lmv_done_writing, @@ -2760,7 +3374,7 @@ static struct md_ops lmv_md_ops = { .setattr = lmv_setattr, .setxattr = lmv_setxattr, .sync = lmv_sync, - .readpage = lmv_readpage, + .read_page = lmv_read_page, .unlink = lmv_unlink, .init_ea_size = lmv_init_ea_size, .cancel_unused = lmv_cancel_unused, @@ -2768,10 +3382,12 @@ static struct md_ops lmv_md_ops = { .lock_match = lmv_lock_match, .get_lustre_md = lmv_get_lustre_md, .free_lustre_md = lmv_free_lustre_md, + .merge_attr = lmv_merge_attr, .set_open_replay_data = lmv_set_open_replay_data, .clear_open_replay_data = lmv_clear_open_replay_data, .intent_getattr_async = lmv_intent_getattr_async, - .revalidate_lock = lmv_revalidate_lock + .revalidate_lock = lmv_revalidate_lock, + .get_fid_from_lsm = lmv_get_fid_from_lsm, }; static int __init lmv_init(void) diff --git a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c index c29c361eb0cc..20bbdfc21d15 100644 --- a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c +++ b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c @@ -169,7 +169,7 @@ static int lmv_tgt_seq_show(struct seq_file *p, void *v) if (!tgt) return 0; - seq_printf(p, "%d: %s %sACTIVE\n", + seq_printf(p, "%u: %s %sACTIVE\n", tgt->ltd_idx, tgt->ltd_uuid.uuid, tgt->ltd_active ? "" : "IN"); return 0; @@ -202,7 +202,7 @@ static struct lprocfs_vars lprocfs_lmv_obd_vars[] = { { NULL } }; -struct file_operations lmv_proc_target_fops = { +const struct file_operations lmv_proc_target_fops = { .owner = THIS_MODULE, .open = lmv_target_seq_open, .read = seq_read, diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 9740568d9521..4d2b7d303fea 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -289,8 +289,8 @@ struct lov_lock { }; struct lov_page { - struct cl_page_slice lps_cl; - int lps_invalid; + struct cl_page_slice lps_cl; + unsigned int lps_stripe; /* stripe index */ }; /* @@ -556,6 +556,8 @@ struct lov_lock_link *lov_lock_link_find(const struct lu_env *env, struct lovsub_lock *sub); struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio, const struct cl_page_slice *slice); + +struct lov_stripe_md *lov_lsm_addref(struct lov_object *lov); int lov_page_stripe(const struct cl_page *page); #define lov_foreach_target(lov, var) \ @@ -742,11 +744,15 @@ static inline struct lov_thread_info *lov_env_info(const struct lu_env *env) static inline struct lov_layout_raid0 *lov_r0(struct lov_object *lov) { LASSERT(lov->lo_type == LLT_RAID0); - LASSERT(lov->lo_lsm->lsm_wire.lw_magic == LOV_MAGIC || - lov->lo_lsm->lsm_wire.lw_magic == LOV_MAGIC_V3); + LASSERT(lov->lo_lsm->lsm_magic == LOV_MAGIC || + lov->lo_lsm->lsm_magic == LOV_MAGIC_V3); return &lov->u.raid0; } +/* lov_pack.c */ +int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, + struct lov_user_md __user *lump); + /** @} lov */ #endif diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index b1f260d43bc7..056ae2ed88e8 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -516,6 +516,5 @@ struct lu_device_type lov_device_type = { .ldt_ops = &lov_device_type_ops, .ldt_ctx_tags = LCT_CL_THREAD }; -EXPORT_SYMBOL(lov_device_type); /** @} lov */ diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c index 5053dead17bb..214c561767e0 100644 --- a/drivers/staging/lustre/lustre/lov/lov_ea.c +++ b/drivers/staging/lustre/lustre/lov/lov_ea.c @@ -66,7 +66,8 @@ static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes, } if (lmm->lmm_stripe_size == 0 || - (le32_to_cpu(lmm->lmm_stripe_size)&(LOV_MIN_STRIPE_SIZE-1)) != 0) { + (le32_to_cpu(lmm->lmm_stripe_size) & + (LOV_MIN_STRIPE_SIZE - 1)) != 0) { CERROR("bad stripe size %u\n", le32_to_cpu(lmm->lmm_stripe_size)); lov_dump_lmm_common(D_WARNING, lmm); @@ -146,21 +147,15 @@ lsm_stripe_by_offset_plain(struct lov_stripe_md *lsm, int *stripeno, *swidth = (u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count; } -static int lsm_destroy_plain(struct lov_stripe_md *lsm, struct obdo *oa, - struct obd_export *md_exp) -{ - return 0; -} - /* Find minimum stripe maxbytes value. For inactive or - * reconnecting targets use LUSTRE_STRIPE_MAXBYTES. + * reconnecting targets use LUSTRE_EXT3_STRIPE_MAXBYTES. */ static void lov_tgt_maxbytes(struct lov_tgt_desc *tgt, __u64 *stripe_maxbytes) { struct obd_import *imp = tgt->ltd_obd->u.cli.cl_import; if (!imp || !tgt->ltd_active) { - *stripe_maxbytes = LUSTRE_STRIPE_MAXBYTES; + *stripe_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; return; } @@ -171,7 +166,7 @@ static void lov_tgt_maxbytes(struct lov_tgt_desc *tgt, __u64 *stripe_maxbytes) if (*stripe_maxbytes > imp->imp_connect_data.ocd_maxbytes) *stripe_maxbytes = imp->imp_connect_data.ocd_maxbytes; } else { - *stripe_maxbytes = LUSTRE_STRIPE_MAXBYTES; + *stripe_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; } spin_unlock(&imp->imp_lock); } @@ -245,7 +240,6 @@ static int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm, const struct lsm_operations lsm_v1_ops = { .lsm_free = lsm_free_plain, - .lsm_destroy = lsm_destroy_plain, .lsm_stripe_by_index = lsm_stripe_by_index_plain, .lsm_stripe_by_offset = lsm_stripe_by_offset_plain, .lsm_lmm_verify = lsm_lmm_verify_v1, @@ -335,7 +329,6 @@ static int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm, const struct lsm_operations lsm_v3_ops = { .lsm_free = lsm_free_plain, - .lsm_destroy = lsm_destroy_plain, .lsm_stripe_by_index = lsm_stripe_by_index_plain, .lsm_stripe_by_offset = lsm_stripe_by_offset_plain, .lsm_lmm_verify = lsm_lmm_verify_v3, diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 12bd511e8988..07e5ede3e952 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -134,8 +134,6 @@ static inline void lov_put_reqset(struct lov_request_set *set) /* lov_merge.c */ void lov_merge_attrs(struct obdo *tgt, struct obdo *src, u64 valid, struct lov_stripe_md *lsm, int stripeno, int *set); -int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm, - u64 size, int shrink); int lov_merge_lvb_kms(struct lov_stripe_md *lsm, struct ost_lvb *lvb, __u64 *kms_place); @@ -157,11 +155,6 @@ int lov_update_common_set(struct lov_request_set *set, int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set **reqset); int lov_fini_getattr_set(struct lov_request_set *set); -int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo, - struct obdo *src_oa, struct lov_stripe_md *lsm, - struct obd_trans_info *oti, - struct lov_request_set **reqset); -int lov_fini_destroy_set(struct lov_request_set *set); int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo, struct obd_trans_info *oti, struct lov_request_set **reqset); @@ -197,8 +190,6 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmm, struct lov_stripe_md *lsm); int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm, int lmm_bytes); -int lov_getstripe(struct obd_export *exp, - struct lov_stripe_md *lsm, struct lov_user_md __user *lump); int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, int pattern, int magic); int lov_free_memmd(struct lov_stripe_md **lsmp); diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 84032a510254..d10157985ed9 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -87,6 +87,9 @@ static void lov_io_sub_inherit(struct cl_io *io, struct lov_io *lio, case CIT_SETATTR: { io->u.ci_setattr.sa_attr = parent->u.ci_setattr.sa_attr; io->u.ci_setattr.sa_valid = parent->u.ci_setattr.sa_valid; + io->u.ci_setattr.sa_stripe_index = stripe; + io->u.ci_setattr.sa_parent_fid = + parent->u.ci_setattr.sa_parent_fid; if (cl_io_is_trunc(io)) { loff_t new_size = parent->u.ci_setattr.sa_attr.lvb_size; @@ -244,14 +247,12 @@ void lov_sub_put(struct lov_io_sub *sub) int lov_page_stripe(const struct cl_page *page) { - struct lovsub_object *subobj; const struct cl_page_slice *slice; - slice = cl_page_at(page, &lovsub_device_type); + slice = cl_page_at(page, &lov_device_type); LASSERT(slice->cpl_obj); - subobj = cl2lovsub(slice->cpl_obj); - return subobj->lso_index; + return cl2lov_page(slice)->lps_stripe; } struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio, @@ -298,8 +299,8 @@ static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio, return result; } -static void lov_io_slice_init(struct lov_io *lio, - struct lov_object *obj, struct cl_io *io) +static int lov_io_slice_init(struct lov_io *lio, struct lov_object *obj, + struct cl_io *io) { io->ci_result = 0; lio->lis_object = obj; @@ -314,6 +315,15 @@ static void lov_io_slice_init(struct lov_io *lio, lio->lis_io_endpos = lio->lis_endpos; if (cl_io_is_append(io)) { LASSERT(io->ci_type == CIT_WRITE); + + /* + * If there is LOV EA hole, then we may cannot locate + * the current file-tail exactly. + */ + if (unlikely(obj->lo_lsm->lsm_pattern & + LOV_PATTERN_F_HOLE)) + return -EIO; + lio->lis_pos = 0; lio->lis_endpos = OBD_OBJECT_EOF; } @@ -349,6 +359,7 @@ static void lov_io_slice_init(struct lov_io *lio, default: LBUG(); } + return 0; } static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) @@ -870,7 +881,7 @@ int lov_io_init_raid0(const struct lu_env *env, struct cl_object *obj, struct lov_object *lov = cl2lov(obj); INIT_LIST_HEAD(&lio->lis_active); - lov_io_slice_init(lio, lov, io); + io->ci_result = lov_io_slice_init(lio, lov, io); if (io->ci_result == 0) { io->ci_result = lov_io_subio_init(env, lio, io); if (io->ci_result == 0) { diff --git a/drivers/staging/lustre/lustre/lov/lov_merge.c b/drivers/staging/lustre/lustre/lov/lov_merge.c index b9c90865fdfc..674af106b50b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_merge.c +++ b/drivers/staging/lustre/lustre/lov/lov_merge.c @@ -105,45 +105,6 @@ int lov_merge_lvb_kms(struct lov_stripe_md *lsm, return rc; } -/* Must be called under the lov_stripe_lock() */ -int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm, - u64 size, int shrink) -{ - struct lov_oinfo *loi; - int stripe = 0; - __u64 kms; - - assert_spin_locked(&lsm->lsm_lock); - LASSERT(lsm->lsm_lock_owner == current_pid()); - - if (shrink) { - for (; stripe < lsm->lsm_stripe_count; stripe++) { - struct lov_oinfo *loi = lsm->lsm_oinfo[stripe]; - - kms = lov_size_to_stripe(lsm, size, stripe); - CDEBUG(D_INODE, - "stripe %d KMS %sing %llu->%llu\n", - stripe, kms > loi->loi_kms ? "increase":"shrink", - loi->loi_kms, kms); - loi->loi_lvb.lvb_size = kms; - loi_kms_set(loi, loi->loi_lvb.lvb_size); - } - return 0; - } - - if (size > 0) - stripe = lov_stripe_number(lsm, size - 1); - kms = lov_size_to_stripe(lsm, size, stripe); - loi = lsm->lsm_oinfo[stripe]; - - CDEBUG(D_INODE, "stripe %d KMS %sincreasing %llu->%llu\n", - stripe, kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms); - if (kms > loi->loi_kms) - loi_kms_set(loi, kms); - - return 0; -} - void lov_merge_attrs(struct obdo *tgt, struct obdo *src, u64 valid, struct lov_stripe_md *lsm, int stripeno, int *set) { diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 9b92d5522edb..b23016f7ec26 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -41,6 +41,7 @@ #include "../../include/linux/libcfs/libcfs.h" #include "../include/obd_support.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_lib.h" #include "../include/lustre_net.h" #include "../include/lustre/lustre_idl.h" @@ -940,7 +941,7 @@ int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg, } case LCFG_PARAM: { struct lprocfs_static_vars lvars = { NULL }; - struct lov_desc *desc = &(obd->u.lov.desc); + struct lov_desc *desc = &obd->u.lov.desc; if (!desc) { rc = -EINVAL; @@ -971,92 +972,6 @@ out: return rc; } -static int lov_recreate(struct obd_export *exp, struct obdo *src_oa, - struct lov_stripe_md **ea, struct obd_trans_info *oti) -{ - struct lov_stripe_md *obj_mdp, *lsm; - struct lov_obd *lov = &exp->exp_obd->u.lov; - unsigned ost_idx; - int rc, i; - - LASSERT(src_oa->o_valid & OBD_MD_FLFLAGS && - src_oa->o_flags & OBD_FL_RECREATE_OBJS); - - obj_mdp = kzalloc(sizeof(*obj_mdp), GFP_NOFS); - if (!obj_mdp) - return -ENOMEM; - - ost_idx = src_oa->o_nlink; - lsm = *ea; - if (!lsm) { - rc = -EINVAL; - goto out; - } - if (ost_idx >= lov->desc.ld_tgt_count || - !lov->lov_tgts[ost_idx]) { - rc = -EINVAL; - goto out; - } - - for (i = 0; i < lsm->lsm_stripe_count; i++) { - struct lov_oinfo *loi = lsm->lsm_oinfo[i]; - - if (lov_oinfo_is_dummy(loi)) - continue; - - if (loi->loi_ost_idx == ost_idx) { - if (ostid_id(&loi->loi_oi) != ostid_id(&src_oa->o_oi)) { - rc = -EINVAL; - goto out; - } - break; - } - } - if (i == lsm->lsm_stripe_count) { - rc = -EINVAL; - goto out; - } - - rc = obd_create(NULL, lov->lov_tgts[ost_idx]->ltd_exp, - src_oa, &obj_mdp, oti); -out: - kfree(obj_mdp); - return rc; -} - -/* the LOV expects oa->o_id to be set to the LOV object id */ -static int lov_create(const struct lu_env *env, struct obd_export *exp, - struct obdo *src_oa, struct lov_stripe_md **ea, - struct obd_trans_info *oti) -{ - struct lov_obd *lov; - int rc = 0; - - LASSERT(ea); - if (!exp) - return -EINVAL; - - if ((src_oa->o_valid & OBD_MD_FLFLAGS) && - src_oa->o_flags == OBD_FL_DELORPHAN) { - /* should be used with LOV anymore */ - LBUG(); - } - - lov = &exp->exp_obd->u.lov; - if (!lov->desc.ld_active_tgt_count) - return -EIO; - - obd_getref(exp->exp_obd); - /* Recreate a specific object id at the given OST index */ - if ((src_oa->o_valid & OBD_MD_FLFLAGS) && - (src_oa->o_flags & OBD_FL_RECREATE_OBJS)) { - rc = lov_recreate(exp, src_oa, ea, oti); - } - - obd_putref(exp->exp_obd); - return rc; -} - #define ASSERT_LSM_MAGIC(lsmp) \ do { \ LASSERT((lsmp)); \ @@ -1065,59 +980,6 @@ do { \ "%p->lsm_magic=%x\n", (lsmp), (lsmp)->lsm_magic); \ } while (0) -static int lov_destroy(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md *lsm, - struct obd_trans_info *oti, struct obd_export *md_exp) -{ - struct lov_request_set *set; - struct obd_info oinfo; - struct lov_request *req; - struct lov_obd *lov; - int rc = 0, err = 0; - - ASSERT_LSM_MAGIC(lsm); - - if (!exp || !exp->exp_obd) - return -ENODEV; - - if (oa->o_valid & OBD_MD_FLCOOKIE) { - LASSERT(oti); - LASSERT(oti->oti_logcookies); - } - - lov = &exp->exp_obd->u.lov; - obd_getref(exp->exp_obd); - rc = lov_prep_destroy_set(exp, &oinfo, oa, lsm, oti, &set); - if (rc) - goto out; - - list_for_each_entry(req, &set->set_list, rq_link) { - if (oa->o_valid & OBD_MD_FLCOOKIE) - oti->oti_logcookies = set->set_cookies + req->rq_stripe; - - err = obd_destroy(env, lov->lov_tgts[req->rq_idx]->ltd_exp, - req->rq_oi.oi_oa, NULL, oti, NULL); - err = lov_update_common_set(set, req, err); - if (err) { - CERROR("%s: destroying objid "DOSTID" subobj " - DOSTID" on OST idx %d: rc = %d\n", - exp->exp_obd->obd_name, POSTID(&oa->o_oi), - POSTID(&req->rq_oi.oi_oa->o_oi), - req->rq_idx, err); - if (!rc) - rc = err; - } - } - - if (rc == 0) - rc = lsm_op_find(lsm->lsm_magic)->lsm_destroy(lsm, oa, md_exp); - - err = lov_fini_destroy_set(set); -out: - obd_putref(exp->exp_obd); - return rc ? rc : err; -} - static int lov_getattr_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { @@ -1267,46 +1129,6 @@ static int lov_setattr_async(struct obd_export *exp, struct obd_info *oinfo, return 0; } -/* find any ldlm lock of the inode in lov - * return 0 not find - * 1 find one - * < 0 error - */ -static int lov_find_cbdata(struct obd_export *exp, - struct lov_stripe_md *lsm, ldlm_iterator_t it, - void *data) -{ - struct lov_obd *lov; - int rc = 0, i; - - ASSERT_LSM_MAGIC(lsm); - - if (!exp || !exp->exp_obd) - return -ENODEV; - - lov = &exp->exp_obd->u.lov; - for (i = 0; i < lsm->lsm_stripe_count; i++) { - struct lov_stripe_md submd; - struct lov_oinfo *loi = lsm->lsm_oinfo[i]; - - if (lov_oinfo_is_dummy(loi)) - continue; - - if (!lov->lov_tgts[loi->loi_ost_idx]) { - CDEBUG(D_HA, "lov idx %d NULL\n", loi->loi_ost_idx); - continue; - } - - submd.lsm_oi = loi->loi_oi; - submd.lsm_stripe_count = 0; - rc = obd_find_cbdata(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp, - &submd, it, data); - if (rc != 0) - return rc; - } - return rc; -} - int lov_statfs_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { struct lov_request_set *lovset = (struct lov_request_set *)data; @@ -1460,7 +1282,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, } desc = (struct lov_desc *)data->ioc_inlbuf1; - memcpy(desc, &(lov->desc), sizeof(*desc)); + memcpy(desc, &lov->desc, sizeof(*desc)); uuidp = (struct obd_uuid *)data->ioc_inlbuf2; genp = (__u32 *)data->ioc_inlbuf3; @@ -1477,9 +1299,6 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, obd_ioctl_freedata(buf, len); break; } - case LL_IOC_LOV_GETSTRIPE: - rc = lov_getstripe(exp, karg, uarg); - break; case OBD_IOC_QUOTACTL: { struct if_quotactl *qctl = karg; struct lov_tgt_desc *tgt = NULL; @@ -1726,6 +1545,8 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, u64 fm_start, fm_end, fm_length, fm_end_offset; u64 curr_loc; int current_extent = 0, rc = 0, i; + /* Whether have we collected enough extents */ + bool enough = false; int ost_eof = 0; /* EOF for object */ int ost_done = 0; /* done with required mapping for this OST? */ int last_stripe; @@ -1860,7 +1681,7 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, lun_start += len_mapped_single_call; fm_local->fm_length = req_fm_len - len_mapped_single_call; req_fm_len = fm_local->fm_length; - fm_local->fm_extent_count = count_local; + fm_local->fm_extent_count = enough ? 1 : count_local; fm_local->fm_mapped_extents = 0; fm_local->fm_flags = fiemap->fm_flags; @@ -1908,6 +1729,12 @@ inactive_tgt: goto finish; } break; + } else if (enough) { + /* + * We've collected enough extents and there are + * more extents after it. + */ + goto finish; } /* If we just need num of extents then go to next device */ @@ -1916,8 +1743,9 @@ inactive_tgt: break; } - len_mapped_single_call = lcl_fm_ext[ext_count-1].fe_logical - - lun_start + lcl_fm_ext[ext_count - 1].fe_length; + len_mapped_single_call = + lcl_fm_ext[ext_count - 1].fe_logical - + lun_start + lcl_fm_ext[ext_count - 1].fe_length; /* Have we finished mapping on this device? */ if (req_fm_len <= len_mapped_single_call) @@ -1926,14 +1754,15 @@ inactive_tgt: /* Clear the EXTENT_LAST flag which can be present on * last extent */ - if (lcl_fm_ext[ext_count-1].fe_flags & FIEMAP_EXTENT_LAST) + if (lcl_fm_ext[ext_count - 1].fe_flags & + FIEMAP_EXTENT_LAST) lcl_fm_ext[ext_count - 1].fe_flags &= ~FIEMAP_EXTENT_LAST; curr_loc = lov_stripe_size(lsm, - lcl_fm_ext[ext_count - 1].fe_logical+ - lcl_fm_ext[ext_count - 1].fe_length, - cur_stripe); + lcl_fm_ext[ext_count - 1].fe_logical + + lcl_fm_ext[ext_count - 1].fe_length, + cur_stripe); if (curr_loc >= fm_key->oa.o_size) ost_eof = 1; @@ -1945,7 +1774,7 @@ inactive_tgt: /* Ran out of available extents? */ if (current_extent >= fiemap->fm_extent_count) - goto finish; + enough = true; } while (ost_done == 0 && ost_eof == 0); if (cur_stripe_wrap == last_stripe) @@ -1985,73 +1814,14 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp, { struct obd_device *obddev = class_exp2obd(exp); struct lov_obd *lov = &obddev->u.lov; - int i, rc; + int rc; if (!vallen || !val) return -EFAULT; obd_getref(obddev); - if (KEY_IS(KEY_LOCK_TO_STRIPE)) { - struct { - char name[16]; - struct ldlm_lock *lock; - } *data = key; - struct ldlm_res_id *res_id = &data->lock->l_resource->lr_name; - struct lov_oinfo *loi; - __u32 *stripe = val; - - if (*vallen < sizeof(*stripe)) { - rc = -EFAULT; - goto out; - } - *vallen = sizeof(*stripe); - - /* XXX This is another one of those bits that will need to - * change if we ever actually support nested LOVs. It uses - * the lock's export to find out which stripe it is. - */ - /* XXX - it's assumed all the locks for deleted OSTs have - * been cancelled. Also, the export for deleted OSTs will - * be NULL and won't match the lock's export. - */ - for (i = 0; i < lsm->lsm_stripe_count; i++) { - loi = lsm->lsm_oinfo[i]; - if (lov_oinfo_is_dummy(loi)) - continue; - - if (!lov->lov_tgts[loi->loi_ost_idx]) - continue; - if (lov->lov_tgts[loi->loi_ost_idx]->ltd_exp == - data->lock->l_conn_export && - ostid_res_name_eq(&loi->loi_oi, res_id)) { - *stripe = i; - rc = 0; - goto out; - } - } - LDLM_ERROR(data->lock, "lock on inode without such object"); - dump_lsm(D_ERROR, lsm); - rc = -ENXIO; - goto out; - } else if (KEY_IS(KEY_LAST_ID)) { - struct obd_id_info *info = val; - __u32 size = sizeof(u64); - struct lov_tgt_desc *tgt; - - LASSERT(*vallen == sizeof(struct obd_id_info)); - tgt = lov->lov_tgts[info->idx]; - - if (!tgt || !tgt->ltd_active) { - rc = -ESRCH; - goto out; - } - - rc = obd_get_info(env, tgt->ltd_exp, keylen, key, - &size, info->data, NULL); - rc = 0; - goto out; - } else if (KEY_IS(KEY_LOVDESC)) { + if (KEY_IS(KEY_LOVDESC)) { struct lov_desc *desc_ret = val; *desc_ret = lov->desc; @@ -2060,22 +1830,6 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp, } else if (KEY_IS(KEY_FIEMAP)) { rc = lov_fiemap(lov, keylen, key, vallen, val, lsm); goto out; - } else if (KEY_IS(KEY_CONNECT_FLAG)) { - struct lov_tgt_desc *tgt; - __u64 ost_idx = *((__u64 *)val); - - LASSERT(*vallen == sizeof(__u64)); - LASSERT(ost_idx < lov->desc.ld_tgt_count); - tgt = lov->lov_tgts[ost_idx]; - - if (!tgt || !tgt->ltd_exp) { - rc = -ESRCH; - goto out; - } - - *((__u64 *)val) = exp_connect_flags(tgt->ltd_exp); - rc = 0; - goto out; } else if (KEY_IS(KEY_TGT_COUNT)) { *((int *)val) = lov->desc.ld_tgt_count; rc = 0; @@ -2098,8 +1852,7 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, u32 count; int i, rc = 0, err; struct lov_tgt_desc *tgt; - unsigned int incr = 0, check_uuid = 0, do_inactive = 0, no_set = 0; - unsigned int next_id = 0, mds_con = 0; + int do_inactive = 0, no_set = 0; if (!set) { no_set = 1; @@ -2111,18 +1864,8 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, obd_getref(obddev); count = lov->desc.ld_tgt_count; - if (KEY_IS(KEY_NEXT_ID)) { - count = vallen / sizeof(struct obd_id_info); - vallen = sizeof(u64); - incr = sizeof(struct obd_id_info); + if (KEY_IS(KEY_CHECKSUM)) { do_inactive = 1; - next_id = 1; - } else if (KEY_IS(KEY_CHECKSUM)) { - do_inactive = 1; - } else if (KEY_IS(KEY_EVICT_BY_NID)) { - /* use defaults: do_inactive = incr = 0; */ - } else if (KEY_IS(KEY_MDS_CONN)) { - mds_con = 1; } else if (KEY_IS(KEY_CACHE_SET)) { LASSERT(!lov->lov_cache); lov->lov_cache = val; @@ -2130,11 +1873,9 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, cl_cache_incref(lov->lov_cache); } - for (i = 0; i < count; i++, val = (char *)val + incr) { - if (next_id) - tgt = lov->lov_tgts[((struct obd_id_info *)val)->idx]; - else - tgt = lov->lov_tgts[i]; + for (i = 0; i < count; i++) { + tgt = lov->lov_tgts[i]; + /* OST was disconnected */ if (!tgt || !tgt->ltd_exp) continue; @@ -2143,34 +1884,8 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, if (!tgt->ltd_active && !do_inactive) continue; - if (mds_con) { - struct mds_group_info *mgi; - - LASSERT(vallen == sizeof(*mgi)); - mgi = (struct mds_group_info *)val; - - /* Only want a specific OSC */ - if (mgi->uuid && !obd_uuid_equals(mgi->uuid, - &tgt->ltd_uuid)) - continue; - - err = obd_set_info_async(env, tgt->ltd_exp, - keylen, key, sizeof(int), - &mgi->group, set); - } else if (next_id) { - err = obd_set_info_async(env, tgt->ltd_exp, - keylen, key, vallen, - ((struct obd_id_info *)val)->data, set); - } else { - /* Only want a specific OSC */ - if (check_uuid && - !obd_uuid_equals(val, &tgt->ltd_uuid)) - continue; - - err = obd_set_info_async(env, tgt->ltd_exp, - keylen, key, vallen, val, set); - } - + err = obd_set_info_async(env, tgt->ltd_exp, keylen, key, + vallen, val, set); if (!rc) rc = err; } @@ -2318,12 +2033,8 @@ static struct obd_ops lov_obd_ops = { .statfs_async = lov_statfs_async, .packmd = lov_packmd, .unpackmd = lov_unpackmd, - .create = lov_create, - .destroy = lov_destroy, .getattr_async = lov_getattr_async, .setattr_async = lov_setattr_async, - .adjust_kms = lov_adjust_kms, - .find_cbdata = lov_find_cbdata, .iocontrol = lov_iocontrol, .get_info = lov_get_info, .set_info_async = lov_set_info_async, diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index f9621b0fd469..52f736338887 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -75,6 +75,13 @@ struct lov_layout_operations { static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov); +void lov_lsm_put(struct cl_object *unused, struct lov_stripe_md *lsm) +{ + if (lsm) + lov_free_memmd(&lsm); +} +EXPORT_SYMBOL(lov_lsm_put); + /***************************************************************************** * * Lov object layout operations. @@ -195,6 +202,10 @@ static int lov_page_slice_fixup(struct lov_object *lov, struct cl_object_header *hdr = cl_object_header(&lov->lo_cl); struct cl_object *o; + if (!stripe) + return hdr->coh_page_bufsize - lov->lo_cl.co_slice_off - + cfs_size_round(sizeof(struct lov_page)); + cl_object_for_each(o, stripe) o->co_slice_off += hdr->coh_page_bufsize; @@ -224,6 +235,7 @@ static int lov_init_raid0(const struct lu_env *env, LASSERT(!lov->lo_lsm); lov->lo_lsm = lsm_addref(lsm); + lov->lo_layout_invalid = true; r0->lo_nr = lsm->lsm_stripe_count; LASSERT(r0->lo_nr <= lov_targets_nr(dev)); @@ -719,6 +731,10 @@ static int lov_layout_change(const struct lu_env *unused, LASSERT(atomic_read(&lov->lo_active_ios) == 0); lov->lo_type = LLT_EMPTY; + /* page bufsize fixup */ + cl_object_header(&lov->lo_cl)->coh_page_bufsize -= + lov_page_slice_fixup(lov, NULL); + result = new_ops->llo_init(env, lu2lov_dev(lov->lo_cl.co_lu.lo_dev), lov, conf, state); @@ -878,8 +894,8 @@ static int lov_attr_get(const struct lu_env *env, struct cl_object *obj, return LOV_2DISPATCH_NOLOCK(cl2lov(obj), llo_getattr, env, obj, attr); } -static int lov_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid) +static int lov_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid) { /* * No dispatch is required here, as no layout implements this. @@ -895,13 +911,30 @@ int lov_lock_init(const struct lu_env *env, struct cl_object *obj, io); } +static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj, + struct lov_user_md __user *lum) +{ + struct lov_object *lov = cl2lov(obj); + struct lov_stripe_md *lsm; + int rc = 0; + + lsm = lov_lsm_addref(lov); + if (!lsm) + return -ENODATA; + + rc = lov_getstripe(cl2lov(obj), lsm, lum); + lov_lsm_put(obj, lsm); + return rc; +} + static const struct cl_object_operations lov_ops = { .coo_page_init = lov_page_init, .coo_lock_init = lov_lock_init, .coo_io_init = lov_io_init, .coo_attr_get = lov_attr_get, - .coo_attr_set = lov_attr_set, - .coo_conf_set = lov_conf_set + .coo_attr_update = lov_attr_update, + .coo_conf_set = lov_conf_set, + .coo_getstripe = lov_object_getstripe }; static const struct lu_object_operations lov_lu_obj_ops = { @@ -938,7 +971,7 @@ struct lu_object *lov_object_alloc(const struct lu_env *env, return obj; } -static struct lov_stripe_md *lov_lsm_addref(struct lov_object *lov) +struct lov_stripe_md *lov_lsm_addref(struct lov_object *lov) { struct lov_stripe_md *lsm = NULL; @@ -969,13 +1002,6 @@ struct lov_stripe_md *lov_lsm_get(struct cl_object *clobj) } EXPORT_SYMBOL(lov_lsm_get); -void lov_lsm_put(struct cl_object *unused, struct lov_stripe_md *lsm) -{ - if (lsm) - lov_free_memmd(&lsm); -} -EXPORT_SYMBOL(lov_lsm_put); - int lov_read_and_clear_async_rc(struct cl_object *clob) { struct lu_object *luobj; diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 869ef41b13ca..be6e9857ce2a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -45,6 +45,7 @@ #include "../include/lustre/lustre_user.h" #include "lov_internal.h" +#include "lov_cl_internal.h" void lov_dump_lmm_common(int level, void *lmmp) { @@ -104,11 +105,9 @@ void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm) * LOVs properly. For now lov_mds_md_size() just assumes one u64 * per stripe. */ -int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) +int lov_obd_packmd(struct lov_obd *lov, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) { - struct obd_device *obd = class_exp2obd(exp); - struct lov_obd *lov = &obd->u.lov; struct lov_mds_md_v1 *lmmv1; struct lov_mds_md_v3 *lmmv3; __u16 stripe_count; @@ -148,16 +147,11 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, stripe_count = 0; } } else { - /* No need to allocate more than maximum supported stripes. - * Anyway, this is pretty inaccurate since ld_tgt_count now - * represents max index and we should rely on the actual number - * of OSTs instead + /* + * To calculate maximum easize by active targets at present, + * which is exactly the maximum easize to be seen by LOV */ - stripe_count = lov_mds_md_max_stripe_count( - lov->lov_ocd.ocd_max_easize, lmm_magic); - - if (stripe_count > lov->desc.ld_tgt_count) - stripe_count = lov->desc.ld_tgt_count; + stripe_count = lov->desc.ld_active_tgt_count; } /* XXX LOV STACKING call into osc for sizes */ @@ -225,6 +219,15 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, return lmm_size; } +int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) +{ + struct obd_device *obd = class_exp2obd(exp); + struct lov_obd *lov = &obd->u.lov; + + return lov_obd_packmd(lov, lmmp, lsm); +} + /* Find the max stripecount we should use */ __u16 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u16 stripe_count) { @@ -284,7 +287,7 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, spin_lock_init(&(*lsmp)->lsm_lock); (*lsmp)->lsm_magic = magic; (*lsmp)->lsm_stripe_count = stripe_count; - (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES * stripe_count; + (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES * stripe_count; (*lsmp)->lsm_pattern = pattern; (*lsmp)->lsm_pool_name[0] = '\0'; (*lsmp)->lsm_layout_gen = 0; @@ -372,16 +375,17 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, * the maximum number of OST indices which will fit in the user buffer. * lmm_magic must be LOV_USER_MAGIC. */ -int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, +int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, struct lov_user_md __user *lump) { /* * XXX huge struct allocated on stack. */ /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ + struct lov_obd *lov; struct lov_user_md_v3 lum; struct lov_mds_md *lmmk = NULL; - int rc, lmm_size; + int rc, lmmk_size, lmm_size; int lum_size; mm_segment_t seg; @@ -401,12 +405,13 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, lum_size = sizeof(struct lov_user_md_v1); if (copy_from_user(&lum, lump, lum_size)) { rc = -EFAULT; - goto out_set; + goto out; } - if ((lum.lmm_magic != LOV_USER_MAGIC) && - (lum.lmm_magic != LOV_USER_MAGIC_V3)) { + if (lum.lmm_magic != LOV_USER_MAGIC_V1 && + lum.lmm_magic != LOV_USER_MAGIC_V3 && + lum.lmm_magic != LOV_USER_MAGIC_SPECIFIC) { rc = -EINVAL; - goto out_set; + goto out; } if (lum.lmm_stripe_count && @@ -415,11 +420,13 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, lum.lmm_stripe_count = lsm->lsm_stripe_count; rc = copy_to_user(lump, &lum, lum_size); rc = -EOVERFLOW; - goto out_set; + goto out; } - rc = lov_packmd(exp, &lmmk, lsm); + lov = lu2lov_dev(obj->lo_cl.co_lu.lo_dev)->ld_lov; + rc = lov_obd_packmd(lov, &lmmk, lsm); if (rc < 0) - goto out_set; + goto out; + lmmk_size = rc; lmm_size = rc; rc = 0; @@ -455,7 +462,7 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, lmm_size = lum_size; } else if (lum.lmm_stripe_count < lmmk->lmm_stripe_count) { rc = -EOVERFLOW; - goto out_set; + goto out_free; } /* * Have a difference between lov_mds_md & lov_user_md. @@ -468,8 +475,9 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, if (copy_to_user(lump, lmmk, lmm_size)) rc = -EFAULT; - obd_free_diskmd(exp, &lmmk); -out_set: +out_free: + kfree(lmmk); +out: set_fs(seg); return rc; } diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index c17026f14896..00bfabad78eb 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -65,7 +65,9 @@ static int lov_raid0_page_is_under_lock(const struct lu_env *env, pgoff_t index = *max_index; unsigned int pps; /* pages per stripe */ - CDEBUG(D_READA, "*max_index = %lu, nr = %d\n", index, r0->lo_nr); + CDEBUG(D_READA, DFID "*max_index = %lu, nr = %d\n", + PFID(lu_object_fid(lov2lu(loo))), index, r0->lo_nr); + if (index == 0) /* the page is not covered by any lock */ return 0; @@ -80,7 +82,12 @@ static int lov_raid0_page_is_under_lock(const struct lu_env *env, /* calculate the end of current stripe */ pps = loo->lo_lsm->lsm_stripe_size >> PAGE_SHIFT; - index = ((slice->cpl_index + pps) & ~(pps - 1)) - 1; + index = slice->cpl_index + pps - slice->cpl_index % pps - 1; + + CDEBUG(D_READA, DFID "*max_index = %lu, index = %lu, pps = %u, stripe_size = %u, stripe no = %u, page index = %lu\n", + PFID(lu_object_fid(lov2lu(loo))), *max_index, index, pps, + loo->lo_lsm->lsm_stripe_size, lov_page_stripe(slice->cpl_page), + slice->cpl_index); /* never exceed the end of the stripe */ *max_index = min_t(pgoff_t, *max_index, index); @@ -122,6 +129,7 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, rc = lov_stripe_offset(loo->lo_lsm, offset, stripe, &suboff); LASSERT(rc == 0); + lpg->lps_stripe = stripe; cl_page_slice_add(page, &lpg->lps_cl, obj, index, &lov_raid0_page_ops); sub = lov_sub_get(env, lio, stripe); diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c index 4c2d21729589..f8c8a361ef79 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pool.c +++ b/drivers/staging/lustre/lustre/lov/lov_pool.c @@ -61,7 +61,7 @@ void lov_pool_putref(struct pool_desc *pool) LASSERT(hlist_unhashed(&pool->pool_hash)); LASSERT(list_empty(&pool->pool_list)); LASSERT(!pool->pool_debugfs_entry); - lov_ost_pool_free(&(pool->pool_obds)); + lov_ost_pool_free(&pool->pool_obds); kfree(pool); } } @@ -92,7 +92,7 @@ static __u32 pool_hashfn(struct cfs_hash *hash_body, const void *key, unsigned m for (i = 0; i < LOV_MAXPOOLNAME; i++) { if (poolname[i] == '\0') break; - result = (result << 4)^(result >> 28) ^ poolname[i]; + result = (result << 4) ^ (result >> 28) ^ poolname[i]; } return (result % mask); } @@ -260,7 +260,7 @@ static int pool_proc_show(struct seq_file *s, void *v) tgt = pool_tgt(iter->pool, iter->idx); up_read(&pool_tgt_rw_sem(iter->pool)); if (tgt) - seq_printf(s, "%s\n", obd_uuid2str(&(tgt->ltd_uuid))); + seq_printf(s, "%s\n", obd_uuid2str(&tgt->ltd_uuid)); return 0; } @@ -400,7 +400,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname) struct pool_desc *new_pool; int rc; - lov = &(obd->u.lov); + lov = &obd->u.lov; if (strlen(poolname) > LOV_MAXPOOLNAME) return -ENAMETOOLONG; @@ -471,7 +471,7 @@ int lov_pool_del(struct obd_device *obd, char *poolname) struct lov_obd *lov; struct pool_desc *pool; - lov = &(obd->u.lov); + lov = &obd->u.lov; /* lookup and kill hash reference */ pool = cfs_hash_del_key(lov->lov_pools_hash_body, poolname); @@ -503,7 +503,7 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname) unsigned int lov_idx; int rc; - lov = &(obd->u.lov); + lov = &obd->u.lov; pool = cfs_hash_lookup(lov->lov_pools_hash_body, poolname); if (!pool) @@ -517,7 +517,7 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname) if (!lov->lov_tgts[lov_idx]) continue; if (obd_uuid_equals(&ost_uuid, - &(lov->lov_tgts[lov_idx]->ltd_uuid))) + &lov->lov_tgts[lov_idx]->ltd_uuid)) break; } /* test if ost found in lov */ @@ -547,7 +547,7 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname) unsigned int lov_idx; int rc = 0; - lov = &(obd->u.lov); + lov = &obd->u.lov; pool = cfs_hash_lookup(lov->lov_pools_hash_body, poolname); if (!pool) @@ -562,7 +562,7 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname) continue; if (obd_uuid_equals(&ost_uuid, - &(lov->lov_tgts[lov_idx]->ltd_uuid))) + &lov->lov_tgts[lov_idx]->ltd_uuid)) break; } diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 4099b51f826e..09dcaf484c89 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -325,84 +325,6 @@ out_set: return rc; } -int lov_fini_destroy_set(struct lov_request_set *set) -{ - if (!set) - return 0; - LASSERT(set->set_exp); - if (atomic_read(&set->set_completes)) { - /* FIXME update qos data here */ - } - - lov_put_reqset(set); - - return 0; -} - -int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo, - struct obdo *src_oa, struct lov_stripe_md *lsm, - struct obd_trans_info *oti, - struct lov_request_set **reqset) -{ - struct lov_request_set *set; - struct lov_obd *lov = &exp->exp_obd->u.lov; - int rc = 0, i; - - set = kzalloc(sizeof(*set), GFP_NOFS); - if (!set) - return -ENOMEM; - lov_init_set(set); - - set->set_exp = exp; - set->set_oi = oinfo; - set->set_oi->oi_md = lsm; - set->set_oi->oi_oa = src_oa; - if (oti && src_oa->o_valid & OBD_MD_FLCOOKIE) - set->set_cookies = oti->oti_logcookies; - - for (i = 0; i < lsm->lsm_stripe_count; i++) { - struct lov_oinfo *loi; - struct lov_request *req; - - loi = lsm->lsm_oinfo[i]; - if (lov_oinfo_is_dummy(loi)) - continue; - - if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) { - CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx); - continue; - } - - req = kzalloc(sizeof(*req), GFP_NOFS); - if (!req) { - rc = -ENOMEM; - goto out_set; - } - - req->rq_stripe = i; - req->rq_idx = loi->loi_ost_idx; - - req->rq_oi.oi_oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!req->rq_oi.oi_oa) { - kfree(req); - rc = -ENOMEM; - goto out_set; - } - memcpy(req->rq_oi.oi_oa, src_oa, sizeof(*req->rq_oi.oi_oa)); - req->rq_oi.oi_oa->o_oi = loi->loi_oi; - lov_set_add_req(req, set); - } - if (!set->set_count) { - rc = -EIO; - goto out_set; - } - *reqset = set; - return rc; -out_set: - lov_fini_destroy_set(set); - return rc; -} - int lov_fini_setattr_set(struct lov_request_set *set) { int rc = 0; diff --git a/drivers/staging/lustre/lustre/lov/lovsub_object.c b/drivers/staging/lustre/lustre/lov/lovsub_object.c index fb2f2660b3e9..a2bac7a3b71b 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_object.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_object.c @@ -98,8 +98,8 @@ static int lovsub_object_print(const struct lu_env *env, void *cookie, return (*p)(env, cookie, "[%d]", los->lso_index); } -static int lovsub_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid) +static int lovsub_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid) { struct lov_object *lov = cl2lovsub(obj)->lso_super; @@ -119,7 +119,7 @@ static int lovsub_object_glimpse(const struct lu_env *env, static const struct cl_object_operations lovsub_ops = { .coo_page_init = lovsub_page_init, .coo_lock_init = lovsub_lock_init, - .coo_attr_set = lovsub_attr_set, + .coo_attr_update = lovsub_attr_update, .coo_glimpse = lovsub_object_glimpse }; diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index 98d15fb247bc..fca9450de57c 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -43,11 +43,10 @@ static ssize_t max_rpcs_in_flight_show(struct kobject *kobj, int len; struct obd_device *dev = container_of(kobj, struct obd_device, obd_kobj); - struct client_obd *cli = &dev->u.cli; + __u32 max; - spin_lock(&cli->cl_loi_list_lock); - len = sprintf(buf, "%u\n", cli->cl_max_rpcs_in_flight); - spin_unlock(&cli->cl_loi_list_lock); + max = obd_get_max_rpcs_in_flight(&dev->u.cli); + len = sprintf(buf, "%u\n", max); return len; } @@ -59,7 +58,6 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, { struct obd_device *dev = container_of(kobj, struct obd_device, obd_kobj); - struct client_obd *cli = &dev->u.cli; int rc; unsigned long val; @@ -67,12 +65,9 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, if (rc) return rc; - if (val < 1 || val > MDC_MAX_RIF_MAX) - return -ERANGE; - - spin_lock(&cli->cl_loi_list_lock); - cli->cl_max_rpcs_in_flight = val; - spin_unlock(&cli->cl_loi_list_lock); + rc = obd_set_max_rpcs_in_flight(&dev->u.cli, val); + if (rc) + count = rc; return count; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index 58f2841cabe4..f446c1c2584b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -34,63 +34,57 @@ #define _MDC_INTERNAL_H #include "../include/lustre_mdc.h" -#include "../include/lustre_mds.h" void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars); void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, - __u64 valid, int ea_size, __u32 suppgid, int flags); -void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, - const struct lu_fid *cfid, int flags); + __u64 valid, size_t ea_size, __u32 suppgid, u32 flags); void mdc_swap_layouts_pack(struct ptlrpc_request *req, struct md_op_data *op_data); -void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, __u32 size, +void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, size_t size, const struct lu_fid *fid); -void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, - struct md_op_data *data, int ea_size); +void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, u32 flags, + struct md_op_data *data, size_t ea_size); void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len); + void *ea, size_t ealen, void *ea2, size_t ea2len); void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - const void *data, int datalen, __u32 mode, __u32 uid, - __u32 gid, cfs_cap_t capability, __u64 rdev); + const void *data, size_t datalen, umode_t mode, uid_t uid, + gid_t gid, cfs_cap_t capability, __u64 rdev); void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - __u32 mode, __u64 rdev, __u64 flags, const void *data, - int datalen); + umode_t mode, __u64 rdev, __u64 flags, const void *data, + size_t datalen); void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen); + const char *old, size_t oldlen, + const char *new, size_t newlen); void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data); -int mdc_enter_request(struct client_obd *cli); -void mdc_exit_request(struct client_obd *cli); /* mdc/mdc_locks.c */ int mdc_set_lock_data(struct obd_export *exp, - __u64 *lockh, void *data, __u64 *bits); + const struct lustre_handle *lockh, + void *data, __u64 *bits); int mdc_null_inode(struct obd_export *exp, const struct lu_fid *fid); -int mdc_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, - ldlm_iterator_t it, void *data); - int mdc_intent_lock(struct obd_export *exp, - struct md_op_data *, - void *lmm, int lmmsize, - struct lookup_intent *, int, + struct md_op_data *op_data, + struct lookup_intent *it, struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags); + int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, + const ldlm_policy_data_t *policy, struct lookup_intent *it, struct md_op_data *op_data, - struct lustre_handle *lockh, void *lmm, int lmmsize, - struct ptlrpc_request **req, __u64 extra_lock_flags); + struct lustre_handle *lockh, __u64 extra_lock_flags); int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, struct list_head *cancels, enum ldlm_mode mode, __u64 bits); /* mdc/mdc_request.c */ -int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data); +int mdc_fid_alloc(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data); struct obd_client_handle; int mdc_set_open_replay_data(struct obd_export *exp, @@ -101,16 +95,17 @@ void mdc_commit_open(struct ptlrpc_request *req); void mdc_replay_open(struct ptlrpc_request *req); int mdc_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, __u32 gid, - cfs_cap_t capability, __u64 rdev, + const void *data, size_t datalen, umode_t mode, uid_t uid, + gid_t gid, cfs_cap_t capability, __u64 rdev, struct ptlrpc_request **request); int mdc_link(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request); int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen, + const char *old, size_t oldlen, + const char *new, size_t newlen, struct ptlrpc_request **request); int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len, + void *ea, size_t ealen, void *ea2, size_t ea2len, struct ptlrpc_request **request, struct md_open_data **mod); int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request); @@ -138,4 +133,12 @@ static inline int mdc_prep_elc_req(struct obd_export *exp, count); } +static inline unsigned long hash_x_index(__u64 hash, int hash64) +{ + if (BITS_PER_LONG == 32 && hash64) + hash >>= 32; + /* save hash 0 with hash 1 */ + return ~0UL - (hash + !hash); +} + #endif diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 143bd7628572..aac7e04873e2 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -37,27 +37,12 @@ static void __mdc_pack_body(struct mdt_body *b, __u32 suppgid) { - b->suppgid = suppgid; - b->uid = from_kuid(&init_user_ns, current_uid()); - b->gid = from_kgid(&init_user_ns, current_gid()); - b->fsuid = from_kuid(&init_user_ns, current_fsuid()); - b->fsgid = from_kgid(&init_user_ns, current_fsgid()); - b->capability = cfs_curproc_cap_pack(); -} - -void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, - const struct lu_fid *cfid, int flags) -{ - struct mdt_body *b = req_capsule_client_get(&req->rq_pill, - &RMF_MDT_BODY); - - if (pfid) { - b->fid1 = *pfid; - b->valid = OBD_MD_FLID; - } - if (cfid) - b->fid2 = *cfid; - b->flags = flags; + b->mbo_suppgid = suppgid; + b->mbo_uid = from_kuid(&init_user_ns, current_uid()); + b->mbo_gid = from_kgid(&init_user_ns, current_gid()); + b->mbo_fsuid = from_kuid(&init_user_ns, current_fsuid()); + b->mbo_fsgid = from_kgid(&init_user_ns, current_fsgid()); + b->mbo_capability = cfs_curproc_cap_pack(); } void mdc_swap_layouts_pack(struct ptlrpc_request *req, @@ -67,43 +52,74 @@ void mdc_swap_layouts_pack(struct ptlrpc_request *req, &RMF_MDT_BODY); __mdc_pack_body(b, op_data->op_suppgids[0]); - b->fid1 = op_data->op_fid1; - b->fid2 = op_data->op_fid2; - b->valid |= OBD_MD_FLID; + b->mbo_fid1 = op_data->op_fid1; + b->mbo_fid2 = op_data->op_fid2; + b->mbo_valid |= OBD_MD_FLID; } void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, - __u64 valid, int ea_size, __u32 suppgid, int flags) + __u64 valid, size_t ea_size, __u32 suppgid, u32 flags) { struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); - b->valid = valid; - b->eadatasize = ea_size; - b->flags = flags; + b->mbo_valid = valid; + b->mbo_eadatasize = ea_size; + b->mbo_flags = flags; __mdc_pack_body(b, suppgid); if (fid) { - b->fid1 = *fid; - b->valid |= OBD_MD_FLID; + b->mbo_fid1 = *fid; + b->mbo_valid |= OBD_MD_FLID; } } -void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, - __u32 size, const struct lu_fid *fid) +/** + * Pack a name (path component) into a request + * + * \param[in] req request + * \param[in] field request field (usually RMF_NAME) + * \param[in] name path component + * \param[in] name_len length of path component + * + * \a field must be present in \a req and of size \a name_len + 1. + * + * \a name must be '\0' terminated of length \a name_len and represent + * a single path component (not contain '/'). + */ +static void mdc_pack_name(struct ptlrpc_request *req, + const struct req_msg_field *field, + const char *name, size_t name_len) +{ + size_t buf_size; + size_t cpy_len; + char *buf; + + buf = req_capsule_client_get(&req->rq_pill, field); + buf_size = req_capsule_get_size(&req->rq_pill, field, RCL_CLIENT); + + LASSERT(name && name_len && buf && buf_size == name_len + 1); + + cpy_len = strlcpy(buf, name, buf_size); + + LASSERT(cpy_len == name_len && lu_name_is_valid_2(buf, cpy_len)); +} + +void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, size_t size, + const struct lu_fid *fid) { struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); - b->fid1 = *fid; - b->valid |= OBD_MD_FLID; - b->size = pgoff; /* !! */ - b->nlink = size; /* !! */ + b->mbo_fid1 = *fid; + b->mbo_valid |= OBD_MD_FLID; + b->mbo_size = pgoff; /* !! */ + b->mbo_nlink = size; /* !! */ __mdc_pack_body(b, -1); - b->mode = LUDA_FID | LUDA_TYPE; + b->mbo_mode = LUDA_FID | LUDA_TYPE; } /* packing of MDS records */ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - const void *data, int datalen, __u32 mode, - __u32 uid, __u32 gid, cfs_cap_t cap_effective, __u64 rdev) + const void *data, size_t datalen, umode_t mode, + uid_t uid, gid_t gid, cfs_cap_t cap_effective, __u64 rdev) { struct mdt_rec_create *rec; char *tmp; @@ -130,22 +146,17 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_bias = op_data->op_bias; rec->cr_umask = current_umask(); - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LOGL0(op_data->op_name, op_data->op_namelen, tmp); - + mdc_pack_name(req, &RMF_NAME, op_data->op_name, op_data->op_namelen); if (data) { tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA); memcpy(tmp, data, datalen); } } -static __u64 mds_pack_open_flags(__u64 flags, __u32 mode) +static inline __u64 mds_pack_open_flags(__u64 flags) { __u64 cr_flags = (flags & (FMODE_READ | FMODE_WRITE | - MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS | - MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK | - MDS_OPEN_BY_FID | MDS_OPEN_LEASE | - MDS_OPEN_RELEASE)); + MDS_OPEN_FL_INTERNAL)); if (flags & O_CREAT) cr_flags |= MDS_OPEN_CREAT; if (flags & O_EXCL) @@ -171,8 +182,8 @@ static __u64 mds_pack_open_flags(__u64 flags, __u32 mode) /* packing of MDS records */ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - __u32 mode, __u64 rdev, __u64 flags, const void *lmm, - int lmmlen) + umode_t mode, __u64 rdev, __u64 flags, const void *lmm, + size_t lmmlen) { struct mdt_rec_create *rec; char *tmp; @@ -190,7 +201,7 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_fid2 = op_data->op_fid2; rec->cr_mode = mode; - cr_flags = mds_pack_open_flags(flags, mode); + cr_flags = mds_pack_open_flags(flags); rec->cr_rdev = rdev; rec->cr_time = op_data->op_mod_time; rec->cr_suppgid1 = op_data->op_suppgids[0]; @@ -200,8 +211,9 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_old_handle = op_data->op_handle; if (op_data->op_name) { - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LOGL0(op_data->op_name, op_data->op_namelen, tmp); + mdc_pack_name(req, &RMF_NAME, op_data->op_name, + op_data->op_namelen); + if (op_data->op_bias & MDS_CREATE_VOLATILE) cr_flags |= MDS_OPEN_VOLATILE; } @@ -295,7 +307,7 @@ static void mdc_ioepoch_pack(struct mdt_ioepoch *epoch, } void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len) + void *ea, size_t ealen, void *ea2, size_t ea2len) { struct mdt_rec_setattr *rec; struct mdt_ioepoch *epoch; @@ -316,7 +328,7 @@ void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, lum = req_capsule_client_get(&req->rq_pill, &RMF_EADATA); if (!ea) { /* Remove LOV EA */ - lum->lmm_magic = LOV_USER_MAGIC_V1; + lum->lmm_magic = cpu_to_le32(LOV_USER_MAGIC_V1); lum->lmm_stripe_size = 0; lum->lmm_stripe_count = 0; lum->lmm_stripe_offset = (typeof(lum->lmm_stripe_offset))(-1); @@ -334,7 +346,6 @@ void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data) { struct mdt_rec_unlink *rec; - char *tmp; CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_unlink)); rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); @@ -352,15 +363,12 @@ void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data) rec->ul_time = op_data->op_mod_time; rec->ul_bias = op_data->op_bias; - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LASSERT(tmp); - LOGL0(op_data->op_name, op_data->op_namelen, tmp); + mdc_pack_name(req, &RMF_NAME, op_data->op_name, op_data->op_namelen); } void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data) { struct mdt_rec_link *rec; - char *tmp; CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_link)); rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); @@ -376,20 +384,21 @@ void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data) rec->lk_time = op_data->op_mod_time; rec->lk_bias = op_data->op_bias; - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LOGL0(op_data->op_name, op_data->op_namelen, tmp); + mdc_pack_name(req, &RMF_NAME, op_data->op_name, op_data->op_namelen); } void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen) + const char *old, size_t oldlen, + const char *new, size_t newlen) { struct mdt_rec_rename *rec; - char *tmp; CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_rename)); rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); /* XXX do something about time, uid, gid */ + rec->rn_opcode = op_data->op_cli_flags & CLI_MIGRATE ? + REINT_MIGRATE : REINT_RENAME; rec->rn_opcode = REINT_RENAME; rec->rn_fsuid = op_data->op_fsuid; rec->rn_fsgid = op_data->op_fsgid; @@ -402,39 +411,34 @@ void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->rn_mode = op_data->op_mode; rec->rn_bias = op_data->op_bias; - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LOGL0(old, oldlen, tmp); + mdc_pack_name(req, &RMF_NAME, old, oldlen); - if (new) { - tmp = req_capsule_client_get(&req->rq_pill, &RMF_SYMTGT); - LOGL0(new, newlen, tmp); - } + if (new) + mdc_pack_name(req, &RMF_SYMTGT, new, newlen); } -void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, - struct md_op_data *op_data, int ea_size) +void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, u32 flags, + struct md_op_data *op_data, size_t ea_size) { struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); - b->valid = valid; + b->mbo_valid = valid; if (op_data->op_bias & MDS_CHECK_SPLIT) - b->valid |= OBD_MD_FLCKSPLIT; + b->mbo_valid |= OBD_MD_FLCKSPLIT; if (op_data->op_bias & MDS_CROSS_REF) - b->valid |= OBD_MD_FLCROSSREF; - b->eadatasize = ea_size; - b->flags = flags; + b->mbo_valid |= OBD_MD_FLCROSSREF; + b->mbo_eadatasize = ea_size; + b->mbo_flags = flags; __mdc_pack_body(b, op_data->op_suppgids[0]); - b->fid1 = op_data->op_fid1; - b->fid2 = op_data->op_fid2; - b->valid |= OBD_MD_FLID; + b->mbo_fid1 = op_data->op_fid1; + b->mbo_fid2 = op_data->op_fid2; + b->mbo_valid |= OBD_MD_FLID; - if (op_data->op_name) { - char *tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - - LOGL0(op_data->op_name, op_data->op_namelen, tmp); - } + if (op_data->op_name) + mdc_pack_name(req, &RMF_NAME, op_data->op_name, + op_data->op_namelen); } static void mdc_hsm_release_pack(struct ptlrpc_request *req, @@ -482,67 +486,3 @@ void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data) mdc_ioepoch_pack(epoch, op_data); mdc_hsm_release_pack(req, op_data); } - -static int mdc_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) -{ - int rc; - - spin_lock(&cli->cl_loi_list_lock); - rc = list_empty(&mcw->mcw_entry); - spin_unlock(&cli->cl_loi_list_lock); - return rc; -}; - -/* We record requests in flight in cli->cl_r_in_flight here. - * There is only one write rpc possible in mdc anyway. If this to change - * in the future - the code may need to be revisited. - */ -int mdc_enter_request(struct client_obd *cli) -{ - int rc = 0; - struct mdc_cache_waiter mcw; - struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); - - spin_lock(&cli->cl_loi_list_lock); - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { - list_add_tail(&mcw.mcw_entry, &cli->cl_cache_waiters); - init_waitqueue_head(&mcw.mcw_waitq); - spin_unlock(&cli->cl_loi_list_lock); - rc = l_wait_event(mcw.mcw_waitq, mdc_req_avail(cli, &mcw), - &lwi); - if (rc) { - spin_lock(&cli->cl_loi_list_lock); - if (list_empty(&mcw.mcw_entry)) - cli->cl_r_in_flight--; - list_del_init(&mcw.mcw_entry); - spin_unlock(&cli->cl_loi_list_lock); - } - } else { - cli->cl_r_in_flight++; - spin_unlock(&cli->cl_loi_list_lock); - } - return rc; -} - -void mdc_exit_request(struct client_obd *cli) -{ - struct list_head *l, *tmp; - struct mdc_cache_waiter *mcw; - - spin_lock(&cli->cl_loi_list_lock); - cli->cl_r_in_flight--; - list_for_each_safe(l, tmp, &cli->cl_cache_waiters) { - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { - /* No free request slots anymore */ - break; - } - - mcw = list_entry(l, struct mdc_cache_waiter, mcw_entry); - list_del_init(&mcw->mcw_entry); - cli->cl_r_in_flight++; - wake_up(&mcw->mcw_waitq); - } - /* Empty waiting list? Decrease reqs in-flight number */ - - spin_unlock(&cli->cl_loi_list_lock); -} diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index f48b58423307..f1f6c082fa42 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -93,8 +93,8 @@ int it_open_error(int phase, struct lookup_intent *it) EXPORT_SYMBOL(it_open_error); /* this must be called on a lockh that is known to have a referenced lock */ -int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, - __u64 *bits) +int mdc_set_lock_data(struct obd_export *exp, const struct lustre_handle *lockh, + void *data, __u64 *bits) { struct ldlm_lock *lock; struct inode *new_inode = data; @@ -102,10 +102,10 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, if (bits) *bits = 0; - if (!*lockh) + if (!lustre_handle_is_used(lockh)) return 0; - lock = ldlm_handle2lock((struct lustre_handle *)lockh); + lock = ldlm_handle2lock(lockh); LASSERT(lock); lock_res_and_lock(lock); @@ -174,7 +174,7 @@ int mdc_null_inode(struct obd_export *exp, fid_build_reg_res_name(fid, &res_id); res = ldlm_resource_get(ns, NULL, &res_id, 0, 0); - if (!res) + if (IS_ERR(res)) return 0; lock_res(res); @@ -185,28 +185,6 @@ int mdc_null_inode(struct obd_export *exp, return 0; } -/* find any ldlm lock of the inode in mdc - * return 0 not find - * 1 find one - * < 0 error - */ -int mdc_find_cbdata(struct obd_export *exp, - const struct lu_fid *fid, - ldlm_iterator_t it, void *data) -{ - struct ldlm_res_id res_id; - int rc = 0; - - fid_build_reg_res_name((struct lu_fid *)fid, &res_id); - rc = ldlm_resource_iterate(class_exp2obd(exp)->obd_namespace, &res_id, - it, data); - if (rc == LDLM_ITER_STOP) - return 1; - else if (rc == LDLM_ITER_CONTINUE) - return 0; - return rc; -} - static inline void mdc_clear_replay_flag(struct ptlrpc_request *req, int rc) { /* Don't hold error requests for replay. */ @@ -240,24 +218,24 @@ static void mdc_realloc_openmsg(struct ptlrpc_request *req, /* FIXME: remove this explicit offset. */ rc = sptlrpc_cli_enlarge_reqbuf(req, DLM_INTENT_REC_OFF + 4, - body->eadatasize); + body->mbo_eadatasize); if (rc) { CERROR("Can't enlarge segment %d size to %d\n", - DLM_INTENT_REC_OFF + 4, body->eadatasize); - body->valid &= ~OBD_MD_FLEASIZE; - body->eadatasize = 0; + DLM_INTENT_REC_OFF + 4, body->mbo_eadatasize); + body->mbo_valid &= ~OBD_MD_FLEASIZE; + body->mbo_eadatasize = 0; } } -static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp, - struct lookup_intent *it, - struct md_op_data *op_data, - void *lmm, int lmmsize, - void *cb_data) +static struct ptlrpc_request * +mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, + struct md_op_data *op_data) { struct ptlrpc_request *req; struct obd_device *obddev = class_exp2obd(exp); struct ldlm_intent *lit; + const void *lmm = op_data->op_data; + u32 lmmsize = op_data->op_data_size; LIST_HEAD(cancels); int count = 0; int mode; @@ -274,7 +252,7 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp, else mode = LCK_PR; } else { - if (it->it_flags & (FMODE_WRITE|MDS_OPEN_TRUNC)) + if (it->it_flags & (FMODE_WRITE | MDS_OPEN_TRUNC)) mode = LCK_CW; else if (it->it_flags & __FMODE_EXEC) mode = LCK_PR; @@ -325,6 +303,9 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp, mdc_open_pack(req, op_data, it->it_create_mode, 0, it->it_flags, lmm, lmmsize); + req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, + obddev->u.cli.cl_max_mds_easize); + ptlrpc_request_set_replen(req); return req; } @@ -336,7 +317,8 @@ mdc_intent_getxattr_pack(struct obd_export *exp, { struct ptlrpc_request *req; struct ldlm_intent *lit; - int rc, count = 0, maxdata; + int rc, count = 0; + u32 maxdata; LIST_HEAD(cancels); req = ptlrpc_request_alloc(class_exp2cliimp(exp), @@ -421,7 +403,7 @@ static struct ptlrpc_request *mdc_intent_getattr_pack(struct obd_export *exp, OBD_MD_MEA | OBD_MD_FLACL; struct ldlm_intent *lit; int rc; - int easize; + u32 easize; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_INTENT_GETATTR); @@ -526,7 +508,7 @@ static int mdc_finish_enqueue(struct obd_export *exp, struct ldlm_reply *lockrep; struct ldlm_lock *lock; void *lvb_data = NULL; - int lvb_len = 0; + u32 lvb_len = 0; LASSERT(rc >= 0); /* Similarly, if we're going to replay this request, we don't want to @@ -605,7 +587,7 @@ static int mdc_finish_enqueue(struct obd_export *exp, mdc_set_open_replay_data(NULL, NULL, it); } - if ((body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE)) != 0) { + if ((body->mbo_valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE)) != 0) { void *eadata; mdc_update_max_ea_from_body(exp, body); @@ -615,7 +597,7 @@ static int mdc_finish_enqueue(struct obd_export *exp, * Eventually, obd_unpackmd() will check the contents. */ eadata = req_capsule_server_sized_get(pill, &RMF_MDT_MD, - body->eadatasize); + body->mbo_eadatasize); if (!eadata) return -EPROTO; @@ -623,7 +605,7 @@ static int mdc_finish_enqueue(struct obd_export *exp, * lock */ lvb_data = eadata; - lvb_len = body->eadatasize; + lvb_len = body->mbo_eadatasize; /* * We save the reply LOV EA in case we have to replay a @@ -639,20 +621,20 @@ static int mdc_finish_enqueue(struct obd_export *exp, if (req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT) < - body->eadatasize) + body->mbo_eadatasize) mdc_realloc_openmsg(req, body); else req_capsule_shrink(pill, &RMF_EADATA, - body->eadatasize, + body->mbo_eadatasize, RCL_CLIENT); req_capsule_set_size(pill, &RMF_EADATA, RCL_CLIENT, - body->eadatasize); + body->mbo_eadatasize); lmm = req_capsule_client_get(pill, &RMF_EADATA); if (lmm) - memcpy(lmm, eadata, body->eadatasize); + memcpy(lmm, eadata, body->mbo_eadatasize); } } } else if (it->it_op & IT_LAYOUT) { @@ -662,7 +644,8 @@ static int mdc_finish_enqueue(struct obd_export *exp, lvb_len = req_capsule_get_size(pill, &RMF_DLM_LVB, RCL_SERVER); if (lvb_len > 0) { lvb_data = req_capsule_server_sized_get(pill, - &RMF_DLM_LVB, lvb_len); + &RMF_DLM_LVB, + lvb_len); if (!lvb_data) return -EPROTO; } @@ -705,9 +688,9 @@ static int mdc_finish_enqueue(struct obd_export *exp, * we don't know in advance the file type. */ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, + const ldlm_policy_data_t *policy, struct lookup_intent *it, struct md_op_data *op_data, - struct lustre_handle *lockh, void *lmm, int lmmsize, - struct ptlrpc_request **reqp, u64 extra_lock_flags) + struct lustre_handle *lockh, u64 extra_lock_flags) { static const ldlm_policy_data_t lookup_policy = { .l_inodebits = { MDS_INODELOCK_LOOKUP } @@ -721,9 +704,8 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, static const ldlm_policy_data_t getxattr_policy = { .l_inodebits = { MDS_INODELOCK_XATTR } }; - ldlm_policy_data_t const *policy = &lookup_policy; struct obd_device *obddev = class_exp2obd(exp); - struct ptlrpc_request *req; + struct ptlrpc_request *req = NULL; u64 flags, saved_flags = extra_lock_flags; struct ldlm_res_id res_id; int generation, resends = 0; @@ -733,40 +715,32 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, LASSERTF(!it || einfo->ei_type == LDLM_IBITS, "lock type %d\n", einfo->ei_type); - fid_build_reg_res_name(&op_data->op_fid1, &res_id); if (it) { + LASSERT(!policy); + saved_flags |= LDLM_FL_HAS_INTENT; - if (it->it_op & (IT_UNLINK | IT_GETATTR | IT_READDIR)) + if (it->it_op & (IT_OPEN | IT_UNLINK | IT_GETATTR | IT_READDIR)) policy = &update_policy; else if (it->it_op & IT_LAYOUT) policy = &layout_policy; else if (it->it_op & (IT_GETXATTR | IT_SETXATTR)) policy = &getxattr_policy; + else + policy = &lookup_policy; } - LASSERT(!reqp); - generation = obddev->u.cli.cl_import->imp_generation; resend: flags = saved_flags; if (!it) { - /* The only way right now is FLOCK, in this case we hide flock - * policy as lmm, but lmmsize is 0 - */ - LASSERT(lmm && lmmsize == 0); + /* The only way right now is FLOCK. */ LASSERTF(einfo->ei_type == LDLM_FLOCK, "lock type %d\n", einfo->ei_type); - policy = lmm; res_id.name[3] = LDLM_FLOCK; - req = NULL; } else if (it->it_op & IT_OPEN) { - req = mdc_intent_open_pack(exp, it, op_data, lmm, lmmsize, - einfo->ei_cbdata); - policy = &update_policy; - einfo->ei_cbdata = NULL; - lmm = NULL; + req = mdc_intent_open_pack(exp, it, op_data); } else if (it->it_op & IT_UNLINK) { req = mdc_intent_unlink_pack(exp, it, op_data); } else if (it->it_op & (IT_GETATTR | IT_LOOKUP)) { @@ -806,7 +780,7 @@ resend: */ if (it) { mdc_get_rpc_lock(obddev->u.cli.cl_rpc_lock, it); - rc = mdc_enter_request(&obddev->u.cli); + rc = obd_get_request_slot(&obddev->u.cli); if (rc != 0) { mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it); mdc_clear_replay_flag(req, 0); @@ -834,13 +808,12 @@ resend: return rc; } - mdc_exit_request(&obddev->u.cli); + obd_put_request_slot(&obddev->u.cli); mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it); if (rc < 0) { - CDEBUG_LIMIT((rc == -EACCES || rc == -EIDRM) ? D_INFO : D_ERROR, - "%s: ldlm_cli_enqueue failed: rc = %d\n", - obddev->obd_name, rc); + CDEBUG(D_INFO, "%s: ldlm_cli_enqueue failed: rc = %d\n", + obddev->obd_name, rc); mdc_clear_replay_flag(req, rc); ptlrpc_req_finished(req); @@ -903,6 +876,9 @@ static int mdc_finish_intent_lock(struct obd_export *exp, LASSERT(request != LP_POISON); LASSERT(request->rq_repmsg != LP_POISON); + if (it->it_op & IT_READDIR) + return 0; + if (!it_disposition(it, DISP_IT_EXECD)) { /* The server failed before it even started executing the * intent, i.e. because it couldn't unpack the request. @@ -917,27 +893,6 @@ static int mdc_finish_intent_lock(struct obd_export *exp, mdt_body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); LASSERT(mdt_body); /* mdc_enqueue checked */ - /* If we were revalidating a fid/name pair, mark the intent in - * case we fail and get called again from lookup - */ - if (fid_is_sane(&op_data->op_fid2) && - it->it_create_mode & M_CHECK_STALE && - it->it_op != IT_GETATTR) { - /* Also: did we find the same inode? */ - /* sever can return one of two fids: - * op_fid2 - new allocated fid - if file is created. - * op_fid3 - existent fid - if file only open. - * op_fid3 is saved in lmv_intent_open - */ - if ((!lu_fid_eq(&op_data->op_fid2, &mdt_body->fid1)) && - (!lu_fid_eq(&op_data->op_fid3, &mdt_body->fid1))) { - CDEBUG(D_DENTRY, "Found stale data "DFID"("DFID")/"DFID - "\n", PFID(&op_data->op_fid2), - PFID(&op_data->op_fid2), PFID(&mdt_body->fid1)); - return -ESTALE; - } - } - rc = it_open_error(DISP_LOOKUP_EXECD, it); if (rc) return rc; @@ -980,10 +935,10 @@ static int mdc_finish_intent_lock(struct obd_export *exp, LDLM_DEBUG(lock, "matching against this"); - LASSERTF(fid_res_name_eq(&mdt_body->fid1, + LASSERTF(fid_res_name_eq(&mdt_body->mbo_fid1, &lock->l_resource->lr_name), "Lock res_id: "DLDLMRES", fid: "DFID"\n", - PLDLMRES(lock->l_resource), PFID(&mdt_body->fid1)); + PLDLMRES(lock->l_resource), PFID(&mdt_body->mbo_fid1)); LDLM_LOCK_PUT(lock); memcpy(&old_lock, lockh, sizeof(*lockh)); @@ -998,8 +953,8 @@ static int mdc_finish_intent_lock(struct obd_export *exp, } CDEBUG(D_DENTRY, "D_IT dentry %.*s intent: %s status %d disp %x rc %d\n", - op_data->op_namelen, op_data->op_name, ldlm_it2str(it->it_op), - it->it_status, it->it_disposition, rc); + (int)op_data->op_namelen, op_data->op_name, + ldlm_it2str(it->it_op), it->it_status, it->it_disposition, rc); return rc; } @@ -1042,6 +997,9 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM; break; + case IT_READDIR: + policy.l_inodebits.bits = MDS_INODELOCK_UPDATE; + break; case IT_LAYOUT: policy.l_inodebits.bits = MDS_INODELOCK_LAYOUT; break; @@ -1095,10 +1053,8 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, * child lookup. */ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int lookup_flags, struct ptlrpc_request **reqp, - ldlm_blocking_callback cb_blocking, - __u64 extra_lock_flags) + struct lookup_intent *it, struct ptlrpc_request **reqp, + ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS, @@ -1112,14 +1068,14 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, LASSERT(it); CDEBUG(D_DLMTRACE, "(name: %.*s,"DFID") in obj "DFID - ", intent: %s flags %#Lo\n", op_data->op_namelen, + ", intent: %s flags %#Lo\n", (int)op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid2), PFID(&op_data->op_fid1), ldlm_it2str(it->it_op), it->it_flags); lockh.cookie = 0; if (fid_is_sane(&op_data->op_fid2) && - (it->it_op & (IT_LOOKUP | IT_GETATTR))) { + (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_READDIR))) { /* We could just return 1 immediately, but since we should only * be called in revalidate_it if we already have a lock, let's * verify that. @@ -1135,13 +1091,13 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, /* For case if upper layer did not alloc fid, do it now. */ if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) { - rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data); + rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc < 0) { CERROR("Can't alloc new fid, rc %d\n", rc); return rc; } } - rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh, lmm, lmmsize, NULL, + rc = mdc_enqueue(exp, &einfo, NULL, it, op_data, &lockh, extra_lock_flags); if (rc < 0) return rc; @@ -1170,7 +1126,7 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env, obddev = class_exp2obd(exp); - mdc_exit_request(&obddev->u.cli); + obd_put_request_slot(&obddev->u.cli); if (OBD_FAIL_CHECK(OBD_FAIL_MDC_GETATTR_ENQUEUE)) rc = -ETIMEDOUT; @@ -1222,15 +1178,15 @@ int mdc_intent_getattr_async(struct obd_export *exp, CDEBUG(D_DLMTRACE, "name: %.*s in inode " DFID ", intent: %s flags %#Lo\n", - op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), - ldlm_it2str(it->it_op), it->it_flags); + (int)op_data->op_namelen, op_data->op_name, + PFID(&op_data->op_fid1), ldlm_it2str(it->it_op), it->it_flags); fid_build_reg_res_name(&op_data->op_fid1, &res_id); req = mdc_intent_getattr_pack(exp, it, op_data); if (IS_ERR(req)) return PTR_ERR(req); - rc = mdc_enter_request(&obddev->u.cli); + rc = obd_get_request_slot(&obddev->u.cli); if (rc != 0) { ptlrpc_req_finished(req); return rc; @@ -1239,7 +1195,7 @@ int mdc_intent_getattr_async(struct obd_export *exp, rc = ldlm_cli_enqueue(exp, &req, einfo, &res_id, &policy, &flags, NULL, 0, LVB_T_NONE, &minfo->mi_lockh, 1); if (rc < 0) { - mdc_exit_request(&obddev->u.cli); + obd_put_request_slot(&obddev->u.cli); ptlrpc_req_finished(req); return rc; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index 5dba2c813857..c921e471fa27 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -86,7 +86,7 @@ int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, fid_build_reg_res_name(fid, &res_id); res = ldlm_resource_get(exp->exp_obd->obd_namespace, NULL, &res_id, 0, 0); - if (!res) + if (IS_ERR(res)) return 0; LDLM_RESOURCE_ADDREF(res); /* Initialize ibits lock policy. */ @@ -99,7 +99,7 @@ int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, } int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len, + void *ea, size_t ealen, void *ea2, size_t ea2len, struct ptlrpc_request **request, struct md_open_data **mod) { LIST_HEAD(cancels); @@ -110,11 +110,10 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, __u64 bits; bits = MDS_INODELOCK_UPDATE; - if (op_data->op_attr.ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) + if (op_data->op_attr.ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) bits |= MDS_INODELOCK_LOOKUP; if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && - (fid_is_sane(&op_data->op_fid1)) && - !OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) + (fid_is_sane(&op_data->op_fid1))) count = mdc_resource_get_unused(exp, &op_data->op_fid1, &cancels, LCK_EX, bits); req = ptlrpc_request_alloc(class_exp2cliimp(exp), @@ -177,8 +176,8 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH); body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - epoch->handle = body->handle; - epoch->ioepoch = body->ioepoch; + epoch->handle = body->mbo_handle; + epoch->ioepoch = body->mbo_ioepoch; req->rq_replay_cb = mdc_replay_open; /** bug 3633, open may be committed and estale answer is not error */ } else if (rc == -ESTALE && (op_data->op_flags & MF_SOM_CHANGE)) { @@ -197,9 +196,9 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, } int mdc_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, __u32 gid, - cfs_cap_t cap_effective, __u64 rdev, - struct ptlrpc_request **request) + const void *data, size_t datalen, umode_t mode, + uid_t uid, gid_t gid, cfs_cap_t cap_effective, + __u64 rdev, struct ptlrpc_request **request) { struct ptlrpc_request *req; int level, rc; @@ -214,11 +213,9 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data, * mdc_fid_alloc() may return errno 1 in case of switch to new * sequence, handle this. */ - rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data); - if (rc < 0) { - CERROR("Can't alloc new fid, rc %d\n", rc); + rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); + if (rc < 0) return rc; - } } rebuild: @@ -307,14 +304,12 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, LASSERT(!req); if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && - (fid_is_sane(&op_data->op_fid1)) && - !OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) + (fid_is_sane(&op_data->op_fid1))) count = mdc_resource_get_unused(exp, &op_data->op_fid1, &cancels, LCK_EX, MDS_INODELOCK_UPDATE); if ((op_data->op_flags & MF_MDC_CANCEL_FID3) && - (fid_is_sane(&op_data->op_fid3)) && - !OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) + (fid_is_sane(&op_data->op_fid3))) count += mdc_resource_get_unused(exp, &op_data->op_fid3, &cancels, LCK_EX, MDS_INODELOCK_FULL); @@ -394,7 +389,7 @@ int mdc_link(struct obd_export *exp, struct md_op_data *op_data, } int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen, + const char *old, size_t oldlen, const char *new, size_t newlen, struct ptlrpc_request **request) { LIST_HEAD(cancels); @@ -431,7 +426,8 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, } req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, oldlen + 1); - req_capsule_set_size(&req->rq_pill, &RMF_SYMTGT, RCL_CLIENT, newlen+1); + req_capsule_set_size(&req->rq_pill, &RMF_SYMTGT, RCL_CLIENT, + newlen + 1); rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); if (rc) { diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 542801f04b0d..f56ea643f9bf 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -39,7 +39,9 @@ # include #include "../include/lustre_acl.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/obd_class.h" +#include "../include/lustre_lmv.h" #include "../include/lustre_fid.h" #include "../include/lprocfs_status.h" #include "../include/lustre_param.h" @@ -57,16 +59,16 @@ static inline int mdc_queue_wait(struct ptlrpc_request *req) struct client_obd *cli = &req->rq_import->imp_obd->u.cli; int rc; - /* mdc_enter_request() ensures that this client has no more + /* obd_get_request_slot() ensures that this client has no more * than cl_max_rpcs_in_flight RPCs simultaneously inf light * against an MDT. */ - rc = mdc_enter_request(cli); + rc = obd_get_request_slot(cli); if (rc != 0) return rc; rc = ptlrpc_queue_wait(req); - mdc_exit_request(cli); + obd_put_request_slot(cli); return rc; } @@ -98,7 +100,7 @@ static int mdc_getstatus(struct obd_export *exp, struct lu_fid *rootfid) goto out; } - *rootfid = body->fid1; + *rootfid = body->mbo_fid1; CDEBUG(D_NET, "root fid="DFID", last_committed=%llu\n", PFID(rootfid), @@ -136,12 +138,12 @@ static int mdc_getattr_common(struct obd_export *exp, if (!body) return -EPROTO; - CDEBUG(D_NET, "mode: %o\n", body->mode); + CDEBUG(D_NET, "mode: %o\n", body->mbo_mode); mdc_update_max_ea_from_body(exp, body); - if (body->eadatasize != 0) { + if (body->mbo_eadatasize != 0) { eadata = req_capsule_server_sized_get(pill, &RMF_MDT_MD, - body->eadatasize); + body->mbo_eadatasize); if (!eadata) return -EPROTO; } @@ -230,32 +232,6 @@ static int mdc_getattr_name(struct obd_export *exp, struct md_op_data *op_data, return rc; } -static int mdc_is_subdir(struct obd_export *exp, - const struct lu_fid *pfid, - const struct lu_fid *cfid, - struct ptlrpc_request **request) -{ - struct ptlrpc_request *req; - int rc; - - *request = NULL; - req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), - &RQF_MDS_IS_SUBDIR, LUSTRE_MDS_VERSION, - MDS_IS_SUBDIR); - if (!req) - return -ENOMEM; - - mdc_is_subdir_pack(req, pfid, cfid, 0); - ptlrpc_request_set_replen(req); - - rc = ptlrpc_queue_wait(req); - if (rc && rc != -EREMOTE) - ptlrpc_req_finished(req); - else - *request = req; - return rc; -} - static int mdc_xattr_common(struct obd_export *exp, const struct req_format *fmt, const struct lu_fid *fid, @@ -397,15 +373,15 @@ static int mdc_unpack_acl(struct ptlrpc_request *req, struct lustre_md *md) void *buf; int rc; - if (!body->aclsize) + if (!body->mbo_aclsize) return 0; - buf = req_capsule_server_sized_get(pill, &RMF_ACL, body->aclsize); + buf = req_capsule_server_sized_get(pill, &RMF_ACL, body->mbo_aclsize); if (!buf) return -EPROTO; - acl = posix_acl_from_xattr(&init_user_ns, buf, body->aclsize); + acl = posix_acl_from_xattr(&init_user_ns, buf, body->mbo_aclsize); if (!acl) return 0; @@ -443,24 +419,24 @@ static int mdc_get_lustre_md(struct obd_export *exp, md->body = req_capsule_server_get(pill, &RMF_MDT_BODY); - if (md->body->valid & OBD_MD_FLEASIZE) { + if (md->body->mbo_valid & OBD_MD_FLEASIZE) { int lmmsize; struct lov_mds_md *lmm; - if (!S_ISREG(md->body->mode)) { + if (!S_ISREG(md->body->mbo_mode)) { CDEBUG(D_INFO, "OBD_MD_FLEASIZE set, should be a regular file, but is not\n"); rc = -EPROTO; goto out; } - if (md->body->eadatasize == 0) { + if (md->body->mbo_eadatasize == 0) { CDEBUG(D_INFO, "OBD_MD_FLEASIZE set, but eadatasize 0\n"); rc = -EPROTO; goto out; } - lmmsize = md->body->eadatasize; + lmmsize = md->body->mbo_eadatasize; lmm = req_capsule_server_sized_get(pill, &RMF_MDT_MD, lmmsize); if (!lmm) { rc = -EPROTO; @@ -471,7 +447,7 @@ static int mdc_get_lustre_md(struct obd_export *exp, if (rc < 0) goto out; - if (rc < sizeof(*md->lsm)) { + if (rc < (typeof(rc))sizeof(*md->lsm)) { CDEBUG(D_INFO, "lsm size too small: rc < sizeof (*md->lsm) (%d < %d)\n", rc, (int)sizeof(*md->lsm)); @@ -479,24 +455,24 @@ static int mdc_get_lustre_md(struct obd_export *exp, goto out; } - } else if (md->body->valid & OBD_MD_FLDIREA) { + } else if (md->body->mbo_valid & OBD_MD_FLDIREA) { int lmvsize; struct lov_mds_md *lmv; - if (!S_ISDIR(md->body->mode)) { + if (!S_ISDIR(md->body->mbo_mode)) { CDEBUG(D_INFO, "OBD_MD_FLDIREA set, should be a directory, but is not\n"); rc = -EPROTO; goto out; } - if (md->body->eadatasize == 0) { + if (md->body->mbo_eadatasize == 0) { CDEBUG(D_INFO, "OBD_MD_FLDIREA is set, but eadatasize 0\n"); return -EPROTO; } - if (md->body->valid & OBD_MD_MEA) { - lmvsize = md->body->eadatasize; + if (md->body->mbo_valid & OBD_MD_MEA) { + lmvsize = md->body->mbo_eadatasize; lmv = req_capsule_server_sized_get(pill, &RMF_MDT_MD, lmvsize); if (!lmv) { @@ -504,15 +480,15 @@ static int mdc_get_lustre_md(struct obd_export *exp, goto out; } - rc = obd_unpackmd(md_exp, (void *)&md->mea, lmv, + rc = obd_unpackmd(md_exp, (void *)&md->lmv, lmv, lmvsize); if (rc < 0) goto out; - if (rc < sizeof(*md->mea)) { + if (rc < (typeof(rc))sizeof(*md->lmv)) { CDEBUG(D_INFO, - "size too small: rc < sizeof(*md->mea) (%d < %d)\n", - rc, (int)sizeof(*md->mea)); + "size too small: rc < sizeof(*md->lmv) (%d < %d)\n", + rc, (int)sizeof(*md->lmv)); rc = -EPROTO; goto out; } @@ -520,12 +496,12 @@ static int mdc_get_lustre_md(struct obd_export *exp, } rc = 0; - if (md->body->valid & OBD_MD_FLACL) { + if (md->body->mbo_valid & OBD_MD_FLACL) { /* for ACL, it's possible that FLACL is set but aclsize is zero. * only when aclsize != 0 there's an actual segment for ACL * in reply buffer. */ - if (md->body->aclsize) { + if (md->body->mbo_aclsize) { rc = mdc_unpack_acl(req, md); if (rc) goto out; @@ -580,9 +556,9 @@ void mdc_replay_open(struct ptlrpc_request *req) file_fh = &och->och_fh; CDEBUG(D_HA, "updating handle from %#llx to %#llx\n", - file_fh->cookie, body->handle.cookie); + file_fh->cookie, body->mbo_handle.cookie); old = *file_fh; - *file_fh = body->handle; + *file_fh = body->mbo_handle; } close_req = mod->mod_close_req; if (close_req) { @@ -597,7 +573,7 @@ void mdc_replay_open(struct ptlrpc_request *req) if (och) LASSERT(!memcmp(&old, &epoch->handle, sizeof(old))); DEBUG_REQ(D_HA, close_req, "updating close body with new fh"); - epoch->handle = body->handle; + epoch->handle = body->mbo_handle; } } @@ -679,11 +655,11 @@ int mdc_set_open_replay_data(struct obd_export *exp, spin_unlock(&open_req->rq_lock); } - rec->cr_fid2 = body->fid1; - rec->cr_ioepoch = body->ioepoch; - rec->cr_old_handle.cookie = body->handle.cookie; + rec->cr_fid2 = body->mbo_fid1; + rec->cr_ioepoch = body->mbo_ioepoch; + rec->cr_old_handle.cookie = body->mbo_handle.cookie; open_req->rq_replay_cb = mdc_replay_open; - if (!fid_is_sane(&body->fid1)) { + if (!fid_is_sane(&body->mbo_fid1)) { DEBUG_REQ(D_ERROR, open_req, "Saving replay request with insane fid"); LBUG(); @@ -701,9 +677,15 @@ static void mdc_free_open(struct md_open_data *mod) imp_connect_disp_stripe(mod->mod_open_req->rq_import)) committed = 1; - LASSERT(mod->mod_open_req->rq_replay == 0); - - DEBUG_REQ(D_RPCTRACE, mod->mod_open_req, "free open request\n"); + /* + * No reason to asssert here if the open request has + * rq_replay == 1. It means that mdc_close failed, and + * close request wasn`t sent. It is not fatal to client. + * The worst thing is eviction if the client gets open lock + */ + DEBUG_REQ(D_RPCTRACE, mod->mod_open_req, + "free open request rq_replay = %d\n", + mod->mod_open_req->rq_replay); ptlrpc_request_committed(mod->mod_open_req, committed); if (mod->mod_close_req) @@ -744,7 +726,7 @@ static void mdc_close_handle_reply(struct ptlrpc_request *req, epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH); epoch->flags |= MF_SOM_AU; - if (repbody->valid & OBD_MD_FLGETATTRLOCK) + if (repbody->mbo_valid & OBD_MD_FLGETATTRLOCK) op_data->op_flags |= MF_GETATTR_LOCK; } } @@ -763,7 +745,7 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, req_fmt = &RQF_MDS_RELEASE_CLOSE; /* allocate a FID for volatile file */ - rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data); + rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc < 0) { CERROR("%s: "DFID" failed to allocate FID: %d\n", obd->obd_name, PFID(&op_data->op_fid1), rc); @@ -773,22 +755,10 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, } *request = NULL; - req = ptlrpc_request_alloc(class_exp2cliimp(exp), req_fmt); - if (!req) - return -ENOMEM; - - rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_CLOSE); - if (rc) { - ptlrpc_request_free(req); - return rc; - } - - /* To avoid a livelock (bug 7034), we need to send CLOSE RPCs to a - * portal whose threads are not taking any DLM locks and are therefore - * always progressing - */ - req->rq_request_portal = MDS_READPAGE_PORTAL; - ptlrpc_at_set_req_timeout(req); + if (OBD_FAIL_CHECK(OBD_FAIL_MDC_CLOSE)) + req = NULL; + else + req = ptlrpc_request_alloc(class_exp2cliimp(exp), req_fmt); /* Ensure that this close's handle is fixed up during replay. */ if (likely(mod)) { @@ -809,6 +779,29 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, CDEBUG(D_HA, "couldn't find open req; expecting close error\n"); } + if (!req) { + /* + * TODO: repeat close after errors + */ + CWARN("%s: close of FID "DFID" failed, file reference will be dropped when this client unmounts or is evicted\n", + obd->obd_name, PFID(&op_data->op_fid1)); + rc = -ENOMEM; + goto out; + } + + rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_CLOSE); + if (rc) { + ptlrpc_request_free(req); + goto out; + } + + /* + * To avoid a livelock (bug 7034), we need to send CLOSE RPCs to a + * portal whose threads are not taking any DLM locks and are therefore + * always progressing + */ + req->rq_request_portal = MDS_READPAGE_PORTAL; + ptlrpc_at_set_req_timeout(req); mdc_close_pack(req, op_data); @@ -854,6 +847,7 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, } } +out: if (mod) { if (rc != 0) mod->mod_close_req = NULL; @@ -936,16 +930,17 @@ static int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, return rc; } -static int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data, - struct page **pages, struct ptlrpc_request **request) +static int mdc_getpage(struct obd_export *exp, const struct lu_fid *fid, + u64 offset, struct page **pages, int npages, + struct ptlrpc_request **request) { - struct ptlrpc_request *req; struct ptlrpc_bulk_desc *desc; - int i; - wait_queue_head_t waitq; - int resends = 0; - struct l_wait_info lwi; - int rc; + struct ptlrpc_request *req; + wait_queue_head_t waitq; + struct l_wait_info lwi; + int resends = 0; + int rc; + int i; *request = NULL; init_waitqueue_head(&waitq); @@ -964,7 +959,7 @@ restart_bulk: req->rq_request_portal = MDS_READPAGE_PORTAL; ptlrpc_at_set_req_timeout(req); - desc = ptlrpc_prep_bulk_imp(req, op_data->op_npages, 1, BULK_PUT_SINK, + desc = ptlrpc_prep_bulk_imp(req, npages, 1, BULK_PUT_SINK, MDS_BULK_PORTAL); if (!desc) { ptlrpc_request_free(req); @@ -972,12 +967,10 @@ restart_bulk: } /* NB req now owns desc and will free it when it gets freed */ - for (i = 0; i < op_data->op_npages; i++) + for (i = 0; i < npages; i++) ptlrpc_prep_bulk_page_pin(desc, pages[i], 0, PAGE_SIZE); - mdc_readdir_pack(req, op_data->op_offset, - PAGE_SIZE * op_data->op_npages, - &op_data->op_fid1); + mdc_readdir_pack(req, offset, PAGE_SIZE * npages, fid); ptlrpc_request_set_replen(req); rc = ptlrpc_queue_wait(req); @@ -988,11 +981,12 @@ restart_bulk: resends++; if (!client_should_resend(resends, &exp->exp_obd->u.cli)) { - CERROR("too many resend retries, returning error\n"); + CERROR("%s: too many resend retries: rc = %d\n", + exp->exp_obd->obd_name, -EIO); return -EIO; } - lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(resends), - NULL, NULL, NULL); + lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(resends), NULL, NULL, + NULL); l_wait_event(waitq, 0, &lwi); goto restart_bulk; @@ -1006,9 +1000,9 @@ restart_bulk: } if (req->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK) { - CERROR("Unexpected # bytes transferred: %d (%ld expected)\n", - req->rq_bulk->bd_nob_transferred, - PAGE_SIZE * op_data->op_npages); + CERROR("%s: unexpected bytes transferred: %d (%ld expected)\n", + exp->exp_obd->obd_name, req->rq_bulk->bd_nob_transferred, + PAGE_SIZE * npages); ptlrpc_req_finished(req); return -EPROTO; } @@ -1017,6 +1011,453 @@ restart_bulk: return 0; } +static void mdc_release_page(struct page *page, int remove) +{ + if (remove) { + lock_page(page); + if (likely(page->mapping)) + truncate_complete_page(page->mapping, page); + unlock_page(page); + } + put_page(page); +} + +static struct page *mdc_page_locate(struct address_space *mapping, __u64 *hash, + __u64 *start, __u64 *end, int hash64) +{ + /* + * Complement of hash is used as an index so that + * radix_tree_gang_lookup() can be used to find a page with starting + * hash _smaller_ than one we are looking for. + */ + unsigned long offset = hash_x_index(*hash, hash64); + struct page *page; + int found; + + spin_lock_irq(&mapping->tree_lock); + found = radix_tree_gang_lookup(&mapping->page_tree, + (void **)&page, offset, 1); + if (found > 0 && !radix_tree_exceptional_entry(page)) { + struct lu_dirpage *dp; + + get_page(page); + spin_unlock_irq(&mapping->tree_lock); + /* + * In contrast to find_lock_page() we are sure that directory + * page cannot be truncated (while DLM lock is held) and, + * hence, can avoid restart. + * + * In fact, page cannot be locked here at all, because + * mdc_read_page_remote does synchronous io. + */ + wait_on_page_locked(page); + if (PageUptodate(page)) { + dp = kmap(page); + if (BITS_PER_LONG == 32 && hash64) { + *start = le64_to_cpu(dp->ldp_hash_start) >> 32; + *end = le64_to_cpu(dp->ldp_hash_end) >> 32; + *hash = *hash >> 32; + } else { + *start = le64_to_cpu(dp->ldp_hash_start); + *end = le64_to_cpu(dp->ldp_hash_end); + } + if (unlikely(*start == 1 && *hash == 0)) + *hash = *start; + else + LASSERTF(*start <= *hash, "start = %#llx,end = %#llx,hash = %#llx\n", + *start, *end, *hash); + CDEBUG(D_VFSTRACE, "offset %lx [%#llx %#llx], hash %#llx\n", + offset, *start, *end, *hash); + if (*hash > *end) { + kunmap(page); + mdc_release_page(page, 0); + page = NULL; + } else if (*end != *start && *hash == *end) { + /* + * upon hash collision, remove this page, + * otherwise put page reference, and + * mdc_read_page_remote() will issue RPC to + * fetch the page we want. + */ + kunmap(page); + mdc_release_page(page, + le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); + page = NULL; + } + } else { + put_page(page); + page = ERR_PTR(-EIO); + } + } else { + spin_unlock_irq(&mapping->tree_lock); + page = NULL; + } + return page; +} + +/* + * Adjust a set of pages, each page containing an array of lu_dirpages, + * so that each page can be used as a single logical lu_dirpage. + * + * A lu_dirpage is laid out as follows, where s = ldp_hash_start, + * e = ldp_hash_end, f = ldp_flags, p = padding, and each "ent" is a + * struct lu_dirent. It has size up to LU_PAGE_SIZE. The ldp_hash_end + * value is used as a cookie to request the next lu_dirpage in a + * directory listing that spans multiple pages (two in this example): + * ________ + * | | + * .|--------v------- -----. + * |s|e|f|p|ent|ent| ... |ent| + * '--|-------------- -----' Each PAGE contains a single + * '------. lu_dirpage. + * .---------v------- -----. + * |s|e|f|p|ent| 0 | ... | 0 | + * '----------------- -----' + * + * However, on hosts where the native VM page size (PAGE_SIZE) is + * larger than LU_PAGE_SIZE, a single host page may contain multiple + * lu_dirpages. After reading the lu_dirpages from the MDS, the + * ldp_hash_end of the first lu_dirpage refers to the one immediately + * after it in the same PAGE (arrows simplified for brevity, but + * in general e0==s1, e1==s2, etc.): + * + * .-------------------- -----. + * |s0|e0|f0|p|ent|ent| ... |ent| + * |---v---------------- -----| + * |s1|e1|f1|p|ent|ent| ... |ent| + * |---v---------------- -----| Here, each PAGE contains + * ... multiple lu_dirpages. + * |---v---------------- -----| + * |s'|e'|f'|p|ent|ent| ... |ent| + * '---|---------------- -----' + * v + * .----------------------------. + * | next PAGE | + * + * This structure is transformed into a single logical lu_dirpage as follows: + * + * - Replace e0 with e' so the request for the next lu_dirpage gets the page + * labeled 'next PAGE'. + * + * - Copy the LDF_COLLIDE flag from f' to f0 to correctly reflect whether + * a hash collision with the next page exists. + * + * - Adjust the lde_reclen of the ending entry of each lu_dirpage to span + * to the first entry of the next lu_dirpage. + */ +#if PAGE_SIZE > LU_PAGE_SIZE +static void mdc_adjust_dirpages(struct page **pages, int cfs_pgs, int lu_pgs) +{ + int i; + + for (i = 0; i < cfs_pgs; i++) { + struct lu_dirpage *dp = kmap(pages[i]); + __u64 hash_end = le64_to_cpu(dp->ldp_hash_end); + __u32 flags = le32_to_cpu(dp->ldp_flags); + struct lu_dirpage *first = dp; + struct lu_dirent *end_dirent = NULL; + struct lu_dirent *ent; + + while (--lu_pgs > 0) { + ent = lu_dirent_start(dp); + for (end_dirent = ent; ent; + end_dirent = ent, ent = lu_dirent_next(ent)); + + /* Advance dp to next lu_dirpage. */ + dp = (struct lu_dirpage *)((char *)dp + LU_PAGE_SIZE); + + /* Check if we've reached the end of the CFS_PAGE. */ + if (!((unsigned long)dp & ~PAGE_MASK)) + break; + + /* Save the hash and flags of this lu_dirpage. */ + hash_end = le64_to_cpu(dp->ldp_hash_end); + flags = le32_to_cpu(dp->ldp_flags); + + /* Check if lu_dirpage contains no entries. */ + if (!end_dirent) + break; + + /* + * Enlarge the end entry lde_reclen from 0 to + * first entry of next lu_dirpage. + */ + LASSERT(!le16_to_cpu(end_dirent->lde_reclen)); + end_dirent->lde_reclen = + cpu_to_le16((char *)(dp->ldp_entries) - + (char *)end_dirent); + } + + first->ldp_hash_end = hash_end; + first->ldp_flags &= ~cpu_to_le32(LDF_COLLIDE); + first->ldp_flags |= flags & cpu_to_le32(LDF_COLLIDE); + + kunmap(pages[i]); + } + LASSERTF(lu_pgs == 0, "left = %d", lu_pgs); +} +#else +#define mdc_adjust_dirpages(pages, cfs_pgs, lu_pgs) do {} while (0) +#endif /* PAGE_SIZE > LU_PAGE_SIZE */ + +/* parameters for readdir page */ +struct readpage_param { + struct md_op_data *rp_mod; + __u64 rp_off; + int rp_hash64; + struct obd_export *rp_exp; + struct md_callback *rp_cb; +}; + +/** + * Read pages from server. + * + * Page in MDS_READPAGE RPC is packed in LU_PAGE_SIZE, and each page contains + * a header lu_dirpage which describes the start/end hash, and whether this + * page is empty (contains no dir entry) or hash collide with next page. + * After client receives reply, several pages will be integrated into dir page + * in PAGE_SIZE (if PAGE_SIZE greater than LU_PAGE_SIZE), and the + * lu_dirpage for this integrated page will be adjusted. + **/ +static int mdc_read_page_remote(void *data, struct page *page0) +{ + struct readpage_param *rp = data; + struct page **page_pool; + struct page *page; + struct lu_dirpage *dp; + int rd_pgs = 0; /* number of pages read actually */ + int npages; + struct md_op_data *op_data = rp->rp_mod; + struct ptlrpc_request *req; + int max_pages = op_data->op_max_pages; + struct inode *inode; + struct lu_fid *fid; + int i; + int rc; + + LASSERT(max_pages > 0 && max_pages <= PTLRPC_MAX_BRW_PAGES); + inode = op_data->op_data; + fid = &op_data->op_fid1; + LASSERT(inode); + + page_pool = kcalloc(max_pages, sizeof(page), GFP_NOFS); + if (page_pool) { + page_pool[0] = page0; + } else { + page_pool = &page0; + max_pages = 1; + } + + for (npages = 1; npages < max_pages; npages++) { + page = page_cache_alloc_cold(inode->i_mapping); + if (!page) + break; + page_pool[npages] = page; + } + + rc = mdc_getpage(rp->rp_exp, fid, rp->rp_off, page_pool, npages, &req); + if (!rc) { + int lu_pgs = req->rq_bulk->bd_nob_transferred; + + rd_pgs = (req->rq_bulk->bd_nob_transferred + + PAGE_SIZE - 1) >> PAGE_SHIFT; + lu_pgs >>= LU_PAGE_SHIFT; + LASSERT(!(req->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK)); + + CDEBUG(D_INODE, "read %d(%d) pages\n", rd_pgs, lu_pgs); + + mdc_adjust_dirpages(page_pool, rd_pgs, lu_pgs); + + SetPageUptodate(page0); + } + + unlock_page(page0); + ptlrpc_req_finished(req); + CDEBUG(D_CACHE, "read %d/%d pages\n", rd_pgs, npages); + for (i = 1; i < npages; i++) { + unsigned long offset; + __u64 hash; + int ret; + + page = page_pool[i]; + + if (rc < 0 || i >= rd_pgs) { + put_page(page); + continue; + } + + SetPageUptodate(page); + + dp = kmap(page); + hash = le64_to_cpu(dp->ldp_hash_start); + kunmap(page); + + offset = hash_x_index(hash, rp->rp_hash64); + + prefetchw(&page->flags); + ret = add_to_page_cache_lru(page, inode->i_mapping, offset, + GFP_KERNEL); + if (!ret) + unlock_page(page); + else + CDEBUG(D_VFSTRACE, "page %lu add to page cache failed: rc = %d\n", + offset, ret); + put_page(page); + } + + if (page_pool != &page0) + kfree(page_pool); + + return rc; +} + +/** + * Read dir page from cache first, if it can not find it, read it from + * server and add into the cache. + * + * \param[in] exp MDC export + * \param[in] op_data client MD stack parameters, transferring parameters + * between different layers on client MD stack. + * \param[in] cb_op callback required for ldlm lock enqueue during + * read page + * \param[in] hash_offset the hash offset of the page to be read + * \param[in] ppage the page to be read + * + * retval = 0 get the page successfully + * errno(<0) get the page failed + */ +static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data, + struct md_callback *cb_op, __u64 hash_offset, + struct page **ppage) +{ + struct lookup_intent it = { .it_op = IT_READDIR }; + struct page *page; + struct inode *dir = op_data->op_data; + struct address_space *mapping; + struct lu_dirpage *dp; + __u64 start = 0; + __u64 end = 0; + struct lustre_handle lockh; + struct ptlrpc_request *enq_req = NULL; + struct readpage_param rp_param; + int rc; + + *ppage = NULL; + + LASSERT(dir); + mapping = dir->i_mapping; + + rc = mdc_intent_lock(exp, op_data, &it, &enq_req, + cb_op->md_blocking_ast, 0); + if (enq_req) + ptlrpc_req_finished(enq_req); + + if (rc < 0) { + CERROR("%s: "DFID" lock enqueue fails: rc = %d\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), rc); + return rc; + } + + rc = 0; + lockh.cookie = it.it_lock_handle; + mdc_set_lock_data(exp, &lockh, dir, NULL); + + rp_param.rp_off = hash_offset; + rp_param.rp_hash64 = op_data->op_cli_flags & CLI_HASH64; + page = mdc_page_locate(mapping, &rp_param.rp_off, &start, &end, + rp_param.rp_hash64); + if (IS_ERR(page)) { + CDEBUG(D_INFO, "%s: dir page locate: " DFID " at %llu: rc %ld\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), + rp_param.rp_off, PTR_ERR(page)); + rc = PTR_ERR(page); + goto out_unlock; + } else if (page) { + /* + * XXX nikita: not entirely correct handling of a corner case: + * suppose hash chain of entries with hash value HASH crosses + * border between pages P0 and P1. First both P0 and P1 are + * cached, seekdir() is called for some entry from the P0 part + * of the chain. Later P0 goes out of cache. telldir(HASH) + * happens and finds P1, as it starts with matching hash + * value. Remaining entries from P0 part of the chain are + * skipped. (Is that really a bug?) + * + * Possible solutions: 0. don't cache P1 is such case, handle + * it as an "overflow" page. 1. invalidate all pages at + * once. 2. use HASH|1 as an index for P1. + */ + goto hash_collision; + } + + rp_param.rp_exp = exp; + rp_param.rp_mod = op_data; + page = read_cache_page(mapping, + hash_x_index(rp_param.rp_off, + rp_param.rp_hash64), + mdc_read_page_remote, &rp_param); + if (IS_ERR(page)) { + CERROR("%s: read cache page: "DFID" at %llu: rc %ld\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), + rp_param.rp_off, PTR_ERR(page)); + rc = PTR_ERR(page); + goto out_unlock; + } + + wait_on_page_locked(page); + (void)kmap(page); + if (!PageUptodate(page)) { + CERROR("%s: page not updated: "DFID" at %llu: rc %d\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), + rp_param.rp_off, -5); + goto fail; + } + if (!PageChecked(page)) + SetPageChecked(page); + if (PageError(page)) { + CERROR("%s: page error: "DFID" at %llu: rc %d\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), + rp_param.rp_off, -5); + goto fail; + } + +hash_collision: + dp = page_address(page); + if (BITS_PER_LONG == 32 && rp_param.rp_hash64) { + start = le64_to_cpu(dp->ldp_hash_start) >> 32; + end = le64_to_cpu(dp->ldp_hash_end) >> 32; + rp_param.rp_off = hash_offset >> 32; + } else { + start = le64_to_cpu(dp->ldp_hash_start); + end = le64_to_cpu(dp->ldp_hash_end); + rp_param.rp_off = hash_offset; + } + if (end == start) { + LASSERT(start == rp_param.rp_off); + CWARN("Page-wide hash collision: %#lx\n", (unsigned long)end); +#if BITS_PER_LONG == 32 + CWARN("Real page-wide hash collision at [%llu %llu] with hash %llu\n", + le64_to_cpu(dp->ldp_hash_start), + le64_to_cpu(dp->ldp_hash_end), hash_offset); +#endif + /* + * Fetch whole overflow chain... + * + * XXX not yet. + */ + goto fail; + } + *ppage = page; +out_unlock: + ldlm_lock_decref(&lockh, it.it_lock_mode); + return rc; +fail: + kunmap(page); + mdc_release_page(page, 1); + rc = -EIO; + goto out_unlock; +} + static int mdc_statfs(const struct lu_env *env, struct obd_export *exp, struct obd_statfs *osfs, __u64 max_age, __u32 flags) @@ -1401,7 +1842,7 @@ out: return rc; } -static struct kuc_hdr *changelog_kuc_hdr(char *buf, int len, int flags) +static struct kuc_hdr *changelog_kuc_hdr(char *buf, size_t len, u32 flags) { struct kuc_hdr *lh = (struct kuc_hdr *)buf; @@ -1415,40 +1856,44 @@ static struct kuc_hdr *changelog_kuc_hdr(char *buf, int len, int flags) return lh; } -#define D_CHANGELOG 0 - struct changelog_show { __u64 cs_startrec; - __u32 cs_flags; + enum changelog_send_flag cs_flags; struct file *cs_fp; char *cs_buf; struct obd_device *cs_obd; }; +static inline char *cs_obd_name(struct changelog_show *cs) +{ + return cs->cs_obd->obd_name; +} + static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, struct llog_rec_hdr *hdr, void *data) { struct changelog_show *cs = data; struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr; struct kuc_hdr *lh; - int len, rc; + size_t len; + int rc; if (rec->cr_hdr.lrh_type != CHANGELOG_REC) { rc = -EINVAL; CERROR("%s: not a changelog rec %x/%d: rc = %d\n", - cs->cs_obd->obd_name, rec->cr_hdr.lrh_type, + cs_obd_name(cs), rec->cr_hdr.lrh_type, rec->cr.cr_type, rc); return rc; } if (rec->cr.cr_index < cs->cs_startrec) { /* Skip entries earlier than what we are interested in */ - CDEBUG(D_CHANGELOG, "rec=%llu start=%llu\n", + CDEBUG(D_HSM, "rec=%llu start=%llu\n", rec->cr.cr_index, cs->cs_startrec); return 0; } - CDEBUG(D_CHANGELOG, "%llu %02d%-5s %llu 0x%x t="DFID" p="DFID + CDEBUG(D_HSM, "%llu %02d%-5s %llu 0x%x t=" DFID " p=" DFID " %.*s\n", rec->cr.cr_index, rec->cr.cr_type, changelog_type2str(rec->cr.cr_type), rec->cr.cr_time, rec->cr.cr_flags & CLF_FLAGMASK, @@ -1462,20 +1907,21 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, memcpy(lh + 1, &rec->cr, len - sizeof(*lh)); rc = libcfs_kkuc_msg_put(cs->cs_fp, lh); - CDEBUG(D_CHANGELOG, "kucmsg fp %p len %d rc %d\n", cs->cs_fp, len, rc); + CDEBUG(D_HSM, "kucmsg fp %p len %zu rc %d\n", cs->cs_fp, len, rc); return rc; } static int mdc_changelog_send_thread(void *csdata) { + enum llog_flag flags = LLOG_F_IS_CAT; struct changelog_show *cs = csdata; struct llog_ctxt *ctxt = NULL; struct llog_handle *llh = NULL; struct kuc_hdr *kuch; int rc; - CDEBUG(D_CHANGELOG, "changelog to fp=%p start %llu\n", + CDEBUG(D_HSM, "changelog to fp=%p start %llu\n", cs->cs_fp, cs->cs_startrec); cs->cs_buf = kzalloc(KUC_CHANGELOG_MSG_MAXSIZE, GFP_NOFS); @@ -1494,10 +1940,14 @@ static int mdc_changelog_send_thread(void *csdata) LLOG_OPEN_EXISTS); if (rc) { CERROR("%s: fail to open changelog catalog: rc = %d\n", - cs->cs_obd->obd_name, rc); + cs_obd_name(cs), rc); goto out; } - rc = llog_init_handle(NULL, llh, LLOG_F_IS_CAT, NULL); + + if (cs->cs_flags & CHANGELOG_FLAG_JOBID) + flags |= LLOG_F_EXT_JOBID; + + rc = llog_init_handle(NULL, llh, flags, NULL); if (rc) { CERROR("llog_init_handle failed %d\n", rc); goto out; @@ -1550,12 +2000,12 @@ static int mdc_ioc_changelog_send(struct obd_device *obd, if (IS_ERR(task)) { rc = PTR_ERR(task); CERROR("%s: can't start changelog thread: rc = %d\n", - obd->obd_name, rc); + cs_obd_name(cs), rc); kfree(cs); } else { rc = 0; - CDEBUG(D_CHANGELOG, "%s: started changelog thread\n", - obd->obd_name); + CDEBUG(D_HSM, "%s: started changelog thread\n", + cs_obd_name(cs)); } CERROR("Failed to start changelog thread: %d\n", rc); @@ -1669,9 +2119,11 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp, * with the request RPC to avoid extra RPC round trips */ count = mdc_resource_get_unused(exp, &op_data->op_fid1, &cancels, - LCK_CR, MDS_INODELOCK_LAYOUT); + LCK_CR, MDS_INODELOCK_LAYOUT | + MDS_INODELOCK_XATTR); count += mdc_resource_get_unused(exp, &op_data->op_fid2, &cancels, - LCK_CR, MDS_INODELOCK_LAYOUT); + LCK_CR, MDS_INODELOCK_LAYOUT | + MDS_INODELOCK_XATTR); req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_SWAP_LAYOUTS); @@ -1917,7 +2369,7 @@ static void lustre_swab_hai(struct hsm_action_item *h) static void lustre_swab_hal(struct hsm_action_list *h) { struct hsm_action_item *hai; - int i; + u32 i; __swab32s(&h->hal_version); __swab32s(&h->hal_count); @@ -1966,14 +2418,14 @@ static int mdc_ioc_hsm_ct_start(struct obd_export *exp, * @param val KUC message (kuc_hdr + hsm_action_list) * @param len total length of message */ -static int mdc_hsm_copytool_send(int len, void *val) +static int mdc_hsm_copytool_send(size_t len, void *val) { struct kuc_hdr *lh = (struct kuc_hdr *)val; struct hsm_action_list *hal = (struct hsm_action_list *)(lh + 1); if (len < sizeof(*lh) + sizeof(*hal)) { - CERROR("Short HSM message %d < %d\n", len, - (int)(sizeof(*lh) + sizeof(*hal))); + CERROR("Short HSM message %zu < %zu\n", len, + sizeof(*lh) + sizeof(*hal)); return -EPROTO; } if (lh->kuc_magic == __swab16(KUC_MAGIC)) { @@ -2044,9 +2496,8 @@ static int mdc_set_info_async(const struct lu_env *env, } spin_unlock(&imp->imp_lock); - rc = do_set_info_async(imp, MDS_SET_INFO, LUSTRE_MDS_VERSION, - keylen, key, vallen, val, set); - return rc; + return do_set_info_async(imp, MDS_SET_INFO, LUSTRE_MDS_VERSION, + keylen, key, vallen, val, set); } if (KEY_IS(KEY_SPTLRPC_CONF)) { sptlrpc_conf_client_adapt(exp->exp_obd); @@ -2065,6 +2516,12 @@ static int mdc_set_info_async(const struct lu_env *env, rc = mdc_hsm_copytool_send(vallen, val); return rc; } + if (KEY_IS(KEY_DEFAULT_EASIZE)) { + u32 *default_easize = val; + + exp->exp_obd->u.cli.cl_default_mds_easize = *default_easize; + return 0; + } CERROR("Unknown key %s\n", (char *)key); return -EINVAL; @@ -2077,18 +2534,18 @@ static int mdc_get_info(const struct lu_env *env, struct obd_export *exp, int rc = -EINVAL; if (KEY_IS(KEY_MAX_EASIZE)) { - int mdsize, *max_easize; + u32 mdsize, *max_easize; if (*vallen != sizeof(int)) return -EINVAL; - mdsize = *(int *)val; + mdsize = *(u32 *)val; if (mdsize > exp->exp_obd->u.cli.cl_max_mds_easize) exp->exp_obd->u.cli.cl_max_mds_easize = mdsize; max_easize = val; *max_easize = exp->exp_obd->u.cli.cl_max_mds_easize; return 0; } else if (KEY_IS(KEY_DEFAULT_EASIZE)) { - int *default_easize; + u32 *default_easize; if (*vallen != sizeof(int)) return -EINVAL; @@ -2105,7 +2562,7 @@ static int mdc_get_info(const struct lu_env *env, struct obd_export *exp, *data = imp->imp_connect_data; return 0; } else if (KEY_IS(KEY_TGT_COUNT)) { - *((int *)val) = 1; + *((u32 *)val) = 1; return 0; } @@ -2199,13 +2656,13 @@ static int mdc_import_event(struct obd_device *obd, struct obd_import *imp, return rc; } -int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data) +int mdc_fid_alloc(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data) { struct client_obd *cli = &exp->exp_obd->u.cli; struct lu_client_seq *seq = cli->cl_seq; - return seq_client_alloc_fid(NULL, seq, fid); + return seq_client_alloc_fid(env, seq, fid); } static struct obd_uuid *mdc_get_uuid(struct obd_export *exp) @@ -2333,8 +2790,8 @@ err_rpc_lock: * a large number of stripes is possible. If a larger reply buffer is * required it will be reallocated in the ptlrpc layer due to overflow. */ -static int mdc_init_ea_size(struct obd_export *exp, int easize, - int def_easize, int cookiesize, int def_cookiesize) +static int mdc_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, + u32 cookiesize, u32 def_cookiesize) { struct obd_device *obd = exp->exp_obd; struct client_obd *cli = &obd->u.cli; @@ -2430,7 +2887,6 @@ static struct obd_ops mdc_obd_ops = { static struct md_ops mdc_md_ops = { .getstatus = mdc_getstatus, .null_inode = mdc_null_inode, - .find_cbdata = mdc_find_cbdata, .close = mdc_close, .create = mdc_create, .done_writing = mdc_done_writing, @@ -2439,13 +2895,12 @@ static struct md_ops mdc_md_ops = { .getattr_name = mdc_getattr_name, .intent_lock = mdc_intent_lock, .link = mdc_link, - .is_subdir = mdc_is_subdir, .rename = mdc_rename, .setattr = mdc_setattr, .setxattr = mdc_setxattr, .getxattr = mdc_getxattr, .sync = mdc_sync, - .readpage = mdc_readpage, + .read_page = mdc_read_page, .unlink = mdc_unlink, .cancel_unused = mdc_cancel_unused, .init_ea_size = mdc_init_ea_size, diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 9d0bd4745865..23374cae5133 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -549,8 +549,9 @@ static int mgc_requeue_thread(void *data) * caused the lock revocation to finish its setup, plus some * random so everyone doesn't try to reconnect at once. */ - to = MGC_TIMEOUT_MIN_SECONDS * HZ; - to += rand * HZ / 100; /* rand is centi-seconds */ + to = msecs_to_jiffies(MGC_TIMEOUT_MIN_SECONDS * MSEC_PER_SEC); + /* rand is centi-seconds */ + to += msecs_to_jiffies(rand * MSEC_PER_SEC / 100); lwi = LWI_TIMEOUT(to, NULL, NULL); l_wait_event(rq_waitq, rq_state & (RQ_STOP | RQ_PRECLEANUP), &lwi); @@ -1158,7 +1159,7 @@ static int mgc_apply_recover_logs(struct obd_device *mgc, while (datalen > 0) { int entry_len = sizeof(*entry); - int is_ost; + int is_ost, i; struct obd_device *obd; char *obdname; char *cname; @@ -1264,11 +1265,17 @@ static int mgc_apply_recover_logs(struct obd_device *mgc, continue; } - /* TODO: iterate all nids to find one */ + /* iterate all nids to find one */ /* find uuid by nid */ - rc = client_import_find_conn(obd->u.cli.cl_import, - entry->u.nids[0], - (struct obd_uuid *)uuid); + rc = -ENOENT; + for (i = 0; i < entry->mne_nid_count; i++) { + rc = client_import_find_conn(obd->u.cli.cl_import, + entry->u.nids[0], + (struct obd_uuid *)uuid); + if (!rc) + break; + } + up_read(&obd->u.cli.cl_sem); if (rc < 0) { CERROR("mgc: cannot find uuid by nid %s\n", @@ -1428,14 +1435,12 @@ again: } mne_swab = !!ptlrpc_rep_need_swab(req); -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 2, 50, 0) +#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE /* This import flag means the server did an extra swab of IR MNE * records (fixed in LU-1252), reverse it here if needed. LU-1644 */ if (unlikely(req->rq_import->imp_need_mne_swab)) mne_swab = !mne_swab; -#else -#warning "LU-1644: Remove old OBD_CONNECT_MNE_SWAB fixup and imp_need_mne_swab" #endif for (i = 0; i < nrpages && ealen > 0; i++) { @@ -1740,8 +1745,6 @@ static struct obd_ops mgc_obd_ops = { .del_conn = client_import_del_conn, .connect = client_connect_import, .disconnect = client_disconnect_export, - /* .enqueue = mgc_enqueue, */ - /* .iocontrol = mgc_iocontrol, */ .set_info_async = mgc_set_info_async, .get_info = mgc_get_info, .import_event = mgc_import_event, diff --git a/drivers/staging/lustre/lustre/obdclass/Makefile b/drivers/staging/lustre/lustre/obdclass/Makefile index df7e47f35a66..b42e109b30e0 100644 --- a/drivers/staging/lustre/lustre/obdclass/Makefile +++ b/drivers/staging/lustre/lustre/obdclass/Makefile @@ -3,6 +3,6 @@ obj-$(CONFIG_LUSTRE_FS) += obdclass.o obdclass-y := linux/linux-module.o linux/linux-obdo.o linux/linux-sysctl.o \ llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \ genops.o uuid.o lprocfs_status.o lprocfs_counters.o \ - lustre_handles.o lustre_peer.o statfs_pack.o \ + lustre_handles.o lustre_peer.o statfs_pack.o linkea.o \ obdo.o obd_config.o obd_mount.o lu_object.o lu_ref.o \ cl_object.o cl_page.o cl_lock.o cl_io.o kernelcomm.o diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index e72f1fc00a13..bc4b7b6b9a20 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -73,7 +73,6 @@ int cl_io_is_going(const struct lu_env *env) { return cl_env_info(env)->clt_current_io != NULL; } -EXPORT_SYMBOL(cl_io_is_going); /** * cl_io invariant that holds at all times when exported cl_io_*() functions @@ -859,9 +858,6 @@ void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page) LASSERT(page->cp_owner); LINVRNT(plist->pl_owner == current); - lockdep_off(); - mutex_lock(&page->cp_mutex); - lockdep_on(); LASSERT(list_empty(&page->cp_batch)); list_add_tail(&page->cp_batch, &plist->pl_pages); ++plist->pl_nr; @@ -877,12 +873,10 @@ void cl_page_list_del(const struct lu_env *env, struct cl_page_list *plist, struct cl_page *page) { LASSERT(plist->pl_nr > 0); + LASSERT(cl_page_is_vmlocked(env, page)); LINVRNT(plist->pl_owner == current); list_del_init(&page->cp_batch); - lockdep_off(); - mutex_unlock(&page->cp_mutex); - lockdep_on(); --plist->pl_nr; lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist); cl_page_put(env, page); @@ -941,8 +935,6 @@ void cl_page_list_splice(struct cl_page_list *list, struct cl_page_list *head) } EXPORT_SYMBOL(cl_page_list_splice); -void cl_page_disown0(const struct lu_env *env, - struct cl_io *io, struct cl_page *pg); /** * Disowns pages in a queue. @@ -959,9 +951,6 @@ void cl_page_list_disown(const struct lu_env *env, LASSERT(plist->pl_nr > 0); list_del_init(&page->cp_batch); - lockdep_off(); - mutex_unlock(&page->cp_mutex); - lockdep_on(); --plist->pl_nr; /* * cl_page_disown0 rather than usual cl_page_disown() is used, @@ -1221,7 +1210,7 @@ void cl_req_page_add(const struct lu_env *env, { struct cl_object *obj; struct cl_req_obj *rqo; - int i; + unsigned int i; LASSERT(list_empty(&page->cp_flight)); LASSERT(!page->cp_req); @@ -1268,7 +1257,7 @@ EXPORT_SYMBOL(cl_req_page_done); */ int cl_req_prep(const struct lu_env *env, struct cl_req *req) { - int i; + unsigned int i; int result; const struct cl_req_slice *slice; @@ -1301,7 +1290,7 @@ void cl_req_attr_set(const struct lu_env *env, struct cl_req *req, { const struct cl_req_slice *slice; struct cl_page *page; - int i; + unsigned int i; LASSERT(!list_empty(&req->crq_pages)); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 91a5806d0239..3199dd4a3b72 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -163,7 +163,7 @@ static spinlock_t *cl_object_attr_guard(struct cl_object *o) * * Prevents data-attributes from changing, until lock is released by * cl_object_attr_unlock(). This has to be called before calls to - * cl_object_attr_get(), cl_object_attr_set(). + * cl_object_attr_get(), cl_object_attr_update(). */ void cl_object_attr_lock(struct cl_object *o) __acquires(cl_object_attr_guard(o)) @@ -217,11 +217,11 @@ EXPORT_SYMBOL(cl_object_attr_get); * Updates data-attributes of an object \a obj. * * Only attributes, mentioned in a validness bit-mask \a v are - * updated. Calls cl_object_operations::coo_attr_set() on every layer, bottom - * to top. + * updated. Calls cl_object_operations::coo_attr_update() on every layer, + * bottom to top. */ -int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned v) +int cl_object_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int v) { struct lu_object_header *top; int result; @@ -231,8 +231,9 @@ int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, top = obj->co_lu.lo_header; result = 0; list_for_each_entry_reverse(obj, &top->loh_layers, co_lu.lo_linkage) { - if (obj->co_ops->coo_attr_set) { - result = obj->co_ops->coo_attr_set(env, obj, attr, v); + if (obj->co_ops->coo_attr_update) { + result = obj->co_ops->coo_attr_update(env, obj, attr, + v); if (result != 0) { if (result > 0) result = 0; @@ -242,7 +243,7 @@ int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, } return result; } -EXPORT_SYMBOL(cl_object_attr_set); +EXPORT_SYMBOL(cl_object_attr_update); /** * Notifies layers (bottom-to-top) that glimpse AST was received. @@ -320,6 +321,27 @@ int cl_object_prune(const struct lu_env *env, struct cl_object *obj) } EXPORT_SYMBOL(cl_object_prune); +/** + * Get stripe information of this object. + */ +int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, + struct lov_user_md __user *uarg) +{ + struct lu_object_header *top; + int result = 0; + + top = obj->co_lu.lo_header; + list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) { + if (obj->co_ops->coo_getstripe) { + result = obj->co_ops->coo_getstripe(env, obj, uarg); + if (result) + break; + } + } + return result; +} +EXPORT_SYMBOL(cl_object_getstripe); + /** * Helper function removing all object locks, and marking object for * deletion. All object pages must have been deleted at this point. @@ -377,7 +399,7 @@ static void cl_env_percpu_refill(void); */ int cl_site_init(struct cl_site *s, struct cl_device *d) { - int i; + size_t i; int result; result = lu_site_init(&s->cs_lu, &d->cd_lu_dev); @@ -411,7 +433,7 @@ static struct cache_stats cl_env_stats = { */ int cl_site_stats_print(const struct cl_site *site, struct seq_file *m) { - int i; + size_t i; static const char *pstate[] = { [CPS_CACHED] = "c", [CPS_OWNED] = "o", @@ -1000,7 +1022,7 @@ static int cl_env_percpu_init(void) * thus we must uninitialize up to i, the rest are undefined. */ for (j = 0; j < i; j++) { - cle = &cl_env_percpu[i]; + cle = &cl_env_percpu[j]; lu_context_exit(&cle->ce_ses); lu_context_fini(&cle->ce_ses); lu_env_fini(&cle->ce_lu); @@ -1126,7 +1148,7 @@ static void *cl_key_init(const struct lu_context *ctx, info = cl0_key_init(ctx, key); if (!IS_ERR(info)) { - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(info->clt_counters); ++i) lu_ref_init(&info->clt_counters[i].ctc_locks_locked); @@ -1138,7 +1160,7 @@ static void cl_key_fini(const struct lu_context *ctx, struct lu_context_key *key, void *data) { struct cl_thread_info *info; - int i; + size_t i; info = data; for (i = 0; i < ARRAY_SIZE(info->clt_counters); ++i) @@ -1150,7 +1172,7 @@ static void cl_key_exit(const struct lu_context *ctx, struct lu_context_key *key, void *data) { struct cl_thread_info *info = data; - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(info->clt_counters); ++i) { LASSERT(info->clt_counters[i].ctc_nr_held == 0); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index db2dc6b39073..63973ba096da 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -151,7 +151,6 @@ struct cl_page *cl_page_alloc(const struct lu_env *env, INIT_LIST_HEAD(&page->cp_layers); INIT_LIST_HEAD(&page->cp_batch); INIT_LIST_HEAD(&page->cp_flight); - mutex_init(&page->cp_mutex); lu_ref_init(&page->cp_reference); head = o->co_lu.lo_header; list_for_each_entry(o, &head->loh_layers, co_lu.lo_linkage) { @@ -171,7 +170,6 @@ struct cl_page *cl_page_alloc(const struct lu_env *env, } return page; } -EXPORT_SYMBOL(cl_page_alloc); /** * Returns a cl_page with index \a idx at the object \a o, and associated with @@ -229,11 +227,6 @@ EXPORT_SYMBOL(cl_page_find); static inline int cl_page_invariant(const struct cl_page *pg) { - /* - * Page invariant is protected by a VM lock. - */ - LINVRNT(cl_page_is_vmlocked(NULL, pg)); - return cl_page_in_use_noref(pg); } @@ -478,7 +471,6 @@ static void cl_page_owner_clear(struct cl_page *page) LASSERT(page->cp_owner->ci_owned_nr > 0); page->cp_owner->ci_owned_nr--; page->cp_owner = NULL; - page->cp_task = NULL; } } @@ -562,7 +554,6 @@ static int cl_page_own0(const struct lu_env *env, struct cl_io *io, PASSERT(env, pg, !pg->cp_owner); PASSERT(env, pg, !pg->cp_req); pg->cp_owner = cl_io_top(io); - pg->cp_task = current; cl_page_owner_set(pg); if (pg->cp_state != CPS_FREEING) { cl_page_state_set(env, pg, CPS_OWNED); @@ -619,7 +610,6 @@ void cl_page_assume(const struct lu_env *env, cl_page_invoid(env, io, pg, CL_PAGE_OP(cpo_assume)); PASSERT(env, pg, !pg->cp_owner); pg->cp_owner = cl_io_top(io); - pg->cp_task = current; cl_page_owner_set(pg); cl_page_state_set(env, pg, CPS_OWNED); } @@ -860,10 +850,6 @@ void cl_page_completion(const struct lu_env *env, PASSERT(env, pg, pg->cp_state == cl_req_type_state(crt)); CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, ioret); - if (crt == CRT_READ && ioret == 0) { - PASSERT(env, pg, !(pg->cp_flags & CPF_READ_COMPLETED)); - pg->cp_flags |= CPF_READ_COMPLETED; - } cl_page_state_set(env, pg, CPS_CACHED); if (crt >= CRT_NR) @@ -872,7 +858,6 @@ void cl_page_completion(const struct lu_env *env, (const struct lu_env *, const struct cl_page_slice *, int), ioret); if (anchor) { - LASSERT(cl_page_is_vmlocked(env, pg)); LASSERT(pg->cp_sync_io == anchor); pg->cp_sync_io = NULL; } @@ -989,10 +974,10 @@ void cl_page_header_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_page *pg) { (*printer)(env, cookie, - "page@%p[%d %p %d %d %d %p %p %#x]\n", + "page@%p[%d %p %d %d %p %p]\n", pg, atomic_read(&pg->cp_ref), pg->cp_obj, - pg->cp_state, pg->cp_error, pg->cp_type, - pg->cp_owner, pg->cp_req, pg->cp_flags); + pg->cp_state, pg->cp_type, + pg->cp_owner, pg->cp_req); } EXPORT_SYMBOL(cl_page_header_print); @@ -1020,7 +1005,6 @@ int cl_page_cancel(const struct lu_env *env, struct cl_page *page) (const struct lu_env *, const struct cl_page_slice *)); } -EXPORT_SYMBOL(cl_page_cancel); /** * Converts a byte offset within object \a obj into a page index. @@ -1046,9 +1030,9 @@ pgoff_t cl_index(const struct cl_object *obj, loff_t offset) } EXPORT_SYMBOL(cl_index); -int cl_page_size(const struct cl_object *obj) +size_t cl_page_size(const struct cl_object *obj) { - return 1 << PAGE_SHIFT; + return 1UL << PAGE_SHIFT; } EXPORT_SYMBOL(cl_page_size); @@ -1087,11 +1071,11 @@ struct cl_client_cache *cl_cache_init(unsigned long lru_page_max) /* Initialize cache data */ atomic_set(&cache->ccc_users, 1); cache->ccc_lru_max = lru_page_max; - atomic_set(&cache->ccc_lru_left, lru_page_max); + atomic_long_set(&cache->ccc_lru_left, lru_page_max); spin_lock_init(&cache->ccc_lru_lock); INIT_LIST_HEAD(&cache->ccc_lru); - atomic_set(&cache->ccc_unstable_nr, 0); + atomic_long_set(&cache->ccc_unstable_nr, 0); init_waitqueue_head(&cache->ccc_unstable_waitq); return cache; diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index d9d2a1952b8b..76e1ee83a723 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -40,10 +40,10 @@ #include "../include/lprocfs_status.h" #include #include "../include/cl_object.h" +#include "../include/lustre/lustre_ioctl.h" #include "llog_internal.h" struct obd_device *obd_devs[MAX_OBD_DEVICES]; -EXPORT_SYMBOL(obd_devs); struct list_head obd_types; DEFINE_RWLOCK(obd_dev_lock); @@ -54,11 +54,9 @@ unsigned int obd_dump_on_timeout; EXPORT_SYMBOL(obd_dump_on_timeout); unsigned int obd_dump_on_eviction; EXPORT_SYMBOL(obd_dump_on_eviction); -unsigned int obd_max_dirty_pages = 256; +unsigned long obd_max_dirty_pages; EXPORT_SYMBOL(obd_max_dirty_pages); -atomic_t obd_unstable_pages; -EXPORT_SYMBOL(obd_unstable_pages); -atomic_t obd_dirty_pages; +atomic_long_t obd_dirty_pages; EXPORT_SYMBOL(obd_dirty_pages); unsigned int obd_timeout = OBD_TIMEOUT_DEFAULT; /* seconds */ EXPORT_SYMBOL(obd_timeout); @@ -76,13 +74,11 @@ EXPORT_SYMBOL(at_early_margin); int at_extra = 30; EXPORT_SYMBOL(at_extra); -atomic_t obd_dirty_transit_pages; +atomic_long_t obd_dirty_transit_pages; EXPORT_SYMBOL(obd_dirty_transit_pages); char obd_jobid_var[JOBSTATS_JOBID_VAR_MAX_LEN + 1] = JOBSTATS_DISABLE; -EXPORT_SYMBOL(obd_jobid_var); - -char obd_jobid_node[JOBSTATS_JOBID_SIZE + 1]; +char obd_jobid_node[LUSTRE_JOBID_SIZE + 1]; /* Get jobid of current process from stored variable or calculate * it from pid and user_id. @@ -93,14 +89,14 @@ char obd_jobid_node[JOBSTATS_JOBID_SIZE + 1]; */ int lustre_get_jobid(char *jobid) { - memset(jobid, 0, JOBSTATS_JOBID_SIZE); + memset(jobid, 0, LUSTRE_JOBID_SIZE); /* Jobstats isn't enabled */ if (strcmp(obd_jobid_var, JOBSTATS_DISABLE) == 0) return 0; /* Use process name + fsuid as jobid */ if (strcmp(obd_jobid_var, JOBSTATS_PROCNAME_UID) == 0) { - snprintf(jobid, JOBSTATS_JOBID_SIZE, "%s.%u", + snprintf(jobid, LUSTRE_JOBID_SIZE, "%s.%u", current_comm(), from_kuid(&init_user_ns, current_fsuid())); return 0; @@ -116,19 +112,6 @@ int lustre_get_jobid(char *jobid) } EXPORT_SYMBOL(lustre_get_jobid); -static inline void obd_data2conn(struct lustre_handle *conn, - struct obd_ioctl_data *data) -{ - memset(conn, 0, sizeof(*conn)); - conn->cookie = data->ioc_cookie; -} - -static inline void obd_conn2data(struct obd_ioctl_data *data, - struct lustre_handle *conn) -{ - data->ioc_cookie = conn->cookie; -} - static int class_resolve_dev_name(__u32 len, const char *name) { int rc; @@ -287,13 +270,6 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) goto out; } - case OBD_IOC_CLOSE_UUID: { - CDEBUG(D_IOCTL, "closing all connections to uuid %s (NOOP)\n", - data->ioc_inlbuf1); - err = 0; - goto out; - } - case OBD_IOC_GETDEVICE: { int index = data->ioc_count; char *status, *str; @@ -467,15 +443,10 @@ static int obd_init_checks(void) return ret; } -extern int class_procfs_init(void); -extern int class_procfs_clean(void); - static int __init obdclass_init(void) { int i, err; - int lustre_register_fs(void); - LCONSOLE_INFO("Lustre: Build Version: " LUSTRE_VERSION_STRING "\n"); spin_lock_init(&obd_types_lock); @@ -542,23 +513,9 @@ static int __init obdclass_init(void) static void obdclass_exit(void) { - int i; - - int lustre_unregister_fs(void); - lustre_unregister_fs(); misc_deregister(&obd_psdev); - for (i = 0; i < class_devno_max(); i++) { - struct obd_device *obd = class_num2obd(i); - - if (obd && obd->obd_set_up && - OBT(obd) && OBP(obd, detach)) { - /* XXX should this call generic detach otherwise? */ - LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); - OBP(obd, detach)(obd); - } - } llog_info_fini(); cl_global_fini(); lu_global_fini(); diff --git a/drivers/staging/lustre/lustre/obdclass/debug.c b/drivers/staging/lustre/lustre/obdclass/debug.c index 8acf67239fa8..0bd4ad20aba7 100644 --- a/drivers/staging/lustre/lustre/obdclass/debug.c +++ b/drivers/staging/lustre/lustre/obdclass/debug.c @@ -48,10 +48,10 @@ int block_debug_setup(void *addr, int len, __u64 off, __u64 id) LASSERT(addr); put_unaligned_le64(off, addr); - put_unaligned_le64(id, addr+LPDS); + put_unaligned_le64(id, addr + LPDS); addr += len - LPDS - LPDS; put_unaligned_le64(off, addr); - put_unaligned_le64(id, addr+LPDS); + put_unaligned_le64(id, addr + LPDS); return 0; } diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 99c2da632b51..cf8bb2a2f40b 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -133,7 +133,6 @@ void class_put_type(struct obd_type *type) module_put(type->typ_dt_ops->owner); spin_unlock(&type->obd_type_lock); } -EXPORT_SYMBOL(class_put_type); #define CLASS_MAX_NAME 1024 @@ -166,10 +165,10 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, !type->typ_name) goto failed; - *(type->typ_dt_ops) = *dt_ops; + *type->typ_dt_ops = *dt_ops; /* md_ops is optional */ if (md_ops) - *(type->typ_md_ops) = *md_ops; + *type->typ_md_ops = *md_ops; strcpy(type->typ_name, name); spin_lock_init(&type->obd_type_lock); @@ -391,7 +390,6 @@ int class_name2dev(const char *name) return -1; } -EXPORT_SYMBOL(class_name2dev); struct obd_device *class_name2obd(const char *name) { @@ -421,7 +419,6 @@ int class_uuid2dev(struct obd_uuid *uuid) return -1; } -EXPORT_SYMBOL(class_uuid2dev); /** * Get obd device from ::obd_devs[] @@ -450,7 +447,6 @@ struct obd_device *class_num2obd(int num) return obd; } -EXPORT_SYMBOL(class_num2obd); /* Search for a client OBD connected to tgt_uuid. If grp_uuid is * specified, then only the client with that uuid is returned, @@ -509,7 +505,7 @@ struct obd_device *class_devices_in_group(struct obd_uuid *grp_uuid, int *next) continue; if (obd_uuid_equals(grp_uuid, &obd->obd_uuid)) { if (next) - *next = i+1; + *next = i + 1; read_unlock(&obd_dev_lock); return obd; } @@ -618,7 +614,7 @@ struct obd_export *class_conn2export(struct lustre_handle *conn) } CDEBUG(D_INFO, "looking for export cookie %#llx\n", conn->cookie); - export = class_handle2object(conn->cookie); + export = class_handle2object(conn->cookie, NULL); return export; } EXPORT_SYMBOL(class_conn2export); @@ -817,7 +813,6 @@ void class_unlink_export(struct obd_export *exp) spin_unlock(&exp->exp_obd->obd_dev_lock); class_export_put(exp); } -EXPORT_SYMBOL(class_unlink_export); /* Import management functions */ static void class_import_destroy(struct obd_import *imp) @@ -973,7 +968,6 @@ void __class_export_add_lock_ref(struct obd_export *exp, struct ldlm_lock *lock) lock, exp, lock->l_exp_refs_nr); spin_unlock(&exp->exp_locks_list_guard); } -EXPORT_SYMBOL(__class_export_add_lock_ref); void __class_export_del_lock_ref(struct obd_export *exp, struct ldlm_lock *lock) { @@ -991,7 +985,6 @@ void __class_export_del_lock_ref(struct obd_export *exp, struct ldlm_lock *lock) lock, exp, lock->l_exp_refs_nr); spin_unlock(&exp->exp_locks_list_guard); } -EXPORT_SYMBOL(__class_export_del_lock_ref); #endif /* A connection defines an export context in which preallocation can @@ -1100,7 +1093,6 @@ EXPORT_SYMBOL(class_fail_export); #if LUSTRE_TRACKS_LOCK_EXP_REFS void (*class_export_dump_hook)(struct obd_export *) = NULL; -EXPORT_SYMBOL(class_export_dump_hook); #endif /* Total amount of zombies to be destroyed */ @@ -1312,3 +1304,135 @@ void obd_zombie_impexp_stop(void) obd_zombie_impexp_notify(); wait_for_completion(&obd_zombie_stop); } + +struct obd_request_slot_waiter { + struct list_head orsw_entry; + wait_queue_head_t orsw_waitq; + bool orsw_signaled; +}; + +static bool obd_request_slot_avail(struct client_obd *cli, + struct obd_request_slot_waiter *orsw) +{ + bool avail; + + spin_lock(&cli->cl_loi_list_lock); + avail = !!list_empty(&orsw->orsw_entry); + spin_unlock(&cli->cl_loi_list_lock); + + return avail; +}; + +/* + * For network flow control, the RPC sponsor needs to acquire a credit + * before sending the RPC. The credits count for a connection is defined + * by the "cl_max_rpcs_in_flight". If all the credits are occpuied, then + * the subsequent RPC sponsors need to wait until others released their + * credits, or the administrator increased the "cl_max_rpcs_in_flight". + */ +int obd_get_request_slot(struct client_obd *cli) +{ + struct obd_request_slot_waiter orsw; + struct l_wait_info lwi; + int rc; + + spin_lock(&cli->cl_loi_list_lock); + if (cli->cl_r_in_flight < cli->cl_max_rpcs_in_flight) { + cli->cl_r_in_flight++; + spin_unlock(&cli->cl_loi_list_lock); + return 0; + } + + init_waitqueue_head(&orsw.orsw_waitq); + list_add_tail(&orsw.orsw_entry, &cli->cl_loi_read_list); + orsw.orsw_signaled = false; + spin_unlock(&cli->cl_loi_list_lock); + + lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); + rc = l_wait_event(orsw.orsw_waitq, + obd_request_slot_avail(cli, &orsw) || + orsw.orsw_signaled, + &lwi); + + /* + * Here, we must take the lock to avoid the on-stack 'orsw' to be + * freed but other (such as obd_put_request_slot) is using it. + */ + spin_lock(&cli->cl_loi_list_lock); + if (rc) { + if (!orsw.orsw_signaled) { + if (list_empty(&orsw.orsw_entry)) + cli->cl_r_in_flight--; + else + list_del(&orsw.orsw_entry); + } + } + + if (orsw.orsw_signaled) { + LASSERT(list_empty(&orsw.orsw_entry)); + + rc = -EINTR; + } + spin_unlock(&cli->cl_loi_list_lock); + + return rc; +} +EXPORT_SYMBOL(obd_get_request_slot); + +void obd_put_request_slot(struct client_obd *cli) +{ + struct obd_request_slot_waiter *orsw; + + spin_lock(&cli->cl_loi_list_lock); + cli->cl_r_in_flight--; + + /* If there is free slot, wakeup the first waiter. */ + if (!list_empty(&cli->cl_loi_read_list) && + likely(cli->cl_r_in_flight < cli->cl_max_rpcs_in_flight)) { + orsw = list_entry(cli->cl_loi_read_list.next, + struct obd_request_slot_waiter, orsw_entry); + list_del_init(&orsw->orsw_entry); + cli->cl_r_in_flight++; + wake_up(&orsw->orsw_waitq); + } + spin_unlock(&cli->cl_loi_list_lock); +} +EXPORT_SYMBOL(obd_put_request_slot); + +__u32 obd_get_max_rpcs_in_flight(struct client_obd *cli) +{ + return cli->cl_max_rpcs_in_flight; +} +EXPORT_SYMBOL(obd_get_max_rpcs_in_flight); + +int obd_set_max_rpcs_in_flight(struct client_obd *cli, __u32 max) +{ + struct obd_request_slot_waiter *orsw; + __u32 old; + int diff; + int i; + + if (max > OBD_MAX_RIF_MAX || max < 1) + return -ERANGE; + + spin_lock(&cli->cl_loi_list_lock); + old = cli->cl_max_rpcs_in_flight; + cli->cl_max_rpcs_in_flight = max; + diff = max - old; + + /* We increase the max_rpcs_in_flight, then wakeup some waiters. */ + for (i = 0; i < diff; i++) { + if (list_empty(&cli->cl_loi_read_list)) + break; + + orsw = list_entry(cli->cl_loi_read_list.next, + struct obd_request_slot_waiter, orsw_entry); + list_del_init(&orsw->orsw_entry); + cli->cl_r_in_flight++; + wake_up(&orsw->orsw_waitq); + } + spin_unlock(&cli->cl_loi_list_lock); + + return 0; +} +EXPORT_SYMBOL(obd_set_max_rpcs_in_flight); diff --git a/drivers/staging/lustre/lustre/obdclass/linkea.c b/drivers/staging/lustre/lustre/obdclass/linkea.c new file mode 100644 index 000000000000..0b1d2f0a422c --- /dev/null +++ b/drivers/staging/lustre/lustre/obdclass/linkea.c @@ -0,0 +1,201 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2013, 2014, Intel Corporation. + * Use is subject to license terms. + * + * Author: Di Wang + */ + +#include "../include/lustre/lustre_idl.h" +#include "../include/obd.h" +#include "../include/lustre_linkea.h" + +int linkea_data_new(struct linkea_data *ldata, struct lu_buf *buf) +{ + ldata->ld_buf = lu_buf_check_and_alloc(buf, PAGE_SIZE); + if (!ldata->ld_buf->lb_buf) + return -ENOMEM; + ldata->ld_leh = ldata->ld_buf->lb_buf; + ldata->ld_leh->leh_magic = LINK_EA_MAGIC; + ldata->ld_leh->leh_len = sizeof(struct link_ea_header); + ldata->ld_leh->leh_reccount = 0; + return 0; +} +EXPORT_SYMBOL(linkea_data_new); + +int linkea_init(struct linkea_data *ldata) +{ + struct link_ea_header *leh; + + LASSERT(ldata->ld_buf); + leh = ldata->ld_buf->lb_buf; + if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) { + leh->leh_magic = LINK_EA_MAGIC; + leh->leh_reccount = __swab32(leh->leh_reccount); + leh->leh_len = __swab64(leh->leh_len); + /* entries are swabbed by linkea_entry_unpack */ + } + if (leh->leh_magic != LINK_EA_MAGIC) + return -EINVAL; + if (leh->leh_reccount == 0) + return -ENODATA; + + ldata->ld_leh = leh; + return 0; +} +EXPORT_SYMBOL(linkea_init); + +/** + * Pack a link_ea_entry. + * All elements are stored as chars to avoid alignment issues. + * Numbers are always big-endian + * \retval record length + */ +int linkea_entry_pack(struct link_ea_entry *lee, const struct lu_name *lname, + const struct lu_fid *pfid) +{ + struct lu_fid tmpfid; + int reclen; + + tmpfid = *pfid; + if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_CRASH)) + tmpfid.f_ver = ~0; + fid_cpu_to_be(&tmpfid, &tmpfid); + memcpy(&lee->lee_parent_fid, &tmpfid, sizeof(tmpfid)); + memcpy(lee->lee_name, lname->ln_name, lname->ln_namelen); + reclen = sizeof(struct link_ea_entry) + lname->ln_namelen; + + lee->lee_reclen[0] = (reclen >> 8) & 0xff; + lee->lee_reclen[1] = reclen & 0xff; + return reclen; +} +EXPORT_SYMBOL(linkea_entry_pack); + +void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen, + struct lu_name *lname, struct lu_fid *pfid) +{ + *reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1]; + memcpy(pfid, &lee->lee_parent_fid, sizeof(*pfid)); + fid_be_to_cpu(pfid, pfid); + if (lname) { + lname->ln_name = lee->lee_name; + lname->ln_namelen = *reclen - sizeof(struct link_ea_entry); + } +} +EXPORT_SYMBOL(linkea_entry_unpack); + +/** + * Add a record to the end of link ea buf + **/ +int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname, + const struct lu_fid *pfid) +{ + LASSERT(ldata->ld_leh); + + if (!lname || !pfid) + return -EINVAL; + + ldata->ld_reclen = lname->ln_namelen + sizeof(struct link_ea_entry); + if (ldata->ld_leh->leh_len + ldata->ld_reclen > + ldata->ld_buf->lb_len) { + if (lu_buf_check_and_grow(ldata->ld_buf, + ldata->ld_leh->leh_len + + ldata->ld_reclen) < 0) + return -ENOMEM; + } + + ldata->ld_leh = ldata->ld_buf->lb_buf; + ldata->ld_lee = ldata->ld_buf->lb_buf + ldata->ld_leh->leh_len; + ldata->ld_reclen = linkea_entry_pack(ldata->ld_lee, lname, pfid); + ldata->ld_leh->leh_len += ldata->ld_reclen; + ldata->ld_leh->leh_reccount++; + CDEBUG(D_INODE, "New link_ea name '" DFID ":%.*s' is added\n", + PFID(pfid), lname->ln_namelen, lname->ln_name); + return 0; +} +EXPORT_SYMBOL(linkea_add_buf); + +/** Del the current record from the link ea buf */ +void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname) +{ + LASSERT(ldata->ld_leh && ldata->ld_lee); + + ldata->ld_leh->leh_reccount--; + ldata->ld_leh->leh_len -= ldata->ld_reclen; + memmove(ldata->ld_lee, (char *)ldata->ld_lee + ldata->ld_reclen, + (char *)ldata->ld_leh + ldata->ld_leh->leh_len - + (char *)ldata->ld_lee); + CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n", + lname->ln_namelen, lname->ln_name); + + if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh + + ldata->ld_leh->leh_len)) + ldata->ld_lee = NULL; +} +EXPORT_SYMBOL(linkea_del_buf); + +/** + * Check if such a link exists in linkEA. + * + * \param ldata link data the search to be done on + * \param lname name in the parent's directory entry pointing to this object + * \param pfid parent fid the link to be found for + * + * \retval 0 success + * \retval -ENOENT link does not exist + * \retval -ve on error + */ +int linkea_links_find(struct linkea_data *ldata, const struct lu_name *lname, + const struct lu_fid *pfid) +{ + struct lu_name tmpname; + struct lu_fid tmpfid; + int count; + + LASSERT(ldata->ld_leh); + + /* link #0 */ + ldata->ld_lee = (struct link_ea_entry *)(ldata->ld_leh + 1); + + for (count = 0; count < ldata->ld_leh->leh_reccount; count++) { + linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, + &tmpname, &tmpfid); + if (tmpname.ln_namelen == lname->ln_namelen && + lu_fid_eq(&tmpfid, pfid) && + (strncmp(tmpname.ln_name, lname->ln_name, + tmpname.ln_namelen) == 0)) + break; + ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee + + ldata->ld_reclen); + } + + if (count == ldata->ld_leh->leh_reccount) { + CDEBUG(D_INODE, "Old link_ea name '%.*s' not found\n", + lname->ln_namelen, lname->ln_name); + ldata->ld_lee = NULL; + ldata->ld_reclen = 0; + return -ENOENT; + } + return 0; +} +EXPORT_SYMBOL(linkea_links_find); diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 33342bfcc90e..be09e04b042f 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -65,6 +65,7 @@ #include "../../include/obd_support.h" #include "../../include/obd_class.h" #include "../../include/lprocfs_status.h" +#include "../../include/lustre/lustre_ioctl.h" #include "../../include/lustre_ver.h" /* buffer MUST be at least the size of obd_ioctl_hdr */ @@ -157,7 +158,6 @@ int obd_ioctl_popdata(void __user *arg, void *data, int len) err = copy_to_user(arg, data, len) ? -EFAULT : 0; return err; } -EXPORT_SYMBOL(obd_ioctl_popdata); /* opening /dev/obd */ static int obd_class_open(struct inode *inode, struct file *file) @@ -191,7 +191,7 @@ static long obd_class_ioctl(struct file *filp, unsigned int cmd, } /* declare character device */ -static struct file_operations obd_psdev_fops = { +static const struct file_operations obd_psdev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = obd_class_ioctl, /* unlocked_ioctl */ .open = obd_class_open, /* open */ @@ -291,7 +291,7 @@ static ssize_t jobid_name_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count) { - if (!count || count > JOBSTATS_JOBID_SIZE) + if (!count || count > LUSTRE_JOBID_SIZE) return -EINVAL; memcpy(obd_jobid_node, buffer, count); diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c index c6cc6a7666e3..41b77a30feb3 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c @@ -44,7 +44,7 @@ #include -void obdo_refresh_inode(struct inode *dst, struct obdo *src, u32 valid) +void obdo_refresh_inode(struct inode *dst, const struct obdo *src, u32 valid) { valid &= src->o_valid; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index 8f70dd2686f9..e6c785afceba 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -45,6 +45,7 @@ #include "../../include/obd_support.h" #include "../../include/lprocfs_status.h" +#include "../../include/obd_class.h" struct static_lustre_uintvalue_attr { struct { @@ -95,8 +96,8 @@ LUSTRE_STATIC_UINT_ATTR(timeout, &obd_timeout); static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr, char *buf) { - return sprintf(buf, "%ul\n", - obd_max_dirty_pages / (1 << (20 - PAGE_SHIFT))); + return sprintf(buf, "%lu\n", + obd_max_dirty_pages / (1 << (20 - PAGE_SHIFT))); } static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr, diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index 1784ca063428..43797f106745 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -80,7 +80,7 @@ static void llog_free_handle(struct llog_handle *loghandle) LASSERT(list_empty(&loghandle->u.phd.phd_entry)); else if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) LASSERT(list_empty(&loghandle->u.chd.chd_head)); - LASSERT(sizeof(*(loghandle->lgh_hdr)) == LLOG_CHUNK_SIZE); + LASSERT(sizeof(*loghandle->lgh_hdr) == LLOG_CHUNK_SIZE); kfree(loghandle->lgh_hdr); out: kfree(loghandle); @@ -137,6 +137,7 @@ static int llog_read_header(const struct lu_env *env, int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, int flags, struct obd_uuid *uuid) { + enum llog_flag fmt = flags & LLOG_F_EXT_MASK; struct llog_log_hdr *llh; int rc; @@ -194,6 +195,7 @@ int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, flags, LLOG_F_IS_CAT, LLOG_F_IS_PLAIN); rc = -EINVAL; } + llh->llh_flags |= fmt; out: if (rc) { kfree(llh); @@ -233,6 +235,10 @@ static int llog_process_thread(void *arg) else last_index = LLOG_BITMAP_BYTES * 8 - 1; + /* Record is not in this buffer. */ + if (index > last_index) + goto out; + while (rc == 0) { struct llog_rec_hdr *rec; @@ -262,7 +268,7 @@ repeat: */ for (rec = (struct llog_rec_hdr *)buf; (char *)rec < buf + LLOG_CHUNK_SIZE; - rec = (struct llog_rec_hdr *)((char *)rec + rec->lrh_len)) { + rec = llog_rec_hdr_next(rec)) { CDEBUG(D_OTHER, "processing rec 0x%p type %#x\n", rec, rec->lrh_type); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c index a82a2950295a..ce8e2f6f002a 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c @@ -63,11 +63,13 @@ static int llog_cat_id2handle(const struct lu_env *env, struct llog_logid *logid) { struct llog_handle *loghandle; + enum llog_flag fmt; int rc = 0; if (!cathandle) return -EBADF; + fmt = cathandle->lgh_hdr->llh_flags & LLOG_F_EXT_MASK; down_write(&cathandle->lgh_lock); list_for_each_entry(loghandle, &cathandle->u.chd.chd_head, u.phd.phd_entry) { @@ -99,7 +101,7 @@ static int llog_cat_id2handle(const struct lu_env *env, return rc; } - rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL); + rc = llog_init_handle(env, loghandle, fmt | LLOG_F_IS_PLAIN, NULL); if (rc < 0) { llog_close(env, loghandle); loghandle = NULL; @@ -107,7 +109,7 @@ static int llog_cat_id2handle(const struct lu_env *env, } down_write(&cathandle->lgh_lock); - list_add(&loghandle->u.phd.phd_entry, &cathandle->u.chd.chd_head); + list_add_tail(&loghandle->u.phd.phd_entry, &cathandle->u.chd.chd_head); up_write(&cathandle->lgh_lock); loghandle->u.phd.phd_cat_handle = cathandle; @@ -123,7 +125,6 @@ out: int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle) { struct llog_handle *loghandle, *n; - int rc; list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head, u.phd.phd_entry) { @@ -134,8 +135,7 @@ int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle) /* if handle was stored in ctxt, remove it too */ if (cathandle->lgh_ctxt->loc_handle == cathandle) cathandle->lgh_ctxt->loc_handle = NULL; - rc = llog_close(env, cathandle); - return rc; + return llog_close(env, cathandle); } EXPORT_SYMBOL(llog_cat_close); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_internal.h b/drivers/staging/lustre/lustre/obdclass/llog_internal.h index f7949525d952..21a93c73756a 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_internal.h +++ b/drivers/staging/lustre/lustre/obdclass/llog_internal.h @@ -70,4 +70,9 @@ int llog_process_or_fork(const struct lu_env *env, llog_cb_t cb, void *data, void *catdata, bool fork); int llog_cat_cleanup(const struct lu_env *env, struct llog_handle *cathandle, struct llog_handle *loghandle, int index); + +static inline struct llog_rec_hdr *llog_rec_hdr_next(struct llog_rec_hdr *rec) +{ + return (struct llog_rec_hdr *)((char *)rec + rec->lrh_len); +} #endif diff --git a/drivers/staging/lustre/lustre/obdclass/llog_obd.c b/drivers/staging/lustre/lustre/obdclass/llog_obd.c index 6ace7e097859..a4277d684614 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_obd.c @@ -210,7 +210,6 @@ LU_KEY_INIT_FINI(llog, struct llog_thread_info); /* context key: llog_thread_key */ LU_CONTEXT_KEY_DEFINE(llog, LCT_MD_THREAD | LCT_MG_THREAD | LCT_LOCAL); LU_KEY_INIT_GENERIC(llog); -EXPORT_SYMBOL(llog_thread_key); int llog_info_init(void) { diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index f7b9b190350c..8c4c1b3f1b45 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -172,20 +172,23 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) __swab64s(&cr->cr.cr_time); lustre_swab_lu_fid(&cr->cr.cr_tfid); lustre_swab_lu_fid(&cr->cr.cr_pfid); - if (CHANGELOG_REC_EXTENDED(&cr->cr)) { - struct llog_changelog_ext_rec *ext = - (struct llog_changelog_ext_rec *)rec; + if (cr->cr.cr_flags & CLF_RENAME) { + struct changelog_ext_rename *rnm = + changelog_rec_rename(&cr->cr); - lustre_swab_lu_fid(&ext->cr.cr_sfid); - lustre_swab_lu_fid(&ext->cr.cr_spfid); - tail = &ext->cr_tail; - } else { - tail = &cr->cr_tail; + lustre_swab_lu_fid(&rnm->cr_sfid); + lustre_swab_lu_fid(&rnm->cr_spfid); } - tail = (struct llog_rec_tail *)((char *)tail + + /* + * Because the tail follows a variable-length structure we need + * to compute its location at runtime + */ + tail = (struct llog_rec_tail *)((char *)&cr->cr + + changelog_rec_size(&cr->cr) + cr->cr.cr_namelen); break; } + case CHANGELOG_USER_REC: { struct llog_changelog_user_rec *cur = @@ -224,6 +227,7 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) __swab32s(&lsr->lsr_uid_h); __swab32s(&lsr->lsr_gid); __swab32s(&lsr->lsr_gid_h); + __swab64s(&lsr->lsr_valid); tail = &lsr->lsr_tail; break; } @@ -343,7 +347,6 @@ void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg) print_lustre_cfg(lcfg); } -EXPORT_SYMBOL(lustre_swab_lustre_cfg); /* used only for compatibility with old on-disk cfg_marker data */ struct cfg_marker32 { @@ -403,4 +406,3 @@ void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size) __swab64s(&marker->cm_canceltime); } } -EXPORT_SYMBOL(lustre_swab_cfg_marker); diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 279b625f1afe..852a5acfefab 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -96,6 +96,12 @@ static const char * const obd_connect_names[] = { "pingless", "flock_deadlock", "disp_stripe", + "open_by_fid", + "lfsck", + "unknown", + "unlink_close", + "unknown", + "dir_stripe", "unknown", NULL }; @@ -309,7 +315,7 @@ struct dentry *ldebugfs_add_simple(struct dentry *root, } EXPORT_SYMBOL_GPL(ldebugfs_add_simple); -static struct file_operations lprocfs_generic_fops = { }; +static const struct file_operations lprocfs_generic_fops = { }; int ldebugfs_add_vars(struct dentry *parent, struct lprocfs_vars *list, @@ -615,7 +621,6 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags); } -EXPORT_SYMBOL(lprocfs_stats_collect); /** * Append a space separated list of current set flags to str. @@ -1043,7 +1048,6 @@ int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid) } return rc; } -EXPORT_SYMBOL(lprocfs_stats_alloc_one); struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num, enum lprocfs_stats_flags flags) @@ -1547,6 +1551,146 @@ void lprocfs_oh_clear(struct obd_histogram *oh) } EXPORT_SYMBOL(lprocfs_oh_clear); +int lprocfs_wr_root_squash(const char __user *buffer, unsigned long count, + struct root_squash_info *squash, char *name) +{ + char kernbuf[64], *tmp, *errmsg; + unsigned long uid, gid; + int rc; + + if (count >= sizeof(kernbuf)) { + errmsg = "string too long"; + rc = -EINVAL; + goto failed_noprint; + } + if (copy_from_user(kernbuf, buffer, count)) { + errmsg = "bad address"; + rc = -EFAULT; + goto failed_noprint; + } + kernbuf[count] = '\0'; + + /* look for uid gid separator */ + tmp = strchr(kernbuf, ':'); + if (!tmp) { + errmsg = "needs uid:gid format"; + rc = -EINVAL; + goto failed; + } + *tmp = '\0'; + tmp++; + + /* parse uid */ + if (kstrtoul(kernbuf, 0, &uid) != 0) { + errmsg = "bad uid"; + rc = -EINVAL; + goto failed; + } + /* parse gid */ + if (kstrtoul(tmp, 0, &gid) != 0) { + errmsg = "bad gid"; + rc = -EINVAL; + goto failed; + } + + squash->rsi_uid = uid; + squash->rsi_gid = gid; + + LCONSOLE_INFO("%s: root_squash is set to %u:%u\n", + name, squash->rsi_uid, squash->rsi_gid); + return count; + +failed: + if (tmp) { + tmp--; + *tmp = ':'; + } + CWARN("%s: failed to set root_squash to \"%s\", %s, rc = %d\n", + name, kernbuf, errmsg, rc); + return rc; +failed_noprint: + CWARN("%s: failed to set root_squash due to %s, rc = %d\n", + name, errmsg, rc); + return rc; +} +EXPORT_SYMBOL(lprocfs_wr_root_squash); + +int lprocfs_wr_nosquash_nids(const char __user *buffer, unsigned long count, + struct root_squash_info *squash, char *name) +{ + char *kernbuf = NULL, *errmsg; + struct list_head tmp; + int len = count; + int rc; + + if (count > 4096) { + errmsg = "string too long"; + rc = -EINVAL; + goto failed; + } + + kernbuf = kzalloc(count + 1, GFP_NOFS); + if (!kernbuf) { + errmsg = "no memory"; + rc = -ENOMEM; + goto failed; + } + + if (copy_from_user(kernbuf, buffer, count)) { + errmsg = "bad address"; + rc = -EFAULT; + goto failed; + } + kernbuf[count] = '\0'; + + if (count > 0 && kernbuf[count - 1] == '\n') + len = count - 1; + + if ((len == 4 && !strncmp(kernbuf, "NONE", len)) || + (len == 5 && !strncmp(kernbuf, "clear", len))) { + /* empty string is special case */ + down_write(&squash->rsi_sem); + if (!list_empty(&squash->rsi_nosquash_nids)) + cfs_free_nidlist(&squash->rsi_nosquash_nids); + up_write(&squash->rsi_sem); + LCONSOLE_INFO("%s: nosquash_nids is cleared\n", name); + kfree(kernbuf); + return count; + } + + INIT_LIST_HEAD(&tmp); + if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) { + errmsg = "can't parse"; + rc = -EINVAL; + goto failed; + } + LCONSOLE_INFO("%s: nosquash_nids set to %s\n", + name, kernbuf); + kfree(kernbuf); + kernbuf = NULL; + + down_write(&squash->rsi_sem); + if (!list_empty(&squash->rsi_nosquash_nids)) + cfs_free_nidlist(&squash->rsi_nosquash_nids); + list_splice(&tmp, &squash->rsi_nosquash_nids); + up_write(&squash->rsi_sem); + + return count; + +failed: + if (kernbuf) { + CWARN("%s: failed to set nosquash_nids to \"%s\", %s rc = %d\n", + name, kernbuf, errmsg, rc); + kfree(kernbuf); + kernbuf = NULL; + } else { + CWARN("%s: failed to set nosquash_nids due to %s rc = %d\n", + name, errmsg, rc); + } + return rc; +} +EXPORT_SYMBOL(lprocfs_wr_nosquash_nids); + static ssize_t lustre_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 9b03059f34d6..054e567e6c8d 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -55,6 +55,34 @@ #include "../include/lu_ref.h" #include +enum { + LU_CACHE_PERCENT_MAX = 50, + LU_CACHE_PERCENT_DEFAULT = 20 +}; + +#define LU_CACHE_NR_MAX_ADJUST 128 +#define LU_CACHE_NR_UNLIMITED -1 +#define LU_CACHE_NR_DEFAULT LU_CACHE_NR_UNLIMITED +#define LU_CACHE_NR_LDISKFS_LIMIT LU_CACHE_NR_UNLIMITED +#define LU_CACHE_NR_ZFS_LIMIT 256 + +#define LU_SITE_BITS_MIN 12 +#define LU_SITE_BITS_MAX 24 +/** + * total 256 buckets, we don't want too many buckets because: + * - consume too much memory + * - avoid unbalanced LRU list + */ +#define LU_SITE_BKT_BITS 8 + +static unsigned int lu_cache_percent = LU_CACHE_PERCENT_DEFAULT; +module_param(lu_cache_percent, int, 0644); +MODULE_PARM_DESC(lu_cache_percent, "Percentage of memory to be used as lu_object cache"); + +static long lu_cache_nr = LU_CACHE_NR_DEFAULT; +module_param(lu_cache_nr, long, 0644); +MODULE_PARM_DESC(lu_cache_nr, "Maximum number of objects in lu_object cache"); + static void lu_object_free(const struct lu_env *env, struct lu_object *o); static __u32 ls_stats_read(struct lprocfs_stats *stats, int idx); @@ -310,10 +338,10 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) struct cfs_hash_bd bd2; struct list_head dispose; int did_sth; - int start; + unsigned int start; int count; int bnr; - int i; + unsigned int i; if (OBD_FAIL_CHECK(OBD_FAIL_OBD_NO_LRU)) return 0; @@ -324,8 +352,13 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) * the dispose list, removing them from LRU and hash table. */ start = s->ls_purge_start; - bnr = (nr == ~0) ? -1 : nr / CFS_HASH_NBKT(s->ls_obj_hash) + 1; + bnr = (nr == ~0) ? -1 : nr / (int)CFS_HASH_NBKT(s->ls_obj_hash) + 1; again: + /* + * It doesn't make any sense to make purge threads parallel, that can + * only bring troubles to us. See LU-5331. + */ + mutex_lock(&s->ls_purge_mutex); did_sth = 0; cfs_hash_for_each_bucket(s->ls_obj_hash, &bd, i) { if (i < start) @@ -371,6 +404,7 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) if (nr == 0) break; } + mutex_unlock(&s->ls_purge_mutex); if (nr != 0 && did_sth && start != 0) { start = 0; /* restart from the first bucket */ @@ -573,6 +607,27 @@ static struct lu_object *lu_object_find(const struct lu_env *env, return lu_object_find_at(env, dev->ld_site->ls_top_dev, f, conf); } +/* + * Limit the lu_object cache to a maximum of lu_cache_nr objects. Because + * the calculation for the number of objects to reclaim is not covered by + * a lock the maximum number of objects is capped by LU_CACHE_MAX_ADJUST. + * This ensures that many concurrent threads will not accidentally purge + * the entire cache. + */ +static void lu_object_limit(const struct lu_env *env, struct lu_device *dev) +{ + __u64 size, nr; + + if (lu_cache_nr == LU_CACHE_NR_UNLIMITED) + return; + + size = cfs_hash_size_get(dev->ld_site->ls_obj_hash); + nr = (__u64)lu_cache_nr; + if (size > nr) + lu_site_purge(env, dev->ld_site, + min_t(__u64, size - nr, LU_CACHE_NR_MAX_ADJUST)); +} + static struct lu_object *lu_object_new(const struct lu_env *env, struct lu_device *dev, const struct lu_fid *f, @@ -590,6 +645,9 @@ static struct lu_object *lu_object_new(const struct lu_env *env, cfs_hash_bd_get_and_lock(hs, (void *)f, &bd, 1); cfs_hash_bd_add_locked(hs, &bd, &o->lo_header->loh_hash); cfs_hash_bd_unlock(hs, &bd, 1); + + lu_object_limit(env, dev); + return o; } @@ -656,6 +714,9 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env, if (likely(PTR_ERR(shadow) == -ENOENT)) { cfs_hash_bd_add_locked(hs, &bd, &o->lo_header->loh_hash); cfs_hash_bd_unlock(hs, &bd, 1); + + lu_object_limit(env, dev); + return o; } @@ -706,13 +767,15 @@ struct lu_object *lu_object_find_slice(const struct lu_env *env, struct lu_object *obj; top = lu_object_find(env, dev, f, conf); - if (!IS_ERR(top)) { - obj = lu_object_locate(top->lo_header, dev->ld_type); - if (!obj) - lu_object_put(env, top); - } else { - obj = top; + if (IS_ERR(top)) + return top; + + obj = lu_object_locate(top->lo_header, dev->ld_type); + if (unlikely(!obj)) { + lu_object_put(env, top); + obj = ERR_PTR(-ENOENT); } + return obj; } EXPORT_SYMBOL(lu_object_find_slice); @@ -726,34 +789,31 @@ int lu_device_type_init(struct lu_device_type *ldt) { int result = 0; + atomic_set(&ldt->ldt_device_nr, 0); INIT_LIST_HEAD(&ldt->ldt_linkage); if (ldt->ldt_ops->ldto_init) result = ldt->ldt_ops->ldto_init(ldt); - if (result == 0) + + if (!result) { + spin_lock(&obd_types_lock); list_add(&ldt->ldt_linkage, &lu_device_types); + spin_unlock(&obd_types_lock); + } + return result; } EXPORT_SYMBOL(lu_device_type_init); void lu_device_type_fini(struct lu_device_type *ldt) { + spin_lock(&obd_types_lock); list_del_init(&ldt->ldt_linkage); + spin_unlock(&obd_types_lock); if (ldt->ldt_ops->ldto_fini) ldt->ldt_ops->ldto_fini(ldt); } EXPORT_SYMBOL(lu_device_type_fini); -void lu_types_stop(void) -{ - struct lu_device_type *ldt; - - list_for_each_entry(ldt, &lu_device_types, ldt_linkage) { - if (ldt->ldt_device_nr == 0 && ldt->ldt_ops->ldto_stop) - ldt->ldt_ops->ldto_stop(ldt); - } -} -EXPORT_SYMBOL(lu_types_stop); - /** * Global list of all sites on this node */ @@ -808,22 +868,14 @@ void lu_site_print(const struct lu_env *env, struct lu_site *s, void *cookie, } EXPORT_SYMBOL(lu_site_print); -enum { - LU_CACHE_PERCENT_MAX = 50, - LU_CACHE_PERCENT_DEFAULT = 20 -}; - -static unsigned int lu_cache_percent = LU_CACHE_PERCENT_DEFAULT; -module_param(lu_cache_percent, int, 0644); -MODULE_PARM_DESC(lu_cache_percent, "Percentage of memory to be used as lu_object cache"); - /** * Return desired hash table order. */ -static int lu_htable_order(void) +static unsigned long lu_htable_order(struct lu_device *top) { + unsigned long bits_max = LU_SITE_BITS_MAX; unsigned long cache_size; - int bits; + unsigned long bits; /* * Calculate hash table size, assuming that we want reasonable @@ -854,7 +906,7 @@ static int lu_htable_order(void) for (bits = 1; (1 << bits) < cache_size; ++bits) { ; } - return bits; + return clamp_t(typeof(bits), bits, LU_SITE_BITS_MIN, bits_max); } static unsigned lu_obj_hop_hash(struct cfs_hash *hs, @@ -930,28 +982,18 @@ static void lu_dev_add_linkage(struct lu_site *s, struct lu_device *d) /** * Initialize site \a s, with \a d as the top level device. */ -#define LU_SITE_BITS_MIN 12 -#define LU_SITE_BITS_MAX 19 -/** - * total 256 buckets, we don't want too many buckets because: - * - consume too much memory - * - avoid unbalanced LRU list - */ -#define LU_SITE_BKT_BITS 8 - int lu_site_init(struct lu_site *s, struct lu_device *top) { struct lu_site_bkt_data *bkt; struct cfs_hash_bd bd; + unsigned long bits; + unsigned long i; char name[16]; - int bits; - int i; memset(s, 0, sizeof(*s)); - bits = lu_htable_order(); - snprintf(name, 16, "lu_site_%s", top->ld_type->ldt_name); - for (bits = min(max(LU_SITE_BITS_MIN, bits), LU_SITE_BITS_MAX); - bits >= LU_SITE_BITS_MIN; bits--) { + mutex_init(&s->ls_purge_mutex); + snprintf(name, sizeof(name), "lu_site_%s", top->ld_type->ldt_name); + for (bits = lu_htable_order(top); bits >= LU_SITE_BITS_MIN; bits--) { s->ls_obj_hash = cfs_hash_create(name, bits, bits, bits - LU_SITE_BKT_BITS, sizeof(*bkt), 0, 0, @@ -959,13 +1001,14 @@ int lu_site_init(struct lu_site *s, struct lu_device *top) CFS_HASH_SPIN_BKTLOCK | CFS_HASH_NO_ITEMREF | CFS_HASH_DEPTH | - CFS_HASH_ASSERT_EMPTY); + CFS_HASH_ASSERT_EMPTY | + CFS_HASH_COUNTER); if (s->ls_obj_hash) break; } if (!s->ls_obj_hash) { - CERROR("failed to create lu_site hash with bits: %d\n", bits); + CERROR("failed to create lu_site hash with bits: %lu\n", bits); return -ENOMEM; } @@ -1082,8 +1125,10 @@ EXPORT_SYMBOL(lu_device_put); */ int lu_device_init(struct lu_device *d, struct lu_device_type *t) { - if (t->ldt_device_nr++ == 0 && t->ldt_ops->ldto_start) + if (atomic_inc_return(&t->ldt_device_nr) == 1 && + t->ldt_ops->ldto_start) t->ldt_ops->ldto_start(t); + memset(d, 0, sizeof(*d)); atomic_set(&d->ld_ref, 0); d->ld_type = t; @@ -1098,9 +1143,8 @@ EXPORT_SYMBOL(lu_device_init); */ void lu_device_fini(struct lu_device *d) { - struct lu_device_type *t; + struct lu_device_type *t = d->ld_type; - t = d->ld_type; if (d->ld_obd) { d->ld_obd->obd_lu_dev = NULL; d->ld_obd = NULL; @@ -1109,8 +1153,10 @@ void lu_device_fini(struct lu_device *d) lu_ref_fini(&d->ld_reference); LASSERTF(atomic_read(&d->ld_ref) == 0, "Refcount is %u\n", atomic_read(&d->ld_ref)); - LASSERT(t->ldt_device_nr > 0); - if (--t->ldt_device_nr == 0 && t->ldt_ops->ldto_stop) + LASSERT(atomic_read(&t->ldt_device_nr) > 0); + + if (atomic_dec_and_test(&t->ldt_device_nr) && + t->ldt_ops->ldto_stop) t->ldt_ops->ldto_stop(t); } EXPORT_SYMBOL(lu_device_fini); @@ -1254,7 +1300,6 @@ void lu_stack_fini(const struct lu_env *env, struct lu_device *top) } } } -EXPORT_SYMBOL(lu_stack_fini); enum { /** @@ -1281,7 +1326,7 @@ static unsigned key_set_version; int lu_context_key_register(struct lu_context_key *key) { int result; - int i; + unsigned int i; LASSERT(key->lct_init); LASSERT(key->lct_fini); @@ -1476,18 +1521,16 @@ void lu_context_key_quiesce(struct lu_context_key *key) ++key_set_version; } } -EXPORT_SYMBOL(lu_context_key_quiesce); void lu_context_key_revive(struct lu_context_key *key) { key->lct_tags &= ~LCT_QUIESCENT; ++key_set_version; } -EXPORT_SYMBOL(lu_context_key_revive); static void keys_fini(struct lu_context *ctx) { - int i; + unsigned int i; if (!ctx->lc_value) return; @@ -1501,7 +1544,7 @@ static void keys_fini(struct lu_context *ctx) static int keys_fill(struct lu_context *ctx) { - int i; + unsigned int i; LINVRNT(ctx->lc_value); for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) { @@ -1614,7 +1657,7 @@ EXPORT_SYMBOL(lu_context_enter); */ void lu_context_exit(struct lu_context *ctx) { - int i; + unsigned int i; LINVRNT(ctx->lc_state == LCS_ENTERED); ctx->lc_state = LCS_LEFT; @@ -1642,7 +1685,6 @@ int lu_context_refill(struct lu_context *ctx) { return likely(ctx->lc_version == key_set_version) ? 0 : keys_fill(ctx); } -EXPORT_SYMBOL(lu_context_refill); /** * lu_ctx_tags/lu_ses_tags will be updated if there are new types of @@ -1696,7 +1738,7 @@ static void lu_site_stats_get(struct cfs_hash *hs, struct lu_site_stats *stats, int populated) { struct cfs_hash_bd bd; - int i; + unsigned int i; cfs_hash_for_each_bucket(hs, &bd, i) { struct lu_site_bkt_data *bkt = cfs_hash_bd_extra_get(hs, &bd); @@ -1940,3 +1982,73 @@ void lu_kmem_fini(struct lu_kmem_descr *caches) } } EXPORT_SYMBOL(lu_kmem_fini); + +void lu_buf_free(struct lu_buf *buf) +{ + LASSERT(buf); + if (buf->lb_buf) { + LASSERT(buf->lb_len > 0); + kvfree(buf->lb_buf); + buf->lb_buf = NULL; + buf->lb_len = 0; + } +} +EXPORT_SYMBOL(lu_buf_free); + +void lu_buf_alloc(struct lu_buf *buf, size_t size) +{ + LASSERT(buf); + LASSERT(!buf->lb_buf); + LASSERT(!buf->lb_len); + buf->lb_buf = libcfs_kvzalloc(size, GFP_NOFS); + if (likely(buf->lb_buf)) + buf->lb_len = size; +} +EXPORT_SYMBOL(lu_buf_alloc); + +void lu_buf_realloc(struct lu_buf *buf, size_t size) +{ + lu_buf_free(buf); + lu_buf_alloc(buf, size); +} +EXPORT_SYMBOL(lu_buf_realloc); + +struct lu_buf *lu_buf_check_and_alloc(struct lu_buf *buf, size_t len) +{ + if (!buf->lb_buf && !buf->lb_len) + lu_buf_alloc(buf, len); + + if ((len > buf->lb_len) && buf->lb_buf) + lu_buf_realloc(buf, len); + + return buf; +} +EXPORT_SYMBOL(lu_buf_check_and_alloc); + +/** + * Increase the size of the \a buf. + * preserves old data in buffer + * old buffer remains unchanged on error + * \retval 0 or -ENOMEM + */ +int lu_buf_check_and_grow(struct lu_buf *buf, size_t len) +{ + char *ptr; + + if (len <= buf->lb_len) + return 0; + + ptr = libcfs_kvzalloc(len, GFP_NOFS); + if (!ptr) + return -ENOMEM; + + /* Free the old buf */ + if (buf->lb_buf) { + memcpy(ptr, buf->lb_buf, buf->lb_len); + kvfree(buf->lb_buf); + } + + buf->lb_buf = ptr; + buf->lb_len = len; + return 0; +} diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c index 082f530c527c..c9445e5ec271 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c @@ -130,7 +130,7 @@ void class_handle_unhash(struct portals_handle *h) } EXPORT_SYMBOL(class_handle_unhash); -void *class_handle2object(__u64 cookie) +void *class_handle2object(__u64 cookie, const void *owner) { struct handle_bucket *bucket; struct portals_handle *h; @@ -145,7 +145,7 @@ void *class_handle2object(__u64 cookie) rcu_read_lock(); list_for_each_entry_rcu(h, &bucket->head, h_link) { - if (h->h_cookie != cookie) + if (h->h_cookie != cookie || h->h_owner != owner) continue; spin_lock(&h->h_lock); @@ -164,8 +164,11 @@ EXPORT_SYMBOL(class_handle2object); void class_handle_free_cb(struct rcu_head *rcu) { - struct portals_handle *h = RCU2HANDLE(rcu); - void *ptr = (void *)(unsigned long)h->h_cookie; + struct portals_handle *h; + void *ptr; + + h = container_of(rcu, struct portals_handle, h_rcu); + ptr = (void *)(unsigned long)h->h_cookie; if (h->h_ops->hop_free) h->h_ops->hop_free(ptr, h->h_size); @@ -214,7 +217,7 @@ static int cleanup_all_handles(void) struct portals_handle *h; spin_lock(&handle_hash[i].lock); - list_for_each_entry_rcu(h, &(handle_hash[i].head), h_link) { + list_for_each_entry_rcu(h, &handle_hash[i].head, h_link) { CERROR("force clean handle %#llx addr %p ops %p\n", h->h_cookie, h, h->h_ops); diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c index 5974a9bf77c0..ffa740aa861c 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c @@ -139,7 +139,6 @@ int class_add_uuid(const char *uuid, __u64 nid) } return 0; } -EXPORT_SYMBOL(class_add_uuid); /* Delete the nids for one uuid if specified, otherwise delete all */ int class_del_uuid(const char *uuid) diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 0eab1236501b..bbed1b72d52e 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -37,6 +37,7 @@ #define DEBUG_SUBSYSTEM S_CLASS #include "../include/obd_class.h" #include +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_log.h" #include "../include/lprocfs_status.h" #include "../include/lustre_param.h" @@ -237,7 +238,7 @@ static int class_attach(struct lustre_cfg *lcfg) /* recovery data */ init_waitqueue_head(&obd->obd_evict_inprogress_waitq); - llog_group_init(&obd->obd_olg, FID_SEQ_LLOG); + llog_group_init(&obd->obd_olg); obd->obd_conn_inprogress = 0; @@ -250,15 +251,6 @@ static int class_attach(struct lustre_cfg *lcfg) } memcpy(obd->obd_uuid.uuid, uuid, len); - /* do the attach */ - if (OBP(obd, attach)) { - rc = OBP(obd, attach)(obd, sizeof(*lcfg), lcfg); - if (rc) { - rc = -EINVAL; - goto out; - } - } - /* Detach drops this */ spin_lock(&obd->obd_dev_lock); atomic_set(&obd->obd_refcount, 1); @@ -422,17 +414,12 @@ static int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg) } /* Leave this on forever */ obd->obd_stopping = 1; - - /* wait for already-arrived-connections to finish. */ - while (obd->obd_conn_inprogress > 0) { - spin_unlock(&obd->obd_dev_lock); - - cond_resched(); - - spin_lock(&obd->obd_dev_lock); - } spin_unlock(&obd->obd_dev_lock); + while (obd->obd_conn_inprogress > 0) + yield(); + smp_rmb(); + if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) { for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++) switch (*flag) { @@ -526,11 +513,6 @@ void class_decref(struct obd_device *obd, const char *scope, const void *source) CERROR("Cleanup %s returned %d\n", obd->obd_name, err); } - if (OBP(obd, detach)) { - err = OBP(obd, detach)(obd); - if (err) - CERROR("Detach returned %d\n", err); - } class_release_dev(obd); } } @@ -756,7 +738,7 @@ static int process_param2_config(struct lustre_cfg *lcfg) } start = ktime_get(); - rc = call_usermodehelper(argv[0], argv, NULL, 1); + rc = call_usermodehelper(argv[0], argv, NULL, UMH_WAIT_PROC); end = ktime_get(); if (rc < 0) { @@ -1026,7 +1008,7 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars, oldfs = get_fs(); set_fs(KERNEL_DS); - rc = (var->fops->write)(&fakefile, sval, + rc = var->fops->write(&fakefile, sval, vallen, NULL); set_fs(oldfs); } @@ -1060,8 +1042,6 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars, } EXPORT_SYMBOL(class_process_proc_param); -extern int lustre_check_exclusion(struct super_block *sb, char *svname); - /** Parse a configuration llog, doing various manipulations on them * for various reasons, (modifications for compatibility, skip obsolete * records, change uuids, etc), then class_process_config() resulting @@ -1317,33 +1297,33 @@ static int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf, if (rc < 0) return rc; - ptr += snprintf(ptr, end-ptr, "cmd=%05x ", lcfg->lcfg_command); + ptr += snprintf(ptr, end - ptr, "cmd=%05x ", lcfg->lcfg_command); if (lcfg->lcfg_flags) - ptr += snprintf(ptr, end-ptr, "flags=%#08x ", + ptr += snprintf(ptr, end - ptr, "flags=%#08x ", lcfg->lcfg_flags); if (lcfg->lcfg_num) - ptr += snprintf(ptr, end-ptr, "num=%#08x ", lcfg->lcfg_num); + ptr += snprintf(ptr, end - ptr, "num=%#08x ", lcfg->lcfg_num); if (lcfg->lcfg_nid) { char nidstr[LNET_NIDSTR_SIZE]; libcfs_nid2str_r(lcfg->lcfg_nid, nidstr, sizeof(nidstr)); - ptr += snprintf(ptr, end-ptr, "nid=%s(%#llx)\n ", + ptr += snprintf(ptr, end - ptr, "nid=%s(%#llx)\n ", nidstr, lcfg->lcfg_nid); } if (lcfg->lcfg_command == LCFG_MARKER) { struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1); - ptr += snprintf(ptr, end-ptr, "marker=%d(%#x)%s '%s'", + ptr += snprintf(ptr, end - ptr, "marker=%d(%#x)%s '%s'", marker->cm_step, marker->cm_flags, marker->cm_tgtname, marker->cm_comment); } else { int i; for (i = 0; i < lcfg->lcfg_bufcount; i++) { - ptr += snprintf(ptr, end-ptr, "%d:%s ", i, + ptr += snprintf(ptr, end - ptr, "%d:%s ", i, lustre_cfg_string(lcfg, i)); } } diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index aa84a50e9904..0d3a3b05a637 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -37,11 +37,11 @@ */ #define DEBUG_SUBSYSTEM S_CLASS -#define D_MOUNT (D_SUPER|D_CONFIG/*|D_WARNING */) +#define D_MOUNT (D_SUPER | D_CONFIG/*|D_WARNING */) #define PRINT_CMD CDEBUG #include "../include/obd.h" -#include "../include/linux/lustre_compat25.h" +#include "../include/lustre_compat.h" #include "../include/obd_class.h" #include "../include/lustre/lustre_user.h" #include "../include/lustre_log.h" @@ -68,7 +68,7 @@ static void (*kill_super_cb)(struct super_block *sb); * this log, and is added to the mgc's list of logs to follow. */ int lustre_process_log(struct super_block *sb, char *logname, - struct config_llog_instance *cfg) + struct config_llog_instance *cfg) { struct lustre_cfg *lcfg; struct lustre_cfg_bufs *bufs; @@ -384,17 +384,15 @@ int lustre_start_mgc(struct super_block *sb) OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV | OBD_CONNECT_LVB_TYPE; -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 2, 50, 0) +#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE data->ocd_connect_flags |= OBD_CONNECT_MNE_SWAB; -#else -#warning "LU-1644: Remove old OBD_CONNECT_MNE_SWAB fixup and imp_need_mne_swab" #endif if (lmd_is_client(lsi->lsi_lmd) && lsi->lsi_lmd->lmd_flags & LMD_FLG_NOIR) data->ocd_connect_flags &= ~OBD_CONNECT_IMP_RECOV; data->ocd_version = LUSTRE_VERSION_CODE; - rc = obd_connect(NULL, &exp, obd, &(obd->obd_uuid), data, NULL); + rc = obd_connect(NULL, &exp, obd, &obd->obd_uuid, data, NULL); if (rc) { CERROR("connect failed %d\n", rc); goto out; @@ -670,7 +668,6 @@ int lustre_common_put_super(struct super_block *sb) } /* Drop a ref to the mounted disk */ lustre_put_lsi(sb); - lu_types_stop(); return rc; } EXPORT_SYMBOL(lustre_common_put_super); @@ -731,7 +728,7 @@ int lustre_check_exclusion(struct super_block *sb, char *svname) static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr) { const char *s1 = ptr, *s2; - __u32 index, *exclude_list; + __u32 index = 0, *exclude_list; int rc = 0, devmax; /* The shortest an ost name can be is 8 chars: -OST0000. @@ -758,7 +755,7 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr) exclude_list[lmd->lmd_exclude_count++] = index; else CDEBUG(D_MOUNT, "ignoring exclude %.*s: type = %#x\n", - (uint)(s2-s1), s1, rc); + (uint)(s2 - s1), s1, rc); s1 = s2; /* now we are pointing at ':' (next exclude) * or ',' (end of excludes) @@ -880,7 +877,7 @@ static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr) */ static int lmd_parse(char *options, struct lustre_mount_data *lmd) { - char *s1, *s2, *devname = NULL; + char *s1, *s2, *s3, *devname = NULL; struct lustre_mount_data *raw = (struct lustre_mount_data *)options; int rc = 0; @@ -913,6 +910,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) /* Skip whitespace and extra commas */ while (*s1 == ' ' || *s1 == ',') s1++; + s3 = s1; /* Client options are parsed in ll_options: eg. flock, * user_xattr, acl @@ -970,6 +968,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) rc = lmd_parse_mgssec(lmd, s1 + 7); if (rc) goto invalid; + s3 = s2; clear++; /* ost exclusion list */ } else if (strncmp(s1, "exclude=", 8) == 0) { @@ -990,10 +989,19 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) size_t length, params_length; char *tail = strchr(s1 + 6, ','); - if (!tail) + if (!tail) { length = strlen(s1); - else - length = tail - s1; + } else { + lnet_nid_t nid; + char *param_str = tail + 1; + int supplementary = 1; + + while (!class_parse_nid_quiet(param_str, &nid, + ¶m_str)) { + supplementary = 0; + } + length = param_str - s1 - supplementary; + } length -= 6; params_length = strlen(lmd->lmd_params); if (params_length + length + 1 >= LMD_PARAMS_MAXLEN) @@ -1001,6 +1009,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) strncat(lmd->lmd_params, s1 + 6, length); lmd->lmd_params[params_length + length] = '\0'; strlcat(lmd->lmd_params, " ", LMD_PARAMS_MAXLEN); + s3 = s1 + 6 + length; clear++; } else if (strncmp(s1, "osd=", 4) == 0) { rc = lmd_parse_string(&lmd->lmd_osd_type, s1 + 4); @@ -1097,7 +1106,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent) struct lustre_sb_info *lsi; int rc; - CDEBUG(D_MOUNT|D_VFSTRACE, "VFS Op: sb %p\n", sb); + CDEBUG(D_MOUNT | D_VFSTRACE, "VFS Op: sb %p\n", sb); lsi = lustre_init_lsi(sb); if (!lsi) @@ -1133,7 +1142,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent) } else { rc = lustre_start_mgc(sb); if (rc) { - lustre_put_lsi(sb); + lustre_common_put_super(sb); goto out; } /* Connect and start */ diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c index 8583a4a8c206..79104a66da96 100644 --- a/drivers/staging/lustre/lustre/obdclass/obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/obdo.c @@ -112,7 +112,7 @@ void obdo_from_inode(struct obdo *dst, struct inode *src, u32 valid) } EXPORT_SYMBOL(obdo_from_inode); -void obdo_to_ioobj(struct obdo *oa, struct obd_ioobj *ioobj) +void obdo_to_ioobj(const struct obdo *oa, struct obd_ioobj *ioobj) { ioobj->ioo_oid = oa->o_oi; if (unlikely(!(oa->o_valid & OBD_MD_FLGROUP))) @@ -125,7 +125,8 @@ void obdo_to_ioobj(struct obdo *oa, struct obd_ioobj *ioobj) } EXPORT_SYMBOL(obdo_to_ioobj); -static void iattr_from_obdo(struct iattr *attr, struct obdo *oa, u32 valid) +static void iattr_from_obdo(struct iattr *attr, const struct obdo *oa, + u32 valid) { valid &= oa->o_valid; @@ -152,12 +153,14 @@ static void iattr_from_obdo(struct iattr *attr, struct obdo *oa, u32 valid) } #if 0 /* you shouldn't be able to change a file's type with setattr */ if (valid & OBD_MD_FLTYPE) { - attr->ia_mode = (attr->ia_mode & ~S_IFMT)|(oa->o_mode & S_IFMT); + attr->ia_mode = (attr->ia_mode & ~S_IFMT) | + (oa->o_mode & S_IFMT); attr->ia_valid |= ATTR_MODE; } #endif if (valid & OBD_MD_FLMODE) { - attr->ia_mode = (attr->ia_mode & S_IFMT)|(oa->o_mode & ~S_IFMT); + attr->ia_mode = (attr->ia_mode & S_IFMT) | + (oa->o_mode & ~S_IFMT); attr->ia_valid |= ATTR_MODE; if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) && !capable(CFS_CAP_FSETID)) @@ -173,7 +176,7 @@ static void iattr_from_obdo(struct iattr *attr, struct obdo *oa, u32 valid) } } -void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid) +void md_from_obdo(struct md_op_data *op_data, const struct obdo *oa, u32 valid) { iattr_from_obdo(&op_data->op_attr, oa, valid); if (valid & OBD_MD_FLBLOCKS) { diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 5b29c4a44fe5..505582ff4d1e 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -41,6 +41,7 @@ #include "../include/cl_object.h" #include "../include/lustre_fid.h" #include "../include/lustre_acl.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_net.h" #include "echo_internal.h" @@ -64,14 +65,14 @@ struct echo_object { struct echo_device *eo_dev; struct list_head eo_obj_chain; - struct lov_stripe_md *eo_lsm; + struct lov_oinfo *eo_oinfo; atomic_t eo_npages; int eo_deleted; }; struct echo_object_conf { struct cl_object_conf eoc_cl; - struct lov_stripe_md **eoc_md; + struct lov_oinfo **eoc_oinfo; }; struct echo_page { @@ -152,9 +153,6 @@ struct echo_object_conf *cl2echo_conf(const struct cl_object_conf *c) } /** @} echo_helpers */ - -static struct echo_object *cl_echo_object_find(struct echo_device *d, - struct lov_stripe_md **lsm); static int cl_echo_object_put(struct echo_object *eco); static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, struct page **pages, int npages, int async); @@ -413,10 +411,13 @@ static int echo_object_init(const struct lu_env *env, struct lu_object *obj, cconf = lu2cl_conf(conf); econf = cl2echo_conf(cconf); - LASSERT(econf->eoc_md); - eco->eo_lsm = *econf->eoc_md; - /* clear the lsm pointer so that it won't get freed. */ - *econf->eoc_md = NULL; + LASSERT(econf->eoc_oinfo); + /* + * Transfer the oinfo pointer to eco that it won't be + * freed. + */ + eco->eo_oinfo = *econf->eoc_oinfo; + *econf->eoc_oinfo = NULL; eco->eo_dev = ed; atomic_set(&eco->eo_npages, 0); @@ -429,52 +430,6 @@ static int echo_object_init(const struct lu_env *env, struct lu_object *obj, return 0; } -/* taken from osc_unpackmd() */ -static int echo_alloc_memmd(struct echo_device *ed, - struct lov_stripe_md **lsmp) -{ - int lsm_size; - - /* If export is lov/osc then use their obd method */ - if (ed->ed_next) - return obd_alloc_memmd(ed->ed_ec->ec_exp, lsmp); - /* OFD has no unpackmd method, do everything here */ - lsm_size = lov_stripe_md_size(1); - - LASSERT(!*lsmp); - *lsmp = kzalloc(lsm_size, GFP_NOFS); - if (!*lsmp) - return -ENOMEM; - - (*lsmp)->lsm_oinfo[0] = kzalloc(sizeof(struct lov_oinfo), GFP_NOFS); - if (!(*lsmp)->lsm_oinfo[0]) { - kfree(*lsmp); - return -ENOMEM; - } - - loi_init((*lsmp)->lsm_oinfo[0]); - (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES; - ostid_set_seq_echo(&(*lsmp)->lsm_oi); - - return lsm_size; -} - -static int echo_free_memmd(struct echo_device *ed, struct lov_stripe_md **lsmp) -{ - int lsm_size; - - /* If export is lov/osc then use their obd method */ - if (ed->ed_next) - return obd_free_memmd(ed->ed_ec->ec_exp, lsmp); - /* OFD has no unpackmd method, do everything here */ - lsm_size = lov_stripe_md_size(1); - - kfree((*lsmp)->lsm_oinfo[0]); - kfree(*lsmp); - *lsmp = NULL; - return 0; -} - static void echo_object_free(const struct lu_env *env, struct lu_object *obj) { struct echo_object *eco = cl2echo_obj(lu2cl(obj)); @@ -489,8 +444,7 @@ static void echo_object_free(const struct lu_env *env, struct lu_object *obj) lu_object_fini(obj); lu_object_header_fini(obj->lo_header); - if (eco->eo_lsm) - echo_free_memmd(eco->eo_dev, &eco->eo_lsm); + kfree(eco->eo_oinfo); kmem_cache_free(echo_object_kmem, eco); } @@ -864,25 +818,21 @@ static struct lu_device_type echo_device_type = { */ /* Interfaces to echo client obd device */ -static struct echo_object *cl_echo_object_find(struct echo_device *d, - struct lov_stripe_md **lsmp) +static struct echo_object * +cl_echo_object_find(struct echo_device *d, const struct ost_id *oi) { struct lu_env *env; struct echo_thread_info *info; struct echo_object_conf *conf; - struct lov_stripe_md *lsm; + struct lov_oinfo *oinfo = NULL; struct echo_object *eco; struct cl_object *obj; struct lu_fid *fid; int refcheck; int rc; - LASSERT(lsmp); - lsm = *lsmp; - LASSERT(lsm); - LASSERTF(ostid_id(&lsm->lsm_oi) != 0, DOSTID"\n", POSTID(&lsm->lsm_oi)); - LASSERTF(ostid_seq(&lsm->lsm_oi) == FID_SEQ_ECHO, DOSTID"\n", - POSTID(&lsm->lsm_oi)); + LASSERTF(ostid_id(oi), DOSTID "\n", POSTID(oi)); + LASSERTF(ostid_seq(oi) == FID_SEQ_ECHO, DOSTID "\n", POSTID(oi)); /* Never return an object if the obd is to be freed. */ if (echo_dev2cl(d)->cd_lu_dev.ld_obd->obd_stopping) @@ -895,16 +845,24 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, info = echo_env_info(env); conf = &info->eti_conf; if (d->ed_next) { - struct lov_oinfo *oinfo = lsm->lsm_oinfo[0]; + oinfo = kzalloc(sizeof(*oinfo), GFP_NOFS); + if (!oinfo) { + eco = ERR_PTR(-ENOMEM); + goto out; + } - LASSERT(oinfo); - oinfo->loi_oi = lsm->lsm_oi; + oinfo->loi_oi = *oi; conf->eoc_cl.u.coc_oinfo = oinfo; } - conf->eoc_md = lsmp; + + /* + * If echo_object_init() is successful then ownership of oinfo + * is transferred to the object. + */ + conf->eoc_oinfo = &oinfo; fid = &info->eti_fid; - rc = ostid_to_fid(fid, &lsm->lsm_oi, 0); + rc = ostid_to_fid(fid, (struct ost_id *)oi, 0); if (rc != 0) { eco = ERR_PTR(rc); goto out; @@ -927,6 +885,7 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, } out: + kfree(oinfo); cl_env_put(env, &refcheck); return eco; } @@ -1051,7 +1010,7 @@ static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, struct cl_io *io; struct cl_page *clp; struct lustre_handle lh = { 0 }; - int page_size = cl_page_size(obj); + size_t page_size = cl_page_size(obj); int refcheck; int rc; int i; @@ -1145,7 +1104,6 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, { struct echo_object *eco; struct echo_client_obd *ec = ed->ed_ec; - struct lov_stripe_md *lsm = NULL; int rc; int created = 0; @@ -1156,30 +1114,19 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, return -EINVAL; } - rc = echo_alloc_memmd(ed, &lsm); - if (rc < 0) { - CERROR("Cannot allocate md: rc = %d\n", rc); - goto failed; - } + if (!ostid_id(&oa->o_oi)) + ostid_set_id(&oa->o_oi, ++last_object_id); - /* setup object ID here */ - lsm->lsm_oi = oa->o_oi; - - if (ostid_id(&lsm->lsm_oi) == 0) - ostid_set_id(&lsm->lsm_oi, ++last_object_id); - - rc = obd_create(env, ec->ec_exp, oa, &lsm, oti); + rc = obd_create(env, ec->ec_exp, oa, oti); if (rc != 0) { CERROR("Cannot create objects: rc = %d\n", rc); goto failed; } created = 1; - /* See what object ID we were given */ - oa->o_oi = lsm->lsm_oi; oa->o_valid |= OBD_MD_FLID; - eco = cl_echo_object_find(ed, &lsm); + eco = cl_echo_object_find(ed, &oa->o_oi); if (IS_ERR(eco)) { rc = PTR_ERR(eco); goto failed; @@ -1190,9 +1137,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, failed: if (created && rc) - obd_destroy(env, ec->ec_exp, oa, lsm, oti, NULL); - if (lsm) - echo_free_memmd(ed, &lsm); + obd_destroy(env, ec->ec_exp, oa, oti); if (rc) CERROR("create object failed with: rc = %d\n", rc); return rc; @@ -1201,32 +1146,21 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, static int echo_get_object(struct echo_object **ecop, struct echo_device *ed, struct obdo *oa) { - struct lov_stripe_md *lsm = NULL; struct echo_object *eco; int rc; - if ((oa->o_valid & OBD_MD_FLID) == 0 || ostid_id(&oa->o_oi) == 0) { - /* disallow use of object id 0 */ - CERROR("No valid oid\n"); + if (!(oa->o_valid & OBD_MD_FLID) || !(oa->o_valid & OBD_MD_FLGROUP) || + !ostid_id(&oa->o_oi)) { + CERROR("invalid oid " DOSTID "\n", POSTID(&oa->o_oi)); return -EINVAL; } - rc = echo_alloc_memmd(ed, &lsm); - if (rc < 0) - return rc; - - lsm->lsm_oi = oa->o_oi; - if (!(oa->o_valid & OBD_MD_FLGROUP)) - ostid_set_seq_echo(&lsm->lsm_oi); - rc = 0; - eco = cl_echo_object_find(ed, &lsm); + eco = cl_echo_object_find(ed, &oa->o_oi); if (!IS_ERR(eco)) *ecop = eco; else rc = PTR_ERR(eco); - if (lsm) - echo_free_memmd(ed, &lsm); return rc; } @@ -1436,13 +1370,12 @@ static int echo_client_prep_commit(const struct lu_env *env, npages = tot_pages; for (i = 0; i < npages; i++, off += PAGE_SIZE) { - rnb[i].offset = off; - rnb[i].len = PAGE_SIZE; - rnb[i].flags = brw_flags; + rnb[i].rnb_offset = off; + rnb[i].rnb_len = PAGE_SIZE; + rnb[i].rnb_flags = brw_flags; } ioo.ioo_bufcnt = npages; - oti->oti_transno = 0; lpages = npages; ret = obd_preprw(env, rw, exp, oa, 1, &ioo, rnb, &lpages, @@ -1452,14 +1385,14 @@ static int echo_client_prep_commit(const struct lu_env *env, LASSERT(lpages == npages); for (i = 0; i < lpages; i++) { - struct page *page = lnb[i].page; + struct page *page = lnb[i].lnb_page; /* read past eof? */ - if (!page && lnb[i].rc == 0) + if (!page && lnb[i].lnb_rc == 0) continue; if (async) - lnb[i].flags |= OBD_BRW_ASYNC; + lnb[i].lnb_flags |= OBD_BRW_ASYNC; if (ostid_id(&oa->o_oi) == ECHO_PERSISTENT_OBJID || (oa->o_valid & OBD_MD_FLFLAGS) == 0 || @@ -1469,13 +1402,13 @@ static int echo_client_prep_commit(const struct lu_env *env, if (rw == OBD_BRW_WRITE) echo_client_page_debug_setup(page, rw, ostid_id(&oa->o_oi), - rnb[i].offset, - rnb[i].len); + rnb[i].rnb_offset, + rnb[i].rnb_len); else echo_client_page_debug_check(page, ostid_id(&oa->o_oi), - rnb[i].offset, - rnb[i].len); + rnb[i].rnb_offset, + rnb[i].rnb_len); } ret = obd_commitrw(env, rw, exp, oa, 1, &ioo, @@ -1613,8 +1546,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - rc = obd_destroy(env, ec->ec_exp, oa, NULL, - &dummy_oti, NULL); + rc = obd_destroy(env, ec->ec_exp, oa, &dummy_oti); if (rc == 0) eco->eo_deleted = 1; echo_put_object(eco); diff --git a/drivers/staging/lustre/lustre/obdecho/echo_internal.h b/drivers/staging/lustre/lustre/obdecho/echo_internal.h index f5034a253f6d..966414fd5424 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_internal.h +++ b/drivers/staging/lustre/lustre/obdecho/echo_internal.h @@ -33,9 +33,9 @@ /* The persistent object (i.e. actually stores stuff!) */ #define ECHO_PERSISTENT_OBJID 1ULL -#define ECHO_PERSISTENT_SIZE ((__u64)(1<<20)) +#define ECHO_PERSISTENT_SIZE ((__u64)(1 << 20)) /* block size to use for data verification */ -#define OBD_ECHO_BLOCK_SIZE (4<<10) +#define OBD_ECHO_BLOCK_SIZE (4 << 10) #endif diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 7e83d395b998..f0062d44ee03 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -119,6 +119,7 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, spin_lock(&cli->cl_loi_list_lock); cli->cl_max_rpcs_in_flight = val; + client_adjust_max_dirty(cli); spin_unlock(&cli->cl_loi_list_lock); return count; @@ -136,10 +137,10 @@ static ssize_t max_dirty_mb_show(struct kobject *kobj, int mult; spin_lock(&cli->cl_loi_list_lock); - val = cli->cl_dirty_max; + val = cli->cl_dirty_max_pages; spin_unlock(&cli->cl_loi_list_lock); - mult = 1 << 20; + mult = 1 << (20 - PAGE_SHIFT); return lprocfs_read_frac_helper(buf, PAGE_SIZE, val, mult); } @@ -166,7 +167,7 @@ static ssize_t max_dirty_mb_store(struct kobject *kobj, return -ERANGE; spin_lock(&cli->cl_loi_list_lock); - cli->cl_dirty_max = (u32)(pages_number << PAGE_SHIFT); + cli->cl_dirty_max_pages = pages_number; osc_wake_cache_waiters(cli); spin_unlock(&cli->cl_loi_list_lock); @@ -181,11 +182,11 @@ static int osc_cached_mb_seq_show(struct seq_file *m, void *v) int shift = 20 - PAGE_SHIFT; seq_printf(m, - "used_mb: %d\n" - "busy_cnt: %d\n", - (atomic_read(&cli->cl_lru_in_list) + - atomic_read(&cli->cl_lru_busy)) >> shift, - atomic_read(&cli->cl_lru_busy)); + "used_mb: %ld\n" + "busy_cnt: %ld\n", + (atomic_long_read(&cli->cl_lru_in_list) + + atomic_long_read(&cli->cl_lru_busy)) >> shift, + atomic_long_read(&cli->cl_lru_busy)); return 0; } @@ -197,8 +198,10 @@ static ssize_t osc_cached_mb_seq_write(struct file *file, { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; - int pages_number, mult, rc; + long pages_number, rc; char kernbuf[128]; + int mult; + u64 val; if (count >= sizeof(kernbuf)) return -EINVAL; @@ -210,14 +213,18 @@ static ssize_t osc_cached_mb_seq_write(struct file *file, mult = 1 << (20 - PAGE_SHIFT); buffer += lprocfs_find_named_value(kernbuf, "used_mb:", &count) - kernbuf; - rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult); + rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult); if (rc) return rc; + if (val > LONG_MAX) + return -ERANGE; + pages_number = (long)val; + if (pages_number < 0) return -ERANGE; - rc = atomic_read(&cli->cl_lru_in_list) - pages_number; + rc = atomic_long_read(&cli->cl_lru_in_list) - pages_number; if (rc > 0) { struct lu_env *env; int refcheck; @@ -244,7 +251,7 @@ static ssize_t cur_dirty_bytes_show(struct kobject *kobj, int len; spin_lock(&cli->cl_loi_list_lock); - len = sprintf(buf, "%lu\n", cli->cl_dirty); + len = sprintf(buf, "%lu\n", cli->cl_dirty_pages << PAGE_SHIFT); spin_unlock(&cli->cl_loi_list_lock); return len; @@ -583,6 +590,7 @@ static ssize_t max_pages_per_rpc_store(struct kobject *kobj, } spin_lock(&cli->cl_loi_list_lock); cli->cl_max_pages_per_rpc = val; + client_adjust_max_dirty(cli); spin_unlock(&cli->cl_loi_list_lock); return count; @@ -596,13 +604,14 @@ static ssize_t unstable_stats_show(struct kobject *kobj, struct obd_device *dev = container_of(kobj, struct obd_device, obd_kobj); struct client_obd *cli = &dev->u.cli; - int pages, mb; + long pages; + int mb; - pages = atomic_read(&cli->cl_unstable_count); + pages = atomic_long_read(&cli->cl_unstable_count); mb = (pages * PAGE_SIZE) >> 20; - return sprintf(buf, "unstable_pages: %8d\n" - "unstable_mb: %8d\n", pages, mb); + return sprintf(buf, "unstable_pages: %20ld\n" + "unstable_mb: %10d\n", pages, mb); } LUSTRE_RO_ATTR(unstable_stats); diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index d011135802d5..4bbe219add98 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -44,7 +44,7 @@ static int extent_debug; /* set it to be true for more debug */ static void osc_update_pending(struct osc_object *obj, int cmd, int delta); static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, - int state); + enum osc_extent_state state); static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, struct osc_async_page *oap, int sent, int rc); static int osc_make_ready(const struct lu_env *env, struct osc_async_page *oap, @@ -177,7 +177,7 @@ static int osc_extent_sanity_check0(struct osc_extent *ext, { struct osc_object *obj = ext->oe_obj; struct osc_async_page *oap; - int page_count; + size_t page_count; int rc = 0; if (!osc_object_is_locked(obj)) { @@ -632,7 +632,7 @@ static inline int overlapped(struct osc_extent *ex1, struct osc_extent *ex2) */ static struct osc_extent *osc_extent_find(const struct lu_env *env, struct osc_object *obj, pgoff_t index, - int *grants) + unsigned int *grants) { struct client_obd *cli = osc_cli(obj); struct osc_lock *olck; @@ -643,10 +643,10 @@ static struct osc_extent *osc_extent_find(const struct lu_env *env, struct osc_extent *found = NULL; pgoff_t chunk; pgoff_t max_end; - int max_pages; /* max_pages_per_rpc */ - int chunksize; + unsigned int max_pages; /* max_pages_per_rpc */ + unsigned int chunksize; int ppc_bits; /* pages per chunk bits */ - int chunk_mask; + pgoff_t chunk_mask; int rc; cur = osc_extent_alloc(obj); @@ -700,8 +700,8 @@ restart: if (!ext) ext = first_extent(obj); while (ext) { - loff_t ext_chk_start = ext->oe_start >> ppc_bits; - loff_t ext_chk_end = ext->oe_end >> ppc_bits; + pgoff_t ext_chk_start = ext->oe_start >> ppc_bits; + pgoff_t ext_chk_end = ext->oe_end >> ppc_bits; LASSERT(sanity_check_nolock(ext) == 0); if (chunk > ext_chk_end + 1) @@ -913,7 +913,7 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, return 0; } -static int extent_wait_cb(struct osc_extent *ext, int state) +static int extent_wait_cb(struct osc_extent *ext, enum osc_extent_state state) { int ret; @@ -928,7 +928,7 @@ static int extent_wait_cb(struct osc_extent *ext, int state) * Wait for the extent's state to become @state. */ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, - int state) + enum osc_extent_state state) { struct osc_object *obj = ext->oe_obj; struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(600), NULL, @@ -958,8 +958,8 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, rc = l_wait_event(ext->oe_waitq, extent_wait_cb(ext, state), &lwi); if (rc == -ETIMEDOUT) { OSC_EXTENT_DUMP(D_ERROR, ext, - "%s: wait ext to %d timedout, recovery in progress?\n", - osc_export(obj)->exp_obd->obd_name, state); + "%s: wait ext to %u timedout, recovery in progress?\n", + osc_export(obj)->exp_obd->obd_name, state); lwi = LWI_INTR(NULL, NULL); rc = l_wait_event(ext->oe_waitq, extent_wait_cb(ext, state), @@ -1099,7 +1099,7 @@ static int osc_extent_make_ready(const struct lu_env *env, struct osc_async_page *oap; struct osc_async_page *last = NULL; struct osc_object *obj = ext->oe_obj; - int page_count = 0; + unsigned int page_count = 0; int rc; /* we're going to grab page lock, so object lock must not be taken. */ @@ -1140,9 +1140,11 @@ static int osc_extent_make_ready(const struct lu_env *env, * the size of file. */ if (!(last->oap_async_flags & ASYNC_COUNT_STABLE)) { - last->oap_count = osc_refresh_count(env, last, OBD_BRW_WRITE); - LASSERT(last->oap_count > 0); - LASSERT(last->oap_page_off + last->oap_count <= PAGE_SIZE); + int last_oap_count = osc_refresh_count(env, last, OBD_BRW_WRITE); + + LASSERT(last_oap_count > 0); + LASSERT(last->oap_page_off + last_oap_count <= PAGE_SIZE); + last->oap_count = last_oap_count; spin_lock(&last->oap_lock); last->oap_async_flags |= ASYNC_COUNT_STABLE; spin_unlock(&last->oap_lock); @@ -1174,7 +1176,8 @@ static int osc_extent_make_ready(const struct lu_env *env, * called to expand the extent for the same IO. To expand the extent, the * page index must be in the same or next chunk of ext->oe_end. */ -static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants) +static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, + unsigned int *grants) { struct osc_object *obj = ext->oe_obj; struct client_obd *cli = osc_cli(obj); @@ -1183,7 +1186,7 @@ static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants) pgoff_t chunk = index >> ppc_bits; pgoff_t end_chunk; pgoff_t end_index; - int chunksize = 1 << cli->cl_chunkbits; + unsigned int chunksize = 1 << cli->cl_chunkbits; int rc = 0; LASSERT(ext->oe_max_end >= index && ext->oe_start <= index); @@ -1361,7 +1364,7 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, if (rc == 0 && srvlock) { struct lu_device *ld = opg->ops_cl.cpl_obj->co_lu.lo_dev; struct osc_stats *stats = &lu2osc_dev(ld)->od_stats; - int bytes = oap->oap_count; + size_t bytes = oap->oap_count; if (crt == CRT_READ) stats->os_lockless_reads += bytes; @@ -1383,18 +1386,16 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, #define OSC_DUMP_GRANT(lvl, cli, fmt, args...) do { \ struct client_obd *__tmp = (cli); \ - CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %d/%d " \ - "unstable_pages: %d/%d dropped: %ld avail: %ld, " \ - "reserved: %ld, flight: %d } lru {in list: %d, " \ - "left: %d, waiters: %d }" fmt, \ + CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %ld/%lu " \ + "dropped: %ld avail: %ld, reserved: %ld, flight: %d }" \ + "lru {in list: %ld, left: %ld, waiters: %d }" fmt "\n", \ __tmp->cl_import->imp_obd->obd_name, \ - __tmp->cl_dirty, __tmp->cl_dirty_max, \ - atomic_read(&obd_dirty_pages), obd_max_dirty_pages, \ - atomic_read(&obd_unstable_pages), obd_max_dirty_pages, \ + __tmp->cl_dirty_pages, __tmp->cl_dirty_max_pages, \ + atomic_long_read(&obd_dirty_pages), obd_max_dirty_pages, \ __tmp->cl_lost_grant, __tmp->cl_avail_grant, \ __tmp->cl_reserved_grant, __tmp->cl_w_in_flight, \ - atomic_read(&__tmp->cl_lru_in_list), \ - atomic_read(&__tmp->cl_lru_busy), \ + atomic_long_read(&__tmp->cl_lru_in_list), \ + atomic_long_read(&__tmp->cl_lru_busy), \ atomic_read(&__tmp->cl_lru_shrinkers), ##args); \ } while (0) @@ -1404,8 +1405,8 @@ static void osc_consume_write_grant(struct client_obd *cli, { assert_spin_locked(&cli->cl_loi_list_lock); LASSERT(!(pga->flag & OBD_BRW_FROM_GRANT)); - atomic_inc(&obd_dirty_pages); - cli->cl_dirty += PAGE_SIZE; + atomic_long_inc(&obd_dirty_pages); + cli->cl_dirty_pages++; pga->flag |= OBD_BRW_FROM_GRANT; CDEBUG(D_CACHE, "using %lu grant credits for brw %p page %p\n", PAGE_SIZE, pga, pga->pg); @@ -1424,12 +1425,12 @@ static void osc_release_write_grant(struct client_obd *cli, } pga->flag &= ~OBD_BRW_FROM_GRANT; - atomic_dec(&obd_dirty_pages); - cli->cl_dirty -= PAGE_SIZE; + atomic_long_dec(&obd_dirty_pages); + cli->cl_dirty_pages--; if (pga->flag & OBD_BRW_NOCACHE) { pga->flag &= ~OBD_BRW_NOCACHE; - atomic_dec(&obd_dirty_transit_pages); - cli->cl_dirty_transit -= PAGE_SIZE; + atomic_long_dec(&obd_dirty_transit_pages); + cli->cl_dirty_transit--; } } @@ -1494,11 +1495,11 @@ static void osc_unreserve_grant(struct client_obd *cli, static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, unsigned int lost_grant) { - int grant = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; + unsigned long grant = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; spin_lock(&cli->cl_loi_list_lock); - atomic_sub(nr_pages, &obd_dirty_pages); - cli->cl_dirty -= nr_pages << PAGE_SHIFT; + atomic_long_sub(nr_pages, &obd_dirty_pages); + cli->cl_dirty_pages -= nr_pages; cli->cl_lost_grant += lost_grant; if (cli->cl_avail_grant < grant && cli->cl_lost_grant >= grant) { /* borrow some grant from truncate to avoid the case that @@ -1511,7 +1512,7 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, spin_unlock(&cli->cl_loi_list_lock); CDEBUG(D_CACHE, "lost %u grant: %lu avail: %lu dirty: %lu\n", lost_grant, cli->cl_lost_grant, - cli->cl_avail_grant, cli->cl_dirty); + cli->cl_avail_grant, cli->cl_dirty_pages << PAGE_SHIFT); } /** @@ -1535,19 +1536,18 @@ static int osc_enter_cache_try(struct client_obd *cli, { int rc; - OSC_DUMP_GRANT(D_CACHE, cli, "need:%d.\n", bytes); + OSC_DUMP_GRANT(D_CACHE, cli, "need:%d\n", bytes); rc = osc_reserve_grant(cli, bytes); if (rc < 0) return 0; - if (cli->cl_dirty + PAGE_SIZE <= cli->cl_dirty_max && - atomic_read(&obd_unstable_pages) + 1 + - atomic_read(&obd_dirty_pages) <= obd_max_dirty_pages) { + if (cli->cl_dirty_pages <= cli->cl_dirty_max_pages && + atomic_long_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) { osc_consume_write_grant(cli, &oap->oap_brw_page); if (transient) { - cli->cl_dirty_transit += PAGE_SIZE; - atomic_inc(&obd_dirty_transit_pages); + cli->cl_dirty_transit++; + atomic_long_inc(&obd_dirty_transit_pages); oap->oap_brw_flags |= OBD_BRW_NOCACHE; } rc = 1; @@ -1581,11 +1581,13 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc = oap->oap_obj; struct lov_oinfo *loi = osc->oo_oinfo; struct osc_cache_waiter ocw; - struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(600), NULL, - LWI_ON_SIGNAL_NOOP, NULL); + struct l_wait_info lwi; int rc = -EDQUOT; - OSC_DUMP_GRANT(D_CACHE, cli, "need:%d.\n", bytes); + lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(AT_OFF ? obd_timeout : at_max), + NULL, LWI_ON_SIGNAL_NOOP, NULL); + + OSC_DUMP_GRANT(D_CACHE, cli, "need:%d\n", bytes); spin_lock(&cli->cl_loi_list_lock); @@ -1593,14 +1595,16 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, * of queued writes and create a discontiguous rpc stream */ if (OBD_FAIL_CHECK(OBD_FAIL_OSC_NO_GRANT) || - cli->cl_dirty_max < PAGE_SIZE || - cli->cl_ar.ar_force_sync || loi->loi_ar.ar_force_sync) { + !cli->cl_dirty_max_pages || cli->cl_ar.ar_force_sync || + loi->loi_ar.ar_force_sync) { + OSC_DUMP_GRANT(D_CACHE, cli, "forced sync i/o\n"); rc = -EDQUOT; goto out; } /* Hopefully normal case - cache space and write credits available */ if (osc_enter_cache_try(cli, oap, bytes, 0)) { + OSC_DUMP_GRANT(D_CACHE, cli, "granted from cache\n"); rc = 0; goto out; } @@ -1615,7 +1619,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, init_waitqueue_head(&ocw.ocw_waitq); ocw.ocw_oap = oap; ocw.ocw_grant = bytes; - while (cli->cl_dirty > 0 || cli->cl_w_in_flight > 0) { + while (cli->cl_dirty_pages > 0 || cli->cl_w_in_flight > 0) { list_add_tail(&ocw.ocw_entry, &cli->cl_cache_waiters); ocw.ocw_rc = 0; spin_unlock(&cli->cl_loi_list_lock); @@ -1629,32 +1633,49 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, spin_lock(&cli->cl_loi_list_lock); - /* l_wait_event is interrupted by signal, or timed out */ if (rc < 0) { - if (rc == -ETIMEDOUT) { - OSC_DUMP_GRANT(D_ERROR, cli, - "try to reserve %d.\n", bytes); - osc_extent_tree_dump(D_ERROR, osc); - rc = -EDQUOT; - } - + /* l_wait_event is interrupted by signal, or timed out */ list_del_init(&ocw.ocw_entry); - goto out; + break; } - LASSERT(list_empty(&ocw.ocw_entry)); rc = ocw.ocw_rc; if (rc != -EDQUOT) - goto out; + break; if (osc_enter_cache_try(cli, oap, bytes, 0)) { rc = 0; - goto out; + break; } } + + switch (rc) { + case 0: + OSC_DUMP_GRANT(D_CACHE, cli, "finally got grant space\n"); + break; + case -ETIMEDOUT: + OSC_DUMP_GRANT(D_CACHE, cli, + "timeout, fall back to sync i/o\n"); + osc_extent_tree_dump(D_CACHE, osc); + /* fall back to synchronous I/O */ + rc = -EDQUOT; + break; + case -EINTR: + /* Ensures restartability - LU-3581 */ + OSC_DUMP_GRANT(D_CACHE, cli, "interrupted\n"); + rc = -ERESTARTSYS; + break; + case -EDQUOT: + OSC_DUMP_GRANT(D_CACHE, cli, + "no grant space, fall back to sync i/o\n"); + break; + default: + CDEBUG(D_CACHE, "%s: event for cache space @ %p never arrived due to %d, fall back to sync i/o\n", + cli->cl_import->imp_obd->obd_name, &ocw, rc); + break; + } out: spin_unlock(&cli->cl_loi_list_lock); - OSC_DUMP_GRANT(D_CACHE, cli, "returned %d.\n", rc); return rc; } @@ -1670,19 +1691,17 @@ void osc_wake_cache_waiters(struct client_obd *cli) ocw->ocw_rc = -EDQUOT; /* we can't dirty more */ - if ((cli->cl_dirty + PAGE_SIZE > cli->cl_dirty_max) || - (atomic_read(&obd_unstable_pages) + 1 + - atomic_read(&obd_dirty_pages) > obd_max_dirty_pages)) { - CDEBUG(D_CACHE, "no dirty room: dirty: %ld osc max %ld, sys max %d\n", - cli->cl_dirty, - cli->cl_dirty_max, obd_max_dirty_pages); + if ((cli->cl_dirty_pages > cli->cl_dirty_max_pages) || + (atomic_long_read(&obd_dirty_pages) + 1 > + obd_max_dirty_pages)) { + CDEBUG(D_CACHE, "no dirty room: dirty: %ld osc max %ld, sys max %ld\n", + cli->cl_dirty_pages, cli->cl_dirty_max_pages, + obd_max_dirty_pages); goto wakeup; } - ocw->ocw_rc = 0; - if (!osc_enter_cache_try(cli, ocw->ocw_oap, ocw->ocw_grant, 0)) - ocw->ocw_rc = -EDQUOT; - + if (osc_enter_cache_try(cli, ocw->ocw_oap, ocw->ocw_grant, 0)) + ocw->ocw_rc = 0; wakeup: CDEBUG(D_CACHE, "wake up %p for oap %p, avail grant %ld, %d\n", ocw, ocw->ocw_oap, cli->cl_avail_grant, ocw->ocw_rc); @@ -1843,97 +1862,6 @@ static void osc_process_ar(struct osc_async_rc *ar, __u64 xid, ar->ar_force_sync = 0; } -/** - * Performs "unstable" page accounting. This function balances the - * increment operations performed in osc_inc_unstable_pages. It is - * registered as the RPC request callback, and is executed when the - * bulk RPC is committed on the server. Thus at this point, the pages - * involved in the bulk transfer are no longer considered unstable. - */ -void osc_dec_unstable_pages(struct ptlrpc_request *req) -{ - struct client_obd *cli = &req->rq_import->imp_obd->u.cli; - struct ptlrpc_bulk_desc *desc = req->rq_bulk; - int page_count = desc->bd_iov_count; - int i; - - /* No unstable page tracking */ - if (!cli->cl_cache) - return; - - LASSERT(page_count >= 0); - - for (i = 0; i < page_count; i++) - dec_node_page_state(desc->bd_iov[i].kiov_page, - NR_UNSTABLE_NFS); - - atomic_sub(page_count, &cli->cl_cache->ccc_unstable_nr); - LASSERT(atomic_read(&cli->cl_cache->ccc_unstable_nr) >= 0); - - atomic_sub(page_count, &cli->cl_unstable_count); - LASSERT(atomic_read(&cli->cl_unstable_count) >= 0); - - atomic_sub(page_count, &obd_unstable_pages); - LASSERT(atomic_read(&obd_unstable_pages) >= 0); - - spin_lock(&req->rq_lock); - req->rq_committed = 1; - req->rq_unstable = 0; - spin_unlock(&req->rq_lock); - - wake_up_all(&cli->cl_cache->ccc_unstable_waitq); -} - -/* "unstable" page accounting. See: osc_dec_unstable_pages. */ -void osc_inc_unstable_pages(struct ptlrpc_request *req) -{ - struct client_obd *cli = &req->rq_import->imp_obd->u.cli; - struct ptlrpc_bulk_desc *desc = req->rq_bulk; - long page_count = desc->bd_iov_count; - int i; - - /* No unstable page tracking */ - if (!cli->cl_cache) - return; - - LASSERT(page_count >= 0); - - for (i = 0; i < page_count; i++) - inc_node_page_state(desc->bd_iov[i].kiov_page, - NR_UNSTABLE_NFS); - - LASSERT(atomic_read(&cli->cl_cache->ccc_unstable_nr) >= 0); - atomic_add(page_count, &cli->cl_cache->ccc_unstable_nr); - - LASSERT(atomic_read(&cli->cl_unstable_count) >= 0); - atomic_add(page_count, &cli->cl_unstable_count); - - LASSERT(atomic_read(&obd_unstable_pages) >= 0); - atomic_add(page_count, &obd_unstable_pages); - - spin_lock(&req->rq_lock); - - /* - * If the request has already been committed (i.e. brw_commit - * called via rq_commit_cb), we need to undo the unstable page - * increments we just performed because rq_commit_cb wont be - * called again. Otherwise, just set the commit callback so the - * unstable page accounting is properly updated when the request - * is committed - */ - if (req->rq_committed) { - /* Drop lock before calling osc_dec_unstable_pages */ - spin_unlock(&req->rq_lock); - osc_dec_unstable_pages(req); - spin_lock(&req->rq_lock); - } else { - req->rq_unstable = 1; - req->rq_commit_cb = osc_dec_unstable_pages; - } - - spin_unlock(&req->rq_lock); -} - /* this must be called holding the loi list lock to give coverage to exit_cache, * async_flag maintenance, and oap_request */ @@ -1945,9 +1873,6 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, __u64 xid = 0; if (oap->oap_request) { - if (!rc) - osc_inc_unstable_pages(oap->oap_request); - xid = ptlrpc_req_xid(oap->oap_request); ptlrpc_req_finished(oap->oap_request); oap->oap_request = NULL; @@ -1979,7 +1904,7 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, */ static int try_to_add_extent_for_io(struct client_obd *cli, struct osc_extent *ext, struct list_head *rpclist, - int *pc, unsigned int *max_pages) + unsigned int *pc, unsigned int *max_pages) { struct osc_extent *tmp; struct osc_async_page *oap = list_first_entry(&ext->oe_pages, @@ -2032,12 +1957,13 @@ static int try_to_add_extent_for_io(struct client_obd *cli, * 5. Traverse the extent tree from the 1st extent; * 6. Above steps exit if there is no space in this RPC. */ -static int get_write_extents(struct osc_object *obj, struct list_head *rpclist) +static unsigned int get_write_extents(struct osc_object *obj, + struct list_head *rpclist) { struct client_obd *cli = osc_cli(obj); struct osc_extent *ext; struct osc_extent *temp; - int page_count = 0; + unsigned int page_count = 0; unsigned int max_pages = cli->cl_max_pages_per_rpc; LASSERT(osc_object_is_locked(obj)); @@ -2175,7 +2101,7 @@ osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli, struct osc_extent *ext; struct osc_extent *next; LIST_HEAD(rpclist); - int page_count = 0; + unsigned int page_count = 0; unsigned int max_pages = cli->cl_max_pages_per_rpc; int rc = 0; @@ -2390,7 +2316,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, struct client_obd *cli = oap->oap_cli; struct osc_object *osc = oap->oap_obj; pgoff_t index; - int grants = 0; + unsigned int grants = 0, tmp; int brw_flags = OBD_BRW_ASYNC; int cmd = OBD_BRW_WRITE; int need_release = 0; @@ -2434,9 +2360,6 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, return rc; } - if (osc_over_unstable_soft_limit(cli)) - brw_flags |= OBD_BRW_SOFT_SYNC; - oap->oap_cmd = cmd; oap->oap_page_off = ops->ops_from; oap->oap_count = ops->ops_to - ops->ops_from; @@ -2476,7 +2399,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, grants = 0; need_release = 1; } else if (ext->oe_end < index) { - int tmp = grants; + tmp = grants; /* try to expand this extent */ rc = osc_extent_expand(ext, index, &tmp); if (rc < 0) { @@ -2501,7 +2424,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, } if (!ext) { - int tmp = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; + tmp = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; /* try to find new extent to cover this page */ LASSERT(!oio->oi_active); @@ -2645,7 +2568,7 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, goto out; spin_lock(&oap->oap_lock); - oap->oap_async_flags |= ASYNC_READY|ASYNC_URGENT; + oap->oap_async_flags |= ASYNC_READY | ASYNC_URGENT; spin_unlock(&oap->oap_lock); if (memory_pressure_get()) diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index c8c3f1ca77be..9c8de15c309c 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -64,7 +64,7 @@ struct osc_io { /** true if this io is lockless. */ unsigned int oi_lockless; /** how many LRU pages are reserved for this IO */ - int oi_lru_reserved; + unsigned long oi_lru_reserved; /** active extents, we know how many bytes is going to be written, * so having an active extent will prevent it from being fragmented @@ -389,7 +389,7 @@ extern struct lu_device_type osc_device_type; extern struct lu_context_key osc_key; extern struct lu_context_key osc_session_key; -#define OSC_FLAGS (ASYNC_URGENT|ASYNC_READY) +#define OSC_FLAGS (ASYNC_URGENT | ASYNC_READY) int osc_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, @@ -608,7 +608,7 @@ struct osc_extent { /** link list of osc_object's oo_{hp|urgent|locking}_exts. */ struct list_head oe_link; /** state of this extent */ - unsigned int oe_state; + enum osc_extent_state oe_state; /** flags for this extent. */ unsigned int oe_intree:1, /** 0 is write, 1 is read */ diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 7a27f0961955..67fe0a254991 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -71,7 +71,6 @@ struct osc_async_page { struct client_obd *oap_cli; struct osc_object *oap_obj; - struct ldlm_lock *oap_ldlm_lock; spinlock_t oap_lock; }; @@ -134,9 +133,9 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo, int osc_process_config_base(struct obd_device *obd, struct lustre_cfg *cfg); int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, struct list_head *ext_list, int cmd); -int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, - int target, bool force); -int osc_lru_reclaim(struct client_obd *cli); +long osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, + long target, bool force); +long osc_lru_reclaim(struct client_obd *cli); unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock); @@ -198,7 +197,7 @@ int osc_quotacheck(struct obd_device *unused, struct obd_export *exp, int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk); void osc_inc_unstable_pages(struct ptlrpc_request *req); void osc_dec_unstable_pages(struct ptlrpc_request *req); -int osc_over_unstable_soft_limit(struct client_obd *cli); +bool osc_over_unstable_soft_limit(struct client_obd *cli); struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env, struct osc_object *obj, pgoff_t index, diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 6e3dcd38913f..8a559cbcdd0c 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -109,11 +109,11 @@ static int osc_io_submit(const struct lu_env *env, struct cl_page_list *qin = &queue->c2_qin; struct cl_page_list *qout = &queue->c2_qout; - int queued = 0; + unsigned int queued = 0; int result = 0; int cmd; int brw_flags; - int max_pages; + unsigned int max_pages; LASSERT(qin->pl_nr > 0); @@ -163,14 +163,19 @@ static int osc_io_submit(const struct lu_env *env, continue; } - cl_page_list_move(qout, qin, page); spin_lock(&oap->oap_lock); - oap->oap_async_flags = ASYNC_URGENT|ASYNC_READY; + oap->oap_async_flags = ASYNC_URGENT | ASYNC_READY; oap->oap_async_flags |= ASYNC_COUNT_STABLE; spin_unlock(&oap->oap_lock); osc_page_submit(env, opg, crt, brw_flags); list_add_tail(&oap->oap_pending_item, &list); + + if (page->cp_sync_io) + cl_page_list_move(qout, qin, page); + else /* async IO */ + cl_page_list_del(env, qin, page); + if (++queued == max_pages) { queued = 0; result = osc_queue_sync_pages(env, osc, &list, cmd, @@ -195,7 +200,7 @@ static int osc_io_submit(const struct lu_env *env, * Expand stripe KMS if necessary. */ static void osc_page_touch_at(const struct lu_env *env, - struct cl_object *obj, pgoff_t idx, unsigned to) + struct cl_object *obj, pgoff_t idx, size_t to) { struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo; struct cl_attr *attr = &osc_env_info(env)->oti_attr; @@ -228,7 +233,7 @@ static void osc_page_touch_at(const struct lu_env *env, attr->cat_size = kms; valid |= CAT_SIZE; } - cl_object_attr_set(env, obj, attr, valid); + cl_object_attr_update(env, obj, attr, valid); cl_object_attr_unlock(obj); } @@ -314,8 +319,8 @@ static int osc_io_rw_iter_init(const struct lu_env *env, struct osc_object *osc = cl2osc(ios->cis_obj); struct client_obd *cli = osc_cli(osc); unsigned long c; - unsigned int npages; - unsigned int max_pages; + unsigned long npages; + unsigned long max_pages; if (cl_io_is_append(io)) return 0; @@ -328,15 +333,15 @@ static int osc_io_rw_iter_init(const struct lu_env *env, if (npages > max_pages) npages = max_pages; - c = atomic_read(cli->cl_lru_left); + c = atomic_long_read(cli->cl_lru_left); if (c < npages && osc_lru_reclaim(cli) > 0) - c = atomic_read(cli->cl_lru_left); + c = atomic_long_read(cli->cl_lru_left); while (c >= npages) { - if (c == atomic_cmpxchg(cli->cl_lru_left, c, c - npages)) { + if (c == atomic_long_cmpxchg(cli->cl_lru_left, c, c - npages)) { oio->oi_lru_reserved = npages; break; } - c = atomic_read(cli->cl_lru_left); + c = atomic_long_read(cli->cl_lru_left); } return 0; @@ -350,7 +355,7 @@ static void osc_io_rw_iter_fini(const struct lu_env *env, struct client_obd *cli = osc_cli(osc); if (oio->oi_lru_reserved > 0) { - atomic_add(oio->oi_lru_reserved, cli->cl_lru_left); + atomic_long_add(oio->oi_lru_reserved, cli->cl_lru_left); oio->oi_lru_reserved = 0; } oio->oi_write_osclock = NULL; @@ -364,7 +369,7 @@ static int osc_io_fault_start(const struct lu_env *env, io = ios->cis_io; fio = &io->u.ci_fault; - CDEBUG(D_INFO, "%lu %d %d\n", + CDEBUG(D_INFO, "%lu %d %zu\n", fio->ft_index, fio->ft_writable, fio->ft_nob); /* * If mapping is writeable, adjust kms to cover this page, @@ -471,18 +476,21 @@ static int osc_io_setattr_start(const struct lu_env *env, attr->cat_ctime = lvb->lvb_ctime; cl_valid |= CAT_CTIME; } - result = cl_object_attr_set(env, obj, attr, cl_valid); + result = cl_object_attr_update(env, obj, attr, + cl_valid); } cl_object_attr_unlock(obj); } memset(oa, 0, sizeof(*oa)); if (result == 0) { oa->o_oi = loi->loi_oi; + obdo_set_parent_fid(oa, io->u.ci_setattr.sa_parent_fid); + oa->o_stripe_idx = io->u.ci_setattr.sa_stripe_index; oa->o_mtime = attr->cat_mtime; oa->o_atime = attr->cat_atime; oa->o_ctime = attr->cat_ctime; - oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLATIME | - OBD_MD_FLCTIME | OBD_MD_FLMTIME; + oa->o_valid |= OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLATIME | + OBD_MD_FLCTIME | OBD_MD_FLMTIME; if (ia_valid & ATTR_SIZE) { oa->o_size = size; oa->o_blocks = OBD_OBJECT_EOF; @@ -559,7 +567,7 @@ static int osc_io_read_start(const struct lu_env *env, if (!slice->cis_io->ci_noatime) { cl_object_attr_lock(obj); attr->cat_atime = ktime_get_real_seconds(); - rc = cl_object_attr_set(env, obj, attr, CAT_ATIME); + rc = cl_object_attr_update(env, obj, attr, CAT_ATIME); cl_object_attr_unlock(obj); } return rc; @@ -576,7 +584,7 @@ static int osc_io_write_start(const struct lu_env *env, cl_object_attr_lock(obj); attr->cat_ctime = ktime_get_real_seconds(); attr->cat_mtime = attr->cat_ctime; - rc = cl_object_attr_set(env, obj, attr, CAT_MTIME | CAT_CTIME); + rc = cl_object_attr_update(env, obj, attr, CAT_MTIME | CAT_CTIME); cl_object_attr_unlock(obj); return rc; diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 717d3ffb6789..39a8a5851603 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -222,7 +222,7 @@ static void osc_lock_lvb_update(const struct lu_env *env, ldlm_lock_allow_match_locked(dlmlock); } - cl_object_attr_set(env, obj, attr, valid); + cl_object_attr_update(env, obj, attr, valid); cl_object_attr_unlock(obj); } @@ -467,7 +467,7 @@ static int osc_dlm_blocking_ast0(const struct lu_env *env, */ attr->cat_kms = ldlm_extent_shift_kms(dlmlock, old_kms); - cl_object_attr_set(env, obj, attr, CAT_KMS); + cl_object_attr_update(env, obj, attr, CAT_KMS); cl_object_attr_unlock(obj); unlock_res_and_lock(dlmlock); diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c index d211d1905e83..aae3a2d4243f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_object.c +++ b/drivers/staging/lustre/lustre/osc/osc_object.c @@ -159,8 +159,8 @@ static int osc_attr_get(const struct lu_env *env, struct cl_object *obj, return 0; } -static int osc_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid) +static int osc_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid) { struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; struct ost_lvb *lvb = &oinfo->loi_lvb; @@ -195,7 +195,6 @@ static int osc_object_glimpse(const struct lu_env *env, static int osc_object_ast_clear(struct ldlm_lock *lock, void *data) { - LASSERT(lock->l_granted_mode == lock->l_req_mode); if (lock->l_ast_data == data) lock->l_ast_data = NULL; return LDLM_ITER_CONTINUE; @@ -262,7 +261,7 @@ static const struct cl_object_operations osc_ops = { .coo_lock_init = osc_lock_init, .coo_io_init = osc_io_init, .coo_attr_get = osc_attr_get, - .coo_attr_set = osc_attr_set, + .coo_attr_update = osc_attr_update, .coo_glimpse = osc_object_glimpse, .coo_prune = osc_object_prune }; diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 355f496a2093..2a7a70aa9e80 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -323,32 +323,6 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj, return result; } -int osc_over_unstable_soft_limit(struct client_obd *cli) -{ - long obd_upages, obd_dpages, osc_upages; - - /* Can't check cli->cl_unstable_count, therefore, no soft limit */ - if (!cli) - return 0; - - obd_upages = atomic_read(&obd_unstable_pages); - obd_dpages = atomic_read(&obd_dirty_pages); - - osc_upages = atomic_read(&cli->cl_unstable_count); - - /* - * obd_max_dirty_pages is the max number of (dirty + unstable) - * pages allowed at any given time. To simulate an unstable page - * only limit, we subtract the current number of dirty pages - * from this max. This difference is roughly the amount of pages - * currently available for unstable pages. Thus, the soft limit - * is half of that difference. Check osc_upages to ensure we don't - * set SOFT_SYNC for OSCs without any outstanding unstable pages. - */ - return osc_upages && - obd_upages >= (obd_max_dirty_pages - obd_dpages) / 2; -} - /** * Helper function called by osc_io_submit() for every page in an immediate * transfer (i.e., transferred synchronously). @@ -368,9 +342,6 @@ void osc_page_submit(const struct lu_env *env, struct osc_page *opg, oap->oap_count = opg->ops_to - opg->ops_from; oap->oap_brw_flags = brw_flags | OBD_BRW_SYNC; - if (osc_over_unstable_soft_limit(oap->oap_cli)) - oap->oap_brw_flags |= OBD_BRW_SOFT_SYNC; - if (capable(CFS_CAP_SYS_RESOURCE)) { oap->oap_brw_flags |= OBD_BRW_NOQUOTA; oap->oap_cmd |= OBD_BRW_NOQUOTA; @@ -409,7 +380,7 @@ static const int lru_shrink_max = 8 << (20 - PAGE_SHIFT); /* 8M */ static int osc_cache_too_much(struct client_obd *cli) { struct cl_client_cache *cache = cli->cl_cache; - int pages = atomic_read(&cli->cl_lru_in_list); + long pages = atomic_long_read(&cli->cl_lru_in_list); unsigned long budget; budget = cache->ccc_lru_max / (atomic_read(&cache->ccc_users) - 2); @@ -417,7 +388,7 @@ static int osc_cache_too_much(struct client_obd *cli) /* if it's going to run out LRU slots, we should free some, but not * too much to maintain fairness among OSCs. */ - if (atomic_read(cli->cl_lru_left) < cache->ccc_lru_max >> 4) { + if (atomic_long_read(cli->cl_lru_left) < cache->ccc_lru_max >> 4) { if (pages >= budget) return lru_shrink_max; else if (pages >= budget / 2) @@ -444,7 +415,7 @@ void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) { LIST_HEAD(lru); struct osc_async_page *oap; - int npages = 0; + long npages = 0; list_for_each_entry(oap, plist, oap_pending_item) { struct osc_page *opg = oap2osc_page(oap); @@ -460,8 +431,8 @@ void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) if (npages > 0) { spin_lock(&cli->cl_lru_list_lock); list_splice_tail(&lru, &cli->cl_lru_list); - atomic_sub(npages, &cli->cl_lru_busy); - atomic_add(npages, &cli->cl_lru_in_list); + atomic_long_sub(npages, &cli->cl_lru_busy); + atomic_long_add(npages, &cli->cl_lru_in_list); spin_unlock(&cli->cl_lru_list_lock); /* XXX: May set force to be true for better performance */ @@ -472,9 +443,9 @@ void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) static void __osc_lru_del(struct client_obd *cli, struct osc_page *opg) { - LASSERT(atomic_read(&cli->cl_lru_in_list) > 0); + LASSERT(atomic_long_read(&cli->cl_lru_in_list) > 0); list_del_init(&opg->ops_lru); - atomic_dec(&cli->cl_lru_in_list); + atomic_long_dec(&cli->cl_lru_in_list); } /** @@ -488,12 +459,12 @@ static void osc_lru_del(struct client_obd *cli, struct osc_page *opg) if (!list_empty(&opg->ops_lru)) { __osc_lru_del(cli, opg); } else { - LASSERT(atomic_read(&cli->cl_lru_busy) > 0); - atomic_dec(&cli->cl_lru_busy); + LASSERT(atomic_long_read(&cli->cl_lru_busy) > 0); + atomic_long_dec(&cli->cl_lru_busy); } spin_unlock(&cli->cl_lru_list_lock); - atomic_inc(cli->cl_lru_left); + atomic_long_inc(cli->cl_lru_left); /* this is a great place to release more LRU pages if * this osc occupies too many LRU pages and kernel is * stealing one of them. @@ -518,7 +489,7 @@ static void osc_lru_use(struct client_obd *cli, struct osc_page *opg) spin_lock(&cli->cl_lru_list_lock); __osc_lru_del(cli, opg); spin_unlock(&cli->cl_lru_list_lock); - atomic_inc(&cli->cl_lru_busy); + atomic_long_inc(&cli->cl_lru_busy); } } @@ -539,11 +510,33 @@ static void discard_pagevec(const struct lu_env *env, struct cl_io *io, } } +/** + * Check if a cl_page can be released, i.e, it's not being used. + * + * If unstable account is turned on, bulk transfer may hold one refcount + * for recovery so we need to check vmpage refcount as well; otherwise, + * even we can destroy cl_page but the corresponding vmpage can't be reused. + */ +static inline bool lru_page_busy(struct client_obd *cli, struct cl_page *page) +{ + if (cl_page_in_use_noref(page)) + return true; + + if (cli->cl_cache->ccc_unstable_check) { + struct page *vmpage = cl_page_vmpage(page); + + /* vmpage have two known users: cl_page and VM page cache */ + if (page_count(vmpage) - page_mapcount(vmpage) > 2) + return true; + } + return false; +} + /** * Drop @target of pages from LRU at most. */ -int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, - int target, bool force) +long osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, + long target, bool force) { struct cl_io *io; struct cl_object *clobj = NULL; @@ -551,12 +544,12 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, struct osc_page *opg; struct osc_page *temp; int maxscan = 0; - int count = 0; + long count = 0; int index = 0; int rc = 0; - LASSERT(atomic_read(&cli->cl_lru_in_list) >= 0); - if (atomic_read(&cli->cl_lru_in_list) == 0 || target <= 0) + LASSERT(atomic_long_read(&cli->cl_lru_in_list) >= 0); + if (atomic_long_read(&cli->cl_lru_in_list) == 0 || target <= 0) return 0; if (!force) { @@ -575,7 +568,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, io = &osc_env_info(env)->oti_io; spin_lock(&cli->cl_lru_list_lock); - maxscan = min(target << 1, atomic_read(&cli->cl_lru_in_list)); + maxscan = min(target << 1, atomic_long_read(&cli->cl_lru_in_list)); list_for_each_entry_safe(opg, temp, &cli->cl_lru_list, ops_lru) { struct cl_page *page; bool will_free = false; @@ -584,7 +577,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, break; page = opg->ops_cl.cpl_page; - if (cl_page_in_use_noref(page)) { + if (lru_page_busy(cli, page)) { list_move_tail(&opg->ops_lru, &cli->cl_lru_list); continue; } @@ -620,7 +613,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, } if (cl_page_own_try(env, io, page) == 0) { - if (!cl_page_in_use_noref(page)) { + if (!lru_page_busy(cli, page)) { /* remove it from lru list earlier to avoid * lock contention */ @@ -663,24 +656,19 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, atomic_dec(&cli->cl_lru_shrinkers); if (count > 0) { - atomic_add(count, cli->cl_lru_left); + atomic_long_add(count, cli->cl_lru_left); wake_up_all(&osc_lru_waitq); } return count > 0 ? count : rc; } -static inline int max_to_shrink(struct client_obd *cli) -{ - return min(atomic_read(&cli->cl_lru_in_list) >> 1, lru_shrink_max); -} - -int osc_lru_reclaim(struct client_obd *cli) +long osc_lru_reclaim(struct client_obd *cli) { struct cl_env_nest nest; struct lu_env *env; struct cl_client_cache *cache = cli->cl_cache; int max_scans; - int rc = 0; + long rc = 0; LASSERT(cache); @@ -693,15 +681,15 @@ int osc_lru_reclaim(struct client_obd *cli) if (rc == -EBUSY) rc = 0; - CDEBUG(D_CACHE, "%s: Free %d pages from own LRU: %p.\n", + CDEBUG(D_CACHE, "%s: Free %ld pages from own LRU: %p.\n", cli->cl_import->imp_obd->obd_name, rc, cli); goto out; } - CDEBUG(D_CACHE, "%s: cli %p no free slots, pages: %d, busy: %d.\n", + CDEBUG(D_CACHE, "%s: cli %p no free slots, pages: %ld, busy: %ld.\n", cli->cl_import->imp_obd->obd_name, cli, - atomic_read(&cli->cl_lru_in_list), - atomic_read(&cli->cl_lru_busy)); + atomic_long_read(&cli->cl_lru_in_list), + atomic_long_read(&cli->cl_lru_busy)); /* Reclaim LRU slots from other client_obd as it can't free enough * from its own. This should rarely happen. @@ -717,10 +705,10 @@ int osc_lru_reclaim(struct client_obd *cli) cli = list_entry(cache->ccc_lru.next, struct client_obd, cl_lru_osc); - CDEBUG(D_CACHE, "%s: cli %p LRU pages: %d, busy: %d.\n", + CDEBUG(D_CACHE, "%s: cli %p LRU pages: %ld, busy: %ld.\n", cli->cl_import->imp_obd->obd_name, cli, - atomic_read(&cli->cl_lru_in_list), - atomic_read(&cli->cl_lru_busy)); + atomic_long_read(&cli->cl_lru_in_list), + atomic_long_read(&cli->cl_lru_busy)); list_move_tail(&cli->cl_lru_osc, &cache->ccc_lru); if (osc_cache_too_much(cli) > 0) { @@ -737,11 +725,18 @@ int osc_lru_reclaim(struct client_obd *cli) out: cl_env_nested_put(&nest, env); - CDEBUG(D_CACHE, "%s: cli %p freed %d pages.\n", + CDEBUG(D_CACHE, "%s: cli %p freed %ld pages.\n", cli->cl_import->imp_obd->obd_name, cli, rc); return rc; } +/** + * osc_lru_reserve() is called to reserve an LRU slot for a cl_page. + * + * Usually the LRU slots are reserved in osc_io_iter_rw_init(). + * Only in the case that the LRU slots are in extreme shortage, it should + * have reserved enough slots for an IO. + */ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, struct osc_page *opg) { @@ -758,8 +753,8 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, goto out; } - LASSERT(atomic_read(cli->cl_lru_left) >= 0); - while (!atomic_add_unless(cli->cl_lru_left, -1, 0)) { + LASSERT(atomic_long_read(cli->cl_lru_left) >= 0); + while (!atomic_long_add_unless(cli->cl_lru_left, -1, 0)) { /* run out of LRU spaces, try to drop some by itself */ rc = osc_lru_reclaim(cli); if (rc < 0) @@ -770,7 +765,7 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, cond_resched(); rc = l_wait_event(osc_lru_waitq, - atomic_read(cli->cl_lru_left) > 0, + atomic_long_read(cli->cl_lru_left) > 0, &lwi); if (rc < 0) @@ -779,7 +774,7 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, out: if (rc >= 0) { - atomic_inc(&cli->cl_lru_busy); + atomic_long_inc(&cli->cl_lru_busy); opg->ops_in_lru = 1; rc = 0; } @@ -787,4 +782,151 @@ out: return rc; } +/** + * Atomic operations are expensive. We accumulate the accounting for the + * same page pgdat to get better performance. + * In practice this can work pretty good because the pages in the same RPC + * are likely from the same page zone. + */ +static inline void unstable_page_accounting(struct ptlrpc_bulk_desc *desc, + int factor) +{ + int page_count = desc->bd_iov_count; + pg_data_t *last = NULL; + int count = 0; + int i; + + for (i = 0; i < page_count; i++) { + pg_data_t *pgdat = page_pgdat(desc->bd_iov[i].bv_page); + + if (likely(pgdat == last)) { + ++count; + continue; + } + + if (count > 0) { + mod_node_page_state(pgdat, NR_UNSTABLE_NFS, + factor * count); + count = 0; + } + last = pgdat; + ++count; + } + if (count > 0) + mod_node_page_state(last, NR_UNSTABLE_NFS, factor * count); +} + +static inline void add_unstable_page_accounting(struct ptlrpc_bulk_desc *desc) +{ + unstable_page_accounting(desc, 1); +} + +static inline void dec_unstable_page_accounting(struct ptlrpc_bulk_desc *desc) +{ + unstable_page_accounting(desc, -1); +} + +/** + * Performs "unstable" page accounting. This function balances the + * increment operations performed in osc_inc_unstable_pages. It is + * registered as the RPC request callback, and is executed when the + * bulk RPC is committed on the server. Thus at this point, the pages + * involved in the bulk transfer are no longer considered unstable. + * + * If this function is called, the request should have been committed + * or req:rq_unstable must have been set; it implies that the unstable + * statistic have been added. + */ +void osc_dec_unstable_pages(struct ptlrpc_request *req) +{ + struct client_obd *cli = &req->rq_import->imp_obd->u.cli; + struct ptlrpc_bulk_desc *desc = req->rq_bulk; + int page_count = desc->bd_iov_count; + long unstable_count; + + LASSERT(page_count >= 0); + dec_unstable_page_accounting(desc); + + unstable_count = atomic_long_sub_return(page_count, + &cli->cl_unstable_count); + LASSERT(unstable_count >= 0); + + unstable_count = atomic_long_sub_return(page_count, + &cli->cl_cache->ccc_unstable_nr); + LASSERT(unstable_count >= 0); + if (!unstable_count) + wake_up_all(&cli->cl_cache->ccc_unstable_waitq); + + if (osc_cache_too_much(cli)) + (void)ptlrpcd_queue_work(cli->cl_lru_work); +} + +/** + * "unstable" page accounting. See: osc_dec_unstable_pages. + */ +void osc_inc_unstable_pages(struct ptlrpc_request *req) +{ + struct client_obd *cli = &req->rq_import->imp_obd->u.cli; + struct ptlrpc_bulk_desc *desc = req->rq_bulk; + long page_count = desc->bd_iov_count; + + /* No unstable page tracking */ + if (!cli->cl_cache || !cli->cl_cache->ccc_unstable_check) + return; + + add_unstable_page_accounting(desc); + atomic_long_add(page_count, &cli->cl_unstable_count); + atomic_long_add(page_count, &cli->cl_cache->ccc_unstable_nr); + + /* + * If the request has already been committed (i.e. brw_commit + * called via rq_commit_cb), we need to undo the unstable page + * increments we just performed because rq_commit_cb wont be + * called again. + */ + spin_lock(&req->rq_lock); + if (unlikely(req->rq_committed)) { + spin_unlock(&req->rq_lock); + + osc_dec_unstable_pages(req); + } else { + req->rq_unstable = 1; + spin_unlock(&req->rq_lock); + } +} + +/** + * Check if it piggybacks SOFT_SYNC flag to OST from this OSC. + * This function will be called by every BRW RPC so it's critical + * to make this function fast. + */ +bool osc_over_unstable_soft_limit(struct client_obd *cli) +{ + long unstable_nr, osc_unstable_count; + + /* Can't check cli->cl_unstable_count, therefore, no soft limit */ + if (!cli->cl_cache || !cli->cl_cache->ccc_unstable_check) + return false; + + osc_unstable_count = atomic_long_read(&cli->cl_unstable_count); + unstable_nr = atomic_long_read(&cli->cl_cache->ccc_unstable_nr); + + CDEBUG(D_CACHE, + "%s: cli: %p unstable pages: %lu, osc unstable pages: %lu\n", + cli->cl_import->imp_obd->obd_name, cli, + unstable_nr, osc_unstable_count); + + /* + * If the LRU slots are in shortage - 25% remaining AND this OSC + * has one full RPC window of unstable pages, it's a good chance + * to piggyback a SOFT_SYNC flag. + * Please notice that the OST won't take immediate response for the + * SOFT_SYNC request so active OSCs will have more chance to carry + * the flag, this is reasonable. + */ + return unstable_nr > cli->cl_cache->ccc_lru_max >> 2 && + osc_unstable_count > cli->cl_max_pages_per_rpc * + cli->cl_max_rpcs_in_flight; +} + /** @} osc */ diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 536b868ff776..749781f022e2 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -41,6 +41,7 @@ #include "../include/lustre_ha.h" #include "../include/lprocfs_status.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_debug.h" #include "../include/lustre_param.h" #include "../include/lustre_fid.h" @@ -102,36 +103,6 @@ static void osc_release_ppga(struct brw_page **ppga, u32 count); static int brw_interpret(const struct lu_env *env, struct ptlrpc_request *req, void *data, int rc); -/* Pack OSC object metadata for disk storage (LE byte order). */ -static int osc_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) -{ - int lmm_size; - - lmm_size = sizeof(**lmmp); - if (!lmmp) - return lmm_size; - - if (*lmmp && !lsm) { - kfree(*lmmp); - *lmmp = NULL; - return 0; - } else if (unlikely(lsm && ostid_id(&lsm->lsm_oi) == 0)) { - return -EBADF; - } - - if (!*lmmp) { - *lmmp = kzalloc(lmm_size, GFP_NOFS); - if (!*lmmp) - return -ENOMEM; - } - - if (lsm) - ostid_cpu_to_le(&lsm->lsm_oi, &(*lmmp)->lmm_oi); - - return lmm_size; -} - /* Unpack OSC object metadata from disk storage (LE byte order). */ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm, int lmm_bytes) @@ -189,7 +160,7 @@ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_MAXBYTES)) (*lsmp)->lsm_maxbytes = imp->imp_connect_data.ocd_maxbytes; else - (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES; + (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; return lsm_size; } @@ -427,24 +398,16 @@ static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, oinfo->oi_cb_up, oinfo, rqset); } -static int osc_real_create(struct obd_export *exp, struct obdo *oa, - struct lov_stripe_md **ea, - struct obd_trans_info *oti) +static int osc_create(const struct lu_env *env, struct obd_export *exp, + struct obdo *oa, struct obd_trans_info *oti) { struct ptlrpc_request *req; struct ost_body *body; - struct lov_stripe_md *lsm; int rc; LASSERT(oa); - LASSERT(ea); - - lsm = *ea; - if (!lsm) { - rc = obd_alloc_memmd(exp, &lsm); - if (rc < 0) - return rc; - } + LASSERT(oa->o_valid & OBD_MD_FLGROUP); + LASSERT(fid_seq_is_echo(ostid_seq(&oa->o_oi))); req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_CREATE); if (!req) { @@ -490,21 +453,10 @@ static int osc_real_create(struct obd_export *exp, struct obdo *oa, oa->o_blksize = cli_brw_size(exp->exp_obd); oa->o_valid |= OBD_MD_FLBLKSZ; - /* XXX LOV STACKING: the lsm that is passed to us from LOV does not - * have valid lsm_oinfo data structs, so don't go touching that. - * This needs to be fixed in a big way. - */ - lsm->lsm_oi = oa->o_oi; - *ea = lsm; - - if (oti) { - oti->oti_transno = lustre_msg_get_transno(req->rq_repmsg); - - if (oa->o_valid & OBD_MD_FLCOOKIE) { - if (!oti->oti_logcookies) - oti_alloc_cookies(oti, 1); - *oti->oti_logcookies = oa->o_lcookie; - } + if (oti && oa->o_valid & OBD_MD_FLCOOKIE) { + if (!oti->oti_logcookies) + oti->oti_logcookies = &oti->oti_onecookie; + *oti->oti_logcookies = oa->o_lcookie; } CDEBUG(D_HA, "transno: %lld\n", @@ -512,8 +464,6 @@ static int osc_real_create(struct obd_export *exp, struct obdo *oa, out_req: ptlrpc_req_finished(req); out: - if (rc && !*ea) - obd_free_memmd(exp, &lsm); return rc; } @@ -649,7 +599,7 @@ static int osc_resource_get_unused(struct obd_export *exp, struct obdo *oa, ostid_build_res_name(&oa->o_oi, &res_id); res = ldlm_resource_get(ns, NULL, &res_id, 0, 0); - if (!res) + if (IS_ERR(res)) return 0; LDLM_RESOURCE_ADDREF(res); @@ -689,30 +639,6 @@ static int osc_can_send_destroy(struct client_obd *cli) return 0; } -static int osc_create(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md **ea, - struct obd_trans_info *oti) -{ - int rc = 0; - - LASSERT(oa); - LASSERT(ea); - LASSERT(oa->o_valid & OBD_MD_FLGROUP); - - if ((oa->o_valid & OBD_MD_FLFLAGS) && - oa->o_flags == OBD_FL_RECREATE_OBJS) { - return osc_real_create(exp, oa, ea, oti); - } - - if (!fid_seq_is_mdt(ostid_seq(&oa->o_oi))) - return osc_real_create(exp, oa, ea, oti); - - /* we should not get here anymore */ - LBUG(); - - return rc; -} - /* Destroy requests can be async always on the client, and we don't even really * care about the return code since the client cannot do anything at all about * a destroy failure. @@ -725,8 +651,7 @@ static int osc_create(const struct lu_env *env, struct obd_export *exp, * cookies to the MDS after committing destroy transactions. */ static int osc_destroy(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md *ea, - struct obd_trans_info *oti, struct obd_export *md_export) + struct obdo *oa, struct obd_trans_info *oti) { struct client_obd *cli = &exp->exp_obd->u.cli; struct ptlrpc_request *req; @@ -794,42 +719,44 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp, static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, long writing_bytes) { - u32 bits = OBD_MD_FLBLOCKS|OBD_MD_FLGRANT; + u32 bits = OBD_MD_FLBLOCKS | OBD_MD_FLGRANT; LASSERT(!(oa->o_valid & bits)); oa->o_valid |= bits; spin_lock(&cli->cl_loi_list_lock); - oa->o_dirty = cli->cl_dirty; - if (unlikely(cli->cl_dirty - cli->cl_dirty_transit > - cli->cl_dirty_max)) { + oa->o_dirty = cli->cl_dirty_pages << PAGE_SHIFT; + if (unlikely(cli->cl_dirty_pages - cli->cl_dirty_transit > + cli->cl_dirty_max_pages)) { CERROR("dirty %lu - %lu > dirty_max %lu\n", - cli->cl_dirty, cli->cl_dirty_transit, cli->cl_dirty_max); + cli->cl_dirty_pages, cli->cl_dirty_transit, + cli->cl_dirty_max_pages); oa->o_undirty = 0; - } else if (unlikely(atomic_read(&obd_unstable_pages) + - atomic_read(&obd_dirty_pages) - - atomic_read(&obd_dirty_transit_pages) > - (long)(obd_max_dirty_pages + 1))) { + } else if (unlikely(atomic_long_read(&obd_dirty_pages) - + atomic_long_read(&obd_dirty_transit_pages) > + (obd_max_dirty_pages + 1))) { /* The atomic_read() allowing the atomic_inc() are * not covered by a lock thus they may safely race and trip * this CERROR() unless we add in a small fudge factor (+1). */ - CERROR("%s: dirty %d + %d - %d > system dirty_max %d\n", + CERROR("%s: dirty %ld + %ld > system dirty_max %lu\n", cli->cl_import->imp_obd->obd_name, - atomic_read(&obd_unstable_pages), - atomic_read(&obd_dirty_pages), - atomic_read(&obd_dirty_transit_pages), + atomic_long_read(&obd_dirty_pages), + atomic_long_read(&obd_dirty_transit_pages), obd_max_dirty_pages); oa->o_undirty = 0; - } else if (unlikely(cli->cl_dirty_max - cli->cl_dirty > 0x7fffffff)) { + } else if (unlikely(cli->cl_dirty_max_pages - cli->cl_dirty_pages > + 0x7fffffff)) { CERROR("dirty %lu - dirty_max %lu too big???\n", - cli->cl_dirty, cli->cl_dirty_max); + cli->cl_dirty_pages, cli->cl_dirty_max_pages); oa->o_undirty = 0; } else { - long max_in_flight = (cli->cl_max_pages_per_rpc << - PAGE_SHIFT)* - (cli->cl_max_rpcs_in_flight + 1); - oa->o_undirty = max(cli->cl_dirty_max, max_in_flight); + unsigned long max_in_flight; + + max_in_flight = (cli->cl_max_pages_per_rpc << PAGE_SHIFT) * + (cli->cl_max_rpcs_in_flight + 1); + oa->o_undirty = max(cli->cl_dirty_max_pages << PAGE_SHIFT, + max_in_flight); } oa->o_grant = cli->cl_avail_grant + cli->cl_reserved_grant; oa->o_dropped = cli->cl_lost_grant; @@ -1029,22 +956,24 @@ static void osc_init_grant(struct client_obd *cli, struct obd_connect_data *ocd) { /* * ocd_grant is the total grant amount we're expect to hold: if we've - * been evicted, it's the new avail_grant amount, cl_dirty will drop - * to 0 as inflight RPCs fail out; otherwise, it's avail_grant + dirty. + * been evicted, it's the new avail_grant amount, cl_dirty_pages will + * drop to 0 as inflight RPCs fail out; otherwise, it's avail_grant + + * dirty. * * race is tolerable here: if we're evicted, but imp_state already - * left EVICTED state, then cl_dirty must be 0 already. + * left EVICTED state, then cl_dirty_pages must be 0 already. */ spin_lock(&cli->cl_loi_list_lock); if (cli->cl_import->imp_state == LUSTRE_IMP_EVICTED) cli->cl_avail_grant = ocd->ocd_grant; else - cli->cl_avail_grant = ocd->ocd_grant - cli->cl_dirty; + cli->cl_avail_grant = ocd->ocd_grant - + (cli->cl_dirty_pages << PAGE_SHIFT); if (cli->cl_avail_grant < 0) { CWARN("%s: available grant < 0: avail/ocd/dirty %ld/%u/%ld\n", cli->cl_import->imp_obd->obd_name, cli->cl_avail_grant, - ocd->ocd_grant, cli->cl_dirty); + ocd->ocd_grant, cli->cl_dirty_pages << PAGE_SHIFT); /* workaround for servers which do not have the patch from * LU-2679 */ @@ -1181,7 +1110,7 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count, } while (nob > 0 && pg_count > 0) { - int count = pga[i]->count > nob ? nob : pga[i]->count; + unsigned int count = pga[i]->count > nob ? nob : pga[i]->count; /* corrupt the data before we compute the checksum, to * simulate an OST->client data error @@ -1191,7 +1120,7 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count, unsigned char *ptr = kmap(pga[i]->pg); int off = pga[i]->off & ~PAGE_MASK; - memcpy(ptr + off, "bad1", min(4, nob)); + memcpy(ptr + off, "bad1", min_t(typeof(nob), 4, nob)); kunmap(pga[i]->pg); } cfs_crypto_hash_update_page(hdesc, pga[i]->pg, @@ -1335,11 +1264,11 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli, if (i > 0 && can_merge_pages(pg_prev, pg)) { niobuf--; - niobuf->len += pg->count; + niobuf->rnb_len += pg->count; } else { - niobuf->offset = pg->off; - niobuf->len = pg->count; - niobuf->flags = pg->flag; + niobuf->rnb_offset = pg->off; + niobuf->rnb_len = pg->count; + niobuf->rnb_flags = pg->flag; } pg_prev = pg; } @@ -1418,6 +1347,11 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli, INIT_LIST_HEAD(&aa->aa_oaps); *reqp = req; + niobuf = req_capsule_client_get(pill, &RMF_NIOBUF_REMOTE); + CDEBUG(D_RPCTRACE, "brw rpc %p - object " DOSTID " offset %lld<>%lld\n", + req, POSTID(&oa->o_oi), niobuf[0].rnb_offset, + niobuf[niocount - 1].rnb_offset + niobuf[niocount - 1].rnb_len); + return 0; out: @@ -1463,7 +1397,8 @@ static int check_write_checksum(struct obdo *oa, const lnet_process_id_t *peer, oa->o_valid & OBD_MD_FLFID ? oa->o_parent_oid : 0, oa->o_valid & OBD_MD_FLFID ? oa->o_parent_ver : 0, POSTID(&oa->o_oi), pga[0]->off, - pga[page_count-1]->off + pga[page_count-1]->count - 1); + pga[page_count - 1]->off + + pga[page_count - 1]->count - 1); CERROR("original client csum %x (type %x), server csum %x (type %x), client csum now %x\n", client_cksum, client_cksum_type, server_cksum, cksum_type, new_cksum); @@ -1565,7 +1500,8 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc) char *router = ""; enum cksum_type cksum_type; - cksum_type = cksum_type_unpack(body->oa.o_valid&OBD_MD_FLFLAGS ? + cksum_type = cksum_type_unpack(body->oa.o_valid & + OBD_MD_FLFLAGS ? body->oa.o_flags : 0); client_cksum = osc_checksum_bulk(rc, aa->aa_page_count, aa->aa_ppga, OST_READ, @@ -1794,7 +1730,8 @@ static int brw_interpret(const struct lu_env *env, if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE) { struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo; - loff_t last_off = last->oap_count + last->oap_obj_off; + loff_t last_off = last->oap_count + last->oap_obj_off + + last->oap_page_off; /* Change file size if this is an out of quota or * direct IO write and it extends the file size @@ -1812,11 +1749,14 @@ static int brw_interpret(const struct lu_env *env, } if (valid != 0) - cl_object_attr_set(env, obj, attr, valid); + cl_object_attr_update(env, obj, attr, valid); cl_object_attr_unlock(obj); } kmem_cache_free(obdo_cachep, aa->aa_oa); + if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE && rc == 0) + osc_inc_unstable_pages(req); + list_for_each_entry_safe(ext, tmp, &aa->aa_exts, oe_link) { list_del_init(&ext->oe_link); osc_extent_finish(env, ext, 1, rc); @@ -1847,21 +1787,21 @@ static int brw_interpret(const struct lu_env *env, static void brw_commit(struct ptlrpc_request *req) { - spin_lock(&req->rq_lock); /* * If osc_inc_unstable_pages (via osc_extent_finish) races with * this called via the rq_commit_cb, I need to ensure * osc_dec_unstable_pages is still called. Otherwise unstable * pages may be leaked. */ - if (req->rq_unstable) { + spin_lock(&req->rq_lock); + if (unlikely(req->rq_unstable)) { + req->rq_unstable = 0; spin_unlock(&req->rq_lock); osc_dec_unstable_pages(req); - spin_lock(&req->rq_lock); } else { req->rq_committed = 1; + spin_unlock(&req->rq_lock); } - spin_unlock(&req->rq_lock); } /** @@ -1881,13 +1821,13 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, struct osc_async_page *tmp; struct cl_req *clerq = NULL; enum cl_req_type crt = (cmd & OBD_BRW_WRITE) ? CRT_WRITE : CRT_READ; - struct ldlm_lock *lock = NULL; struct cl_req_attr *crattr = NULL; u64 starting_offset = OBD_OBJECT_EOF; u64 ending_offset = 0; int mpflag = 0; int mem_tight = 0; int page_count = 0; + bool soft_sync = false; int i; int rc; struct ost_body *body; @@ -1915,6 +1855,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, } } + soft_sync = osc_over_unstable_soft_limit(cli); if (mem_tight) mpflag = cfs_memory_pressure_get_and_set(); @@ -1947,10 +1888,11 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, rc = PTR_ERR(clerq); goto out; } - lock = oap->oap_ldlm_lock; } if (mem_tight) oap->oap_brw_flags |= OBD_BRW_MEMALLOC; + if (soft_sync) + oap->oap_brw_flags |= OBD_BRW_SOFT_SYNC; pga[i] = &oap->oap_brw_page; pga[i]->off = oap->oap_obj_off + oap->oap_page_off; CDEBUG(0, "put page %p index %lu oap %p flg %x to pga\n", @@ -1964,10 +1906,6 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, LASSERT(clerq); crattr->cra_oa = oa; cl_req_attr_set(env, clerq, crattr, ~0ULL); - if (lock) { - oa->o_handle = lock->l_remote_handle; - oa->o_valid |= OBD_MD_FLHANDLE; - } rc = cl_req_prep(env, clerq); if (rc != 0) { @@ -1998,7 +1936,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY); crattr->cra_oa = &body->oa; cl_req_attr_set(env, clerq, crattr, - OBD_MD_FLMTIME|OBD_MD_FLCTIME|OBD_MD_FLATIME); + OBD_MD_FLMTIME | OBD_MD_FLCTIME | OBD_MD_FLATIME); lustre_msg_set_jobid(req->rq_reqmsg, crattr->cra_jobid); @@ -2044,7 +1982,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, } spin_unlock(&cli->cl_loi_list_lock); - DEBUG_REQ(D_INODE, req, "%d pages, aa %p. now %dr/%dw in flight", + DEBUG_REQ(D_INODE, req, "%d pages, aa %p. now %ur/%dw in flight", page_count, aa, cli->cl_r_in_flight, cli->cl_w_in_flight); @@ -2116,27 +2054,6 @@ static int osc_set_data_with_check(struct lustre_handle *lockh, return set; } -/* find any ldlm lock of the inode in osc - * return 0 not find - * 1 find one - * < 0 error - */ -static int osc_find_cbdata(struct obd_export *exp, struct lov_stripe_md *lsm, - ldlm_iterator_t replace, void *data) -{ - struct ldlm_res_id res_id; - struct obd_device *obd = class_exp2obd(exp); - int rc = 0; - - ostid_build_res_name(&lsm->lsm_oi, &res_id); - rc = ldlm_resource_iterate(obd->obd_namespace, &res_id, replace, data); - if (rc == LDLM_ITER_STOP) - return 1; - if (rc == LDLM_ITER_CONTINUE) - return 0; - return rc; -} - static int osc_enqueue_fini(struct ptlrpc_request *req, osc_enqueue_upcall_f upcall, void *cookie, struct lustre_handle *lockh, enum ldlm_mode mode, @@ -2586,71 +2503,6 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp, return rc; } -/* Retrieve object striping information. - * - * @lmmu is a pointer to an in-core struct with lmm_ost_count indicating - * the maximum number of OST indices which will fit in the user buffer. - * lmm_magic must be LOV_MAGIC (we only use 1 slot here). - */ -static int osc_getstripe(struct lov_stripe_md *lsm, - struct lov_user_md __user *lump) -{ - /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ - struct lov_user_md_v3 lum, *lumk; - struct lov_user_ost_data_v1 *lmm_objects; - int rc = 0, lum_size; - - if (!lsm) - return -ENODATA; - - /* we only need the header part from user space to get lmm_magic and - * lmm_stripe_count, (the header part is common to v1 and v3) - */ - lum_size = sizeof(struct lov_user_md_v1); - if (copy_from_user(&lum, lump, lum_size)) - return -EFAULT; - - if ((lum.lmm_magic != LOV_USER_MAGIC_V1) && - (lum.lmm_magic != LOV_USER_MAGIC_V3)) - return -EINVAL; - - /* lov_user_md_vX and lov_mds_md_vX must have the same size */ - LASSERT(sizeof(struct lov_user_md_v1) == sizeof(struct lov_mds_md_v1)); - LASSERT(sizeof(struct lov_user_md_v3) == sizeof(struct lov_mds_md_v3)); - LASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lumk->lmm_objects[0])); - - /* we can use lov_mds_md_size() to compute lum_size - * because lov_user_md_vX and lov_mds_md_vX have the same size - */ - if (lum.lmm_stripe_count > 0) { - lum_size = lov_mds_md_size(lum.lmm_stripe_count, lum.lmm_magic); - lumk = kzalloc(lum_size, GFP_NOFS); - if (!lumk) - return -ENOMEM; - - if (lum.lmm_magic == LOV_USER_MAGIC_V1) - lmm_objects = - &(((struct lov_user_md_v1 *)lumk)->lmm_objects[0]); - else - lmm_objects = &(lumk->lmm_objects[0]); - lmm_objects->l_ost_oi = lsm->lsm_oi; - } else { - lum_size = lov_mds_md_size(0, lum.lmm_magic); - lumk = &lum; - } - - lumk->lmm_oi = lsm->lsm_oi; - lumk->lmm_stripe_count = 1; - - if (copy_to_user(lump, lumk, lum_size)) - rc = -EFAULT; - - if (lumk != &lum) - kfree(lumk); - - return rc; -} - static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void __user *uarg) { @@ -2664,57 +2516,6 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, return -EINVAL; } switch (cmd) { - case OBD_IOC_LOV_GET_CONFIG: { - char *buf; - struct lov_desc *desc; - struct obd_uuid uuid; - - buf = NULL; - len = 0; - if (obd_ioctl_getdata(&buf, &len, uarg)) { - err = -EINVAL; - goto out; - } - - data = (struct obd_ioctl_data *)buf; - - if (sizeof(*desc) > data->ioc_inllen1) { - obd_ioctl_freedata(buf, len); - err = -EINVAL; - goto out; - } - - if (data->ioc_inllen2 < sizeof(uuid)) { - obd_ioctl_freedata(buf, len); - err = -EINVAL; - goto out; - } - - desc = (struct lov_desc *)data->ioc_inlbuf1; - desc->ld_tgt_count = 1; - desc->ld_active_tgt_count = 1; - desc->ld_default_stripe_count = 1; - desc->ld_default_stripe_size = 0; - desc->ld_default_stripe_offset = 0; - desc->ld_pattern = 0; - memcpy(&desc->ld_uuid, &obd->obd_uuid, sizeof(uuid)); - - memcpy(data->ioc_inlbuf2, &obd->obd_uuid, sizeof(uuid)); - - err = copy_to_user(uarg, buf, len); - if (err) - err = -EFAULT; - obd_ioctl_freedata(buf, len); - goto out; - } - case LL_IOC_LOV_SETSTRIPE: - err = obd_alloc_memmd(exp, karg); - if (err > 0) - err = 0; - goto out; - case LL_IOC_LOV_GETSTRIPE: - err = osc_getstripe(karg, uarg); - goto out; case OBD_IOC_CLIENT_RECOVER: err = ptlrpc_recover_import(obd->u.cli.cl_import, data->ioc_inlbuf1, 0); @@ -2749,51 +2550,7 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp, if (!vallen || !val) return -EFAULT; - if (KEY_IS(KEY_LOCK_TO_STRIPE)) { - __u32 *stripe = val; - *vallen = sizeof(*stripe); - *stripe = 0; - return 0; - } else if (KEY_IS(KEY_LAST_ID)) { - struct ptlrpc_request *req; - u64 *reply; - char *tmp; - int rc; - - req = ptlrpc_request_alloc(class_exp2cliimp(exp), - &RQF_OST_GET_INFO_LAST_ID); - if (!req) - return -ENOMEM; - - req_capsule_set_size(&req->rq_pill, &RMF_SETINFO_KEY, - RCL_CLIENT, keylen); - rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO); - if (rc) { - ptlrpc_request_free(req); - return rc; - } - - tmp = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_KEY); - memcpy(tmp, key, keylen); - - req->rq_no_delay = 1; - req->rq_no_resend = 1; - ptlrpc_request_set_replen(req); - rc = ptlrpc_queue_wait(req); - if (rc) - goto out; - - reply = req_capsule_server_get(&req->rq_pill, &RMF_OBD_ID); - if (!reply) { - rc = -EPROTO; - goto out; - } - - *((u64 *)val) = *reply; -out: - ptlrpc_req_finished(req); - return rc; - } else if (KEY_IS(KEY_FIEMAP)) { + if (KEY_IS(KEY_FIEMAP)) { struct ll_fiemap_info_key *fm_key = key; struct ldlm_res_id res_id; ldlm_policy_data_t policy; @@ -2931,11 +2688,11 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp, if (KEY_IS(KEY_CACHE_LRU_SHRINK)) { struct client_obd *cli = &obd->u.cli; - int nr = atomic_read(&cli->cl_lru_in_list) >> 1; - int target = *(int *)val; + long nr = atomic_long_read(&cli->cl_lru_in_list) >> 1; + long target = *(long *)val; nr = osc_lru_shrink(env, cli, min(nr, target), true); - *(int *)val -= nr; + *(long *)val -= nr; return 0; } @@ -3014,8 +2771,9 @@ static int osc_reconnect(const struct lu_env *env, long lost_grant; spin_lock(&cli->cl_loi_list_lock); - data->ocd_grant = (cli->cl_avail_grant + cli->cl_dirty) ?: - 2 * cli_brw_size(obd); + data->ocd_grant = (cli->cl_avail_grant + + (cli->cl_dirty_pages << PAGE_SHIFT)) ?: + 2 * cli_brw_size(obd); lost_grant = cli->cl_lost_grant; cli->cl_lost_grant = 0; spin_unlock(&cli->cl_loi_list_lock); @@ -3346,7 +3104,6 @@ static struct obd_ops osc_obd_ops = { .disconnect = osc_disconnect, .statfs = osc_statfs, .statfs_async = osc_statfs_async, - .packmd = osc_packmd, .unpackmd = osc_unpackmd, .create = osc_create, .destroy = osc_destroy, @@ -3354,7 +3111,6 @@ static struct obd_ops osc_obd_ops = { .getattr_async = osc_getattr_async, .setattr = osc_setattr, .setattr_async = osc_setattr_async, - .find_cbdata = osc_find_cbdata, .iocontrol = osc_iocontrol, .get_info = osc_get_info, .set_info_async = osc_set_info_async, diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index d4463d7c81d2..8c51d51a678b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -45,6 +45,7 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req); static int ptlrpcd_check_work(struct ptlrpc_request *req); +static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async); /** * Initialize passed in client structure \a cl. @@ -89,7 +90,6 @@ struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid) return c; } -EXPORT_SYMBOL(ptlrpc_uuid_to_connection); /** * Allocate and initialize new bulk descriptor on the sender. @@ -202,7 +202,7 @@ void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc, int unpin) if (unpin) { for (i = 0; i < desc->bd_iov_count; i++) - put_page(desc->bd_iov[i].kiov_page); + put_page(desc->bd_iov[i].bv_page); } kfree(desc); @@ -283,8 +283,8 @@ int ptlrpc_at_get_net_latency(struct ptlrpc_request *req) } /* Adjust expected network latency */ -static void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req, - unsigned int service_time) +void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req, + unsigned int service_time) { unsigned int nl, oldnl; struct imp_at *at; @@ -364,31 +364,37 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req) } rc = unpack_reply(early_req); - if (rc == 0) { - /* Expecting to increase the service time estimate here */ - ptlrpc_at_adj_service(req, - lustre_msg_get_timeout(early_req->rq_repmsg)); - ptlrpc_at_adj_net_latency(req, - lustre_msg_get_service_time(early_req->rq_repmsg)); - } - - sptlrpc_cli_finish_early_reply(early_req); - - if (rc != 0) { + if (rc) { + sptlrpc_cli_finish_early_reply(early_req); spin_lock(&req->rq_lock); return rc; } - /* Adjust the local timeout for this req */ - ptlrpc_at_set_req_timeout(req); + /* + * Use new timeout value just to adjust the local value for this + * request, don't include it into at_history. It is unclear yet why + * service time increased and should it be counted or skipped, e.g. + * that can be recovery case or some error or server, the real reply + * will add all new data if it is worth to add. + */ + req->rq_timeout = lustre_msg_get_timeout(early_req->rq_repmsg); + lustre_msg_set_timeout(req->rq_reqmsg, req->rq_timeout); + + /* Network latency can be adjusted, it is pure network delays */ + ptlrpc_at_adj_net_latency(req, + lustre_msg_get_service_time(early_req->rq_repmsg)); + + sptlrpc_cli_finish_early_reply(early_req); spin_lock(&req->rq_lock); olddl = req->rq_deadline; /* - * server assumes it now has rq_timeout from when it sent the - * early reply, so client should give it at least that long. + * server assumes it now has rq_timeout from when the request + * arrived, so the client should give it at least that long. + * since we don't know the arrival time we'll use the original + * sent time */ - req->rq_deadline = ktime_get_real_seconds() + req->rq_timeout + + req->rq_deadline = req->rq_sent + req->rq_timeout + ptlrpc_at_get_net_latency(req); DEBUG_REQ(D_ADAPTTO, req, @@ -884,7 +890,6 @@ struct ptlrpc_request_set *ptlrpc_prep_fcset(int max, set_producer_func func, return set; } -EXPORT_SYMBOL(ptlrpc_prep_fcset); /** * Wind down and free request set structure previously allocated with @@ -1004,7 +1009,6 @@ void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc, wake_up(&pc->pc_partners[i]->pc_set->set_waitq); } } -EXPORT_SYMBOL(ptlrpc_set_add_new_req); /** * Based on the current state of the import, determine if the request @@ -1035,8 +1039,8 @@ static int ptlrpc_import_delay_req(struct obd_import *imp, *status = -EIO; } else if (ptlrpc_send_limit_expired(req)) { /* probably doesn't need to be a D_ERROR after initial testing */ - DEBUG_REQ(D_ERROR, req, "send limit expired "); - *status = -EIO; + DEBUG_REQ(D_HA, req, "send limit expired "); + *status = -ETIMEDOUT; } else if (req->rq_send_state == LUSTRE_IMP_CONNECTING && imp->imp_state == LUSTRE_IMP_CONNECTING) { /* allow CONNECT even if import is invalid */ @@ -1073,36 +1077,42 @@ static int ptlrpc_import_delay_req(struct obd_import *imp, } /** - * Decide if the error message regarding provided request \a req - * should be printed to the console or not. - * Makes it's decision on request status and other properties. - * Returns 1 to print error on the system console or 0 if not. + * Decide if the error message should be printed to the console or not. + * Makes its decision based on request type, status, and failure frequency. + * + * \param[in] req request that failed and may need a console message + * + * \retval false if no message should be printed + * \retval true if console message should be printed */ -static int ptlrpc_console_allow(struct ptlrpc_request *req) +static bool ptlrpc_console_allow(struct ptlrpc_request *req) { __u32 opc; - int err; LASSERT(req->rq_reqmsg); opc = lustre_msg_get_opc(req->rq_reqmsg); - /* - * Suppress particular reconnect errors which are to be expected. No - * errors are suppressed for the initial connection on an import - */ - if ((lustre_handle_is_used(&req->rq_import->imp_remote_handle)) && - (opc == OST_CONNECT || opc == MDS_CONNECT || opc == MGS_CONNECT)) { - /* Suppress timed out reconnect requests */ - if (req->rq_timedout) - return 0; + /* Suppress particular reconnect errors which are to be expected. */ + if (opc == OST_CONNECT || opc == MDS_CONNECT || opc == MGS_CONNECT) { + int err; - /* Suppress unavailable/again reconnect requests */ + /* Suppress timed out reconnect requests */ + if (lustre_handle_is_used(&req->rq_import->imp_remote_handle) || + req->rq_timedout) + return false; + + /* + * Suppress most unavailable/again reconnect requests, but + * print occasionally so it is clear client is trying to + * connect to a server where no target is running. + */ err = lustre_msg_get_status(req->rq_repmsg); - if (err == -ENODEV || err == -EAGAIN) - return 0; + if ((err == -ENODEV || err == -EAGAIN) && + req->rq_import->imp_conn_cnt % 30 != 20) + return false; } - return 1; + return true; } /** @@ -1116,14 +1126,14 @@ static int ptlrpc_check_status(struct ptlrpc_request *req) err = lustre_msg_get_status(req->rq_repmsg); if (lustre_msg_get_type(req->rq_repmsg) == PTL_RPC_MSG_ERR) { struct obd_import *imp = req->rq_import; + lnet_nid_t nid = imp->imp_connection->c_peer.nid; __u32 opc = lustre_msg_get_opc(req->rq_reqmsg); if (ptlrpc_console_allow(req)) - LCONSOLE_ERROR_MSG(0x011, "%s: Communicating with %s, operation %s failed with %d.\n", + LCONSOLE_ERROR_MSG(0x011, "%s: operation %s to node %s failed: rc = %d\n", imp->imp_obd->obd_name, - libcfs_nid2str( - imp->imp_connection->c_peer.nid), - ll_opcode2str(opc), err); + ll_opcode2str(opc), + libcfs_nid2str(nid), err); return err < 0 ? err : -EINVAL; } @@ -1280,7 +1290,7 @@ static int after_reply(struct ptlrpc_request *req) * some reason. Try to reconnect, and if that fails, punt to * the upcall. */ - if (ll_rpc_recoverable_error(rc)) { + if (ptlrpc_recoverable_error(rc)) { if (req->rq_send_state != LUSTRE_IMP_FULL || imp->imp_obd->obd_no_recov || imp->imp_dlm_fake) { return rc; @@ -1628,8 +1638,10 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) req->rq_waiting || req->rq_wait_ctx) { int status; - if (!ptlrpc_unregister_reply(req, 1)) + if (!ptlrpc_unregister_reply(req, 1)) { + ptlrpc_unregister_bulk(req, 1); continue; + } spin_lock(&imp->imp_lock); if (ptlrpc_import_delay_req(imp, req, @@ -1995,7 +2007,6 @@ int ptlrpc_expired_set(void *data) */ return 1; } -EXPORT_SYMBOL(ptlrpc_expired_set); /** * Sets rq_intr flag in \a req under spinlock. @@ -2012,7 +2023,7 @@ EXPORT_SYMBOL(ptlrpc_mark_interrupted); * Interrupts (sets interrupted flag) all uncompleted requests in * a set \a data. Callback for l_wait_event for interruptible waits. */ -void ptlrpc_interrupted_set(void *data) +static void ptlrpc_interrupted_set(void *data) { struct ptlrpc_request_set *set = data; struct list_head *tmp; @@ -2030,7 +2041,6 @@ void ptlrpc_interrupted_set(void *data) ptlrpc_mark_interrupted(req); } } -EXPORT_SYMBOL(ptlrpc_interrupted_set); /** * Get the smallest timeout in the set; this does NOT set a timeout. @@ -2074,7 +2084,6 @@ int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set) } return timeout; } -EXPORT_SYMBOL(ptlrpc_set_next_timeout); /** * Send all unset request from the set and then wait until all @@ -2325,7 +2334,7 @@ EXPORT_SYMBOL(ptlrpc_req_xid); * The request owner (i.e. the thread doing the I/O) must call... * Returns 0 on success or 1 if unregistering cannot be made. */ -int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) +static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) { int rc; wait_queue_head_t *wq; @@ -2390,7 +2399,6 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) } return 0; } -EXPORT_SYMBOL(ptlrpc_unregister_reply); static void ptlrpc_free_request(struct ptlrpc_request *req) { @@ -2451,7 +2459,8 @@ void ptlrpc_free_committed(struct obd_import *imp) imp->imp_obd->obd_name, imp->imp_peer_committed_transno, imp->imp_generation); - if (imp->imp_generation != imp->imp_last_generation_checked) + if (imp->imp_generation != imp->imp_last_generation_checked || + !imp->imp_last_transno_checked) skip_committed_list = false; imp->imp_last_transno_checked = imp->imp_peer_committed_transno; @@ -2499,6 +2508,9 @@ free_req: if (req->rq_import_generation < imp->imp_generation) { DEBUG_REQ(D_RPCTRACE, req, "free stale open request"); ptlrpc_free_request(req); + } else if (!req->rq_replay) { + DEBUG_REQ(D_RPCTRACE, req, "free closed open request"); + ptlrpc_free_request(req); } } } @@ -2541,7 +2553,6 @@ void ptlrpc_resend_req(struct ptlrpc_request *req) ptlrpc_client_wake_req(req); spin_unlock(&req->rq_lock); } -EXPORT_SYMBOL(ptlrpc_resend_req); /** * Grab additional reference on a request \a req @@ -2610,7 +2621,6 @@ void ptlrpc_retain_replayable_request(struct ptlrpc_request *req, list_add(&req->rq_replay_list, &imp->imp_replay_list); } -EXPORT_SYMBOL(ptlrpc_retain_replayable_request); /** * Send request and wait until it completes. @@ -2783,7 +2793,6 @@ int ptlrpc_replay_req(struct ptlrpc_request *req) ptlrpcd_add_req(req); return 0; } -EXPORT_SYMBOL(ptlrpc_replay_req); /** * Aborts all in-flight request on import \a imp sending and delayed lists @@ -2843,7 +2852,6 @@ void ptlrpc_abort_inflight(struct obd_import *imp) spin_unlock(&imp->imp_lock); } -EXPORT_SYMBOL(ptlrpc_abort_inflight); /** * Abort all uncompleted requests in request set \a set @@ -2929,7 +2937,6 @@ __u64 ptlrpc_next_xid(void) return next; } -EXPORT_SYMBOL(ptlrpc_next_xid); /** * Get a glimpse at what next xid value might have been. diff --git a/drivers/staging/lustre/lustre/ptlrpc/connection.c b/drivers/staging/lustre/lustre/ptlrpc/connection.c index 177a379da9fa..7b020d60c9e5 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/connection.c +++ b/drivers/staging/lustre/lustre/ptlrpc/connection.c @@ -82,7 +82,6 @@ out: libcfs_nid2str(conn->c_peer.nid)); return conn; } -EXPORT_SYMBOL(ptlrpc_connection_get); int ptlrpc_connection_put(struct ptlrpc_connection *conn) { @@ -118,7 +117,6 @@ int ptlrpc_connection_put(struct ptlrpc_connection *conn) return rc; } -EXPORT_SYMBOL(ptlrpc_connection_put); struct ptlrpc_connection * ptlrpc_connection_addref(struct ptlrpc_connection *conn) @@ -130,7 +128,6 @@ ptlrpc_connection_addref(struct ptlrpc_connection *conn) return conn; } -EXPORT_SYMBOL(ptlrpc_connection_addref); int ptlrpc_connection_init(void) { @@ -146,13 +143,11 @@ int ptlrpc_connection_init(void) return 0; } -EXPORT_SYMBOL(ptlrpc_connection_init); void ptlrpc_connection_fini(void) { cfs_hash_putref(conn_hash); } -EXPORT_SYMBOL(ptlrpc_connection_fini); /* * Hash operations for net_peer<->connection diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index b1ce72511509..283dfb296d35 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -543,7 +543,7 @@ static int ptlrpc_ni_init(void) rc = LNetNIInit(pid); if (rc < 0) { CDEBUG(D_NET, "Can't init network interface: %d\n", rc); - return -ENOENT; + return rc; } /* CAVEAT EMPTOR: how we process portals events is _radically_ @@ -561,7 +561,7 @@ static int ptlrpc_ni_init(void) CERROR("Failed to allocate event queue: %d\n", rc); LNetNIFini(); - return -ENOMEM; + return rc; } int ptlrpc_init_portals(void) @@ -570,7 +570,7 @@ int ptlrpc_init_portals(void) if (rc != 0) { CERROR("network initialisation failed\n"); - return -EIO; + return rc; } rc = ptlrpcd_addref(); if (rc == 0) diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 3292e6ea0102..a23d0a05b574 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -307,7 +307,8 @@ void ptlrpc_invalidate_import(struct obd_import *imp) */ lwi = LWI_TIMEOUT_INTERVAL( cfs_timeout_cap(cfs_time_seconds(timeout)), - (timeout > 1)?cfs_time_seconds(1):cfs_time_seconds(1)/2, + (timeout > 1) ? cfs_time_seconds(1) : + cfs_time_seconds(1) / 2, NULL, NULL); rc = l_wait_event(imp->imp_recovery_waitq, (atomic_read(&imp->imp_inflight) == 0), @@ -424,7 +425,6 @@ void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt) ptlrpc_pinger_force(imp); } } -EXPORT_SYMBOL(ptlrpc_fail_import); int ptlrpc_reconnect_import(struct obd_import *imp) { @@ -698,7 +698,8 @@ int ptlrpc_connect_import(struct obd_import *imp) request->rq_send_state = LUSTRE_IMP_CONNECTING; /* Allow a slightly larger reply for future growth compatibility */ req_capsule_set_size(&request->rq_pill, &RMF_CONNECT_DATA, RCL_SERVER, - sizeof(struct obd_connect_data)+16*sizeof(__u64)); + sizeof(struct obd_connect_data) + + 16 * sizeof(__u64)); ptlrpc_request_set_replen(request); request->rq_interpret_reply = ptlrpc_connect_interpret; @@ -750,6 +751,153 @@ static int ptlrpc_busy_reconnect(int rc) return (rc == -EBUSY) || (rc == -EAGAIN); } +static int ptlrpc_connect_set_flags(struct obd_import *imp, + struct obd_connect_data *ocd, + u64 old_connect_flags, + struct obd_export *exp, int init_connect) +{ + struct client_obd *cli = &imp->imp_obd->u.cli; + static bool warned; + + if ((imp->imp_connect_flags_orig & OBD_CONNECT_IBITS) && + !(ocd->ocd_connect_flags & OBD_CONNECT_IBITS)) { + LCONSOLE_WARN("%s: MDS %s does not support ibits lock, either very old or invalid: requested %#llx, replied %#llx\n", + imp->imp_obd->obd_name, + imp->imp_connection->c_remote_uuid.uuid, + imp->imp_connect_flags_orig, + ocd->ocd_connect_flags); + return -EPROTO; + } + + spin_lock(&imp->imp_lock); + list_del(&imp->imp_conn_current->oic_item); + list_add(&imp->imp_conn_current->oic_item, &imp->imp_conn_list); + imp->imp_last_success_conn = imp->imp_conn_current->oic_last_attempt; + + spin_unlock(&imp->imp_lock); + + if (!warned && (ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && + (ocd->ocd_version > LUSTRE_VERSION_CODE + + LUSTRE_VERSION_OFFSET_WARN || + ocd->ocd_version < LUSTRE_VERSION_CODE - + LUSTRE_VERSION_OFFSET_WARN)) { + /* + * Sigh, some compilers do not like #ifdef in the middle + * of macro arguments + */ + const char *older = "older than client. Consider upgrading server"; + const char *newer = "newer than client. Consider recompiling application"; + + LCONSOLE_WARN("Server %s version (%d.%d.%d.%d) is much %s (%s)\n", + obd2cli_tgt(imp->imp_obd), + OBD_OCD_VERSION_MAJOR(ocd->ocd_version), + OBD_OCD_VERSION_MINOR(ocd->ocd_version), + OBD_OCD_VERSION_PATCH(ocd->ocd_version), + OBD_OCD_VERSION_FIX(ocd->ocd_version), + ocd->ocd_version > LUSTRE_VERSION_CODE ? + newer : older, LUSTRE_VERSION_STRING); + warned = true; + } + +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0) + /* + * Check if server has LU-1252 fix applied to not always swab + * the IR MNE entries. Do this only once per connection. This + * fixup is version-limited, because we don't want to carry the + * OBD_CONNECT_MNE_SWAB flag around forever, just so long as we + * need interop with unpatched 2.2 servers. For newer servers, + * the client will do MNE swabbing only as needed. LU-1644 + */ + if (unlikely((ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && + !(ocd->ocd_connect_flags & OBD_CONNECT_MNE_SWAB) && + OBD_OCD_VERSION_MAJOR(ocd->ocd_version) == 2 && + OBD_OCD_VERSION_MINOR(ocd->ocd_version) == 2 && + OBD_OCD_VERSION_PATCH(ocd->ocd_version) < 55 && + !strcmp(imp->imp_obd->obd_type->typ_name, + LUSTRE_MGC_NAME))) + imp->imp_need_mne_swab = 1; + else /* clear if server was upgraded since last connect */ + imp->imp_need_mne_swab = 0; +#endif + + if (ocd->ocd_connect_flags & OBD_CONNECT_CKSUM) { + /* + * We sent to the server ocd_cksum_types with bits set + * for algorithms we understand. The server masked off + * the checksum types it doesn't support + */ + if (!(ocd->ocd_cksum_types & cksum_types_supported_client())) { + LCONSOLE_WARN("The negotiation of the checksum algorithm to use with server %s failed (%x/%x), disabling checksums\n", + obd2cli_tgt(imp->imp_obd), + ocd->ocd_cksum_types, + cksum_types_supported_client()); + cli->cl_checksum = 0; + cli->cl_supp_cksum_types = OBD_CKSUM_ADLER; + } else { + cli->cl_supp_cksum_types = ocd->ocd_cksum_types; + } + } else { + /* + * The server does not support OBD_CONNECT_CKSUM. + * Enforce ADLER for backward compatibility + */ + cli->cl_supp_cksum_types = OBD_CKSUM_ADLER; + } + cli->cl_cksum_type = cksum_type_select(cli->cl_supp_cksum_types); + + if (ocd->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) + cli->cl_max_pages_per_rpc = + min(ocd->ocd_brw_size >> PAGE_SHIFT, + cli->cl_max_pages_per_rpc); + else if (imp->imp_connect_op == MDS_CONNECT || + imp->imp_connect_op == MGS_CONNECT) + cli->cl_max_pages_per_rpc = 1; + + LASSERT((cli->cl_max_pages_per_rpc <= PTLRPC_MAX_BRW_PAGES) && + (cli->cl_max_pages_per_rpc > 0)); + + client_adjust_max_dirty(cli); + + /* + * Reset ns_connect_flags only for initial connect. It might be + * changed in while using FS and if we reset it in reconnect + * this leads to losing user settings done before such as + * disable lru_resize, etc. + */ + if (old_connect_flags != exp_connect_flags(exp) || init_connect) { + CDEBUG(D_HA, "%s: Resetting ns_connect_flags to server flags: %#llx\n", + imp->imp_obd->obd_name, ocd->ocd_connect_flags); + imp->imp_obd->obd_namespace->ns_connect_flags = + ocd->ocd_connect_flags; + imp->imp_obd->obd_namespace->ns_orig_connect_flags = + ocd->ocd_connect_flags; + } + + if ((ocd->ocd_connect_flags & OBD_CONNECT_AT) && + (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) + /* + * We need a per-message support flag, because + * a. we don't know if the incoming connect reply + * supports AT or not (in reply_in_callback) + * until we unpack it. + * b. failovered server means export and flags are gone + * (in ptlrpc_send_reply). + * Can only be set when we know AT is supported at + * both ends + */ + imp->imp_msghdr_flags |= MSGHDR_AT_SUPPORT; + else + imp->imp_msghdr_flags &= ~MSGHDR_AT_SUPPORT; + + if ((ocd->ocd_connect_flags & OBD_CONNECT_FULL20) && + (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) + imp->imp_msghdr_flags |= MSGHDR_CKSUM_INCOMPAT18; + else + imp->imp_msghdr_flags &= ~MSGHDR_CKSUM_INCOMPAT18; + + return 0; +} + /** * interpret_reply callback for connect RPCs. * Looks into returned status of connect operation and decides @@ -762,7 +910,6 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, { struct ptlrpc_connect_async_args *aa = data; struct obd_import *imp = request->rq_import; - struct client_obd *cli = &imp->imp_obd->u.cli; struct lustre_handle old_hdl; __u64 old_connect_flags; int msg_flags; @@ -842,7 +989,21 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, old_connect_flags = exp_connect_flags(exp); exp->exp_connect_data = *ocd; imp->imp_obd->obd_self_export->exp_connect_data = *ocd; + + /* + * The net statistics after (re-)connect is not valid anymore, + * because may reflect other routing, etc. + */ + at_init(&imp->imp_at.iat_net_latency, 0, 0); + ptlrpc_at_adj_net_latency(request, + lustre_msg_get_service_time(request->rq_repmsg)); + + /* Import flags should be updated before waking import at FULL state */ + rc = ptlrpc_connect_set_flags(imp, ocd, old_connect_flags, exp, + aa->pcaa_initial_connect); class_export_put(exp); + if (rc) + goto out; obd_import_event(imp->imp_obd, imp, IMP_EVENT_OCD); @@ -987,151 +1148,13 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, finish: rc = ptlrpc_import_recovery_state_machine(imp); - if (rc != 0) { - if (rc == -ENOTCONN) { - CDEBUG(D_HA, "evicted/aborted by %s@%s during recovery; invalidating and reconnecting\n", - obd2cli_tgt(imp->imp_obd), - imp->imp_connection->c_remote_uuid.uuid); - ptlrpc_connect_import(imp); - imp->imp_connect_tried = 1; - return 0; - } - } else { - static bool warned; - - spin_lock(&imp->imp_lock); - list_del(&imp->imp_conn_current->oic_item); - list_add(&imp->imp_conn_current->oic_item, &imp->imp_conn_list); - imp->imp_last_success_conn = - imp->imp_conn_current->oic_last_attempt; - - spin_unlock(&imp->imp_lock); - - if ((imp->imp_connect_flags_orig & OBD_CONNECT_IBITS) && - !(ocd->ocd_connect_flags & OBD_CONNECT_IBITS)) { - LCONSOLE_WARN("%s: MDS %s does not support ibits lock, either very old or invalid: requested %llx, replied %llx\n", - imp->imp_obd->obd_name, - imp->imp_connection->c_remote_uuid.uuid, - imp->imp_connect_flags_orig, - ocd->ocd_connect_flags); - rc = -EPROTO; - goto out; - } - - if (!warned && (ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && - (ocd->ocd_version > LUSTRE_VERSION_CODE + - LUSTRE_VERSION_OFFSET_WARN || - ocd->ocd_version < LUSTRE_VERSION_CODE - - LUSTRE_VERSION_OFFSET_WARN)) { - /* Sigh, some compilers do not like #ifdef in the middle - * of macro arguments - */ - const char *older = "older than client. Consider upgrading server"; - const char *newer = "newer than client. Consider recompiling application"; - - LCONSOLE_WARN("Server %s version (%d.%d.%d.%d) is much %s (%s)\n", - obd2cli_tgt(imp->imp_obd), - OBD_OCD_VERSION_MAJOR(ocd->ocd_version), - OBD_OCD_VERSION_MINOR(ocd->ocd_version), - OBD_OCD_VERSION_PATCH(ocd->ocd_version), - OBD_OCD_VERSION_FIX(ocd->ocd_version), - ocd->ocd_version > LUSTRE_VERSION_CODE ? - newer : older, LUSTRE_VERSION_STRING); - warned = true; - } - -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 2, 50, 0) - /* Check if server has LU-1252 fix applied to not always swab - * the IR MNE entries. Do this only once per connection. This - * fixup is version-limited, because we don't want to carry the - * OBD_CONNECT_MNE_SWAB flag around forever, just so long as we - * need interop with unpatched 2.2 servers. For newer servers, - * the client will do MNE swabbing only as needed. LU-1644 - */ - if (unlikely((ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && - !(ocd->ocd_connect_flags & OBD_CONNECT_MNE_SWAB) && - OBD_OCD_VERSION_MAJOR(ocd->ocd_version) == 2 && - OBD_OCD_VERSION_MINOR(ocd->ocd_version) == 2 && - OBD_OCD_VERSION_PATCH(ocd->ocd_version) < 55 && - strcmp(imp->imp_obd->obd_type->typ_name, - LUSTRE_MGC_NAME) == 0)) - imp->imp_need_mne_swab = 1; - else /* clear if server was upgraded since last connect */ - imp->imp_need_mne_swab = 0; -#else -#warning "LU-1644: Remove old OBD_CONNECT_MNE_SWAB fixup and imp_need_mne_swab" -#endif - - if (ocd->ocd_connect_flags & OBD_CONNECT_CKSUM) { - /* We sent to the server ocd_cksum_types with bits set - * for algorithms we understand. The server masked off - * the checksum types it doesn't support - */ - if ((ocd->ocd_cksum_types & - cksum_types_supported_client()) == 0) { - LCONSOLE_WARN("The negotiation of the checksum algorithm to use with server %s failed (%x/%x), disabling checksums\n", - obd2cli_tgt(imp->imp_obd), - ocd->ocd_cksum_types, - cksum_types_supported_client()); - cli->cl_checksum = 0; - cli->cl_supp_cksum_types = OBD_CKSUM_ADLER; - } else { - cli->cl_supp_cksum_types = ocd->ocd_cksum_types; - } - } else { - /* The server does not support OBD_CONNECT_CKSUM. - * Enforce ADLER for backward compatibility - */ - cli->cl_supp_cksum_types = OBD_CKSUM_ADLER; - } - cli->cl_cksum_type = cksum_type_select(cli->cl_supp_cksum_types); - - if (ocd->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) - cli->cl_max_pages_per_rpc = - min(ocd->ocd_brw_size >> PAGE_SHIFT, - cli->cl_max_pages_per_rpc); - else if (imp->imp_connect_op == MDS_CONNECT || - imp->imp_connect_op == MGS_CONNECT) - cli->cl_max_pages_per_rpc = 1; - - /* Reset ns_connect_flags only for initial connect. It might be - * changed in while using FS and if we reset it in reconnect - * this leads to losing user settings done before such as - * disable lru_resize, etc. - */ - if (old_connect_flags != exp_connect_flags(exp) || - aa->pcaa_initial_connect) { - CDEBUG(D_HA, "%s: Resetting ns_connect_flags to server flags: %#llx\n", - imp->imp_obd->obd_name, ocd->ocd_connect_flags); - imp->imp_obd->obd_namespace->ns_connect_flags = - ocd->ocd_connect_flags; - imp->imp_obd->obd_namespace->ns_orig_connect_flags = - ocd->ocd_connect_flags; - } - - if ((ocd->ocd_connect_flags & OBD_CONNECT_AT) && - (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) - /* We need a per-message support flag, because - * a. we don't know if the incoming connect reply - * supports AT or not (in reply_in_callback) - * until we unpack it. - * b. failovered server means export and flags are gone - * (in ptlrpc_send_reply). - * Can only be set when we know AT is supported at - * both ends - */ - imp->imp_msghdr_flags |= MSGHDR_AT_SUPPORT; - else - imp->imp_msghdr_flags &= ~MSGHDR_AT_SUPPORT; - - if ((ocd->ocd_connect_flags & OBD_CONNECT_FULL20) && - (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) - imp->imp_msghdr_flags |= MSGHDR_CKSUM_INCOMPAT18; - else - imp->imp_msghdr_flags &= ~MSGHDR_CKSUM_INCOMPAT18; - - LASSERT((cli->cl_max_pages_per_rpc <= PTLRPC_MAX_BRW_PAGES) && - (cli->cl_max_pages_per_rpc > 0)); + if (rc == -ENOTCONN) { + CDEBUG(D_HA, "evicted/aborted by %s@%s during recovery; invalidating and reconnecting\n", + obd2cli_tgt(imp->imp_obd), + imp->imp_connection->c_remote_uuid.uuid); + ptlrpc_connect_import(imp); + imp->imp_connect_tried = 1; + return 0; } out: @@ -1497,10 +1520,13 @@ EXPORT_SYMBOL(ptlrpc_disconnect_import); /* Adaptive Timeout utils */ extern unsigned int at_min, at_max, at_history; -/* Bin into timeslices using AT_BINS bins. - * This gives us a max of the last binlimit*AT_BINS secs without the storage, - * but still smoothing out a return to normalcy from a slow response. - * (E.g. remember the maximum latency in each minute of the last 4 minutes.) +/* + *Update at_current with the specified value (bounded by at_min and at_max), + * as well as the AT history "bins". + * - Bin into timeslices using AT_BINS bins. + * - This gives us a max of the last at_history seconds without the storage, + * but still smoothing out a return to normalcy from a slow response. + * - (E.g. remember the maximum latency in each minute of the last 4 minutes.) */ int at_measured(struct adaptive_timeout *at, unsigned int val) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index ab5d85174245..839ef3e80c1a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -667,11 +667,8 @@ static struct req_format *req_formats[] = { &RQF_MDS_SYNC, &RQF_MDS_CLOSE, &RQF_MDS_RELEASE_CLOSE, - &RQF_MDS_PIN, - &RQF_MDS_UNPIN, &RQF_MDS_READPAGE, &RQF_MDS_WRITEPAGE, - &RQF_MDS_IS_SUBDIR, &RQF_MDS_DONE_WRITING, &RQF_MDS_REINT, &RQF_MDS_REINT_CREATE, @@ -1116,9 +1113,9 @@ EXPORT_SYMBOL(RMF_SWAP_LAYOUTS); struct req_format { const char *rf_name; - int rf_idx; + size_t rf_idx; struct { - int nr; + size_t nr; const struct req_msg_field **d; } rf_fields[RCL_NR]; }; @@ -1389,15 +1386,6 @@ struct req_format RQF_MDS_RELEASE_CLOSE = mdt_release_close_client, mds_last_unlink_server); EXPORT_SYMBOL(RQF_MDS_RELEASE_CLOSE); -struct req_format RQF_MDS_PIN = - DEFINE_REQ_FMT0("MDS_PIN", - mdt_body_capa, mdt_body_only); -EXPORT_SYMBOL(RQF_MDS_PIN); - -struct req_format RQF_MDS_UNPIN = - DEFINE_REQ_FMT0("MDS_UNPIN", mdt_body_only, empty); -EXPORT_SYMBOL(RQF_MDS_UNPIN); - struct req_format RQF_MDS_DONE_WRITING = DEFINE_REQ_FMT0("MDS_DONE_WRITING", mdt_close_client, mdt_body_only); @@ -1448,11 +1436,6 @@ struct req_format RQF_MDS_WRITEPAGE = mdt_body_capa, mdt_body_only); EXPORT_SYMBOL(RQF_MDS_WRITEPAGE); -struct req_format RQF_MDS_IS_SUBDIR = - DEFINE_REQ_FMT0("MDS_IS_SUBDIR", - mdt_body_only, mdt_body_only); -EXPORT_SYMBOL(RQF_MDS_IS_SUBDIR); - struct req_format RQF_LLOG_ORIGIN_HANDLE_CREATE = DEFINE_REQ_FMT0("LLOG_ORIGIN_HANDLE_CREATE", llog_origin_handle_create_client, llogd_body_only); @@ -1572,9 +1555,9 @@ EXPORT_SYMBOL(RQF_OST_GET_INFO_FIEMAP); */ int req_layout_init(void) { - int i; - int j; - int k; + size_t i; + size_t j; + size_t k; struct req_format *rf = NULL; for (i = 0; i < ARRAY_SIZE(req_formats); ++i) { @@ -1616,7 +1599,7 @@ EXPORT_SYMBOL(req_layout_fini); */ static void req_capsule_init_area(struct req_capsule *pill) { - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(pill->rc_area[RCL_CLIENT]); i++) { pill->rc_area[RCL_CLIENT][i] = -1; @@ -1667,8 +1650,7 @@ EXPORT_SYMBOL(req_capsule_fini); static int __req_format_is_sane(const struct req_format *fmt) { - return - 0 <= fmt->rf_idx && fmt->rf_idx < ARRAY_SIZE(req_formats) && + return fmt->rf_idx < ARRAY_SIZE(req_formats) && req_formats[fmt->rf_idx] == fmt; } @@ -1702,11 +1684,11 @@ EXPORT_SYMBOL(req_capsule_set); * variable-sized fields. The field sizes come from the declared \a rmf_size * field of a \a pill's \a rc_fmt's RMF's. */ -int req_capsule_filled_sizes(struct req_capsule *pill, - enum req_location loc) +size_t req_capsule_filled_sizes(struct req_capsule *pill, + enum req_location loc) { const struct req_format *fmt = pill->rc_fmt; - int i; + size_t i; for (i = 0; i < fmt->rf_fields[loc].nr; ++i) { if (pill->rc_area[loc][i] == -1) { @@ -1761,11 +1743,11 @@ EXPORT_SYMBOL(req_capsule_server_pack); * Returns the PTLRPC request or reply (\a loc) buffer offset of a \a pill * corresponding to the given RMF (\a field). */ -static int __req_capsule_offset(const struct req_capsule *pill, +static u32 __req_capsule_offset(const struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc) { - int offset; + u32 offset; offset = field->rmf_offset[pill->rc_fmt->rf_idx][loc]; LASSERTF(offset > 0, "%s:%s, off=%d, loc=%d\n", pill->rc_fmt->rf_name, @@ -1869,10 +1851,10 @@ static void *__req_capsule_get(struct req_capsule *pill, const struct req_format *fmt; struct lustre_msg *msg; void *value; - int len; - int offset; + u32 len; + u32 offset; - void *(*getter)(struct lustre_msg *m, int n, int minlen); + void *(*getter)(struct lustre_msg *m, u32 n, u32 minlen); static const char *rcl_names[RCL_NR] = { [RCL_CLIENT] = "client", @@ -1899,20 +1881,20 @@ static void *__req_capsule_get(struct req_capsule *pill, */ len = lustre_msg_buflen(msg, offset); if ((len % field->rmf_size) != 0) { - CERROR("%s: array field size mismatch %d modulo %d != 0 (%d)\n", + CERROR("%s: array field size mismatch %d modulo %u != 0 (%d)\n", field->rmf_name, len, field->rmf_size, loc); return NULL; } } else if (pill->rc_area[loc][offset] != -1) { len = pill->rc_area[loc][offset]; } else { - len = max(field->rmf_size, 0); + len = max_t(typeof(field->rmf_size), field->rmf_size, 0); } value = getter(msg, offset, len); if (!value) { DEBUG_REQ(D_ERROR, pill->rc_req, - "Wrong buffer for field `%s' (%d of %d) in format `%s': %d vs. %d (%s)\n", + "Wrong buffer for field `%s' (%u of %u) in format `%s': %u vs. %u (%s)\n", field->rmf_name, offset, lustre_msg_bufcount(msg), fmt->rf_name, lustre_msg_buflen(msg, offset), len, rcl_names[loc]); @@ -1958,7 +1940,7 @@ EXPORT_SYMBOL(req_capsule_client_swab_get); */ void *req_capsule_client_sized_get(struct req_capsule *pill, const struct req_msg_field *field, - int len) + u32 len) { req_capsule_set_size(pill, field, RCL_CLIENT, len); return __req_capsule_get(pill, field, RCL_CLIENT, NULL, 0); @@ -1999,7 +1981,7 @@ EXPORT_SYMBOL(req_capsule_server_swab_get); */ void *req_capsule_server_sized_get(struct req_capsule *pill, const struct req_msg_field *field, - int len) + u32 len) { req_capsule_set_size(pill, field, RCL_SERVER, len); return __req_capsule_get(pill, field, RCL_SERVER, NULL, 0); @@ -2008,7 +1990,7 @@ EXPORT_SYMBOL(req_capsule_server_sized_get); void *req_capsule_server_sized_swab_get(struct req_capsule *pill, const struct req_msg_field *field, - int len, void *swabber) + u32 len, void *swabber) { req_capsule_set_size(pill, field, RCL_SERVER, len); return __req_capsule_get(pill, field, RCL_SERVER, swabber, 0); @@ -2024,23 +2006,25 @@ EXPORT_SYMBOL(req_capsule_server_sized_swab_get); */ void req_capsule_set_size(struct req_capsule *pill, const struct req_msg_field *field, - enum req_location loc, int size) + enum req_location loc, u32 size) { LASSERT(loc == RCL_SERVER || loc == RCL_CLIENT); - if ((size != field->rmf_size) && + if ((size != (u32)field->rmf_size) && (field->rmf_size != -1) && !(field->rmf_flags & RMF_F_NO_SIZE_CHECK) && (size > 0)) { + u32 rmf_size = (u32)field->rmf_size; + if ((field->rmf_flags & RMF_F_STRUCT_ARRAY) && - (size % field->rmf_size != 0)) { - CERROR("%s: array field size mismatch %d %% %d != 0 (%d)\n", - field->rmf_name, size, field->rmf_size, loc); + (size % rmf_size != 0)) { + CERROR("%s: array field size mismatch %u %% %u != 0 (%d)\n", + field->rmf_name, size, rmf_size, loc); LBUG(); } else if (!(field->rmf_flags & RMF_F_STRUCT_ARRAY) && - size < field->rmf_size) { - CERROR("%s: field size mismatch %d != %d (%d)\n", - field->rmf_name, size, field->rmf_size, loc); + size < rmf_size) { + CERROR("%s: field size mismatch %u != %u (%d)\n", + field->rmf_name, size, rmf_size, loc); LBUG(); } } @@ -2057,7 +2041,7 @@ EXPORT_SYMBOL(req_capsule_set_size); * actually sets the size in pill.rc_area[loc][offset], but this function * returns the message buflen[offset], maybe we should use another name. */ -int req_capsule_get_size(const struct req_capsule *pill, +u32 req_capsule_get_size(const struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc) { @@ -2075,7 +2059,7 @@ EXPORT_SYMBOL(req_capsule_get_size); * * See also req_capsule_set_size(). */ -int req_capsule_msg_size(struct req_capsule *pill, enum req_location loc) +u32 req_capsule_msg_size(struct req_capsule *pill, enum req_location loc) { return lustre_msg_size(pill->rc_req->rq_import->imp_msg_magic, pill->rc_fmt->rf_fields[loc].nr, @@ -2090,10 +2074,11 @@ int req_capsule_msg_size(struct req_capsule *pill, enum req_location loc) * This function should not be used for formats which contain variable size * fields. */ -int req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, +u32 req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, enum req_location loc) { - int size, i = 0; + size_t i = 0; + u32 size; /* * This function should probably LASSERT() that fmt has no fields with @@ -2103,7 +2088,7 @@ int req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, * we do. */ size = lustre_msg_hdr_size(magic, fmt->rf_fields[loc].nr); - if (size < 0) + if (!size) return size; for (; i < fmt->rf_fields[loc].nr; ++i) @@ -2135,7 +2120,7 @@ int req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, void req_capsule_extend(struct req_capsule *pill, const struct req_format *fmt) { int i; - int j; + size_t j; const struct req_format *old; @@ -2193,7 +2178,7 @@ static int req_capsule_field_present(const struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc) { - int offset; + u32 offset; LASSERT(loc == RCL_SERVER || loc == RCL_CLIENT); LASSERT(req_capsule_has_field(pill, field, loc)); @@ -2210,12 +2195,11 @@ static int req_capsule_field_present(const struct req_capsule *pill, */ void req_capsule_shrink(struct req_capsule *pill, const struct req_msg_field *field, - unsigned int newlen, - enum req_location loc) + u32 newlen, enum req_location loc) { const struct req_format *fmt; struct lustre_msg *msg; - int len; + u32 len; int offset; fmt = pill->rc_fmt; @@ -2228,7 +2212,7 @@ void req_capsule_shrink(struct req_capsule *pill, msg = __req_msg(pill, loc); len = lustre_msg_buflen(msg, offset); - LASSERTF(newlen <= len, "%s:%s, oldlen=%d, newlen=%d\n", + LASSERTF(newlen <= len, "%s:%s, oldlen=%u, newlen=%u\n", fmt->rf_name, field->rmf_name, len, newlen); if (loc == RCL_CLIENT) diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index bc93b75744e1..9bad57d65db4 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -191,7 +191,7 @@ ptlrpc_ldebugfs_register(struct dentry *root, char *dir, LASSERT(!*debugfs_root_ret); LASSERT(!*stats_ret); - svc_stats = lprocfs_alloc_stats(EXTRA_MAX_OPCODES+LUSTRE_MAX_OPCODES, + svc_stats = lprocfs_alloc_stats(EXTRA_MAX_OPCODES + LUSTRE_MAX_OPCODES, 0); if (!svc_stats) return; @@ -937,7 +937,7 @@ static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter) static int ptlrpc_lprocfs_svc_req_history_open(struct inode *inode, struct file *file) { - static struct seq_operations sops = { + static const struct seq_operations sops = { .start = ptlrpc_lprocfs_svc_req_history_start, .stop = ptlrpc_lprocfs_svc_req_history_stop, .next = ptlrpc_lprocfs_svc_req_history_next, diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 11ec82545347..9c937398a085 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -295,7 +295,6 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) } return 0; } -EXPORT_SYMBOL(ptlrpc_unregister_bulk); static void ptlrpc_at_set_reply(struct ptlrpc_request *req, int flags) { @@ -398,7 +397,8 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags) lustre_msg_set_status(req->rq_repmsg, ptlrpc_status_hton(req->rq_status)); lustre_msg_set_opc(req->rq_repmsg, - req->rq_reqmsg ? lustre_msg_get_opc(req->rq_reqmsg) : 0); + req->rq_reqmsg ? + lustre_msg_get_opc(req->rq_reqmsg) : 0); target_pack_pool_reply(req); @@ -433,7 +433,6 @@ out: ptlrpc_connection_put(conn); return rc; } -EXPORT_SYMBOL(ptlrpc_send_reply); int ptlrpc_reply(struct ptlrpc_request *req) { @@ -441,7 +440,6 @@ int ptlrpc_reply(struct ptlrpc_request *req) return 0; return ptlrpc_send_reply(req, 0); } -EXPORT_SYMBOL(ptlrpc_reply); /** * For request \a req send an error reply back. Create empty @@ -468,13 +466,11 @@ int ptlrpc_send_error(struct ptlrpc_request *req, int may_be_difficult) rc = ptlrpc_send_reply(req, may_be_difficult); return rc; } -EXPORT_SYMBOL(ptlrpc_send_error); int ptlrpc_error(struct ptlrpc_request *req) { return ptlrpc_send_error(req, 0); } -EXPORT_SYMBOL(ptlrpc_error); /** * Send request \a request. @@ -490,7 +486,8 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) struct ptlrpc_connection *connection; lnet_handle_me_t reply_me_h; lnet_md_t reply_md; - struct obd_device *obd = request->rq_import->imp_obd; + struct obd_import *imp = request->rq_import; + struct obd_device *obd = imp->imp_obd; if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_RPC)) return 0; @@ -503,7 +500,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) */ LASSERT(!request->rq_receiving_reply); LASSERT(!((lustre_msg_get_flags(request->rq_reqmsg) & MSG_REPLAY) && - (request->rq_import->imp_state == LUSTRE_IMP_FULL))); + (imp->imp_state == LUSTRE_IMP_FULL))); if (unlikely(obd && obd->obd_fail)) { CDEBUG(D_HA, "muting rpc for failed imp obd %s\n", @@ -516,15 +513,22 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) return -ENODEV; } - connection = request->rq_import->imp_connection; + connection = imp->imp_connection; lustre_msg_set_handle(request->rq_reqmsg, - &request->rq_import->imp_remote_handle); + &imp->imp_remote_handle); lustre_msg_set_type(request->rq_reqmsg, PTL_RPC_MSG_REQUEST); - lustre_msg_set_conn_cnt(request->rq_reqmsg, - request->rq_import->imp_conn_cnt); - lustre_msghdr_set_flags(request->rq_reqmsg, - request->rq_import->imp_msghdr_flags); + lustre_msg_set_conn_cnt(request->rq_reqmsg, imp->imp_conn_cnt); + lustre_msghdr_set_flags(request->rq_reqmsg, imp->imp_msghdr_flags); + + /** + * For enabled AT all request should have AT_SUPPORT in the + * FULL import state when OBD_CONNECT_AT is set + */ + LASSERT(AT_OFF || imp->imp_state != LUSTRE_IMP_FULL || + (imp->imp_msghdr_flags & MSGHDR_AT_SUPPORT) || + !(imp->imp_connect_data.ocd_connect_flags & + OBD_CONNECT_AT)); if (request->rq_resend) lustre_msg_add_flags(request->rq_reqmsg, MSG_RESENT); @@ -628,7 +632,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) ptlrpc_request_addref(request); if (obd && obd->obd_svc_stats) lprocfs_counter_add(obd->obd_svc_stats, PTLRPC_REQACTIVE_CNTR, - atomic_read(&request->rq_import->imp_inflight)); + atomic_read(&imp->imp_inflight)); OBD_FAIL_TIMEOUT(OBD_FAIL_PTLRPC_DELAY_SEND, request->rq_timeout + 5); @@ -640,7 +644,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) request->rq_deadline = request->rq_sent + request->rq_timeout + ptlrpc_at_get_net_latency(request); - ptlrpc_pinger_sending_on_import(request->rq_import); + ptlrpc_pinger_sending_on_import(imp); DEBUG_REQ(D_INFO, request, "send flg=%x", lustre_msg_get_flags(request->rq_reqmsg)); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index b514f18fae50..871768511e8c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -50,36 +50,34 @@ #include "ptlrpc_internal.h" -static inline int lustre_msg_hdr_size_v2(int count) +static inline u32 lustre_msg_hdr_size_v2(u32 count) { return cfs_size_round(offsetof(struct lustre_msg_v2, lm_buflens[count])); } -int lustre_msg_hdr_size(__u32 magic, int count) +u32 lustre_msg_hdr_size(__u32 magic, u32 count) { switch (magic) { case LUSTRE_MSG_MAGIC_V2: return lustre_msg_hdr_size_v2(count); default: LASSERTF(0, "incorrect message magic: %08x\n", magic); - return -EINVAL; + return 0; } } -EXPORT_SYMBOL(lustre_msg_hdr_size); void ptlrpc_buf_set_swabbed(struct ptlrpc_request *req, const int inout, - int index) + u32 index) { if (inout) lustre_set_req_swabbed(req, index); else lustre_set_rep_swabbed(req, index); } -EXPORT_SYMBOL(ptlrpc_buf_set_swabbed); int ptlrpc_buf_need_swab(struct ptlrpc_request *req, const int inout, - int index) + u32 index) { if (inout) return (ptlrpc_req_need_swab(req) && @@ -88,12 +86,11 @@ int ptlrpc_buf_need_swab(struct ptlrpc_request *req, const int inout, return (ptlrpc_rep_need_swab(req) && !lustre_rep_swabbed(req, index)); } -EXPORT_SYMBOL(ptlrpc_buf_need_swab); /* early reply size */ -int lustre_msg_early_size(void) +u32 lustre_msg_early_size(void) { - static int size; + static u32 size; if (!size) { /* Always reply old ptlrpc_body_v2 to keep interoperability @@ -111,9 +108,9 @@ int lustre_msg_early_size(void) } EXPORT_SYMBOL(lustre_msg_early_size); -int lustre_msg_size_v2(int count, __u32 *lengths) +u32 lustre_msg_size_v2(int count, __u32 *lengths) { - int size; + u32 size; int i; size = lustre_msg_hdr_size_v2(count); @@ -131,7 +128,7 @@ EXPORT_SYMBOL(lustre_msg_size_v2); * target then the first buffer will be stripped because the ptlrpc * data is part of the lustre_msg_v1 header. b=14043 */ -int lustre_msg_size(__u32 magic, int count, __u32 *lens) +u32 lustre_msg_size(__u32 magic, int count, __u32 *lens) { __u32 size[] = { sizeof(struct ptlrpc_body) }; @@ -148,15 +145,14 @@ int lustre_msg_size(__u32 magic, int count, __u32 *lens) return lustre_msg_size_v2(count, lens); default: LASSERTF(0, "incorrect message magic: %08x\n", magic); - return -EINVAL; + return 0; } } -EXPORT_SYMBOL(lustre_msg_size); /* This is used to determine the size of a buffer that was already packed * and will correctly handle the different message formats. */ -int lustre_packed_msg_size(struct lustre_msg *msg) +u32 lustre_packed_msg_size(struct lustre_msg *msg) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: @@ -166,7 +162,6 @@ int lustre_packed_msg_size(struct lustre_msg *msg) return 0; } } -EXPORT_SYMBOL(lustre_packed_msg_size); void lustre_init_msg_v2(struct lustre_msg_v2 *msg, int count, __u32 *lens, char **bufs) @@ -227,7 +222,6 @@ int lustre_pack_request(struct ptlrpc_request *req, __u32 magic, int count, /* only use new format, we don't need to be compatible with 1.4 */ return lustre_pack_request_v2(req, count, lens, bufs); } -EXPORT_SYMBOL(lustre_pack_request); #if RS_DEBUG LIST_HEAD(ptlrpc_rs_debug_lru); @@ -369,7 +363,6 @@ int lustre_pack_reply_flags(struct ptlrpc_request *req, int count, __u32 *lens, lustre_msg_size(req->rq_reqmsg->lm_magic, count, lens)); return rc; } -EXPORT_SYMBOL(lustre_pack_reply_flags); int lustre_pack_reply(struct ptlrpc_request *req, int count, __u32 *lens, char **bufs) @@ -378,11 +371,9 @@ int lustre_pack_reply(struct ptlrpc_request *req, int count, __u32 *lens, } EXPORT_SYMBOL(lustre_pack_reply); -void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, int n, int min_size) +void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, u32 n, u32 min_size) { - int i, offset, buflen, bufcount; - - LASSERT(n >= 0); + u32 i, offset, buflen, bufcount; bufcount = m->lm_bufcount; if (unlikely(n >= bufcount)) { @@ -406,7 +397,7 @@ void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, int n, int min_size) return (char *)m + offset; } -void *lustre_msg_buf(struct lustre_msg *m, int n, int min_size) +void *lustre_msg_buf(struct lustre_msg *m, u32 n, u32 min_size) { switch (m->lm_magic) { case LUSTRE_MSG_MAGIC_V2: @@ -419,7 +410,7 @@ void *lustre_msg_buf(struct lustre_msg *m, int n, int min_size) } EXPORT_SYMBOL(lustre_msg_buf); -static int lustre_shrink_msg_v2(struct lustre_msg_v2 *msg, int segment, +static int lustre_shrink_msg_v2(struct lustre_msg_v2 *msg, u32 segment, unsigned int newlen, int move_data) { char *tail = NULL, *newpos; @@ -493,7 +484,6 @@ void lustre_free_reply_state(struct ptlrpc_reply_state *rs) sptlrpc_svc_free_rs(rs); } -EXPORT_SYMBOL(lustre_free_reply_state); static int lustre_unpack_msg_v2(struct lustre_msg_v2 *m, int len) { @@ -581,7 +571,6 @@ int ptlrpc_unpack_req_msg(struct ptlrpc_request *req, int len) } return rc; } -EXPORT_SYMBOL(ptlrpc_unpack_req_msg); int ptlrpc_unpack_rep_msg(struct ptlrpc_request *req, int len) { @@ -594,7 +583,6 @@ int ptlrpc_unpack_rep_msg(struct ptlrpc_request *req, int len) } return rc; } -EXPORT_SYMBOL(ptlrpc_unpack_rep_msg); static inline int lustre_unpack_ptlrpc_body_v2(struct ptlrpc_request *req, const int inout, int offset) @@ -647,7 +635,7 @@ int lustre_unpack_rep_ptlrpc_body(struct ptlrpc_request *req, int offset) } } -static inline int lustre_msg_buflen_v2(struct lustre_msg_v2 *m, int n) +static inline u32 lustre_msg_buflen_v2(struct lustre_msg_v2 *m, u32 n) { if (n >= m->lm_bufcount) return 0; @@ -662,14 +650,14 @@ static inline int lustre_msg_buflen_v2(struct lustre_msg_v2 *m, int n) * * returns zero for non-existent message indices */ -int lustre_msg_buflen(struct lustre_msg *m, int n) +u32 lustre_msg_buflen(struct lustre_msg *m, u32 n) { switch (m->lm_magic) { case LUSTRE_MSG_MAGIC_V2: return lustre_msg_buflen_v2(m, n); default: CERROR("incorrect message magic: %08x\n", m->lm_magic); - return -EINVAL; + return 0; } } EXPORT_SYMBOL(lustre_msg_buflen); @@ -677,23 +665,22 @@ EXPORT_SYMBOL(lustre_msg_buflen); /* NB return the bufcount for lustre_msg_v2 format, so if message is packed * in V1 format, the result is one bigger. (add struct ptlrpc_body). */ -int lustre_msg_bufcount(struct lustre_msg *m) +u32 lustre_msg_bufcount(struct lustre_msg *m) { switch (m->lm_magic) { case LUSTRE_MSG_MAGIC_V2: return m->lm_bufcount; default: CERROR("incorrect message magic: %08x\n", m->lm_magic); - return -EINVAL; + return 0; } } -EXPORT_SYMBOL(lustre_msg_bufcount); -char *lustre_msg_string(struct lustre_msg *m, int index, int max_len) +char *lustre_msg_string(struct lustre_msg *m, u32 index, u32 max_len) { /* max_len == 0 means the string should fill the buffer */ char *str; - int slen, blen; + u32 slen, blen; switch (m->lm_magic) { case LUSTRE_MSG_MAGIC_V2: @@ -731,11 +718,10 @@ char *lustre_msg_string(struct lustre_msg *m, int index, int max_len) return str; } -EXPORT_SYMBOL(lustre_msg_string); /* Wrap up the normal fixed length cases */ -static inline void *__lustre_swab_buf(struct lustre_msg *msg, int index, - int min_size, void *swabber) +static inline void *__lustre_swab_buf(struct lustre_msg *msg, u32 index, + u32 min_size, void *swabber) { void *ptr = NULL; @@ -804,7 +790,7 @@ __u32 lustre_msg_get_flags(struct lustre_msg *msg) } EXPORT_SYMBOL(lustre_msg_get_flags); -void lustre_msg_add_flags(struct lustre_msg *msg, int flags) +void lustre_msg_add_flags(struct lustre_msg *msg, u32 flags) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -820,7 +806,7 @@ void lustre_msg_add_flags(struct lustre_msg *msg, int flags) } EXPORT_SYMBOL(lustre_msg_add_flags); -void lustre_msg_set_flags(struct lustre_msg *msg, int flags) +void lustre_msg_set_flags(struct lustre_msg *msg, u32 flags) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -834,9 +820,8 @@ void lustre_msg_set_flags(struct lustre_msg *msg, int flags) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_flags); -void lustre_msg_clear_flags(struct lustre_msg *msg, int flags) +void lustre_msg_clear_flags(struct lustre_msg *msg, u32 flags) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -868,9 +853,8 @@ __u32 lustre_msg_get_op_flags(struct lustre_msg *msg) return 0; } } -EXPORT_SYMBOL(lustre_msg_get_op_flags); -void lustre_msg_add_op_flags(struct lustre_msg *msg, int flags) +void lustre_msg_add_op_flags(struct lustre_msg *msg, u32 flags) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -903,7 +887,6 @@ struct lustre_handle *lustre_msg_get_handle(struct lustre_msg *msg) return NULL; } } -EXPORT_SYMBOL(lustre_msg_get_handle); __u32 lustre_msg_get_type(struct lustre_msg *msg) { @@ -924,7 +907,7 @@ __u32 lustre_msg_get_type(struct lustre_msg *msg) } EXPORT_SYMBOL(lustre_msg_get_type); -void lustre_msg_add_version(struct lustre_msg *msg, int version) +void lustre_msg_add_version(struct lustre_msg *msg, u32 version) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -938,7 +921,6 @@ void lustre_msg_add_version(struct lustre_msg *msg, int version) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_add_version); __u32 lustre_msg_get_opc(struct lustre_msg *msg) { @@ -1055,7 +1037,6 @@ __u64 lustre_msg_get_slv(struct lustre_msg *msg) return -EINVAL; } } -EXPORT_SYMBOL(lustre_msg_get_slv); void lustre_msg_set_slv(struct lustre_msg *msg, __u64 slv) { @@ -1075,7 +1056,6 @@ void lustre_msg_set_slv(struct lustre_msg *msg, __u64 slv) return; } } -EXPORT_SYMBOL(lustre_msg_set_slv); __u32 lustre_msg_get_limit(struct lustre_msg *msg) { @@ -1094,7 +1074,6 @@ __u32 lustre_msg_get_limit(struct lustre_msg *msg) return -EINVAL; } } -EXPORT_SYMBOL(lustre_msg_get_limit); void lustre_msg_set_limit(struct lustre_msg *msg, __u64 limit) { @@ -1114,7 +1093,6 @@ void lustre_msg_set_limit(struct lustre_msg *msg, __u64 limit) return; } } -EXPORT_SYMBOL(lustre_msg_set_limit); __u32 lustre_msg_get_conn_cnt(struct lustre_msg *msg) { @@ -1145,7 +1123,6 @@ __u32 lustre_msg_get_magic(struct lustre_msg *msg) return 0; } } -EXPORT_SYMBOL(lustre_msg_get_magic); __u32 lustre_msg_get_timeout(struct lustre_msg *msg) { @@ -1203,8 +1180,9 @@ __u32 lustre_msg_calc_cksum(struct lustre_msg *msg) unsigned int hsize = 4; cfs_crypto_hash_digest(CFS_HASH_ALG_CRC32, (unsigned char *)pb, - lustre_msg_buflen(msg, MSG_PTLRPC_BODY_OFF), - NULL, 0, (unsigned char *)&crc, &hsize); + lustre_msg_buflen(msg, + MSG_PTLRPC_BODY_OFF), + NULL, 0, (unsigned char *)&crc, &hsize); return crc; } default: @@ -1227,7 +1205,6 @@ void lustre_msg_set_handle(struct lustre_msg *msg, struct lustre_handle *handle) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_handle); void lustre_msg_set_type(struct lustre_msg *msg, __u32 type) { @@ -1243,7 +1220,6 @@ void lustre_msg_set_type(struct lustre_msg *msg, __u32 type) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_type); void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc) { @@ -1259,7 +1235,6 @@ void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_opc); void lustre_msg_set_versions(struct lustre_msg *msg, __u64 *versions) { @@ -1326,7 +1301,6 @@ void lustre_msg_set_conn_cnt(struct lustre_msg *msg, __u32 conn_cnt) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_conn_cnt); void lustre_msg_set_timeout(struct lustre_msg *msg, __u32 timeout) { @@ -1377,7 +1351,7 @@ void lustre_msg_set_jobid(struct lustre_msg *msg, char *jobid) LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg); if (jobid) - memcpy(pb->pb_jobid, jobid, JOBSTATS_JOBID_SIZE); + memcpy(pb->pb_jobid, jobid, LUSTRE_JOBID_SIZE); else if (pb->pb_jobid[0] == '\0') lustre_get_jobid(pb->pb_jobid); return; @@ -1491,7 +1465,6 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *b) */ CLASSERT(offsetof(typeof(*b), pb_jobid) != 0); } -EXPORT_SYMBOL(lustre_swab_ptlrpc_body); void lustre_swab_connect(struct obd_connect_data *ocd) { @@ -1591,7 +1564,6 @@ void lustre_swab_obd_statfs(struct obd_statfs *os) CLASSERT(offsetof(typeof(*os), os_spare8) != 0); CLASSERT(offsetof(typeof(*os), os_spare9) != 0); } -EXPORT_SYMBOL(lustre_swab_obd_statfs); void lustre_swab_obd_ioobj(struct obd_ioobj *ioo) { @@ -1599,33 +1571,28 @@ void lustre_swab_obd_ioobj(struct obd_ioobj *ioo) __swab32s(&ioo->ioo_max_brw); __swab32s(&ioo->ioo_bufcnt); } -EXPORT_SYMBOL(lustre_swab_obd_ioobj); void lustre_swab_niobuf_remote(struct niobuf_remote *nbr) { - __swab64s(&nbr->offset); - __swab32s(&nbr->len); - __swab32s(&nbr->flags); + __swab64s(&nbr->rnb_offset); + __swab32s(&nbr->rnb_len); + __swab32s(&nbr->rnb_flags); } -EXPORT_SYMBOL(lustre_swab_niobuf_remote); void lustre_swab_ost_body(struct ost_body *b) { lustre_swab_obdo(&b->oa); } -EXPORT_SYMBOL(lustre_swab_ost_body); void lustre_swab_ost_last_id(u64 *id) { __swab64s(id); } -EXPORT_SYMBOL(lustre_swab_ost_last_id); void lustre_swab_generic_32s(__u32 *val) { __swab32s(val); } -EXPORT_SYMBOL(lustre_swab_generic_32s); void lustre_swab_gl_desc(union ldlm_gl_desc *desc) { @@ -1674,37 +1641,36 @@ EXPORT_SYMBOL(lustre_swab_lquota_lvb); void lustre_swab_mdt_body(struct mdt_body *b) { - lustre_swab_lu_fid(&b->fid1); - lustre_swab_lu_fid(&b->fid2); + lustre_swab_lu_fid(&b->mbo_fid1); + lustre_swab_lu_fid(&b->mbo_fid2); /* handle is opaque */ - __swab64s(&b->valid); - __swab64s(&b->size); - __swab64s(&b->mtime); - __swab64s(&b->atime); - __swab64s(&b->ctime); - __swab64s(&b->blocks); - __swab64s(&b->ioepoch); - __swab64s(&b->t_state); - __swab32s(&b->fsuid); - __swab32s(&b->fsgid); - __swab32s(&b->capability); - __swab32s(&b->mode); - __swab32s(&b->uid); - __swab32s(&b->gid); - __swab32s(&b->flags); - __swab32s(&b->rdev); - __swab32s(&b->nlink); - CLASSERT(offsetof(typeof(*b), unused2) != 0); - __swab32s(&b->suppgid); - __swab32s(&b->eadatasize); - __swab32s(&b->aclsize); - __swab32s(&b->max_mdsize); - __swab32s(&b->max_cookiesize); - __swab32s(&b->uid_h); - __swab32s(&b->gid_h); - CLASSERT(offsetof(typeof(*b), padding_5) != 0); + __swab64s(&b->mbo_valid); + __swab64s(&b->mbo_size); + __swab64s(&b->mbo_mtime); + __swab64s(&b->mbo_atime); + __swab64s(&b->mbo_ctime); + __swab64s(&b->mbo_blocks); + __swab64s(&b->mbo_ioepoch); + __swab64s(&b->mbo_t_state); + __swab32s(&b->mbo_fsuid); + __swab32s(&b->mbo_fsgid); + __swab32s(&b->mbo_capability); + __swab32s(&b->mbo_mode); + __swab32s(&b->mbo_uid); + __swab32s(&b->mbo_gid); + __swab32s(&b->mbo_flags); + __swab32s(&b->mbo_rdev); + __swab32s(&b->mbo_nlink); + CLASSERT(offsetof(typeof(*b), mbo_unused2) != 0); + __swab32s(&b->mbo_suppgid); + __swab32s(&b->mbo_eadatasize); + __swab32s(&b->mbo_aclsize); + __swab32s(&b->mbo_max_mdsize); + __swab32s(&b->mbo_max_cookiesize); + __swab32s(&b->mbo_uid_h); + __swab32s(&b->mbo_gid_h); + CLASSERT(offsetof(typeof(*b), mbo_padding_5) != 0); } -EXPORT_SYMBOL(lustre_swab_mdt_body); void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b) { @@ -1713,7 +1679,6 @@ void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b) __swab32s(&b->flags); CLASSERT(offsetof(typeof(*b), padding) != 0); } -EXPORT_SYMBOL(lustre_swab_mdt_ioepoch); void lustre_swab_mgs_target_info(struct mgs_target_info *mti) { @@ -1729,11 +1694,10 @@ void lustre_swab_mgs_target_info(struct mgs_target_info *mti) for (i = 0; i < MTI_NIDS_MAX; i++) __swab64s(&mti->mti_nids[i]); } -EXPORT_SYMBOL(lustre_swab_mgs_target_info); void lustre_swab_mgs_nidtbl_entry(struct mgs_nidtbl_entry *entry) { - int i; + __u8 i; __swab64s(&entry->mne_version); __swab32s(&entry->mne_instance); @@ -1760,14 +1724,12 @@ void lustre_swab_mgs_config_body(struct mgs_config_body *body) __swab32s(&body->mcb_units); __swab16s(&body->mcb_type); } -EXPORT_SYMBOL(lustre_swab_mgs_config_body); void lustre_swab_mgs_config_res(struct mgs_config_res *body) { __swab64s(&body->mcr_offset); __swab64s(&body->mcr_size); } -EXPORT_SYMBOL(lustre_swab_mgs_config_res); static void lustre_swab_obd_dqinfo(struct obd_dqinfo *i) { @@ -1800,7 +1762,6 @@ void lustre_swab_obd_quotactl(struct obd_quotactl *q) lustre_swab_obd_dqinfo(&q->qc_dqinfo); lustre_swab_obd_dqblk(&q->qc_dqblk); } -EXPORT_SYMBOL(lustre_swab_obd_quotactl); void lustre_swab_fid2path(struct getinfo_fid2path *gf) { @@ -1822,7 +1783,7 @@ static void lustre_swab_fiemap_extent(struct ll_fiemap_extent *fm_extent) void lustre_swab_fiemap(struct ll_user_fiemap *fiemap) { - int i; + __u32 i; __swab64s(&fiemap->fm_start); __swab64s(&fiemap->fm_length); @@ -1834,7 +1795,6 @@ void lustre_swab_fiemap(struct ll_user_fiemap *fiemap) for (i = 0; i < fiemap->fm_mapped_extents; i++) lustre_swab_fiemap_extent(&fiemap->fm_extents[i]); } -EXPORT_SYMBOL(lustre_swab_fiemap); void lustre_swab_mdt_rec_reint (struct mdt_rec_reint *rr) { @@ -1863,7 +1823,6 @@ void lustre_swab_mdt_rec_reint (struct mdt_rec_reint *rr) CLASSERT(offsetof(typeof(*rr), rr_padding_4) != 0); }; -EXPORT_SYMBOL(lustre_swab_mdt_rec_reint); void lustre_swab_lov_desc(struct lov_desc *ld) { @@ -1878,19 +1837,43 @@ void lustre_swab_lov_desc(struct lov_desc *ld) } EXPORT_SYMBOL(lustre_swab_lov_desc); -static void print_lum(struct lov_user_md *lum) +/* This structure is always in little-endian */ +static void lustre_swab_lmv_mds_md_v1(struct lmv_mds_md_v1 *lmm1) { - CDEBUG(D_OTHER, "lov_user_md %p:\n", lum); - CDEBUG(D_OTHER, "\tlmm_magic: %#x\n", lum->lmm_magic); - CDEBUG(D_OTHER, "\tlmm_pattern: %#x\n", lum->lmm_pattern); - CDEBUG(D_OTHER, "\tlmm_object_id: %llu\n", lmm_oi_id(&lum->lmm_oi)); - CDEBUG(D_OTHER, "\tlmm_object_gr: %llu\n", lmm_oi_seq(&lum->lmm_oi)); - CDEBUG(D_OTHER, "\tlmm_stripe_size: %#x\n", lum->lmm_stripe_size); - CDEBUG(D_OTHER, "\tlmm_stripe_count: %#x\n", lum->lmm_stripe_count); - CDEBUG(D_OTHER, "\tlmm_stripe_offset/lmm_layout_gen: %#x\n", - lum->lmm_stripe_offset); + int i; + + __swab32s(&lmm1->lmv_magic); + __swab32s(&lmm1->lmv_stripe_count); + __swab32s(&lmm1->lmv_master_mdt_index); + __swab32s(&lmm1->lmv_hash_type); + __swab32s(&lmm1->lmv_layout_version); + for (i = 0; i < lmm1->lmv_stripe_count; i++) + lustre_swab_lu_fid(&lmm1->lmv_stripe_fids[i]); } +void lustre_swab_lmv_mds_md(union lmv_mds_md *lmm) +{ + switch (lmm->lmv_magic) { + case LMV_MAGIC_V1: + lustre_swab_lmv_mds_md_v1(&lmm->lmv_md_v1); + break; + default: + break; + } +} +EXPORT_SYMBOL(lustre_swab_lmv_mds_md); + +void lustre_swab_lmv_user_md(struct lmv_user_md *lum) +{ + __swab32s(&lum->lum_magic); + __swab32s(&lum->lum_stripe_count); + __swab32s(&lum->lum_stripe_offset); + __swab32s(&lum->lum_hash_type); + __swab32s(&lum->lum_type); + CLASSERT(offsetof(typeof(*lum), lum_padding1)); +} +EXPORT_SYMBOL(lustre_swab_lmv_user_md); + static void lustre_swab_lmm_oi(struct ost_id *oi) { __swab64s(&oi->oi.oi_id); @@ -1905,7 +1888,6 @@ static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum) __swab32s(&lum->lmm_stripe_size); __swab16s(&lum->lmm_stripe_count); __swab16s(&lum->lmm_stripe_offset); - print_lum(lum); } void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum) @@ -1941,9 +1923,9 @@ void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod, int i; for (i = 0; i < stripe_count; i++) { - lustre_swab_ost_id(&(lod[i].l_ost_oi)); - __swab32s(&(lod[i].l_ost_gen)); - __swab32s(&(lod[i].l_ost_idx)); + lustre_swab_ost_id(&lod[i].l_ost_oi); + __swab32s(&lod[i].l_ost_gen); + __swab32s(&lod[i].l_ost_idx); } } EXPORT_SYMBOL(lustre_swab_lov_user_md_objects); @@ -1973,7 +1955,6 @@ void lustre_swab_ldlm_intent(struct ldlm_intent *i) { __swab64s(&i->opc); } -EXPORT_SYMBOL(lustre_swab_ldlm_intent); static void lustre_swab_ldlm_resource_desc(struct ldlm_resource_desc *r) { @@ -1997,7 +1978,6 @@ void lustre_swab_ldlm_request(struct ldlm_request *rq) __swab32s(&rq->lock_count); /* lock_handle[] opaque */ } -EXPORT_SYMBOL(lustre_swab_ldlm_request); void lustre_swab_ldlm_reply(struct ldlm_reply *r) { @@ -2008,7 +1988,6 @@ void lustre_swab_ldlm_reply(struct ldlm_reply *r) __swab64s(&r->lock_policy_res1); __swab64s(&r->lock_policy_res2); } -EXPORT_SYMBOL(lustre_swab_ldlm_reply); /* Dump functions */ void dump_ioo(struct obd_ioobj *ioo) @@ -2018,14 +1997,12 @@ void dump_ioo(struct obd_ioobj *ioo) POSTID(&ioo->ioo_oid), ioo->ioo_max_brw, ioo->ioo_bufcnt); } -EXPORT_SYMBOL(dump_ioo); void dump_rniobuf(struct niobuf_remote *nb) { CDEBUG(D_RPCTRACE, "niobuf_remote: offset=%llu, len=%d, flags=%x\n", - nb->offset, nb->len, nb->flags); + nb->rnb_offset, nb->rnb_len, nb->rnb_flags); } -EXPORT_SYMBOL(dump_rniobuf); static void dump_obdo(struct obdo *oa) { @@ -2093,13 +2070,11 @@ void dump_ost_body(struct ost_body *ob) { dump_obdo(&ob->oa); } -EXPORT_SYMBOL(dump_ost_body); void dump_rcs(__u32 *rc) { CDEBUG(D_RPCTRACE, "rmf_rcs: %d\n", *rc); } -EXPORT_SYMBOL(dump_rcs); static inline int req_ptlrpc_body_swabbed(struct ptlrpc_request *req) { @@ -2184,14 +2159,12 @@ void lustre_swab_lustre_capa(struct lustre_capa *c) __swab32s(&c->lc_timeout); __swab32s(&c->lc_expiry); } -EXPORT_SYMBOL(lustre_swab_lustre_capa); void lustre_swab_hsm_user_state(struct hsm_user_state *state) { __swab32s(&state->hus_states); __swab32s(&state->hus_archive_id); } -EXPORT_SYMBOL(lustre_swab_hsm_user_state); void lustre_swab_hsm_state_set(struct hsm_state_set *hss) { @@ -2214,14 +2187,12 @@ void lustre_swab_hsm_current_action(struct hsm_current_action *action) __swab32s(&action->hca_action); lustre_swab_hsm_extent(&action->hca_location); } -EXPORT_SYMBOL(lustre_swab_hsm_current_action); void lustre_swab_hsm_user_item(struct hsm_user_item *hui) { lustre_swab_lu_fid(&hui->hui_fid); lustre_swab_hsm_extent(&hui->hui_extent); } -EXPORT_SYMBOL(lustre_swab_hsm_user_item); void lustre_swab_layout_intent(struct layout_intent *li) { @@ -2230,7 +2201,6 @@ void lustre_swab_layout_intent(struct layout_intent *li) __swab64s(&li->li_start); __swab64s(&li->li_end); } -EXPORT_SYMBOL(lustre_swab_layout_intent); void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk) { @@ -2241,7 +2211,6 @@ void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk) __swab16s(&hpk->hpk_flags); __swab16s(&hpk->hpk_errval); } -EXPORT_SYMBOL(lustre_swab_hsm_progress_kernel); void lustre_swab_hsm_request(struct hsm_request *hr) { @@ -2251,7 +2220,6 @@ void lustre_swab_hsm_request(struct hsm_request *hr) __swab32s(&hr->hr_itemcount); __swab32s(&hr->hr_data_len); } -EXPORT_SYMBOL(lustre_swab_hsm_request); void lustre_swab_swap_layouts(struct mdc_swap_layouts *msl) { @@ -2264,4 +2232,3 @@ void lustre_swab_close_data(struct close_data *cd) lustre_swab_lu_fid(&cd->cd_fid); __swab64s(&cd->cd_data_version); } -EXPORT_SYMBOL(lustre_swab_close_data); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pers.c b/drivers/staging/lustre/lustre/ptlrpc/pers.c index 6c820e944171..5b9fb11c0b6b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pers.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pers.c @@ -64,9 +64,9 @@ void ptlrpc_add_bulk_page(struct ptlrpc_bulk_desc *desc, struct page *page, { lnet_kiov_t *kiov = &desc->bd_iov[desc->bd_iov_count]; - kiov->kiov_page = page; - kiov->kiov_offset = pageoffset; - kiov->kiov_len = len; + kiov->bv_page = page; + kiov->bv_offset = pageoffset; + kiov->bv_len = len; desc->bd_iov_count++; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index c0529d808d81..5504fc2363ac 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -340,7 +340,6 @@ void ptlrpc_pinger_sending_on_import(struct obd_import *imp) { ptlrpc_update_next_ping(imp, 0); } -EXPORT_SYMBOL(ptlrpc_pinger_sending_on_import); void ptlrpc_pinger_commit_expected(struct obd_import *imp) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index a9831fab80f3..f14d193287da 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -53,6 +53,8 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait); int ptlrpcd_start(struct ptlrpcd_ctl *pc); /* client.c */ +void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req, + unsigned int service_time); struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned npages, unsigned max_brw, unsigned type, unsigned portal); int ptlrpc_request_cache_init(void); @@ -60,6 +62,11 @@ void ptlrpc_request_cache_fini(void); struct ptlrpc_request *ptlrpc_request_cache_alloc(gfp_t flags); void ptlrpc_request_cache_free(struct ptlrpc_request *req); void ptlrpc_init_xid(void); +void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc, + struct ptlrpc_request *req); +int ptlrpc_expired_set(void *data); +int ptlrpc_set_next_timeout(struct ptlrpc_request_set *); +void ptlrpc_resend_req(struct ptlrpc_request *request); /* events.c */ int ptlrpc_init_portals(void); @@ -268,7 +275,7 @@ void sptlrpc_conf_fini(void); int sptlrpc_init(void); void sptlrpc_fini(void); -static inline int ll_rpc_recoverable_error(int rc) +static inline bool ptlrpc_recoverable_error(int rc) { return (rc == -ENOTCONN || rc == -ENODEV); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index 0a374b6c2f71..1f55d642aa75 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -412,7 +412,7 @@ static int ptlrpcd(void *arg) * an argument, describing its "scope". */ rc = lu_context_init(&env.le_ctx, - LCT_CL_THREAD|LCT_REMEMBER|LCT_NOREF); + LCT_CL_THREAD | LCT_REMEMBER | LCT_NOREF); if (rc == 0) { rc = lu_context_init(env.le_ses, LCT_SESSION | LCT_REMEMBER | LCT_NOREF); @@ -567,7 +567,7 @@ int ptlrpcd_start(struct ptlrpcd_ctl *pc) * ptlrpcd thread (or a thread-set) has to be given an argument, * describing its "scope". */ - rc = lu_context_init(&pc->pc_env.le_ctx, LCT_CL_THREAD|LCT_REMEMBER); + rc = lu_context_init(&pc->pc_env.le_ctx, LCT_CL_THREAD | LCT_REMEMBER); if (rc != 0) goto out; diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c index 718b3a8d61c6..405faf0dc9fc 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/recover.c +++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c @@ -201,7 +201,6 @@ int ptlrpc_resend(struct obd_import *imp) return 0; } -EXPORT_SYMBOL(ptlrpc_resend); /** * Go through all requests in delayed list and wake their threads @@ -221,7 +220,6 @@ void ptlrpc_wake_delayed(struct obd_import *imp) } spin_unlock(&imp->imp_lock); } -EXPORT_SYMBOL(ptlrpc_wake_delayed); void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index dbd819fa6b75..5d3995d5c69a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -311,6 +311,19 @@ static int import_sec_check_expire(struct obd_import *imp) return sptlrpc_import_sec_adapt(imp, NULL, NULL); } +/** + * Get and validate the client side ptlrpc security facilities from + * \a imp. There is a race condition on client reconnect when the import is + * being destroyed while there are outstanding client bound requests. In + * this case do not output any error messages if import secuity is not + * found. + * + * \param[in] imp obd import associated with client + * \param[out] sec client side ptlrpc security + * + * \retval 0 if security retrieved successfully + * \retval -ve errno if there was a problem + */ static int import_sec_validate_get(struct obd_import *imp, struct ptlrpc_sec **sec) { @@ -323,9 +336,11 @@ static int import_sec_validate_get(struct obd_import *imp, } *sec = sptlrpc_import_sec_ref(imp); + /* Only output an error when the import is still active */ if (!*sec) { - CERROR("import %p (%s) with no sec\n", - imp, ptlrpc_import_state_name(imp->imp_state)); + if (list_empty(&imp->imp_zombie_chain)) + CERROR("import %p (%s) with no sec\n", + imp, ptlrpc_import_state_name(imp->imp_state)); return -EACCES; } @@ -499,7 +514,7 @@ static int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req) newctx, newctx->cc_flags); set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC)); } else { /* * it's possible newctx == oldctx if we're switching @@ -718,8 +733,9 @@ again: req->rq_restart = 0; spin_unlock(&req->rq_lock); - lwi = LWI_TIMEOUT_INTR(timeout * HZ, ctx_refresh_timeout, - ctx_refresh_interrupt, req); + lwi = LWI_TIMEOUT_INTR(msecs_to_jiffies(timeout * MSEC_PER_SEC), + ctx_refresh_timeout, ctx_refresh_interrupt, + req); rc = l_wait_event(req->rq_reply_waitq, ctx_check_refresh(ctx), &lwi); /* diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index 5f4d79718589..b2cc5ea6cb93 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -139,7 +139,7 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v) "cache missing: %lu\n" "low free mark: %lu\n" "max waitqueue depth: %u\n" - "max wait time: %ld/%u\n", + "max wait time: %ld/%lu\n", totalram_pages, PAGES_PER_POOL, page_pools.epp_max_pages, @@ -158,7 +158,7 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v) page_pools.epp_st_lowfree, page_pools.epp_st_max_wqlen, page_pools.epp_st_max_wait, - HZ); + msecs_to_jiffies(MSEC_PER_SEC)); spin_unlock(&page_pools.epp_lock); @@ -326,12 +326,12 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc) LASSERT(page_pools.epp_pools[p_idx]); for (i = 0; i < desc->bd_iov_count; i++) { - LASSERT(desc->bd_enc_iov[i].kiov_page); + LASSERT(desc->bd_enc_iov[i].bv_page); LASSERT(g_idx != 0 || page_pools.epp_pools[p_idx]); LASSERT(!page_pools.epp_pools[p_idx][g_idx]); page_pools.epp_pools[p_idx][g_idx] = - desc->bd_enc_iov[i].kiov_page; + desc->bd_enc_iov[i].bv_page; if (++g_idx == PAGES_PER_POOL) { p_idx++; @@ -348,7 +348,6 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc) kfree(desc->bd_enc_iov); desc->bd_enc_iov = NULL; } -EXPORT_SYMBOL(sptlrpc_enc_pool_put_pages); static inline void enc_pools_alloc(void) { @@ -432,12 +431,13 @@ void sptlrpc_enc_pool_fini(void) if (page_pools.epp_st_access > 0) { CDEBUG(D_SEC, - "max pages %lu, grows %u, grow fails %u, shrinks %u, access %lu, missing %lu, max qlen %u, max wait %ld/%d\n", + "max pages %lu, grows %u, grow fails %u, shrinks %u, access %lu, missing %lu, max qlen %u, max wait %ld/%ld\n", page_pools.epp_st_max_pages, page_pools.epp_st_grows, page_pools.epp_st_grow_fails, page_pools.epp_st_shrinks, page_pools.epp_st_access, page_pools.epp_st_missings, page_pools.epp_st_max_wqlen, - page_pools.epp_st_max_wait, HZ); + page_pools.epp_st_max_wait, + msecs_to_jiffies(MSEC_PER_SEC)); } } @@ -456,13 +456,11 @@ const char *sptlrpc_get_hash_name(__u8 hash_alg) { return cfs_crypto_hash_name(cfs_hash_alg_id[hash_alg]); } -EXPORT_SYMBOL(sptlrpc_get_hash_name); __u8 sptlrpc_get_hash_alg(const char *algname) { return cfs_crypto_hash_alg(algname); } -EXPORT_SYMBOL(sptlrpc_get_hash_alg); int bulk_sec_desc_unpack(struct lustre_msg *msg, int offset, int swabbed) { @@ -522,9 +520,10 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, hashsize = cfs_crypto_hash_digestsize(cfs_hash_alg_id[alg]); for (i = 0; i < desc->bd_iov_count; i++) { - cfs_crypto_hash_update_page(hdesc, desc->bd_iov[i].kiov_page, - desc->bd_iov[i].kiov_offset & ~PAGE_MASK, - desc->bd_iov[i].kiov_len); + cfs_crypto_hash_update_page(hdesc, desc->bd_iov[i].bv_page, + desc->bd_iov[i].bv_offset & + ~PAGE_MASK, + desc->bd_iov[i].bv_len); } if (hashsize > buflen) { @@ -542,4 +541,3 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, return err; } -EXPORT_SYMBOL(sptlrpc_get_bulk_checksum); diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c index c14035479c5f..2181a85efd49 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c @@ -58,7 +58,6 @@ enum lustre_sec_part sptlrpc_target_sec_part(struct obd_device *obd) CERROR("unknown target %p(%s)\n", obd, type); return LUSTRE_SP_ANY; } -EXPORT_SYMBOL(sptlrpc_target_sec_part); /**************************************** * user supplied flavor string parsing * diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c index 9b9801ece582..8ffd000eafac 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c @@ -71,7 +71,6 @@ void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec) CDEBUG(D_SEC, "added sec %p(%s)\n", sec, sec->ps_policy->sp_name); } -EXPORT_SYMBOL(sptlrpc_gc_add_sec); void sptlrpc_gc_del_sec(struct ptlrpc_sec *sec) { @@ -95,7 +94,6 @@ void sptlrpc_gc_del_sec(struct ptlrpc_sec *sec) CDEBUG(D_SEC, "del sec %p(%s)\n", sec, sec->ps_policy->sp_name); } -EXPORT_SYMBOL(sptlrpc_gc_del_sec); static void sec_process_ctx_list(void) { @@ -182,7 +180,8 @@ again: /* check ctx list again before sleep */ sec_process_ctx_list(); - lwi = LWI_TIMEOUT(SEC_GC_INTERVAL * HZ, NULL, NULL); + lwi = LWI_TIMEOUT(msecs_to_jiffies(SEC_GC_INTERVAL * MSEC_PER_SEC), + NULL, NULL); l_wait_event(thread->t_ctl_waitq, thread_is_stopping(thread) || thread_is_signal(thread), diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c index 5c4590b0c521..cd305bcb334a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c @@ -154,13 +154,13 @@ static void corrupt_bulk_data(struct ptlrpc_bulk_desc *desc) unsigned int off, i; for (i = 0; i < desc->bd_iov_count; i++) { - if (desc->bd_iov[i].kiov_len == 0) + if (desc->bd_iov[i].bv_len == 0) continue; - ptr = kmap(desc->bd_iov[i].kiov_page); - off = desc->bd_iov[i].kiov_offset & ~PAGE_MASK; + ptr = kmap(desc->bd_iov[i].bv_page); + off = desc->bd_iov[i].bv_offset & ~PAGE_MASK; ptr[off] ^= 0x1; - kunmap(desc->bd_iov[i].kiov_page); + kunmap(desc->bd_iov[i].bv_page); return; } } @@ -249,9 +249,12 @@ int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req) unsigned int hsize = 4; cfs_crypto_hash_digest(CFS_HASH_ALG_CRC32, - lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, 0), - lustre_msg_buflen(msg, PLAIN_PACK_MSG_OFF), - NULL, 0, (unsigned char *)&cksum, &hsize); + lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, + 0), + lustre_msg_buflen(msg, + PLAIN_PACK_MSG_OFF), + NULL, 0, (unsigned char *)&cksum, + &hsize); if (cksum != msg->lm_cksum) { CDEBUG(D_SEC, "early reply checksum mismatch: %08x != %08x\n", @@ -349,11 +352,11 @@ int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx, /* fix the actual data size */ for (i = 0, nob = 0; i < desc->bd_iov_count; i++) { - if (desc->bd_iov[i].kiov_len + nob > desc->bd_nob_transferred) { - desc->bd_iov[i].kiov_len = + if (desc->bd_iov[i].bv_len + nob > desc->bd_nob_transferred) { + desc->bd_iov[i].bv_len = desc->bd_nob_transferred - nob; } - nob += desc->bd_iov[i].kiov_len; + nob += desc->bd_iov[i].bv_len; } rc = plain_verify_bulk_csum(desc, req->rq_flvr.u_bulk.hash.hash_alg, @@ -869,9 +872,12 @@ int plain_authorize(struct ptlrpc_request *req) unsigned int hsize = 4; cfs_crypto_hash_digest(CFS_HASH_ALG_CRC32, - lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, 0), - lustre_msg_buflen(msg, PLAIN_PACK_MSG_OFF), - NULL, 0, (unsigned char *)&msg->lm_cksum, &hsize); + lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, + 0), + lustre_msg_buflen(msg, + PLAIN_PACK_MSG_OFF), + NULL, 0, (unsigned char *)&msg->lm_cksum, + &hsize); req->rq_reply_off = 0; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 4788c4940c2a..72f39308eebb 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -1005,6 +1005,10 @@ ptlrpc_at_remove_timed(struct ptlrpc_request *req) array->paa_count--; } +/* + * Attempt to extend the request deadline by sending an early reply to the + * client. + */ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) { struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt; @@ -1039,24 +1043,26 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) return -ENOSYS; } - /* Fake our processing time into the future to ask the clients - * for some extra amount of time + /* + * We want to extend the request deadline by at_extra seconds, + * so we set our service estimate to reflect how much time has + * passed since this request arrived plus an additional + * at_extra seconds. The client will calculate the new deadline + * based on this service estimate (plus some additional time to + * account for network latency). See ptlrpc_at_recv_early_reply */ at_measured(&svcpt->scp_at_estimate, at_extra + ktime_get_real_seconds() - req->rq_arrival_time.tv_sec); + newdl = req->rq_arrival_time.tv_sec + at_get(&svcpt->scp_at_estimate); /* Check to see if we've actually increased the deadline - * we may be past adaptive_max */ - if (req->rq_deadline >= req->rq_arrival_time.tv_sec + - at_get(&svcpt->scp_at_estimate)) { + if (req->rq_deadline >= newdl) { DEBUG_REQ(D_WARNING, req, "Couldn't add any time (%ld/%lld), not sending early reply\n", - olddl, req->rq_arrival_time.tv_sec + - at_get(&svcpt->scp_at_estimate) - - ktime_get_real_seconds()); + olddl, newdl - ktime_get_real_seconds()); return -ETIMEDOUT; } - newdl = ktime_get_real_seconds() + at_get(&svcpt->scp_at_estimate); reqcopy = ptlrpc_request_cache_alloc(GFP_NOFS); if (!reqcopy) @@ -1982,11 +1988,12 @@ ptlrpc_wait_event(struct ptlrpc_service_part *svcpt, cond_resched(); l_wait_event_exclusive_head(svcpt->scp_waitq, - ptlrpc_thread_stopping(thread) || - ptlrpc_server_request_incoming(svcpt) || - ptlrpc_server_request_pending(svcpt, false) || - ptlrpc_rqbd_pending(svcpt) || - ptlrpc_at_check(svcpt), &lwi); + ptlrpc_thread_stopping(thread) || + ptlrpc_server_request_incoming(svcpt) || + ptlrpc_server_request_pending(svcpt, + false) || + ptlrpc_rqbd_pending(svcpt) || + ptlrpc_at_check(svcpt), &lwi); if (ptlrpc_thread_stopping(thread)) return -EINTR; @@ -2049,7 +2056,7 @@ static int ptlrpc_main(void *arg) } rc = lu_context_init(&env->le_ctx, - svc->srv_ctx_tags|LCT_REMEMBER|LCT_NOREF); + svc->srv_ctx_tags | LCT_REMEMBER | LCT_NOREF); if (rc) goto out_srv_fini; @@ -2349,7 +2356,7 @@ static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt) while (!list_empty(&zombie)) { thread = list_entry(zombie.next, - struct ptlrpc_thread, t_link); + struct ptlrpc_thread, t_link); list_del(&thread->t_link); kfree(thread); } @@ -2398,7 +2405,6 @@ int ptlrpc_start_threads(struct ptlrpc_service *svc) ptlrpc_stop_all_threads(svc); return rc; } -EXPORT_SYMBOL(ptlrpc_start_threads); int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait) { @@ -2539,8 +2545,8 @@ int ptlrpc_hr_init(void) LASSERT(hrp->hrp_nthrs > 0); hrp->hrp_thrs = kzalloc_node(hrp->hrp_nthrs * sizeof(*hrt), GFP_NOFS, - cfs_cpt_spread_node(ptlrpc_hr.hr_cpt_table, - i)); + cfs_cpt_spread_node(ptlrpc_hr.hr_cpt_table, + i)); if (!hrp->hrp_thrs) { rc = -ENOMEM; goto out; @@ -2593,7 +2599,8 @@ static void ptlrpc_wait_replies(struct ptlrpc_service_part *svcpt) NULL, NULL); rc = l_wait_event(svcpt->scp_waitq, - atomic_read(&svcpt->scp_nreps_difficult) == 0, &lwi); + atomic_read(&svcpt->scp_nreps_difficult) == 0, + &lwi); if (rc == 0) break; CWARN("Unexpectedly long timeout %s %p\n", @@ -2639,7 +2646,7 @@ ptlrpc_service_unlink_rqbd(struct ptlrpc_service *svc) * event with its 'unlink' flag set for each posted rqbd */ list_for_each_entry(rqbd, &svcpt->scp_rqbd_posted, - rqbd_list) { + rqbd_list) { rc = LNetMDUnlink(rqbd->rqbd_md_h); LASSERT(rc == 0 || rc == -ENOENT); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 6cc2b2edf3fc..e5945e2ccc49 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -190,28 +190,30 @@ void lustre_assert_wire_constants(void) (long long)REINT_SETXATTR); LASSERTF(REINT_RMENTRY == 8, "found %lld\n", (long long)REINT_RMENTRY); - LASSERTF(REINT_MAX == 9, "found %lld\n", + LASSERTF(REINT_MIGRATE == 9, "found %lld\n", + (long long)REINT_MIGRATE); + LASSERTF(REINT_MAX == 10, "found %lld\n", (long long)REINT_MAX); LASSERTF(DISP_IT_EXECD == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)DISP_IT_EXECD); + (unsigned)DISP_IT_EXECD); LASSERTF(DISP_LOOKUP_EXECD == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)DISP_LOOKUP_EXECD); + (unsigned)DISP_LOOKUP_EXECD); LASSERTF(DISP_LOOKUP_NEG == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)DISP_LOOKUP_NEG); + (unsigned)DISP_LOOKUP_NEG); LASSERTF(DISP_LOOKUP_POS == 0x00000008UL, "found 0x%.8xUL\n", - (unsigned)DISP_LOOKUP_POS); + (unsigned)DISP_LOOKUP_POS); LASSERTF(DISP_OPEN_CREATE == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)DISP_OPEN_CREATE); + (unsigned)DISP_OPEN_CREATE); LASSERTF(DISP_OPEN_OPEN == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)DISP_OPEN_OPEN); + (unsigned)DISP_OPEN_OPEN); LASSERTF(DISP_ENQ_COMPLETE == 0x00400000UL, "found 0x%.8xUL\n", - (unsigned)DISP_ENQ_COMPLETE); + (unsigned)DISP_ENQ_COMPLETE); LASSERTF(DISP_ENQ_OPEN_REF == 0x00800000UL, "found 0x%.8xUL\n", - (unsigned)DISP_ENQ_OPEN_REF); + (unsigned)DISP_ENQ_OPEN_REF); LASSERTF(DISP_ENQ_CREATE_REF == 0x01000000UL, "found 0x%.8xUL\n", - (unsigned)DISP_ENQ_CREATE_REF); + (unsigned)DISP_ENQ_CREATE_REF); LASSERTF(DISP_OPEN_LOCK == 0x02000000UL, "found 0x%.8xUL\n", - (unsigned)DISP_OPEN_LOCK); + (unsigned)DISP_OPEN_LOCK); LASSERTF(MDS_STATUS_CONN == 1, "found %lld\n", (long long)MDS_STATUS_CONN); LASSERTF(MDS_STATUS_LOV == 2, "found %lld\n", @@ -219,55 +221,55 @@ void lustre_assert_wire_constants(void) LASSERTF(LUSTRE_BFLAG_UNCOMMITTED_WRITES == 1, "found %lld\n", (long long)LUSTRE_BFLAG_UNCOMMITTED_WRITES); LASSERTF(MF_SOM_CHANGE == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)MF_SOM_CHANGE); + (unsigned)MF_SOM_CHANGE); LASSERTF(MF_EPOCH_OPEN == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)MF_EPOCH_OPEN); + (unsigned)MF_EPOCH_OPEN); LASSERTF(MF_EPOCH_CLOSE == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)MF_EPOCH_CLOSE); + (unsigned)MF_EPOCH_CLOSE); LASSERTF(MF_MDC_CANCEL_FID1 == 0x00000008UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID1); + (unsigned)MF_MDC_CANCEL_FID1); LASSERTF(MF_MDC_CANCEL_FID2 == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID2); + (unsigned)MF_MDC_CANCEL_FID2); LASSERTF(MF_MDC_CANCEL_FID3 == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID3); + (unsigned)MF_MDC_CANCEL_FID3); LASSERTF(MF_MDC_CANCEL_FID4 == 0x00000040UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID4); + (unsigned)MF_MDC_CANCEL_FID4); LASSERTF(MF_SOM_AU == 0x00000080UL, "found 0x%.8xUL\n", - (unsigned)MF_SOM_AU); + (unsigned)MF_SOM_AU); LASSERTF(MF_GETATTR_LOCK == 0x00000100UL, "found 0x%.8xUL\n", - (unsigned)MF_GETATTR_LOCK); + (unsigned)MF_GETATTR_LOCK); LASSERTF(MDS_ATTR_MODE == 0x0000000000000001ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_MODE); + (long long)MDS_ATTR_MODE); LASSERTF(MDS_ATTR_UID == 0x0000000000000002ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_UID); + (long long)MDS_ATTR_UID); LASSERTF(MDS_ATTR_GID == 0x0000000000000004ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_GID); + (long long)MDS_ATTR_GID); LASSERTF(MDS_ATTR_SIZE == 0x0000000000000008ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_SIZE); + (long long)MDS_ATTR_SIZE); LASSERTF(MDS_ATTR_ATIME == 0x0000000000000010ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_ATIME); + (long long)MDS_ATTR_ATIME); LASSERTF(MDS_ATTR_MTIME == 0x0000000000000020ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_MTIME); + (long long)MDS_ATTR_MTIME); LASSERTF(MDS_ATTR_CTIME == 0x0000000000000040ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_CTIME); + (long long)MDS_ATTR_CTIME); LASSERTF(MDS_ATTR_ATIME_SET == 0x0000000000000080ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_ATIME_SET); + (long long)MDS_ATTR_ATIME_SET); LASSERTF(MDS_ATTR_MTIME_SET == 0x0000000000000100ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_MTIME_SET); + (long long)MDS_ATTR_MTIME_SET); LASSERTF(MDS_ATTR_FORCE == 0x0000000000000200ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_FORCE); + (long long)MDS_ATTR_FORCE); LASSERTF(MDS_ATTR_ATTR_FLAG == 0x0000000000000400ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_ATTR_FLAG); + (long long)MDS_ATTR_ATTR_FLAG); LASSERTF(MDS_ATTR_KILL_SUID == 0x0000000000000800ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_KILL_SUID); + (long long)MDS_ATTR_KILL_SUID); LASSERTF(MDS_ATTR_KILL_SGID == 0x0000000000001000ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_KILL_SGID); + (long long)MDS_ATTR_KILL_SGID); LASSERTF(MDS_ATTR_CTIME_SET == 0x0000000000002000ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_CTIME_SET); + (long long)MDS_ATTR_CTIME_SET); LASSERTF(MDS_ATTR_FROM_OPEN == 0x0000000000004000ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_FROM_OPEN); + (long long)MDS_ATTR_FROM_OPEN); LASSERTF(MDS_ATTR_BLOCKS == 0x0000000000008000ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_BLOCKS); + (long long)MDS_ATTR_BLOCKS); LASSERTF(FLD_QUERY == 900, "found %lld\n", (long long)FLD_QUERY); LASSERTF(FLD_FIRST_OPC == 900, "found %lld\n", @@ -418,15 +420,15 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct lustre_mdt_attrs *)0)->lma_self_fid) == 16, "found %lld\n", (long long)(int)sizeof(((struct lustre_mdt_attrs *)0)->lma_self_fid)); LASSERTF(LMAI_RELEASED == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)LMAI_RELEASED); + (unsigned)LMAI_RELEASED); LASSERTF(LMAC_HSM == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)LMAC_HSM); + (unsigned)LMAC_HSM); LASSERTF(LMAC_SOM == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)LMAC_SOM); + (unsigned)LMAC_SOM); LASSERTF(LMAC_NOT_IN_OI == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)LMAC_NOT_IN_OI); + (unsigned)LMAC_NOT_IN_OI); LASSERTF(LMAC_FID_ON_OST == 0x00000008UL, "found 0x%.8xUL\n", - (unsigned)LMAC_FID_ON_OST); + (unsigned)LMAC_FID_ON_OST); /* Checks for struct ost_id */ LASSERTF((int)sizeof(struct ost_id) == 16, "found %lld\n", @@ -452,35 +454,35 @@ void lustre_assert_wire_constants(void) LASSERTF(FID_SEQ_IGIF == 12, "found %lld\n", (long long)FID_SEQ_IGIF); LASSERTF(FID_SEQ_IGIF_MAX == 0x00000000ffffffffULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_IGIF_MAX); + (long long)FID_SEQ_IGIF_MAX); LASSERTF(FID_SEQ_IDIF == 0x0000000100000000ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_IDIF); + (long long)FID_SEQ_IDIF); LASSERTF(FID_SEQ_IDIF_MAX == 0x00000001ffffffffULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_IDIF_MAX); + (long long)FID_SEQ_IDIF_MAX); LASSERTF(FID_SEQ_START == 0x0000000200000000ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_START); + (long long)FID_SEQ_START); LASSERTF(FID_SEQ_LOCAL_FILE == 0x0000000200000001ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_LOCAL_FILE); + (long long)FID_SEQ_LOCAL_FILE); LASSERTF(FID_SEQ_DOT_LUSTRE == 0x0000000200000002ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_DOT_LUSTRE); + (long long)FID_SEQ_DOT_LUSTRE); LASSERTF(FID_SEQ_SPECIAL == 0x0000000200000004ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_SPECIAL); + (long long)FID_SEQ_SPECIAL); LASSERTF(FID_SEQ_QUOTA == 0x0000000200000005ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_QUOTA); + (long long)FID_SEQ_QUOTA); LASSERTF(FID_SEQ_QUOTA_GLB == 0x0000000200000006ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_QUOTA_GLB); + (long long)FID_SEQ_QUOTA_GLB); LASSERTF(FID_SEQ_ROOT == 0x0000000200000007ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_ROOT); + (long long)FID_SEQ_ROOT); LASSERTF(FID_SEQ_NORMAL == 0x0000000200000400ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_NORMAL); + (long long)FID_SEQ_NORMAL); LASSERTF(FID_SEQ_LOV_DEFAULT == 0xffffffffffffffffULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_LOV_DEFAULT); + (long long)FID_SEQ_LOV_DEFAULT); LASSERTF(FID_OID_SPECIAL_BFL == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)FID_OID_SPECIAL_BFL); + (unsigned)FID_OID_SPECIAL_BFL); LASSERTF(FID_OID_DOT_LUSTRE == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)FID_OID_DOT_LUSTRE); + (unsigned)FID_OID_DOT_LUSTRE); LASSERTF(FID_OID_DOT_LUSTRE_OBF == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)FID_OID_DOT_LUSTRE_OBF); + (unsigned)FID_OID_DOT_LUSTRE_OBF); /* Checks for struct lu_dirent */ LASSERTF((int)sizeof(struct lu_dirent) == 32, "found %lld\n", @@ -510,11 +512,11 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct lu_dirent *)0)->lde_name[0]) == 1, "found %lld\n", (long long)(int)sizeof(((struct lu_dirent *)0)->lde_name[0])); LASSERTF(LUDA_FID == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)LUDA_FID); + (unsigned)LUDA_FID); LASSERTF(LUDA_TYPE == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)LUDA_TYPE); + (unsigned)LUDA_TYPE); LASSERTF(LUDA_64BITHASH == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)LUDA_64BITHASH); + (unsigned)LUDA_64BITHASH); /* Checks for struct luda_type */ LASSERTF((int)sizeof(struct luda_type) == 2, "found %lld\n", @@ -602,9 +604,9 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct lustre_msg_v2 *)0)->lm_buflens[0]) == 4, "found %lld\n", (long long)(int)sizeof(((struct lustre_msg_v2 *)0)->lm_buflens[0])); LASSERTF(LUSTRE_MSG_MAGIC_V2 == 0x0BD00BD3, "found 0x%.8x\n", - LUSTRE_MSG_MAGIC_V2); + LUSTRE_MSG_MAGIC_V2); LASSERTF(LUSTRE_MSG_MAGIC_V2_SWABBED == 0xD30BD00B, "found 0x%.8x\n", - LUSTRE_MSG_MAGIC_V2_SWABBED); + LUSTRE_MSG_MAGIC_V2_SWABBED); /* Checks for struct ptlrpc_body */ LASSERTF((int)sizeof(struct ptlrpc_body_v3) == 184, "found %lld\n", @@ -682,7 +684,7 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct ptlrpc_body_v3, pb_padding)); LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding) == 32, "found %lld\n", (long long)(int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding)); - CLASSERT(JOBSTATS_JOBID_SIZE == 32); + CLASSERT(LUSTRE_JOBID_SIZE == 32); LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_jobid) == 152, "found %lld\n", (long long)(int)offsetof(struct ptlrpc_body_v3, pb_jobid)); LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_jobid) == 32, "found %lld\n", @@ -780,61 +782,61 @@ void lustre_assert_wire_constants(void) LASSERTF(MSG_PTLRPC_HEADER_OFF == 31, "found %lld\n", (long long)MSG_PTLRPC_HEADER_OFF); LASSERTF(PTLRPC_MSG_VERSION == 0x00000003, "found 0x%.8x\n", - PTLRPC_MSG_VERSION); + PTLRPC_MSG_VERSION); LASSERTF(LUSTRE_VERSION_MASK == 0xffff0000, "found 0x%.8x\n", - LUSTRE_VERSION_MASK); + LUSTRE_VERSION_MASK); LASSERTF(LUSTRE_OBD_VERSION == 0x00010000, "found 0x%.8x\n", - LUSTRE_OBD_VERSION); + LUSTRE_OBD_VERSION); LASSERTF(LUSTRE_MDS_VERSION == 0x00020000, "found 0x%.8x\n", - LUSTRE_MDS_VERSION); + LUSTRE_MDS_VERSION); LASSERTF(LUSTRE_OST_VERSION == 0x00030000, "found 0x%.8x\n", - LUSTRE_OST_VERSION); + LUSTRE_OST_VERSION); LASSERTF(LUSTRE_DLM_VERSION == 0x00040000, "found 0x%.8x\n", - LUSTRE_DLM_VERSION); + LUSTRE_DLM_VERSION); LASSERTF(LUSTRE_LOG_VERSION == 0x00050000, "found 0x%.8x\n", - LUSTRE_LOG_VERSION); + LUSTRE_LOG_VERSION); LASSERTF(LUSTRE_MGS_VERSION == 0x00060000, "found 0x%.8x\n", - LUSTRE_MGS_VERSION); + LUSTRE_MGS_VERSION); LASSERTF(MSGHDR_AT_SUPPORT == 1, "found %lld\n", (long long)MSGHDR_AT_SUPPORT); LASSERTF(MSGHDR_CKSUM_INCOMPAT18 == 2, "found %lld\n", (long long)MSGHDR_CKSUM_INCOMPAT18); LASSERTF(MSG_OP_FLAG_MASK == 0xffff0000UL, "found 0x%.8xUL\n", - (unsigned)MSG_OP_FLAG_MASK); + (unsigned)MSG_OP_FLAG_MASK); LASSERTF(MSG_OP_FLAG_SHIFT == 16, "found %lld\n", (long long)MSG_OP_FLAG_SHIFT); LASSERTF(MSG_GEN_FLAG_MASK == 0x0000ffffUL, "found 0x%.8xUL\n", - (unsigned)MSG_GEN_FLAG_MASK); + (unsigned)MSG_GEN_FLAG_MASK); LASSERTF(MSG_LAST_REPLAY == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)MSG_LAST_REPLAY); + (unsigned)MSG_LAST_REPLAY); LASSERTF(MSG_RESENT == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)MSG_RESENT); + (unsigned)MSG_RESENT); LASSERTF(MSG_REPLAY == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)MSG_REPLAY); + (unsigned)MSG_REPLAY); LASSERTF(MSG_DELAY_REPLAY == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)MSG_DELAY_REPLAY); + (unsigned)MSG_DELAY_REPLAY); LASSERTF(MSG_VERSION_REPLAY == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)MSG_VERSION_REPLAY); + (unsigned)MSG_VERSION_REPLAY); LASSERTF(MSG_REQ_REPLAY_DONE == 0x00000040UL, "found 0x%.8xUL\n", - (unsigned)MSG_REQ_REPLAY_DONE); + (unsigned)MSG_REQ_REPLAY_DONE); LASSERTF(MSG_LOCK_REPLAY_DONE == 0x00000080UL, "found 0x%.8xUL\n", - (unsigned)MSG_LOCK_REPLAY_DONE); + (unsigned)MSG_LOCK_REPLAY_DONE); LASSERTF(MSG_CONNECT_RECOVERING == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_RECOVERING); + (unsigned)MSG_CONNECT_RECOVERING); LASSERTF(MSG_CONNECT_RECONNECT == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_RECONNECT); + (unsigned)MSG_CONNECT_RECONNECT); LASSERTF(MSG_CONNECT_REPLAYABLE == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_REPLAYABLE); + (unsigned)MSG_CONNECT_REPLAYABLE); LASSERTF(MSG_CONNECT_LIBCLIENT == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_LIBCLIENT); + (unsigned)MSG_CONNECT_LIBCLIENT); LASSERTF(MSG_CONNECT_INITIAL == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_INITIAL); + (unsigned)MSG_CONNECT_INITIAL); LASSERTF(MSG_CONNECT_ASYNC == 0x00000040UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_ASYNC); + (unsigned)MSG_CONNECT_ASYNC); LASSERTF(MSG_CONNECT_NEXT_VER == 0x00000080UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_NEXT_VER); + (unsigned)MSG_CONNECT_NEXT_VER); LASSERTF(MSG_CONNECT_TRANSNO == 0x00000100UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_TRANSNO); + (unsigned)MSG_CONNECT_TRANSNO); /* Checks for struct obd_connect_data */ LASSERTF((int)sizeof(struct obd_connect_data) == 192, "found %lld\n", @@ -1069,12 +1071,18 @@ void lustre_assert_wire_constants(void) "found 0x%.16llxULL\n", OBD_CONNECT_FLOCK_DEAD); LASSERTF(OBD_CONNECT_OPEN_BY_FID == 0x20000000000000ULL, "found 0x%.16llxULL\n", OBD_CONNECT_OPEN_BY_FID); + LASSERTF(OBD_CONNECT_LFSCK == 0x40000000000000ULL, "found 0x%.16llxULL\n", + OBD_CONNECT_LFSCK); + LASSERTF(OBD_CONNECT_UNLINK_CLOSE == 0x100000000000000ULL, "found 0x%.16llxULL\n", + OBD_CONNECT_UNLINK_CLOSE); + LASSERTF(OBD_CONNECT_DIR_STRIPE == 0x400000000000000ULL, "found 0x%.16llxULL\n", + OBD_CONNECT_DIR_STRIPE); LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)OBD_CKSUM_CRC32); + (unsigned)OBD_CKSUM_CRC32); LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)OBD_CKSUM_ADLER); + (unsigned)OBD_CKSUM_ADLER); LASSERTF(OBD_CKSUM_CRC32C == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)OBD_CKSUM_CRC32C); + (unsigned)OBD_CKSUM_CRC32C); /* Checks for struct obdo */ LASSERTF((int)sizeof(struct obdo) == 208, "found %lld\n", @@ -1346,7 +1354,7 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct lov_mds_md_v1, lmm_objects[0])); LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects[0]) == 24, "found %lld\n", (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects[0])); - CLASSERT(LOV_MAGIC_V1 == 0x0BD10BD0); + CLASSERT(LOV_MAGIC_V1 == (0x0BD10000 | 0x0BD0)); /* Checks for struct lov_mds_md_v3 */ LASSERTF((int)sizeof(struct lov_mds_md_v3) == 48, "found %lld\n", @@ -1375,7 +1383,7 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct lov_mds_md_v3, lmm_layout_gen)); LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_layout_gen) == 2, "found %lld\n", (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_layout_gen)); - CLASSERT(LOV_MAXPOOLNAME == 16); + CLASSERT(LOV_MAXPOOLNAME == 15); LASSERTF((int)offsetof(struct lov_mds_md_v3, lmm_pool_name[16]) == 48, "found %lld\n", (long long)(int)offsetof(struct lov_mds_md_v3, lmm_pool_name[16])); LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_pool_name[16]) == 1, "found %lld\n", @@ -1384,15 +1392,64 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct lov_mds_md_v3, lmm_objects[0])); LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_objects[0]) == 24, "found %lld\n", (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_objects[0])); - CLASSERT(LOV_MAGIC_V3 == 0x0BD30BD0); + CLASSERT(LOV_MAGIC_V3 == (0x0BD30000 | 0x0BD0)); LASSERTF(LOV_PATTERN_RAID0 == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)LOV_PATTERN_RAID0); + (unsigned)LOV_PATTERN_RAID0); LASSERTF(LOV_PATTERN_RAID1 == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)LOV_PATTERN_RAID1); + (unsigned)LOV_PATTERN_RAID1); LASSERTF(LOV_PATTERN_FIRST == 0x00000100UL, "found 0x%.8xUL\n", - (unsigned)LOV_PATTERN_FIRST); + (unsigned)LOV_PATTERN_FIRST); LASSERTF(LOV_PATTERN_CMOBD == 0x00000200UL, "found 0x%.8xUL\n", - (unsigned)LOV_PATTERN_CMOBD); + (unsigned)LOV_PATTERN_CMOBD); + + /* Checks for struct lmv_mds_md_v1 */ + LASSERTF((int)sizeof(struct lmv_mds_md_v1) == 56, "found %lld\n", + (long long)(int)sizeof(struct lmv_mds_md_v1)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_magic) == 0, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_magic)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_magic) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_magic)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_stripe_count) == 4, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_stripe_count)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_stripe_count) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_stripe_count)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_master_mdt_index) == 8, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_master_mdt_index)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_master_mdt_index) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_master_mdt_index)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_hash_type) == 12, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_hash_type)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_hash_type) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_hash_type)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_layout_version) == 16, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_layout_version)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_layout_version) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_layout_version)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_padding1) == 20, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_padding1)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding1) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding1)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_padding2) == 24, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_padding2)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding2) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding2)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_padding3) == 32, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_padding3)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding3) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding3)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_pool_name[16]) == 56, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_pool_name[16])); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_pool_name[16]) == 1, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_pool_name[16])); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_stripe_fids[0]) == 56, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_stripe_fids[0])); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_stripe_fids[0]) == 16, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_stripe_fids[0])); + CLASSERT(LMV_MAGIC_V1 == 0x0CD20CD0); + CLASSERT(LMV_MAGIC_STRIPE == 0x0CD40CD0); + CLASSERT(LMV_HASH_TYPE_MASK == 0x0000ffff); + CLASSERT(LMV_HASH_FLAG_MIGRATION == 0x80000000); + CLASSERT(LMV_HASH_FLAG_DEAD == 0x40000000); /* Checks for struct obd_statfs */ LASSERTF((int)sizeof(struct obd_statfs) == 144, "found %lld\n", @@ -1582,53 +1639,53 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_padding) == 4, "found %lld\n", (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_padding)); LASSERTF(Q_QUOTACHECK == 0x800100, "found 0x%.8x\n", - Q_QUOTACHECK); + Q_QUOTACHECK); LASSERTF(Q_INITQUOTA == 0x800101, "found 0x%.8x\n", - Q_INITQUOTA); + Q_INITQUOTA); LASSERTF(Q_GETOINFO == 0x800102, "found 0x%.8x\n", - Q_GETOINFO); + Q_GETOINFO); LASSERTF(Q_GETOQUOTA == 0x800103, "found 0x%.8x\n", - Q_GETOQUOTA); + Q_GETOQUOTA); LASSERTF(Q_FINVALIDATE == 0x800104, "found 0x%.8x\n", - Q_FINVALIDATE); + Q_FINVALIDATE); /* Checks for struct niobuf_remote */ LASSERTF((int)sizeof(struct niobuf_remote) == 16, "found %lld\n", (long long)(int)sizeof(struct niobuf_remote)); - LASSERTF((int)offsetof(struct niobuf_remote, offset) == 0, "found %lld\n", - (long long)(int)offsetof(struct niobuf_remote, offset)); - LASSERTF((int)sizeof(((struct niobuf_remote *)0)->offset) == 8, "found %lld\n", - (long long)(int)sizeof(((struct niobuf_remote *)0)->offset)); - LASSERTF((int)offsetof(struct niobuf_remote, len) == 8, "found %lld\n", - (long long)(int)offsetof(struct niobuf_remote, len)); - LASSERTF((int)sizeof(((struct niobuf_remote *)0)->len) == 4, "found %lld\n", - (long long)(int)sizeof(((struct niobuf_remote *)0)->len)); - LASSERTF((int)offsetof(struct niobuf_remote, flags) == 12, "found %lld\n", - (long long)(int)offsetof(struct niobuf_remote, flags)); - LASSERTF((int)sizeof(((struct niobuf_remote *)0)->flags) == 4, "found %lld\n", - (long long)(int)sizeof(((struct niobuf_remote *)0)->flags)); + LASSERTF((int)offsetof(struct niobuf_remote, rnb_offset) == 0, "found %lld\n", + (long long)(int)offsetof(struct niobuf_remote, rnb_offset)); + LASSERTF((int)sizeof(((struct niobuf_remote *)0)->rnb_offset) == 8, "found %lld\n", + (long long)(int)sizeof(((struct niobuf_remote *)0)->rnb_offset)); + LASSERTF((int)offsetof(struct niobuf_remote, rnb_len) == 8, "found %lld\n", + (long long)(int)offsetof(struct niobuf_remote, rnb_len)); + LASSERTF((int)sizeof(((struct niobuf_remote *)0)->rnb_len) == 4, "found %lld\n", + (long long)(int)sizeof(((struct niobuf_remote *)0)->rnb_len)); + LASSERTF((int)offsetof(struct niobuf_remote, rnb_flags) == 12, "found %lld\n", + (long long)(int)offsetof(struct niobuf_remote, rnb_flags)); + LASSERTF((int)sizeof(((struct niobuf_remote *)0)->rnb_flags) == 4, "found %lld\n", + (long long)(int)sizeof(((struct niobuf_remote *)0)->rnb_flags)); LASSERTF(OBD_BRW_READ == 0x01, "found 0x%.8x\n", - OBD_BRW_READ); + OBD_BRW_READ); LASSERTF(OBD_BRW_WRITE == 0x02, "found 0x%.8x\n", - OBD_BRW_WRITE); + OBD_BRW_WRITE); LASSERTF(OBD_BRW_SYNC == 0x08, "found 0x%.8x\n", - OBD_BRW_SYNC); + OBD_BRW_SYNC); LASSERTF(OBD_BRW_CHECK == 0x10, "found 0x%.8x\n", - OBD_BRW_CHECK); + OBD_BRW_CHECK); LASSERTF(OBD_BRW_FROM_GRANT == 0x20, "found 0x%.8x\n", - OBD_BRW_FROM_GRANT); + OBD_BRW_FROM_GRANT); LASSERTF(OBD_BRW_GRANTED == 0x40, "found 0x%.8x\n", - OBD_BRW_GRANTED); + OBD_BRW_GRANTED); LASSERTF(OBD_BRW_NOCACHE == 0x80, "found 0x%.8x\n", - OBD_BRW_NOCACHE); + OBD_BRW_NOCACHE); LASSERTF(OBD_BRW_NOQUOTA == 0x100, "found 0x%.8x\n", - OBD_BRW_NOQUOTA); + OBD_BRW_NOQUOTA); LASSERTF(OBD_BRW_SRVLOCK == 0x200, "found 0x%.8x\n", - OBD_BRW_SRVLOCK); + OBD_BRW_SRVLOCK); LASSERTF(OBD_BRW_ASYNC == 0x400, "found 0x%.8x\n", - OBD_BRW_ASYNC); + OBD_BRW_ASYNC); LASSERTF(OBD_BRW_MEMALLOC == 0x800, "found 0x%.8x\n", - OBD_BRW_MEMALLOC); + OBD_BRW_MEMALLOC); LASSERTF(OBD_BRW_OVER_USRQUOTA == 0x1000, "found 0x%.8x\n", OBD_BRW_OVER_USRQUOTA); LASSERTF(OBD_BRW_OVER_GRPQUOTA == 0x2000, "found 0x%.8x\n", @@ -1663,203 +1720,203 @@ void lustre_assert_wire_constants(void) /* Checks for struct mdt_body */ LASSERTF((int)sizeof(struct mdt_body) == 216, "found %lld\n", (long long)(int)sizeof(struct mdt_body)); - LASSERTF((int)offsetof(struct mdt_body, fid1) == 0, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, fid1)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->fid1) == 16, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->fid1)); - LASSERTF((int)offsetof(struct mdt_body, fid2) == 16, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, fid2)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->fid2) == 16, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->fid2)); - LASSERTF((int)offsetof(struct mdt_body, handle) == 32, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, handle)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->handle) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->handle)); - LASSERTF((int)offsetof(struct mdt_body, valid) == 40, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, valid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->valid) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->valid)); - LASSERTF((int)offsetof(struct mdt_body, size) == 48, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, size)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->size) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->size)); - LASSERTF((int)offsetof(struct mdt_body, mtime) == 56, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, mtime)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->mtime) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->mtime)); - LASSERTF((int)offsetof(struct mdt_body, atime) == 64, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, atime)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->atime) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->atime)); - LASSERTF((int)offsetof(struct mdt_body, ctime) == 72, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, ctime)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->ctime) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->ctime)); - LASSERTF((int)offsetof(struct mdt_body, blocks) == 80, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, blocks)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->blocks) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->blocks)); - LASSERTF((int)offsetof(struct mdt_body, t_state) == 96, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, t_state)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->t_state) == 8, + LASSERTF((int)offsetof(struct mdt_body, mbo_fid1) == 0, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_fid1)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_fid1) == 16, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_fid1)); + LASSERTF((int)offsetof(struct mdt_body, mbo_fid2) == 16, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_fid2)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_fid2) == 16, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_fid2)); + LASSERTF((int)offsetof(struct mdt_body, mbo_handle) == 32, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_handle)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_handle) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_handle)); + LASSERTF((int)offsetof(struct mdt_body, mbo_valid) == 40, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_valid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_valid) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_valid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_size) == 48, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_size)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_size) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_size)); + LASSERTF((int)offsetof(struct mdt_body, mbo_mtime) == 56, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_mtime)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_mtime) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_mtime)); + LASSERTF((int)offsetof(struct mdt_body, mbo_atime) == 64, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_atime)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_atime) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_atime)); + LASSERTF((int)offsetof(struct mdt_body, mbo_ctime) == 72, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_ctime)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_ctime) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_ctime)); + LASSERTF((int)offsetof(struct mdt_body, mbo_blocks) == 80, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_blocks)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_blocks) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_blocks)); + LASSERTF((int)offsetof(struct mdt_body, mbo_t_state) == 96, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_t_state)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_t_state) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->t_state)); - LASSERTF((int)offsetof(struct mdt_body, fsuid) == 104, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, fsuid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->fsuid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->fsuid)); - LASSERTF((int)offsetof(struct mdt_body, fsgid) == 108, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, fsgid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->fsgid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->fsgid)); - LASSERTF((int)offsetof(struct mdt_body, capability) == 112, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, capability)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->capability) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->capability)); - LASSERTF((int)offsetof(struct mdt_body, mode) == 116, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, mode)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->mode) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->mode)); - LASSERTF((int)offsetof(struct mdt_body, uid) == 120, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, uid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->uid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->uid)); - LASSERTF((int)offsetof(struct mdt_body, gid) == 124, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, gid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->gid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->gid)); - LASSERTF((int)offsetof(struct mdt_body, flags) == 128, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, flags)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->flags) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->flags)); - LASSERTF((int)offsetof(struct mdt_body, rdev) == 132, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, rdev)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->rdev) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->rdev)); - LASSERTF((int)offsetof(struct mdt_body, nlink) == 136, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, nlink)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->nlink) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->nlink)); - LASSERTF((int)offsetof(struct mdt_body, unused2) == 140, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, unused2)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->unused2) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->unused2)); - LASSERTF((int)offsetof(struct mdt_body, suppgid) == 144, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, suppgid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->suppgid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->suppgid)); - LASSERTF((int)offsetof(struct mdt_body, eadatasize) == 148, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, eadatasize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->eadatasize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->eadatasize)); - LASSERTF((int)offsetof(struct mdt_body, aclsize) == 152, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, aclsize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->aclsize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->aclsize)); - LASSERTF((int)offsetof(struct mdt_body, max_mdsize) == 156, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, max_mdsize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->max_mdsize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->max_mdsize)); - LASSERTF((int)offsetof(struct mdt_body, max_cookiesize) == 160, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, max_cookiesize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->max_cookiesize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->max_cookiesize)); - LASSERTF((int)offsetof(struct mdt_body, uid_h) == 164, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, uid_h)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->uid_h) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->uid_h)); - LASSERTF((int)offsetof(struct mdt_body, gid_h) == 168, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, gid_h)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->gid_h) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->gid_h)); - LASSERTF((int)offsetof(struct mdt_body, padding_5) == 172, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_5)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_5) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_5)); - LASSERTF((int)offsetof(struct mdt_body, padding_6) == 176, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_6)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_6) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_6)); - LASSERTF((int)offsetof(struct mdt_body, padding_7) == 184, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_7)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_7) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_7)); - LASSERTF((int)offsetof(struct mdt_body, padding_8) == 192, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_8)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_8) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_8)); - LASSERTF((int)offsetof(struct mdt_body, padding_9) == 200, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_9)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_9) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_9)); - LASSERTF((int)offsetof(struct mdt_body, padding_10) == 208, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_10)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_10) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_10)); + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_t_state)); + LASSERTF((int)offsetof(struct mdt_body, mbo_fsuid) == 104, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_fsuid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_fsuid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_fsuid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_fsgid) == 108, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_fsgid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_fsgid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_fsgid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_capability) == 112, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_capability)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_capability) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_capability)); + LASSERTF((int)offsetof(struct mdt_body, mbo_mode) == 116, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_mode)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_mode) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_mode)); + LASSERTF((int)offsetof(struct mdt_body, mbo_uid) == 120, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_uid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_uid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_uid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_gid) == 124, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_gid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_gid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_gid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_flags) == 128, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_flags)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_flags) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_flags)); + LASSERTF((int)offsetof(struct mdt_body, mbo_rdev) == 132, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_rdev)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_rdev) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_rdev)); + LASSERTF((int)offsetof(struct mdt_body, mbo_nlink) == 136, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_nlink)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_nlink) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_nlink)); + LASSERTF((int)offsetof(struct mdt_body, mbo_unused2) == 140, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_unused2)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_unused2) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_unused2)); + LASSERTF((int)offsetof(struct mdt_body, mbo_suppgid) == 144, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_suppgid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_suppgid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_suppgid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_eadatasize) == 148, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_eadatasize)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_eadatasize) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_eadatasize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_aclsize) == 152, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_aclsize)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_aclsize) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_aclsize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_max_mdsize) == 156, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_max_mdsize)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_max_mdsize) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_max_mdsize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_max_cookiesize) == 160, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_max_cookiesize)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_max_cookiesize) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_max_cookiesize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_uid_h) == 164, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_uid_h)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_uid_h) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_uid_h)); + LASSERTF((int)offsetof(struct mdt_body, mbo_gid_h) == 168, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_gid_h)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_gid_h) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_gid_h)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_5) == 172, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_5)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_5) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_5)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_6) == 176, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_6)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_6) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_6)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_7) == 184, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_7)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_7) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_7)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_8) == 192, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_8)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_8) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_8)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_9) == 200, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_9)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_9) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_9)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_10) == 208, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_10)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_10) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_10)); LASSERTF(MDS_FMODE_CLOSED == 000000000000UL, "found 0%.11oUL\n", - MDS_FMODE_CLOSED); + MDS_FMODE_CLOSED); LASSERTF(MDS_FMODE_EXEC == 000000000004UL, "found 0%.11oUL\n", - MDS_FMODE_EXEC); + MDS_FMODE_EXEC); LASSERTF(MDS_FMODE_EPOCH == 000001000000UL, "found 0%.11oUL\n", - MDS_FMODE_EPOCH); + MDS_FMODE_EPOCH); LASSERTF(MDS_FMODE_TRUNC == 000002000000UL, "found 0%.11oUL\n", - MDS_FMODE_TRUNC); + MDS_FMODE_TRUNC); LASSERTF(MDS_FMODE_SOM == 000004000000UL, "found 0%.11oUL\n", - MDS_FMODE_SOM); + MDS_FMODE_SOM); LASSERTF(MDS_OPEN_CREATED == 000000000010UL, "found 0%.11oUL\n", - MDS_OPEN_CREATED); + MDS_OPEN_CREATED); LASSERTF(MDS_OPEN_CROSS == 000000000020UL, "found 0%.11oUL\n", - MDS_OPEN_CROSS); + MDS_OPEN_CROSS); LASSERTF(MDS_OPEN_CREAT == 000000000100UL, "found 0%.11oUL\n", - MDS_OPEN_CREAT); + MDS_OPEN_CREAT); LASSERTF(MDS_OPEN_EXCL == 000000000200UL, "found 0%.11oUL\n", - MDS_OPEN_EXCL); + MDS_OPEN_EXCL); LASSERTF(MDS_OPEN_TRUNC == 000000001000UL, "found 0%.11oUL\n", - MDS_OPEN_TRUNC); + MDS_OPEN_TRUNC); LASSERTF(MDS_OPEN_APPEND == 000000002000UL, "found 0%.11oUL\n", - MDS_OPEN_APPEND); + MDS_OPEN_APPEND); LASSERTF(MDS_OPEN_SYNC == 000000010000UL, "found 0%.11oUL\n", - MDS_OPEN_SYNC); + MDS_OPEN_SYNC); LASSERTF(MDS_OPEN_DIRECTORY == 000000200000UL, "found 0%.11oUL\n", - MDS_OPEN_DIRECTORY); + MDS_OPEN_DIRECTORY); LASSERTF(MDS_OPEN_BY_FID == 000040000000UL, "found 0%.11oUL\n", - MDS_OPEN_BY_FID); + MDS_OPEN_BY_FID); LASSERTF(MDS_OPEN_DELAY_CREATE == 000100000000UL, "found 0%.11oUL\n", - MDS_OPEN_DELAY_CREATE); + MDS_OPEN_DELAY_CREATE); LASSERTF(MDS_OPEN_OWNEROVERRIDE == 000200000000UL, "found 0%.11oUL\n", - MDS_OPEN_OWNEROVERRIDE); + MDS_OPEN_OWNEROVERRIDE); LASSERTF(MDS_OPEN_JOIN_FILE == 000400000000UL, "found 0%.11oUL\n", - MDS_OPEN_JOIN_FILE); + MDS_OPEN_JOIN_FILE); LASSERTF(MDS_OPEN_LOCK == 004000000000UL, "found 0%.11oUL\n", - MDS_OPEN_LOCK); + MDS_OPEN_LOCK); LASSERTF(MDS_OPEN_HAS_EA == 010000000000UL, "found 0%.11oUL\n", - MDS_OPEN_HAS_EA); + MDS_OPEN_HAS_EA); LASSERTF(MDS_OPEN_HAS_OBJS == 020000000000UL, "found 0%.11oUL\n", - MDS_OPEN_HAS_OBJS); + MDS_OPEN_HAS_OBJS); LASSERTF(MDS_OPEN_NORESTORE == 00000000000100000000000ULL, "found 0%.22lloULL\n", - (long long)MDS_OPEN_NORESTORE); + (long long)MDS_OPEN_NORESTORE); LASSERTF(MDS_OPEN_NEWSTRIPE == 00000000000200000000000ULL, "found 0%.22lloULL\n", - (long long)MDS_OPEN_NEWSTRIPE); + (long long)MDS_OPEN_NEWSTRIPE); LASSERTF(MDS_OPEN_VOLATILE == 00000000000400000000000ULL, "found 0%.22lloULL\n", - (long long)MDS_OPEN_VOLATILE); + (long long)MDS_OPEN_VOLATILE); LASSERTF(LUSTRE_SYNC_FL == 0x00000008, "found 0x%.8x\n", - LUSTRE_SYNC_FL); + LUSTRE_SYNC_FL); LASSERTF(LUSTRE_IMMUTABLE_FL == 0x00000010, "found 0x%.8x\n", - LUSTRE_IMMUTABLE_FL); + LUSTRE_IMMUTABLE_FL); LASSERTF(LUSTRE_APPEND_FL == 0x00000020, "found 0x%.8x\n", - LUSTRE_APPEND_FL); + LUSTRE_APPEND_FL); LASSERTF(LUSTRE_NOATIME_FL == 0x00000080, "found 0x%.8x\n", - LUSTRE_NOATIME_FL); + LUSTRE_NOATIME_FL); LASSERTF(LUSTRE_DIRSYNC_FL == 0x00010000, "found 0x%.8x\n", - LUSTRE_DIRSYNC_FL); + LUSTRE_DIRSYNC_FL); LASSERTF(MDS_INODELOCK_LOOKUP == 0x000001, "found 0x%.8x\n", - MDS_INODELOCK_LOOKUP); + MDS_INODELOCK_LOOKUP); LASSERTF(MDS_INODELOCK_UPDATE == 0x000002, "found 0x%.8x\n", - MDS_INODELOCK_UPDATE); + MDS_INODELOCK_UPDATE); LASSERTF(MDS_INODELOCK_OPEN == 0x000004, "found 0x%.8x\n", - MDS_INODELOCK_OPEN); + MDS_INODELOCK_OPEN); LASSERTF(MDS_INODELOCK_LAYOUT == 0x000008, "found 0x%.8x\n", - MDS_INODELOCK_LAYOUT); + MDS_INODELOCK_LAYOUT); /* Checks for struct mdt_ioepoch */ LASSERTF((int)sizeof(struct mdt_ioepoch) == 24, "found %lld\n", @@ -2617,35 +2674,6 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct lmv_desc *)0)->ld_uuid) == 40, "found %lld\n", (long long)(int)sizeof(((struct lmv_desc *)0)->ld_uuid)); - /* Checks for struct lmv_stripe_md */ - LASSERTF((int)sizeof(struct lmv_stripe_md) == 32, "found %lld\n", - (long long)(int)sizeof(struct lmv_stripe_md)); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_magic) == 0, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_magic)); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_magic) == 4, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_magic)); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_count) == 4, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_count)); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_count) == 4, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_count)); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_master) == 8, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_master)); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_master) == 4, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_master)); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_padding) == 12, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_padding)); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_padding) == 4, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_padding)); - CLASSERT(LOV_MAXPOOLNAME == 16); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_pool_name[16]) == 32, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_pool_name[16])); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_pool_name[16]) == 1, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_pool_name[16])); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_ids[0]) == 32, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_ids[0])); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_ids[0]) == 16, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_ids[0])); - /* Checks for struct lov_desc */ LASSERTF((int)sizeof(struct lov_desc) == 88, "found %lld\n", (long long)(int)sizeof(struct lov_desc)); @@ -3195,10 +3223,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct llog_setattr64_rec, lsr_gid_h)); LASSERTF((int)sizeof(((struct llog_setattr64_rec *)0)->lsr_gid_h) == 4, "found %lld\n", (long long)(int)sizeof(((struct llog_setattr64_rec *)0)->lsr_gid_h)); - LASSERTF((int)offsetof(struct llog_setattr64_rec, lsr_padding) == 48, "found %lld\n", - (long long)(int)offsetof(struct llog_setattr64_rec, lsr_padding)); - LASSERTF((int)sizeof(((struct llog_setattr64_rec *)0)->lsr_padding) == 8, "found %lld\n", - (long long)(int)sizeof(((struct llog_setattr64_rec *)0)->lsr_padding)); + LASSERTF((int)offsetof(struct llog_setattr64_rec, lsr_valid) == 48, "found %lld\n", + (long long)(int)offsetof(struct llog_setattr64_rec, lsr_valid)); + LASSERTF((int)sizeof(((struct llog_setattr64_rec *)0)->lsr_valid) == 8, "found %lld\n", + (long long)(int)sizeof(((struct llog_setattr64_rec *)0)->lsr_valid)); LASSERTF((int)offsetof(struct llog_setattr64_rec, lsr_tail) == 56, "found %lld\n", (long long)(int)offsetof(struct llog_setattr64_rec, lsr_tail)); LASSERTF((int)sizeof(((struct llog_setattr64_rec *)0)->lsr_tail) == 8, "found %lld\n", @@ -3272,50 +3300,6 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct changelog_rec *)0)->cr_pfid) == 16, "found %lld\n", (long long)(int)sizeof(((struct changelog_rec *)0)->cr_pfid)); - /* Checks for struct changelog_ext_rec */ - LASSERTF((int)sizeof(struct changelog_ext_rec) == 96, "found %lld\n", - (long long)(int)sizeof(struct changelog_ext_rec)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_namelen) == 0, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_namelen)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_namelen) == 2, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_namelen)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_flags) == 2, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_flags)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_flags) == 2, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_flags)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_type) == 4, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_type)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_type) == 4, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_type)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_index) == 8, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_index)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_index) == 8, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_index)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_prev) == 16, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_prev)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_prev) == 8, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_prev)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_time) == 24, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_time)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_time) == 8, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_time)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_tfid) == 32, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_tfid)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_tfid) == 16, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_tfid)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_pfid) == 48, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_pfid)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_pfid) == 16, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_pfid)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_sfid) == 64, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_sfid)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_sfid) == 16, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_sfid)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_spfid) == 80, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_spfid)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_spfid) == 16, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_spfid)); - /* Checks for struct changelog_setinfo */ LASSERTF((int)sizeof(struct changelog_setinfo) == 12, "found %lld\n", (long long)(int)sizeof(struct changelog_setinfo)); @@ -3339,10 +3323,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct llog_changelog_rec, cr)); LASSERTF((int)sizeof(((struct llog_changelog_rec *)0)->cr) == 64, "found %lld\n", (long long)(int)sizeof(((struct llog_changelog_rec *)0)->cr)); - LASSERTF((int)offsetof(struct llog_changelog_rec, cr_tail) == 80, "found %lld\n", - (long long)(int)offsetof(struct llog_changelog_rec, cr_tail)); - LASSERTF((int)sizeof(((struct llog_changelog_rec *)0)->cr_tail) == 8, "found %lld\n", - (long long)(int)sizeof(((struct llog_changelog_rec *)0)->cr_tail)); + LASSERTF((int)offsetof(struct llog_changelog_rec, cr_do_not_use) == 80, "found %lld\n", + (long long)(int)offsetof(struct llog_changelog_rec, cr_do_not_use)); + LASSERTF((int)sizeof(((struct llog_changelog_rec *)0)->cr_do_not_use) == 8, "found %lld\n", + (long long)(int)sizeof(((struct llog_changelog_rec *)0)->cr_do_not_use)); /* Checks for struct llog_changelog_user_rec */ LASSERTF((int)sizeof(struct llog_changelog_user_rec) == 40, "found %lld\n", @@ -3506,6 +3490,19 @@ void lustre_assert_wire_constants(void) CLASSERT(LLOG_ORIGIN_HANDLE_DESTROY == 509); CLASSERT(LLOG_FIRST_OPC == 501); CLASSERT(LLOG_LAST_OPC == 510); + CLASSERT(LLOG_CONFIG_ORIG_CTXT == 0); + CLASSERT(LLOG_CONFIG_REPL_CTXT == 1); + CLASSERT(LLOG_MDS_OST_ORIG_CTXT == 2); + CLASSERT(LLOG_MDS_OST_REPL_CTXT == 3); + CLASSERT(LLOG_SIZE_ORIG_CTXT == 4); + CLASSERT(LLOG_SIZE_REPL_CTXT == 5); + CLASSERT(LLOG_TEST_ORIG_CTXT == 8); + CLASSERT(LLOG_TEST_REPL_CTXT == 9); + CLASSERT(LLOG_CHANGELOG_ORIG_CTXT == 12); + CLASSERT(LLOG_CHANGELOG_REPL_CTXT == 13); + CLASSERT(LLOG_CHANGELOG_USER_ORIG_CTXT == 14); + CLASSERT(LLOG_AGENT_ORIG_CTXT == 15); + CLASSERT(LLOG_MAX_CTXTS == 16); /* Checks for struct llogd_conn_body */ LASSERTF((int)sizeof(struct llogd_conn_body) == 40, "found %lld\n", @@ -3943,9 +3940,9 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct hsm_progress *)0)->padding) == 4, "found %lld\n", (long long)(int)sizeof(((struct hsm_progress *)0)->padding)); LASSERTF(HP_FLAG_COMPLETED == 0x01, "found 0x%.8x\n", - HP_FLAG_COMPLETED); + HP_FLAG_COMPLETED); LASSERTF(HP_FLAG_RETRY == 0x02, "found 0x%.8x\n", - HP_FLAG_RETRY); + HP_FLAG_RETRY); LASSERTF((int)offsetof(struct hsm_copy, hc_data_version) == 0, "found %lld\n", (long long)(int)offsetof(struct hsm_copy, hc_data_version)); @@ -4100,9 +4097,9 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_data_len) == 4, "found %lld\n", (long long)(int)sizeof(((struct hsm_request *)0)->hr_data_len)); LASSERTF(HSM_FORCE_ACTION == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)HSM_FORCE_ACTION); + (unsigned)HSM_FORCE_ACTION); LASSERTF(HSM_GHOST_COPY == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)HSM_GHOST_COPY); + (unsigned)HSM_GHOST_COPY); /* Checks for struct hsm_user_request */ LASSERTF((int)sizeof(struct hsm_user_request) == 24, "found %lld\n", diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index 8dade197f053..ea15cc638097 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -483,10 +483,8 @@ static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on) memset(&bdev->rds_info, 0, sizeof(bdev->rds_info)); } - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, - bdev->cache_fm_rds_system); - - return err; + return bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, + bdev->cache_fm_rds_system); } static int bcm2048_get_rds_no_lock(struct bcm2048_device *bdev) @@ -1834,9 +1832,7 @@ static int bcm2048_deinit(struct bcm2048_device *bdev) if (err < 0) return err; - err = bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); - - return err; + return bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); } /* @@ -1995,9 +1991,7 @@ static ssize_t bcm2048_##prop##_read(struct device *dev, \ \ value = bcm2048_get_##prop(bdev); \ \ - value = sprintf(buf, mask "\n", value); \ - \ - return value; \ + return sprintf(buf, mask "\n", value); \ } #define DEFINE_SYSFS_PROPERTY(prop, signal, size, mask, check) \ diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c index 692ba3e63e14..fedeb3c3549e 100644 --- a/drivers/staging/media/cxd2099/cxd2099.c +++ b/drivers/staging/media/cxd2099/cxd2099.c @@ -660,7 +660,7 @@ static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) struct cxd *ci = ca->data; mutex_lock(&ci->lock); - printk(kern_INFO "write_data %d\n", ecount); + dev_info(&ci->i2c->dev, "write_data %d\n", ecount); write_reg(ci, 0x0d, ecount>>8); write_reg(ci, 0x0e, ecount&0xff); write_block(ci, 0x11, ebuf, ecount); diff --git a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h index f4f35c9ad1ab..d3f34f9bf712 100644 --- a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h +++ b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h @@ -544,41 +544,41 @@ struct vpfe_isif_raw_config { /* IPIPE module configurations */ /* IPIPE input configuration */ -#define VPFE_IPIPE_INPUT_CONFIG (1 << 0) +#define VPFE_IPIPE_INPUT_CONFIG BIT(0) /* LUT based Defect Pixel Correction */ -#define VPFE_IPIPE_LUTDPC (1 << 1) +#define VPFE_IPIPE_LUTDPC BIT(1) /* On the fly (OTF) Defect Pixel Correction */ -#define VPFE_IPIPE_OTFDPC (1 << 2) +#define VPFE_IPIPE_OTFDPC BIT(2) /* Noise Filter - 1 */ -#define VPFE_IPIPE_NF1 (1 << 3) +#define VPFE_IPIPE_NF1 BIT(3) /* Noise Filter - 2 */ -#define VPFE_IPIPE_NF2 (1 << 4) +#define VPFE_IPIPE_NF2 BIT(4) /* White Balance. Also a control ID */ -#define VPFE_IPIPE_WB (1 << 5) +#define VPFE_IPIPE_WB BIT(5) /* 1st RGB to RBG Blend module */ -#define VPFE_IPIPE_RGB2RGB_1 (1 << 6) +#define VPFE_IPIPE_RGB2RGB_1 BIT(6) /* 2nd RGB to RBG Blend module */ -#define VPFE_IPIPE_RGB2RGB_2 (1 << 7) +#define VPFE_IPIPE_RGB2RGB_2 BIT(7) /* Gamma Correction */ -#define VPFE_IPIPE_GAMMA (1 << 8) +#define VPFE_IPIPE_GAMMA BIT(8) /* 3D LUT color conversion */ -#define VPFE_IPIPE_3D_LUT (1 << 9) +#define VPFE_IPIPE_3D_LUT BIT(9) /* RGB to YCbCr module */ -#define VPFE_IPIPE_RGB2YUV (1 << 10) +#define VPFE_IPIPE_RGB2YUV BIT(10) /* YUV 422 conversion module */ -#define VPFE_IPIPE_YUV422_CONV (1 << 11) +#define VPFE_IPIPE_YUV422_CONV BIT(11) /* Edge Enhancement */ -#define VPFE_IPIPE_YEE (1 << 12) +#define VPFE_IPIPE_YEE BIT(12) /* Green Imbalance Correction */ -#define VPFE_IPIPE_GIC (1 << 13) +#define VPFE_IPIPE_GIC BIT(13) /* CFA Interpolation */ -#define VPFE_IPIPE_CFA (1 << 14) +#define VPFE_IPIPE_CFA BIT(14) /* Chroma Artifact Reduction */ -#define VPFE_IPIPE_CAR (1 << 15) +#define VPFE_IPIPE_CAR BIT(15) /* Chroma Gain Suppression */ -#define VPFE_IPIPE_CGS (1 << 16) +#define VPFE_IPIPE_CGS BIT(16) /* Global brightness and contrast control */ -#define VPFE_IPIPE_GBCE (1 << 17) +#define VPFE_IPIPE_GBCE BIT(17) #define VPFE_IPIPE_MAX_MODULES 18 diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index ae9202ded59f..569bcdc9ce2f 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -146,9 +146,8 @@ enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev) u32 field_status; field_status = isif_read(isif->isif_cfg.base_addr, MODESET); - field_status = (field_status >> DM365_ISIF_MDFS_OFFSET) & - DM365_ISIF_MDFS_MASK; - return field_status; + return (field_status >> DM365_ISIF_MDFS_OFFSET) & + DM365_ISIF_MDFS_MASK; } static int @@ -594,8 +593,7 @@ isif_validate_raw_params(struct vpfe_isif_raw_config *params) ret = isif_validate_dfc_params(¶ms->dfc); if (ret) return ret; - ret = isif_validate_bclamp_params(¶ms->bclamp); - return ret; + return isif_validate_bclamp_params(¶ms->bclamp); } static int isif_set_params(struct v4l2_subdev *sd, void *params) diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index 3cd56cc132c7..128662623ea8 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c @@ -128,7 +128,7 @@ resizer_configure_passthru(struct vpfe_resizer_device *resizer, int bypass) static void configure_resizer_out_params(struct vpfe_resizer_device *resizer, int index, void *output_spec, unsigned char partial, - unsigned flag) + unsigned int flag) { struct resizer_params *param = &resizer->config; struct v4l2_mbus_framefmt *outformat; diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 3319fb8f7d01..8be9f854510f 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -37,7 +37,7 @@ static struct media_entity *vpfe_get_input_entity struct media_pad *remote; remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); - if (remote == NULL) { + if (!remote) { pr_err("Invalid media connection to isif/ccdc\n"); return NULL; } @@ -54,7 +54,7 @@ static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video) int i; remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); - if (remote == NULL) { + if (!remote) { pr_err("Invalid media connection to isif/ccdc\n"); return -EINVAL; } @@ -107,7 +107,7 @@ __vpfe_video_get_format(struct vpfe_video_device *video, int ret; subdev = vpfe_video_remote_subdev(video, &pad); - if (subdev == NULL) + if (!subdev) return -EINVAL; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; @@ -236,7 +236,7 @@ static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe) * format of the connected pad. */ subdev = vpfe_video_remote_subdev(pipe->outputs[0], NULL); - if (subdev == NULL) + if (!subdev) return -EPIPE; while (1) { @@ -413,7 +413,7 @@ static int vpfe_open(struct file *file) /* Allocate memory for the file handle object */ handle = kzalloc(sizeof(struct vpfe_fh), GFP_KERNEL); - if (handle == NULL) + if (!handle) return -ENOMEM; v4l2_fh_init(&handle->vfh, &video->video_dev); @@ -683,14 +683,14 @@ static int vpfe_enum_fmt(struct file *file, void *priv, } /* get the remote pad */ remote = media_entity_remote_pad(&video->pad); - if (remote == NULL) { + if (!remote) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote pad for video node\n"); return -EINVAL; } /* get the remote subdev */ subdev = vpfe_video_remote_subdev(video, NULL); - if (subdev == NULL) { + if (!subdev) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote subdev for video node\n"); return -EINVAL; diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c index 44f565547179..04d881b391c7 100644 --- a/drivers/staging/media/lirc/lirc_bt829.c +++ b/drivers/staging/media/lirc/lirc_bt829.c @@ -120,7 +120,7 @@ int init_module(void) int rc; pdev = do_pci_probe(); - if (pdev == NULL) + if (!pdev) return -ENODEV; rc = pci_enable_device(pdev); @@ -163,7 +163,6 @@ err_put_dev: return rc; } - void cleanup_module(void) { struct pci_dev *pdev = to_pci_dev(atir_driver.dev); @@ -174,7 +173,6 @@ void cleanup_module(void) pci_dev_put(pdev); } - static int atir_init_start(void) { pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400); @@ -187,10 +185,9 @@ static int atir_init_start(void) static void cycle_delay(int cycle) { - udelay(WAIT_CYCLE*cycle); + udelay(WAIT_CYCLE * cycle); } - static int poll_main(void) { unsigned char status_high, status_low; diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index ff1926ca1f96..198a8057f2f1 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -32,7 +32,6 @@ #include #include - #define MOD_AUTHOR "Venky Raju " #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" #define MOD_NAME "lirc_imon" @@ -212,7 +211,6 @@ static void deregister_from_lirc(struct imon_context *context) else dev_info(&context->usbdev->dev, "Deregistered iMON driver (minor:%d)\n", minor); - } /** @@ -429,7 +427,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, do { memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7); - context->usb_tx_buf[7] = (unsigned char) seq; + context->usb_tx_buf[7] = (unsigned char)seq; retval = send_packet(context); if (retval) { @@ -447,7 +445,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, if (context->vfd_proto_6p) { /* Send packet #6 */ memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); - context->usb_tx_buf[7] = (unsigned char) seq; + context->usb_tx_buf[7] = (unsigned char)seq; retval = send_packet(context); if (retval) dev_err(&context->usbdev->dev, @@ -563,7 +561,7 @@ static void submit_data(struct imon_context *context) value |= PULSE_BIT; for (i = 0; i < 4; ++i) - buf[i] = value>>(i*8); + buf[i] = value >> (i * 8); lirc_buffer_write(context->driver->rbuf, buf); wake_up(&context->driver->rbuf->wait_poll); @@ -589,7 +587,7 @@ static void imon_incoming_packet(struct imon_context *context, if (len != 8) { dev_warn(dev, "imon %s: invalid incoming packet size (len = %d, intf%d)\n", - __func__, len, intf); + __func__, len, intf); return; } @@ -704,7 +702,7 @@ static int imon_probe(struct usb_interface *interface, /* prevent races probing devices w/multiple interfaces */ mutex_lock(&driver_lock); - context = kzalloc(sizeof(struct imon_context), GFP_KERNEL); + context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) goto driver_unlock; @@ -784,11 +782,11 @@ static int imon_probe(struct usb_interface *interface, __func__, vfd_proto_6p); } - driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + driver = kzalloc(sizeof(*driver), GFP_KERNEL); if (!driver) goto free_context; - rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + rbuf = kmalloc(sizeof(*rbuf), GFP_KERNEL); if (!rbuf) goto free_driver; @@ -797,16 +795,11 @@ static int imon_probe(struct usb_interface *interface, goto free_rbuf; } rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rx_urb) { - dev_err(dev, "%s: usb_alloc_urb failed for IR urb\n", __func__); + if (!rx_urb) goto free_lirc_buf; - } tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!tx_urb) { - dev_err(dev, "%s: usb_alloc_urb failed for display urb\n", - __func__); + if (!tx_urb) goto free_rx_urb; - } mutex_init(&context->ctx_lock); context->vfd_proto_6p = vfd_proto_6p; @@ -835,7 +828,7 @@ static int imon_probe(struct usb_interface *interface, } dev_info(dev, "Registered iMON driver (lirc minor: %d)\n", - lirc_minor); + lirc_minor); /* Needed while unregistering! */ driver->minor = lirc_minor; @@ -856,8 +849,8 @@ static int imon_probe(struct usb_interface *interface, context->display = 1; usb_fill_int_urb(context->rx_urb, context->usbdev, - usb_rcvintpipe(context->usbdev, - context->rx_endpoint->bEndpointAddress), + usb_rcvintpipe(context->usbdev, + context->rx_endpoint->bEndpointAddress), context->usb_rx_buf, sizeof(context->usb_rx_buf), usb_rx_callback, context, context->rx_endpoint->bInterval); @@ -882,7 +875,7 @@ static int imon_probe(struct usb_interface *interface, } dev_info(dev, "iMON device (%04x:%04x, intf%d) on usb<%d:%d> initialized\n", - vendor, product, ifnum, usbdev->bus->busnum, usbdev->devnum); + vendor, product, ifnum, usbdev->bus->busnum, usbdev->devnum); /* Everything went fine. Just unlock and return retval (with is 0) */ mutex_unlock(&context->ctx_lock); @@ -973,8 +966,8 @@ static int imon_resume(struct usb_interface *intf) struct imon_context *context = usb_get_intfdata(intf); usb_fill_int_urb(context->rx_urb, context->usbdev, - usb_rcvintpipe(context->usbdev, - context->rx_endpoint->bEndpointAddress), + usb_rcvintpipe(context->usbdev, + context->rx_endpoint->bEndpointAddress), context->usb_rx_buf, sizeof(context->usb_rx_buf), usb_rx_callback, context, context->rx_endpoint->bInterval); diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 3906ac6e686d..64d99ec292e5 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -163,12 +163,12 @@ static unsigned int init_lirc_timer(void) if (count >= 1000 && timeelapsed > 0) { if (default_timer == 0) { /* autodetect timer */ - newtimer = (1000000*count)/timeelapsed; + newtimer = (1000000 * count) / timeelapsed; pr_info("%u Hz timer detected\n", newtimer); return newtimer; } - newtimer = (1000000*count)/timeelapsed; - if (abs(newtimer - default_timer) > default_timer/10) { + newtimer = (1000000 * count) / timeelapsed; + if (abs(newtimer - default_timer) > default_timer / 10) { /* bad timer */ pr_notice("bad timer: %u Hz\n", newtimer); pr_notice("using default timer: %u Hz\n", diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c index 2218d0042030..4678ae10b030 100644 --- a/drivers/staging/media/lirc/lirc_sasem.c +++ b/drivers/staging/media/lirc/lirc_sasem.c @@ -47,7 +47,6 @@ #include #include - #define MOD_AUTHOR "Oliver Stabel , " \ "Tim Davies " #define MOD_DESC "USB Driver for Sasem Remote Controller V1.1" @@ -73,7 +72,7 @@ static void usb_tx_callback(struct urb *urb); /* VFD file_operations function prototypes */ static int vfd_open(struct inode *inode, struct file *file); -static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg); +static long vfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static int vfd_close(struct inode *inode, struct file *file); static ssize_t vfd_write(struct file *file, const char __user *buf, size_t n_bytes, loff_t *pos); @@ -86,7 +85,6 @@ static void ir_close(void *data); #define SASEM_DATA_BUF_SZ 32 struct sasem_context { - struct usb_device *dev; int vfd_isopen; /* VFD port has been opened */ unsigned int vfd_contrast; /* VFD contrast */ @@ -156,7 +154,6 @@ static int debug; /*** M O D U L E C O D E ***/ - MODULE_AUTHOR(MOD_AUTHOR); MODULE_DESCRIPTION(MOD_DESC); MODULE_LICENSE("GPL"); @@ -186,7 +183,6 @@ static void deregister_from_lirc(struct sasem_context *context) else dev_info(&context->dev->dev, "Deregistered Sasem driver (minor:%d)\n", minor); - } /** @@ -243,7 +239,7 @@ exit: * Called when the VFD device (e.g. /dev/usb/lcd) * is closed by the application. */ -static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg) +static long vfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct sasem_context *context; @@ -297,7 +293,6 @@ static int vfd_close(struct inode *inode, struct file *file) context->vfd_isopen = 0; dev_info(&context->dev->dev, "VFD port closed\n"); if (!context->dev_present && !context->ir_isopen) { - /* Device disconnected before close and IR port is * not open. If IR port is open, context will be * deleted by ir_close. */ @@ -546,9 +541,7 @@ static void ir_close(void *data) * at disconnect time, so do it now. */ deregister_from_lirc(context); - if (!context->vfd_isopen) { - mutex_unlock(&context->ctx_lock); delete_context(context); return; @@ -633,7 +626,6 @@ static void usb_rx_callback(struct urb *urb) return; switch (urb->status) { - case -ENOENT: /* usbcore unlink successful! */ return; @@ -651,8 +643,6 @@ static void usb_rx_callback(struct urb *urb) usb_submit_urb(context->rx_urb, GFP_ATOMIC); } - - /** * Callback function for USB core API: Probe */ @@ -709,7 +699,6 @@ static int sasem_probe(struct usb_interface *interface, } else if (!vfd_ep_found && usb_endpoint_is_int_out(ep)) { - tx_endpoint = ep; vfd_ep_found = 1; if (debug) @@ -735,17 +724,17 @@ static int sasem_probe(struct usb_interface *interface, /* Allocate memory */ alloc_status = 0; - context = kzalloc(sizeof(struct sasem_context), GFP_KERNEL); + context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) { alloc_status = 1; goto alloc_status_switch; } - driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + driver = kzalloc(sizeof(*driver), GFP_KERNEL); if (!driver) { alloc_status = 2; goto alloc_status_switch; } - rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + rbuf = kmalloc(sizeof(*rbuf), GFP_KERNEL); if (!rbuf) { alloc_status = 3; goto alloc_status_switch; @@ -758,17 +747,12 @@ static int sasem_probe(struct usb_interface *interface, } rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!rx_urb) { - dev_err(&interface->dev, - "%s: usb_alloc_urb failed for IR urb\n", __func__); alloc_status = 5; goto alloc_status_switch; } if (vfd_ep_found) { tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!tx_urb) { - dev_err(&interface->dev, - "%s: usb_alloc_urb failed for VFD urb", - __func__); alloc_status = 6; goto alloc_status_switch; } diff --git a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt index 42ff0d8b2ead..48aa45acc953 100644 --- a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt +++ b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt @@ -51,6 +51,140 @@ Description: uses. Users: +What: /sys/class/most/mostcore/devices//dci +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + If the network interface controller is attached via USB, a dci + directory is created that allows applications to use the + controller's direct communication interface (DCI) to exchange + information. +Users: + +What: /sys/class/most/mostcore/devices//dci/arb_address +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to set an arbitrary DCI register address an + application wants to read from or write to. +Users: + +What: /sys/class/most/mostcore/devices//dci/arb_value +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to read from or write to the arbitrary DCI register + whose address is stored in arb_address. +Users: + +What: /sys/class/most/mostcore/devices//dci/mep_eui48_hi +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/class/most/mostcore/devices//dci/mep_eui48_lo +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/class/most/mostcore/devices//dci/mep_eui48_mi +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/class/most/mostcore/devices//dci/mep_filter +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP filter address. +Users: + +What: /sys/class/most/mostcore/devices//dci/mep_hash0 +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/class/most/mostcore/devices//dci/mep_hash1 +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/class/most/mostcore/devices//dci/mep_hash2 +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/class/most/mostcore/devices//dci/mep_hash3 +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/class/most/mostcore/devices//dci/ni_state +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + Indicates the current network interface state. +Users: + +What: /sys/class/most/mostcore/devices//dci/node_address +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + Indicates the current node address. +Users: + +What: /sys/class/most/mostcore/devices//dci/node_position +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + Indicates the current node position. +Users: + +What: /sys/class/most/mostcore/devices//dci/packet_bandwidth +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + Indicates the configured packet bandwidth. +Users: + +What: /sys/class/most/mostcore/devices//dci/sync_ep +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm +Description: + Triggers the controller's synchronization process for a certain + endpoint. +Users: + What: /sys/class/most/mostcore/devices/// Date: June 2015 KernelVersion: 4.3 diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index de4f76abfb47..7f51024dc5eb 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -57,7 +57,11 @@ static inline bool ch_has_mbo(struct aim_channel *c) static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) { - *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + if (!kfifo_peek(&c->fifo, mbo)) { + *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + if (*mbo) + kfifo_in(&c->fifo, mbo, 1); + } return *mbo; } @@ -130,7 +134,7 @@ static int aim_open(struct inode *inode, struct file *filp) if (!c->dev) { pr_info("WARN: Device is destroyed\n"); mutex_unlock(&c->io_mutex); - return -EBUSY; + return -ENODEV; } if (c->access_ref) { @@ -184,8 +188,7 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) { int ret; - size_t actual_len; - size_t max_len; + size_t to_copy, left; struct mbo *mbo = NULL; struct aim_channel *c = filp->private_data; @@ -201,27 +204,28 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, } if (unlikely(!c->dev)) { - ret = -EPIPE; + ret = -ENODEV; goto unlock; } - max_len = c->cfg->buffer_size; - actual_len = min(count, max_len); - mbo->buffer_length = actual_len; - - if (copy_from_user(mbo->virt_address, buf, mbo->buffer_length)) { + to_copy = min(count, c->cfg->buffer_size - c->mbo_offs); + left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy); + if (left == to_copy) { ret = -EFAULT; - goto put_mbo; + goto unlock; } - ret = most_submit_mbo(mbo); - if (ret) - goto put_mbo; + c->mbo_offs += to_copy - left; + if (c->mbo_offs >= c->cfg->buffer_size || + c->cfg->data_type == MOST_CH_CONTROL || + c->cfg->data_type == MOST_CH_ASYNC) { + kfifo_skip(&c->fifo); + mbo->buffer_length = c->mbo_offs; + c->mbo_offs = 0; + most_submit_mbo(mbo); + } - mutex_unlock(&c->io_mutex); - return actual_len; -put_mbo: - most_put_mbo(mbo); + ret = to_copy - left; unlock: mutex_unlock(&c->io_mutex); return ret; @@ -256,7 +260,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) /* make sure we don't submit to gone devices */ if (unlikely(!c->dev)) { mutex_unlock(&c->io_mutex); - return -EIO; + return -ENODEV; } to_copy = min_t(size_t, @@ -290,7 +294,7 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait) if (!kfifo_is_empty(&c->fifo)) mask |= POLLIN | POLLRDNORM; } else { - if (ch_has_mbo(c)) + if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c)) mask |= POLLOUT | POLLWRNORM; } return mask; @@ -366,7 +370,7 @@ static int aim_rx_completion(struct mbo *mbo) spin_lock(&c->unlink); if (!c->access_ref || !c->dev) { spin_unlock(&c->unlink); - return -EFAULT; + return -ENODEV; } kfifo_in(&c->fifo, &mbo, 1); spin_unlock(&c->unlink); @@ -499,23 +503,27 @@ static struct most_aim cdev_aim = { static int __init mod_init(void) { + int err; + pr_info("init()\n"); INIT_LIST_HEAD(&channel_list); spin_lock_init(&ch_list_lock); ida_init(&minor_id); - if (alloc_chrdev_region(&aim_devno, 0, 50, "cdev") < 0) - return -EIO; + err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev"); + if (err < 0) + goto dest_ida; major = MAJOR(aim_devno); aim_class = class_create(THIS_MODULE, "most_cdev_aim"); if (IS_ERR(aim_class)) { pr_err("no udev support\n"); + err = PTR_ERR(aim_class); goto free_cdev; } - - if (most_register_aim(&cdev_aim)) + err = most_register_aim(&cdev_aim); + if (err) goto dest_class; return 0; @@ -523,7 +531,9 @@ dest_class: class_destroy(aim_class); free_cdev: unregister_chrdev_region(aim_devno, 1); - return -EIO; +dest_ida: + ida_destroy(&minor_id); + return err; } static void __exit mod_exit(void) diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 2f42de44d051..4659a6450c04 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -298,15 +298,16 @@ static struct net_dev_context *get_net_dev_context( struct most_interface *iface) { struct net_dev_context *nd, *tmp; + unsigned long flags; - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_for_each_entry_safe(nd, tmp, &net_devices, list) { if (nd->iface == iface) { - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); return nd; } } - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); return NULL; } @@ -316,6 +317,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, { struct net_dev_context *nd; struct net_dev_channel *ch; + unsigned long flags; if (!iface) return -EINVAL; @@ -332,9 +334,9 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, nd->iface = iface; - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_add(&nd->list, &net_devices); - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); } ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx; @@ -377,6 +379,7 @@ static int aim_disconnect_channel(struct most_interface *iface, { struct net_dev_context *nd; struct net_dev_channel *ch; + unsigned long flags; nd = get_net_dev_context(iface); if (!nd) @@ -398,9 +401,9 @@ static int aim_disconnect_channel(struct most_interface *iface, most_net_rm_netdev_safe(nd); if (!nd->rx.linked && !nd->tx.linked) { - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_del(&nd->list); - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); kfree(nd); } @@ -514,20 +517,21 @@ static int __init most_net_init(void) static void __exit most_net_exit(void) { struct net_dev_context *nd, *tmp; + unsigned long flags; - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_for_each_entry_safe(nd, tmp, &net_devices, list) { list_del(&nd->list); - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); /* * do not call most_stop_channel() here, because channels are * going to be closed in ndo_stop() after unregister_netdev() */ most_net_rm_netdev_safe(nd); kfree(nd); - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); } - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); most_deregister_aim(&aim); pr_info("most_net_exit()\n"); diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c index 9c645801cff4..e4198e5e064b 100644 --- a/drivers/staging/most/aim-sound/sound.c +++ b/drivers/staging/most/aim-sound/sound.c @@ -234,7 +234,6 @@ static int playback_thread(void *data) while (!kthread_should_stop()) { struct mbo *mbo = NULL; bool period_elapsed = false; - int ret; wait_event_interruptible( channel->playback_waitq, @@ -250,10 +249,7 @@ static int playback_thread(void *data) else memset(mbo->virt_address, 0, mbo->buffer_length); - ret = most_submit_mbo(mbo); - if (ret) - channel->is_stream_running = false; - + most_submit_mbo(mbo); if (period_elapsed) snd_pcm_period_elapsed(channel->substream); } @@ -457,7 +453,7 @@ static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) /** * Initialization of struct snd_pcm_ops */ -static struct snd_pcm_ops pcm_ops = { +static const struct snd_pcm_ops pcm_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -611,7 +607,8 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id, channel->id = channel_id; init_waitqueue_head(&channel->playback_waitq); - if (audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg)) + ret = audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg); + if (ret) goto err_free_card; snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME); diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 13abf7c275a4..e0748416aee5 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -79,7 +79,7 @@ static int aim_vdev_open(struct file *filp) struct most_video_dev *mdev = video_drvdata(filp); struct aim_fh *fh; - pr_info("aim_vdev_open()\n"); + v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n"); switch (vdev->vfl_type) { case VFL_TYPE_GRABBER: @@ -93,7 +93,7 @@ static int aim_vdev_open(struct file *filp) return -ENOMEM; if (!atomic_inc_and_test(&mdev->access_ref)) { - pr_err("too many clients\n"); + v4l2_err(&mdev->v4l2_dev, "too many clients\n"); ret = -EBUSY; goto err_dec; } @@ -106,7 +106,7 @@ static int aim_vdev_open(struct file *filp) ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info); if (ret) { - pr_err("most_start_channel() failed\n"); + v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n"); goto err_rm; } @@ -128,7 +128,7 @@ static int aim_vdev_close(struct file *filp) struct most_video_dev *mdev = fh->mdev; struct mbo *mbo, *tmp; - pr_info("aim_vdev_close()\n"); + v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n"); /* * We need to put MBOs back before we call most_stop_channel() @@ -139,15 +139,15 @@ static int aim_vdev_close(struct file *filp) * This must be implemented in core. */ - spin_lock(&mdev->list_lock); + spin_lock_irq(&mdev->list_lock); mdev->mute = true; list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) { list_del(&mbo->list); - spin_unlock(&mdev->list_lock); + spin_unlock_irq(&mdev->list_lock); most_put_mbo(mbo); - spin_lock(&mdev->list_lock); + spin_lock_irq(&mdev->list_lock); } - spin_unlock(&mdev->list_lock); + spin_unlock_irq(&mdev->list_lock); most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info); mdev->mute = false; @@ -187,7 +187,7 @@ static ssize_t aim_vdev_read(struct file *filp, char __user *buf, int const cnt = rem < count ? rem : count; if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) { - pr_err("read: copy_to_user failed\n"); + v4l2_err(&mdev->v4l2_dev, "read: copy_to_user failed\n"); if (!ret) ret = -EFAULT; return ret; @@ -200,9 +200,9 @@ static ssize_t aim_vdev_read(struct file *filp, char __user *buf, if (cnt >= rem) { fh->offs = 0; - spin_lock(&mdev->list_lock); + spin_lock_irq(&mdev->list_lock); list_del(&mbo->list); - spin_unlock(&mdev->list_lock); + spin_unlock_irq(&mdev->list_lock); most_put_mbo(mbo); } } @@ -250,16 +250,16 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, return 0; } -static int vidioc_querycap(struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct aim_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - pr_info("vidioc_querycap()\n"); + v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n"); strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver)); - strlcpy(cap->card, "my_card", sizeof(cap->card)); + strlcpy(cap->card, "MOST", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "%s", mdev->iface->description); @@ -270,10 +270,13 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - pr_info("vidioc_enum_fmt_vid_cap() %d\n", f->index); + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index); if (f->index) return -EINVAL; @@ -289,7 +292,10 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - pr_info("vidioc_g_fmt_vid_cap()\n"); + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n"); aim_set_format_struct(f); return 0; @@ -298,7 +304,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct aim_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; return aim_set_format(mdev, VIDIOC_TRY_FMT, f); @@ -307,7 +313,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct aim_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; return aim_set_format(mdev, VIDIOC_S_FMT, f); @@ -315,7 +321,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { - pr_info("vidioc_g_std()\n"); + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n"); *norm = V4L2_STD_UNKNOWN; return 0; @@ -352,7 +361,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) struct aim_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - pr_info("vidioc_s_input(%d)\n", index); + v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index); if (index >= V4L2_AIM_MAX_INPUT) return -EINVAL; @@ -360,7 +369,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) return 0; } -static struct v4l2_file_operations aim_fops = { +static const struct v4l2_file_operations aim_fops = { .owner = THIS_MODULE, .open = aim_vdev_open, .release = aim_vdev_close, @@ -393,45 +402,46 @@ static const struct video_device aim_videodev_template = { static struct most_video_dev *get_aim_dev( struct most_interface *iface, int channel_idx) { - struct most_video_dev *mdev, *tmp; + struct most_video_dev *mdev; + unsigned long flags; - spin_lock(&list_lock); - list_for_each_entry_safe(mdev, tmp, &video_devices, list) { + spin_lock_irqsave(&list_lock, flags); + list_for_each_entry(mdev, &video_devices, list) { if (mdev->iface == iface && mdev->ch_idx == channel_idx) { - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); return mdev; } } - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); return NULL; } static int aim_rx_data(struct mbo *mbo) { + unsigned long flags; struct most_video_dev *mdev = get_aim_dev(mbo->ifp, mbo->hdm_channel_id); if (!mdev) return -EIO; - spin_lock(&mdev->list_lock); + spin_lock_irqsave(&mdev->list_lock, flags); if (unlikely(mdev->mute)) { - spin_unlock(&mdev->list_lock); + spin_unlock_irqrestore(&mdev->list_lock, flags); return -EIO; } list_add_tail(&mbo->list, &mdev->pending_mbos); - spin_unlock(&mdev->list_lock); + spin_unlock_irqrestore(&mdev->list_lock, flags); wake_up_interruptible(&mdev->wait_data); return 0; } static int aim_register_videodev(struct most_video_dev *mdev) { - int retval = -ENOMEM; int ret; - pr_info("aim_register_videodev()\n"); + v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n"); init_waitqueue_head(&mdev->wait_data); @@ -444,27 +454,24 @@ static int aim_register_videodev(struct most_video_dev *mdev) *mdev->vdev = aim_videodev_template; mdev->vdev->v4l2_dev = &mdev->v4l2_dev; mdev->vdev->lock = &mdev->lock; - strcpy(mdev->vdev->name, "most v4l2 aim video"); + snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s", + mdev->v4l2_dev.name); /* Register the v4l2 device */ video_set_drvdata(mdev->vdev, mdev); - retval = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1); - if (retval != 0) { - pr_err("video_register_device failed (%d)\n", retval); - ret = -ENODEV; - goto err_vbi_dev; + ret = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1); + if (ret) { + v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n", + ret); + video_device_release(mdev->vdev); } - return 0; - -err_vbi_dev: - video_device_release(mdev->vdev); return ret; } static void aim_unregister_videodev(struct most_video_dev *mdev) { - pr_info("aim_unregister_videodev()\n"); + v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n"); video_unregister_device(mdev->vdev); } @@ -485,7 +492,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, int ret; struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); - pr_info("aim_probe_channel()\n"); + pr_info("aim_probe_channel(%s)\n", name); if (mdev) { pr_err("channel already linked\n"); @@ -498,8 +505,8 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, } if (ccfg->data_type != MOST_CH_SYNC && - ccfg->data_type != MOST_CH_ISOC_AVP) { - pr_err("wrong channel type, expect sync or isoc_avp\n"); + ccfg->data_type != MOST_CH_ISOC) { + pr_err("wrong channel type, expect sync or isoc\n"); return -EINVAL; } @@ -516,8 +523,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, mdev->v4l2_dev.release = aim_v4l2_dev_release; /* Create the v4l2_device */ - strlcpy(mdev->v4l2_dev.name, "most_video_device", - sizeof(mdev->v4l2_dev.name)); + strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name)); ret = v4l2_device_register(NULL, &mdev->v4l2_dev); if (ret) { pr_err("v4l2_device_register() failed\n"); @@ -529,9 +535,10 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, if (ret) goto err_unreg; - spin_lock(&list_lock); + spin_lock_irq(&list_lock); list_add(&mdev->list, &video_devices); - spin_unlock(&list_lock); + spin_unlock_irq(&list_lock); + v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n"); return 0; err_unreg: @@ -545,16 +552,16 @@ static int aim_disconnect_channel(struct most_interface *iface, { struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); - pr_info("aim_disconnect_channel()\n"); - if (!mdev) { pr_err("no such channel is linked\n"); return -ENOENT; } - spin_lock(&list_lock); + v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n"); + + spin_lock_irq(&list_lock); list_del(&mdev->list); - spin_unlock(&list_lock); + spin_unlock_irq(&list_lock); aim_unregister_videodev(mdev); v4l2_device_disconnect(&mdev->v4l2_dev); @@ -585,17 +592,17 @@ static void __exit aim_exit(void) * we simulate this call here. * This must be fixed in core. */ - spin_lock(&list_lock); + spin_lock_irq(&list_lock); list_for_each_entry_safe(mdev, tmp, &video_devices, list) { list_del(&mdev->list); - spin_unlock(&list_lock); + spin_unlock_irq(&list_lock); aim_unregister_videodev(mdev); v4l2_device_disconnect(&mdev->v4l2_dev); v4l2_device_put(&mdev->v4l2_dev); - spin_lock(&list_lock); + spin_lock_irq(&list_lock); } - spin_unlock(&list_lock); + spin_unlock_irq(&list_lock); most_deregister_aim(&aim_info); BUG_ON(!list_empty(&video_devices)); diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 3c524506ee22..0b9816ce1761 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -2,7 +2,7 @@ * dim2_hal.c - DIM2 HAL implementation * (MediaLB, Device Interface Macro IP, OS62420) * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,18 +19,6 @@ #include "dim2_reg.h" #include -/* - * The number of frames per sub-buffer for synchronous channels. - * Allowed values: 1, 2, 4, 8, 16, 32, 64. - */ -#define FRAMES_PER_SUBBUFF 16 - -/* - * Size factor for synchronous DBR buffer. - * Minimal value is 4*FRAMES_PER_SUBBUFF. - */ -#define SYNC_DBR_FACTOR (4u * (u16)FRAMES_PER_SUBBUFF) - /* * Size factor for isochronous DBR buffer. * Minimal value is 3. @@ -61,12 +49,11 @@ #define DBR_SIZE (16 * 1024) /* specified by IP */ #define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE) +#define ROUND_UP_TO(x, d) (((x) + (d) - 1) / (d) * (d)) + /* -------------------------------------------------------------------------- */ /* generic helper functions and macros */ -#define MLBC0_FCNT_VAL_MACRO(n) MLBC0_FCNT_VAL_ ## n ## FPSB -#define MLBC0_FCNT_VAL(fpsb) MLBC0_FCNT_VAL_MACRO(fpsb) - static inline u32 bit_mask(u8 position) { return (u32)1 << position; @@ -81,10 +68,20 @@ static inline bool dim_on_error(u8 error_id, const char *error_message) /* -------------------------------------------------------------------------- */ /* types and local variables */ +struct async_tx_dbr { + u8 ch_addr; + u16 rpc; + u16 wpc; + u16 rest_size; + u16 sz_queue[CDT0_RPC_MASK + 1]; +}; + struct lld_global_vars_t { bool dim_is_initialized; bool mcm_is_initialized; struct dim2_regs __iomem *dim2; /* DIM2 core base address */ + struct async_tx_dbr atx_dbr; + u32 fcnt; u32 dbr_map[DBR_MAP_SIZE]; }; @@ -149,15 +146,34 @@ static void free_dbr(int offs, int size) /* -------------------------------------------------------------------------- */ -static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) +static void dim2_transfer_madr(u32 val) { - dimcb_io_write(&g.dim2->MADR, ctr_addr); + dimcb_io_write(&g.dim2->MADR, val); - /* wait till transfer is completed */ + /* wait for transfer completion */ while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) continue; dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ +} + +static void dim2_clear_dbr(u16 addr, u16 size) +{ + enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 }; + + 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); + + for (; addr < end_addr; addr++) + dim2_transfer_madr(cmd | addr); +} + +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); } @@ -182,13 +198,7 @@ static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) dimcb_io_write(&g.dim2->MDWE2, mask[2]); dimcb_io_write(&g.dim2->MDWE3, mask[3]); - dimcb_io_write(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr); - - /* wait till transfer is completed */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) - continue; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr); } static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value) @@ -252,6 +262,13 @@ static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size, dim2_write_ctr(CDT + ch_addr, cdt); } +static u16 dim2_rpc(u8 ch_addr) +{ + u32 cdt0 = dim2_read_ctr(CDT + ch_addr, 0); + + return (cdt0 >> CDT0_RPC_SHIFT) & CDT0_RPC_MASK; +} + static void dim2_clear_cdt(u8 ch_addr) { u32 cdt[4] = { 0, 0, 0, 0 }; @@ -356,6 +373,52 @@ static void dim2_clear_channel(u8 ch_addr) dim2_clear_cat(MLB_CAT, ch_addr); dim2_clear_cdt(ch_addr); + + /* clear channel status bit */ + dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); +} + +/* -------------------------------------------------------------------------- */ +/* trace async tx dbr fill state */ + +static inline u16 norm_pc(u16 pc) +{ + return pc & CDT0_RPC_MASK; +} + +static void dbrcnt_init(u8 ch_addr, u16 dbr_size) +{ + g.atx_dbr.rest_size = dbr_size; + g.atx_dbr.rpc = dim2_rpc(ch_addr); + g.atx_dbr.wpc = g.atx_dbr.rpc; +} + +static void dbrcnt_enq(int buf_sz) +{ + g.atx_dbr.rest_size -= buf_sz; + g.atx_dbr.sz_queue[norm_pc(g.atx_dbr.wpc)] = buf_sz; + g.atx_dbr.wpc++; +} + +u16 dim_dbr_space(struct dim_channel *ch) +{ + u16 cur_rpc; + struct async_tx_dbr *dbr = &g.atx_dbr; + + if (ch->addr != dbr->ch_addr) + return 0xFFFF; + + cur_rpc = dim2_rpc(ch->addr); + + while (norm_pc(dbr->rpc) != cur_rpc) { + dbr->rest_size += dbr->sz_queue[norm_pc(dbr->rpc)]; + dbr->rpc++; + } + + if ((u16)(dbr->wpc - dbr->rpc) >= CDT0_RPC_MASK) + return 0; + + return dbr->rest_size; } /* -------------------------------------------------------------------------- */ @@ -398,7 +461,8 @@ static inline bool check_packet_length(u32 packet_length) static inline bool check_bytes_per_frame(u32 bytes_per_frame) { - u16 const max_size = ((u16)CDT3_BD_MASK + 1u) / SYNC_DBR_FACTOR; + u16 const bd_factor = g.fcnt + 2; + u16 const max_size = ((u16)CDT3_BD_MASK + 1u) >> bd_factor; if (bytes_per_frame <= 0) return false; /* too small */ @@ -439,7 +503,7 @@ static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) { u16 n; u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; - u32 const unit = bytes_per_frame * (u16)FRAMES_PER_SUBBUFF; + u32 const unit = bytes_per_frame << g.fcnt; if (buf_size > max_size) buf_size = max_size; @@ -479,7 +543,7 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock) dimcb_io_write(&g.dim2->MLBC0, enable_6pin << MLBC0_MLBPEN_BIT | mlb_clock << MLBC0_MLBCLK_SHIFT | - MLBC0_FCNT_VAL(FRAMES_PER_SUBBUFF) << MLBC0_FCNT_SHIFT | + g.fcnt << MLBC0_FCNT_SHIFT | true << MLBC0_MLBEN_BIT); /* activate all HBI channels */ @@ -515,20 +579,17 @@ static inline bool service_channel(u8 ch_addr, u8 idx) { u8 const shift = idx * 16; u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1); + u32 mask[4] = { 0, 0, 0, 0 }; + u32 adt_w[4] = { 0, 0, 0, 0 }; if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0) return false; - { - u32 mask[4] = { 0, 0, 0, 0 }; - u32 adt_w[4] = { 0, 0, 0, 0 }; - - mask[1] = - bit_mask(ADT1_DNE_BIT + shift) | - bit_mask(ADT1_ERR_BIT + shift) | - bit_mask(ADT1_RDY_BIT + shift); - dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); - } + mask[1] = + bit_mask(ADT1_DNE_BIT + shift) | + bit_mask(ADT1_ERR_BIT + shift) | + bit_mask(ADT1_RDY_BIT + shift); + dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); /* clear channel status bit */ dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); @@ -612,6 +673,9 @@ static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) ++state->level; + if (ch->addr == g.atx_dbr.ch_addr) + dbrcnt_enq(buf_size); + if (ch->packet_length || ch->bytes_per_frame) dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size); else @@ -650,7 +714,8 @@ static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number) /* -------------------------------------------------------------------------- */ /* API */ -u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock) +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock, + u32 fcnt) { g.dim_is_initialized = false; @@ -662,7 +727,11 @@ u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock) if (mlb_clock >= 8) return DIM_INIT_ERR_MLB_CLOCK; + if (fcnt > MLBC0_FCNT_MAX_VAL) + return DIM_INIT_ERR_MLB_CLOCK; + g.dim2 = dim_base_address; + g.fcnt = fcnt; g.dbr_map[0] = 0; g.dbr_map[1] = 0; @@ -693,7 +762,7 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, if (!check_channel_address(ch_address)) return DIM_INIT_ERR_CHANNEL_ADDRESS; - ch->dbr_size = hw_buffer_size; + ch->dbr_size = ROUND_UP_TO(hw_buffer_size, DBR_BLOCK_SIZE); ch->dbr_addr = alloc_dbr(ch->dbr_size); if (ch->dbr_addr >= DBR_SIZE) return DIM_INIT_ERR_OUT_OF_MEMORY; @@ -706,6 +775,12 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, return DIM_NO_ERROR; } +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); @@ -749,8 +824,16 @@ u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address, u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, u16 max_buffer_size) { - return init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address, - max_buffer_size); + u8 ret = init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address, + max_buffer_size); + + 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)); + } + + return ret; } u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, @@ -781,6 +864,8 @@ u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, u16 bytes_per_frame) { + u16 bd_factor = g.fcnt + 2; + if (!g.dim_is_initialized || !ch) return DIM_ERR_DRIVER_NOT_INITIALIZED; @@ -790,13 +875,14 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, if (!check_bytes_per_frame(bytes_per_frame)) return DIM_ERR_BAD_CONFIG; - ch->dbr_size = bytes_per_frame * SYNC_DBR_FACTOR; + ch->dbr_size = bytes_per_frame << bd_factor; ch->dbr_addr = alloc_dbr(ch->dbr_size); if (ch->dbr_addr >= DBR_SIZE) return DIM_INIT_ERR_OUT_OF_MEMORY; sync_init(ch, ch_address / 2, bytes_per_frame); + dim2_clear_dbr(ch->dbr_addr, ch->dbr_size); dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx, ch->dbr_addr, ch->dbr_size, 0, true); @@ -808,6 +894,11 @@ u8 dim_destroy_channel(struct dim_channel *ch) if (!g.dim_is_initialized || !ch) return DIM_ERR_DRIVER_NOT_INITIALIZED; + if (ch->addr == g.atx_dbr.ch_addr) { + dimcb_io_write(&g.dim2->MIEN, 0); + g.atx_dbr.ch_addr = 0; + } + dim2_clear_channel(ch->addr); if (ch->dbr_addr < DBR_SIZE) free_dbr(ch->dbr_addr, ch->dbr_size); @@ -816,7 +907,7 @@ u8 dim_destroy_channel(struct dim_channel *ch) return DIM_NO_ERROR; } -void dim_service_irq(struct dim_channel *const *channels) +void dim_service_ahb_int_irq(struct dim_channel *const *channels) { bool state_changed; @@ -848,10 +939,6 @@ void dim_service_irq(struct dim_channel *const *channels) ++ch; } } while (state_changed); - - /* clear pending Interrupts */ - dimcb_io_write(&g.dim2->MS0, 0); - dimcb_io_write(&g.dim2->MS1, 0); } u8 dim_service_channel(struct dim_channel *ch) diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index 1c924e869de7..6df6ea5f7da4 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -60,7 +60,8 @@ struct dim_channel { u16 done_sw_buffers_number; /*< Done software buffers number. */ }; -u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock); +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock, + u32 fcnt); void dim_shutdown(void); @@ -86,13 +87,17 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, u8 dim_destroy_channel(struct dim_channel *ch); -void dim_service_irq(struct dim_channel *const *channels); +void dim_service_mlb_int_irq(void); + +void dim_service_ahb_int_irq(struct dim_channel *const *channels); u8 dim_service_channel(struct dim_channel *ch); struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch, struct dim_ch_state_t *state_ptr); +u16 dim_dbr_space(struct dim_channel *ch); + bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index a36449551513..78b2c3dd9bb3 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -1,7 +1,7 @@ /* * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -45,15 +45,15 @@ module_param(clock_speed, charp, 0); MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed"); /* - * ############################################################################# + * The parameter representing the number of frames per sub-buffer for + * synchronous channels. Valid values: [0 .. 6]. * - * The define below activates an utility function used by HAL-simu - * for calling DIM interrupt handler. - * It is used only for TEST PURPOSE and shall be commented before release. - * - * ############################################################################# + * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per + * sub-buffer 1, 2, 4, 8, 16, 32, 64. */ -/* #define ENABLE_HDM_TEST */ +static u8 fcnt = 4; /* (1 << fcnt) frames per subbuffer */ +module_param(fcnt, byte, 0); +MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2"); static DEFINE_SPINLOCK(dim_lock); @@ -85,7 +85,6 @@ struct hdm_channel { * @most_iface: most interface structure * @capabilities: an array of channel capability data * @io_base: I/O register base address - * @irq_ahb0: dim2 AHB0 irq number * @clk_speed: user selectable (through command line parameter) clock speed * @netinfo_task: thread to deliver network status * @netinfo_waitq: waitq for the thread to sleep @@ -100,7 +99,6 @@ struct dim2_hdm { struct most_interface most_iface; char name[16 + sizeof "dim2-"]; void __iomem *io_base; - unsigned int irq_ahb0; int clk_speed; struct task_struct *netinfo_task; wait_queue_head_t netinfo_waitq; @@ -118,10 +116,6 @@ struct dim2_hdm { (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) -#if defined(ENABLE_HDM_TEST) -static struct dim2_hdm *test_dev; -#endif - bool dim2_sysfs_get_state_cb(void) { bool state; @@ -212,7 +206,8 @@ static int startup_dim(struct platform_device *pdev) return ret; } - hal_ret = dim_startup(dev->io_base, dev->clk_speed); + pr_info("sync: num of frames per sub-buffer: %u\n", fcnt); + hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); if (hal_ret != DIM_NO_ERROR) { pr_err("dim_startup failed: %d\n", hal_ret); if (pdata && pdata->destroy) @@ -254,6 +249,11 @@ static int try_start_dim_transfer(struct hdm_channel *hdm_ch) mbo = list_first_entry(head, struct mbo, list); buf_size = mbo->buffer_length; + if (dim_dbr_space(&hdm_ch->ch) < buf_size) { + spin_unlock_irqrestore(&dim_lock, flags); + return -EAGAIN; + } + BUG_ON(mbo->bus_address == 0); if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) { list_del(head->next); @@ -411,6 +411,22 @@ static struct dim_channel **get_active_channels(struct dim2_hdm *dev, return buffer; } +static irqreturn_t dim2_mlb_isr(int irq, void *_dev) +{ + struct dim2_hdm *dev = _dev; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + dim_service_mlb_int_irq(); + spin_unlock_irqrestore(&dim_lock, flags); + + if (dev->atx_idx >= 0 && dev->hch[dev->atx_idx].is_initialized) + while (!try_start_dim_transfer(dev->hch + dev->atx_idx)) + continue; + + return IRQ_HANDLED; +} + /** * dim2_tasklet_fn - tasklet function * @data: private data @@ -452,30 +468,14 @@ static irqreturn_t dim2_ahb_isr(int irq, void *_dev) unsigned long flags; spin_lock_irqsave(&dim_lock, flags); - dim_service_irq(get_active_channels(dev, buffer)); + dim_service_ahb_int_irq(get_active_channels(dev, buffer)); spin_unlock_irqrestore(&dim_lock, flags); -#if !defined(ENABLE_HDM_TEST) dim2_tasklet.data = (unsigned long)dev; tasklet_schedule(&dim2_tasklet); -#else - dim2_tasklet_fn((unsigned long)dev); -#endif return IRQ_HANDLED; } -#if defined(ENABLE_HDM_TEST) - -/* - * Utility function used by HAL-simu for calling DIM interrupt handler. - * It is used only for TEST PURPOSE. - */ -void raise_dim_interrupt(void) -{ - (void)dim2_ahb_isr(0, test_dev); -} -#endif - /** * complete_all_mbos - complete MBO's in a list * @head: list head @@ -545,7 +545,7 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx, hdm_ch->name, buf_size, new_size); spin_lock_irqsave(&dim_lock, flags); hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr, - buf_size); + is_tx ? new_size * 2 : new_size); break; case MOST_CH_ASYNC: new_size = dim_norm_ctrl_async_buffer_size(buf_size); @@ -558,9 +558,10 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx, pr_warn("%s: fixed buffer size (%d -> %d)\n", hdm_ch->name, buf_size, new_size); spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, buf_size); + hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, + is_tx ? new_size * 2 : new_size); break; - case MOST_CH_ISOC_AVP: + case MOST_CH_ISOC: new_size = dim_norm_isoc_buffer_size(buf_size, sub_size); if (new_size == 0) { pr_err("%s: invalid sub-buffer size or too small buffer size\n", @@ -705,12 +706,14 @@ static int poison_channel(struct most_interface *most_iface, int ch_idx) if (!hdm_ch->is_initialized) return -EPERM; + tasklet_disable(&dim2_tasklet); spin_lock_irqsave(&dim_lock, flags); hal_ret = dim_destroy_channel(&hdm_ch->ch); hdm_ch->is_initialized = false; if (ch_idx == dev->atx_idx) dev->atx_idx = -1; spin_unlock_irqrestore(&dim_lock, flags); + tasklet_enable(&dim2_tasklet); if (hal_ret != DIM_NO_ERROR) { pr_err("HAL Failed to close channel %s\n", hdm_ch->name); ret = -EFAULT; @@ -735,6 +738,7 @@ static int dim2_probe(struct platform_device *pdev) struct resource *res; int ret, i; struct kobject *kobj; + int irq; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) @@ -743,29 +747,37 @@ static int dim2_probe(struct platform_device *pdev) dev->atx_idx = -1; platform_set_drvdata(pdev, dev); -#if defined(ENABLE_HDM_TEST) - test_dev = dev; -#else res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->io_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dev->io_base)) return PTR_ERR(dev->io_base); - ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get ahb0_int irq\n"); return -ENODEV; } - dev->irq_ahb0 = ret; - ret = devm_request_irq(&pdev->dev, dev->irq_ahb0, dim2_ahb_isr, 0, - "mlb_ahb0", dev); + ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0, + "dim2_ahb0_int", dev); if (ret) { - dev_err(&pdev->dev, "failed to request IRQ: %d, err: %d\n", - dev->irq_ahb0, ret); + dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq); return ret; } -#endif + + irq = platform_get_irq(pdev, 1); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get mlb_int irq\n"); + return -ENODEV; + } + + ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0, + "dim2_mlb_int", dev); + if (ret) { + dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq); + return ret; + } + init_waitqueue_head(&dev->netinfo_waitq); dev->deliver_netinfo = 0; dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev, @@ -785,7 +797,7 @@ static int dim2_probe(struct platform_device *pdev) cap->name_suffix = hdm_ch->name; cap->direction = MOST_CH_RX | MOST_CH_TX; cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | - MOST_CH_ISOC_AVP | MOST_CH_SYNC; + MOST_CH_ISOC | MOST_CH_SYNC; cap->num_buffers_packet = MAX_BUFFERS_PACKET; cap->buffer_size_packet = MAX_BUF_SIZE_PACKET; cap->num_buffers_streaming = MAX_BUFFERS_STREAMING; diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h index e0837b6b9ae1..01fe499411ff 100644 --- a/drivers/staging/most/hdm-dim2/dim2_reg.h +++ b/drivers/staging/most/hdm-dim2/dim2_reg.h @@ -77,13 +77,7 @@ enum { MLBC0_FCNT_SHIFT = 15, MLBC0_FCNT_MASK = 7, - MLBC0_FCNT_VAL_1FPSB = 0, - MLBC0_FCNT_VAL_2FPSB = 1, - MLBC0_FCNT_VAL_4FPSB = 2, - MLBC0_FCNT_VAL_8FPSB = 3, - MLBC0_FCNT_VAL_16FPSB = 4, - MLBC0_FCNT_VAL_32FPSB = 5, - MLBC0_FCNT_VAL_64FPSB = 6, + MLBC0_FCNT_MAX_VAL = 6, MLBC0_MLBEN_BIT = 0, @@ -123,6 +117,9 @@ enum { }; enum { + CDT0_RPC_SHIFT = 16 + 11, + CDT0_RPC_MASK = DIM2_MASK(5), + CDT1_BS_ISOC_SHIFT = 0, CDT1_BS_ISOC_MASK = DIM2_MASK(9), diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c index 2b28e4a51131..d8b22f91d2c3 100644 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.c +++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.c @@ -39,7 +39,7 @@ static struct attribute *bus_default_attrs[] = { NULL, }; -static struct attribute_group bus_attr_group = { +static const struct attribute_group bus_attr_group = { .attrs = bus_default_attrs, }; diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index aeae071f2823..26c9adb29308 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -43,8 +43,9 @@ #define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */ #define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */ -#define USB_DEV_ID_INIC 0xCF18 /* PID: USB INIC */ -#define HW_RESYNC 0x0000 +#define USB_DEV_ID_OS81118 0xCF18 /* PID: USB OS81118 */ +#define USB_DEV_ID_OS81119 0xCF19 /* PID: USB OS81119 */ +#define USB_DEV_ID_OS81210 0xCF30 /* PID: USB OS81210 */ /* DRCI Addresses */ #define DRCI_REG_NI_STATE 0x0100 #define DRCI_REG_PACKET_BW 0x0101 @@ -63,34 +64,31 @@ #define DRCI_READ_REQ 0xA0 #define DRCI_WRITE_REQ 0xA1 -/** - * struct buf_anchor - used to create a list of pending URBs - * @urb: pointer to USB request block - * @clear_work_obj: - * @list: linked list - * @urb_completion: - */ -struct buf_anchor { - struct urb *urb; - struct work_struct clear_work_obj; - struct list_head list; - struct completion urb_compl; -}; - -#define to_buf_anchor(w) container_of(w, struct buf_anchor, clear_work_obj) - /** * struct most_dci_obj - Direct Communication Interface * @kobj:position in sysfs * @usb_device: pointer to the usb device + * @reg_addr: register address for arbitrary DCI access */ struct most_dci_obj { struct kobject kobj; struct usb_device *usb_device; + u16 reg_addr; }; #define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) +struct most_dev; + +struct clear_hold_work { + struct work_struct ws; + struct most_dev *mdev; + unsigned int channel; + int pipe; +}; + +#define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws) + /** * struct most_dev - holds all usb interface specific stuff * @parent: parent object in sysfs @@ -104,10 +102,10 @@ struct most_dci_obj { * @link_stat: link status of hardware * @description: device description * @suffix: suffix for channel name - * @anchor_list_lock: locks list access + * @channel_lock: synchronize channel access * @padding_active: indicates channel uses padding * @is_channel_healthy: health status table of each channel - * @anchor_list: list of anchored items + * @busy_urbs: list of anchored items * @io_mutex: synchronize I/O with disconnect * @link_stat_timer: timer for link status reports * @poll_work_obj: work for polling link status @@ -124,10 +122,11 @@ struct most_dev { u16 link_stat; char description[MAX_STRING_LEN]; char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN]; - spinlock_t anchor_list_lock[MAX_NUM_ENDPOINTS]; + spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */ bool padding_active[MAX_NUM_ENDPOINTS]; bool is_channel_healthy[MAX_NUM_ENDPOINTS]; - struct list_head *anchor_list; + struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS]; + struct usb_anchor *busy_urbs; struct mutex io_mutex; struct timer_list link_stat_timer; struct work_struct poll_work_obj; @@ -191,40 +190,24 @@ static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) * free_anchored_buffers - free device's anchored items * @mdev: the device * @channel: channel ID + * @status: status of MBO termination */ -static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel) +static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, + enum mbo_status_flags status) { struct mbo *mbo; - struct buf_anchor *anchor, *tmp; - unsigned long flags; + struct urb *urb; - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], - list) { - struct urb *urb = anchor->urb; - - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - if (likely(urb)) { - mbo = urb->context; - if (!irqs_disabled()) { - usb_kill_urb(urb); - } else { - usb_unlink_urb(urb); - wait_for_completion(&anchor->urb_compl); - } - if ((mbo) && (mbo->complete)) { - mbo->status = MBO_E_CLOSE; - mbo->processed_length = 0; - mbo->complete(mbo); - } - usb_free_urb(urb); + while ((urb = usb_get_from_anchor(&mdev->busy_urbs[channel]))) { + mbo = urb->context; + usb_kill_urb(urb); + if (mbo && mbo->complete) { + mbo->status = status; + mbo->processed_length = 0; + mbo->complete(mbo); } - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_del(&anchor->list); - cancel_work_sync(&anchor->clear_work_obj); - kfree(anchor); + usb_free_urb(urb); } - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); } /** @@ -241,7 +224,7 @@ static unsigned int get_stream_frame_size(struct most_channel_config *cfg) return frame_size; } switch (cfg->data_type) { - case MOST_CH_ISOC_AVP: + case MOST_CH_ISOC: frame_size = AV_PACKETS_PER_XACT * sub_size; break; case MOST_CH_SYNC: @@ -274,22 +257,28 @@ static unsigned int get_stream_frame_size(struct most_channel_config *cfg) */ static int hdm_poison_channel(struct most_interface *iface, int channel) { - struct most_dev *mdev; + struct most_dev *mdev = to_mdev(iface); + unsigned long flags; + spinlock_t *lock; /* temp. lock */ - mdev = to_mdev(iface); if (unlikely(!iface)) { dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n"); return -EIO; } - if (unlikely((channel < 0) || (channel >= iface->num_channels))) { + if (unlikely(channel < 0 || channel >= iface->num_channels)) { dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n"); return -ECHRNG; } + lock = mdev->channel_lock + channel; + spin_lock_irqsave(lock, flags); mdev->is_channel_healthy[channel] = false; + spin_unlock_irqrestore(lock, flags); + + cancel_work_sync(&mdev->clear_work[channel].ws); mutex_lock(&mdev->io_mutex); - free_anchored_buffers(mdev, channel); + free_anchored_buffers(mdev, channel, MBO_E_CLOSE); if (mdev->padding_active[channel]) mdev->padding_active[channel] = false; @@ -313,10 +302,10 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo) { struct most_channel_config *conf = &mdev->conf[channel]; - unsigned int j, num_frames, frame_size; + unsigned int frame_size = get_stream_frame_size(conf); + unsigned int j, num_frames; u16 rd_addr, wr_addr; - frame_size = get_stream_frame_size(conf); if (!frame_size) return -EIO; num_frames = mbo->buffer_length / frame_size; @@ -350,10 +339,10 @@ static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo) static int hdm_remove_padding(struct most_dev *mdev, int channel, struct mbo *mbo) { - unsigned int j, num_frames, frame_size; struct most_channel_config *const conf = &mdev->conf[channel]; + unsigned int frame_size = get_stream_frame_size(conf); + unsigned int j, num_frames; - frame_size = get_stream_frame_size(conf); if (!frame_size) return -EIO; num_frames = mbo->processed_length / USB_MTU; @@ -380,37 +369,29 @@ static int hdm_remove_padding(struct most_dev *mdev, int channel, */ static void hdm_write_completion(struct urb *urb) { - struct mbo *mbo; - struct buf_anchor *anchor; - struct most_dev *mdev; - struct device *dev; - unsigned int channel; + struct mbo *mbo = urb->context; + struct most_dev *mdev = to_mdev(mbo->ifp); + unsigned int channel = mbo->hdm_channel_id; + struct device *dev = &mdev->usb_device->dev; + spinlock_t *lock = mdev->channel_lock + channel; unsigned long flags; - mbo = urb->context; - anchor = mbo->priv; - mdev = to_mdev(mbo->ifp); - channel = mbo->hdm_channel_id; - dev = &mdev->usb_device->dev; - - if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || - (!mdev->is_channel_healthy[channel])) { - complete(&anchor->urb_compl); + spin_lock_irqsave(lock, flags); + if (urb->status == -ENOENT || urb->status == -ECONNRESET || + !mdev->is_channel_healthy[channel]) { + spin_unlock_irqrestore(lock, flags); return; } - if (unlikely(urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN))) { + if (unlikely(urb->status && urb->status != -ESHUTDOWN)) { mbo->processed_length = 0; switch (urb->status) { case -EPIPE: dev_warn(dev, "Broken OUT pipe detected\n"); - most_stop_enqueue(&mdev->iface, channel); - mbo->status = MBO_E_INVAL; - usb_unlink_urb(urb); - INIT_WORK(&anchor->clear_work_obj, wq_clear_halt); - schedule_work(&anchor->clear_work_obj); + mdev->is_channel_healthy[channel] = false; + spin_unlock_irqrestore(lock, flags); + mdev->clear_work[channel].pipe = urb->pipe; + schedule_work(&mdev->clear_work[channel].ws); return; case -ENODEV: case -EPROTO: @@ -425,10 +406,7 @@ static void hdm_write_completion(struct urb *urb) mbo->processed_length = urb->actual_length; } - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_del(&anchor->list); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - kfree(anchor); + spin_unlock_irqrestore(lock, flags); if (likely(mbo->complete)) mbo->complete(mbo); @@ -545,36 +523,29 @@ static void hdm_write_completion(struct urb *urb) */ static void hdm_read_completion(struct urb *urb) { - struct mbo *mbo; - struct buf_anchor *anchor; - struct most_dev *mdev; - struct device *dev; + struct mbo *mbo = urb->context; + struct most_dev *mdev = to_mdev(mbo->ifp); + unsigned int channel = mbo->hdm_channel_id; + struct device *dev = &mdev->usb_device->dev; + spinlock_t *lock = mdev->channel_lock + channel; unsigned long flags; - unsigned int channel; - mbo = urb->context; - anchor = mbo->priv; - mdev = to_mdev(mbo->ifp); - channel = mbo->hdm_channel_id; - dev = &mdev->usb_device->dev; - - if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || - (!mdev->is_channel_healthy[channel])) { - complete(&anchor->urb_compl); + spin_lock_irqsave(lock, flags); + if (urb->status == -ENOENT || urb->status == -ECONNRESET || + !mdev->is_channel_healthy[channel]) { + spin_unlock_irqrestore(lock, flags); return; } - if (unlikely(urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN))) { + if (unlikely(urb->status && urb->status != -ESHUTDOWN)) { mbo->processed_length = 0; switch (urb->status) { case -EPIPE: dev_warn(dev, "Broken IN pipe detected\n"); - mbo->status = MBO_E_INVAL; - usb_unlink_urb(urb); - INIT_WORK(&anchor->clear_work_obj, wq_clear_halt); - schedule_work(&anchor->clear_work_obj); + mdev->is_channel_healthy[channel] = false; + spin_unlock_irqrestore(lock, flags); + mdev->clear_work[channel].pipe = urb->pipe; + schedule_work(&mdev->clear_work[channel].ws); return; case -ENODEV: case -EPROTO: @@ -588,21 +559,15 @@ static void hdm_read_completion(struct urb *urb) } } else { mbo->processed_length = urb->actual_length; - if (!mdev->padding_active[channel]) { - mbo->status = MBO_SUCCESS; - } else { - if (hdm_remove_padding(mdev, channel, mbo)) { - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - } else { - mbo->status = MBO_SUCCESS; - } + mbo->status = MBO_SUCCESS; + if (mdev->padding_active[channel] && + hdm_remove_padding(mdev, channel, mbo)) { + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; } } - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_del(&anchor->list); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - kfree(anchor); + + spin_unlock_irqrestore(lock, flags); if (likely(mbo->complete)) mbo->complete(mbo); @@ -628,18 +593,16 @@ static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mbo) { struct most_dev *mdev; - struct buf_anchor *anchor; struct most_channel_config *conf; struct device *dev; int retval = 0; struct urb *urb; - unsigned long flags; unsigned long length; void *virt_address; if (unlikely(!iface || !mbo)) return -EIO; - if (unlikely(iface->num_channels <= channel) || (channel < 0)) + if (unlikely(iface->num_channels <= channel || channel < 0)) return -ECHRNG; mdev = to_mdev(iface); @@ -650,32 +613,15 @@ static int hdm_enqueue(struct most_interface *iface, int channel, return -ENODEV; urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC); - if (!urb) { - dev_err(dev, "Failed to allocate URB\n"); + if (!urb) return -ENOMEM; - } - anchor = kzalloc(sizeof(*anchor), GFP_ATOMIC); - if (!anchor) { - retval = -ENOMEM; + if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] && + hdm_add_padding(mdev, channel, mbo)) { + retval = -EIO; goto _error; } - anchor->urb = urb; - init_completion(&anchor->urb_compl); - mbo->priv = anchor; - - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_add_tail(&anchor->list, &mdev->anchor_list[channel]); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - - if ((mdev->padding_active[channel]) && - (conf->direction & MOST_CH_TX)) - if (hdm_add_padding(mdev, channel, mbo)) { - retval = -EIO; - goto _error_1; - } - urb->transfer_dma = mbo->bus_address; virt_address = mbo->virt_address; length = mbo->buffer_length; @@ -688,7 +634,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, length, hdm_write_completion, mbo); - if (conf->data_type != MOST_CH_ISOC_AVP) + if (conf->data_type != MOST_CH_ISOC) urb->transfer_flags |= URB_ZERO_PACKET; } else { usb_fill_bulk_urb(urb, mdev->usb_device, @@ -701,6 +647,8 @@ static int hdm_enqueue(struct most_interface *iface, int channel, } urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + usb_anchor_urb(urb, &mdev->busy_urbs[channel]); + retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { dev_err(dev, "URB submit failed with error %d.\n", retval); @@ -709,10 +657,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, return 0; _error_1: - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_del(&anchor->list); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - kfree(anchor); + usb_unanchor_urb(urb); _error: usb_free_urb(urb); return retval; @@ -731,29 +676,30 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, unsigned int frame_size; unsigned int temp_size; unsigned int tail_space; - struct most_dev *mdev; - struct device *dev; + struct most_dev *mdev = to_mdev(iface); + struct device *dev = &mdev->usb_device->dev; - mdev = to_mdev(iface); mdev->is_channel_healthy[channel] = true; - dev = &mdev->usb_device->dev; + mdev->clear_work[channel].channel = channel; + mdev->clear_work[channel].mdev = mdev; + INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt); if (unlikely(!iface || !conf)) { dev_err(dev, "Bad interface or config pointer.\n"); return -EINVAL; } - if (unlikely((channel < 0) || (channel >= iface->num_channels))) { + if (unlikely(channel < 0 || channel >= iface->num_channels)) { dev_err(dev, "Channel ID out of range.\n"); return -EINVAL; } - if ((!conf->num_buffers) || (!conf->buffer_size)) { + if (!conf->num_buffers || !conf->buffer_size) { dev_err(dev, "Misconfig: buffer size or #buffers zero.\n"); return -EINVAL; } - if (!(conf->data_type == MOST_CH_SYNC) && - !((conf->data_type == MOST_CH_ISOC_AVP) && - (conf->packets_per_xact != 0xFF))) { + if (conf->data_type != MOST_CH_SYNC && + !(conf->data_type == MOST_CH_ISOC && + conf->packets_per_xact != 0xFF)) { mdev->padding_active[channel] = false; goto exit; } @@ -762,7 +708,7 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, temp_size = conf->buffer_size; frame_size = get_stream_frame_size(conf); - if ((frame_size == 0) || (frame_size > USB_MTU)) { + if (frame_size == 0 || frame_size > USB_MTU) { dev_warn(dev, "Misconfig: frame size wrong\n"); return -EINVAL; } @@ -807,17 +753,17 @@ static int hdm_update_netinfo(struct most_dev *mdev) if (!is_valid_ether_addr(mdev->hw_addr)) { if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) { dev_err(dev, "Vendor request \"hw_addr_hi\" failed\n"); - return -1; + return -EFAULT; } if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) { dev_err(dev, "Vendor request \"hw_addr_mid\" failed\n"); - return -1; + return -EFAULT; } if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) { dev_err(dev, "Vendor request \"hw_addr_low\" failed\n"); - return -1; + return -EFAULT; } mutex_lock(&mdev->io_mutex); @@ -832,7 +778,7 @@ static int hdm_update_netinfo(struct most_dev *mdev) if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) { dev_err(dev, "Vendor request \"link status\" failed\n"); - return -1; + return -EFAULT; } mutex_lock(&mdev->io_mutex); @@ -886,25 +832,22 @@ static void link_stat_timer_handler(unsigned long data) */ static void wq_netinfo(struct work_struct *wq_obj) { - struct most_dev *mdev; - int i, prev_link_stat; + struct most_dev *mdev = to_mdev_from_work(wq_obj); + int i, prev_link_stat = mdev->link_stat; u8 prev_hw_addr[6]; - mdev = to_mdev_from_work(wq_obj); - prev_link_stat = mdev->link_stat; - for (i = 0; i < 6; i++) prev_hw_addr[i] = mdev->hw_addr[i]; if (hdm_update_netinfo(mdev) < 0) return; - if ((prev_link_stat != mdev->link_stat) || - (prev_hw_addr[0] != mdev->hw_addr[0]) || - (prev_hw_addr[1] != mdev->hw_addr[1]) || - (prev_hw_addr[2] != mdev->hw_addr[2]) || - (prev_hw_addr[3] != mdev->hw_addr[3]) || - (prev_hw_addr[4] != mdev->hw_addr[4]) || - (prev_hw_addr[5] != mdev->hw_addr[5])) + if (prev_link_stat != mdev->link_stat || + prev_hw_addr[0] != mdev->hw_addr[0] || + prev_hw_addr[1] != mdev->hw_addr[1] || + prev_hw_addr[2] != mdev->hw_addr[2] || + prev_hw_addr[3] != mdev->hw_addr[3] || + prev_hw_addr[4] != mdev->hw_addr[4] || + prev_hw_addr[5] != mdev->hw_addr[5]) most_deliver_netinfo(&mdev->iface, mdev->link_stat, &mdev->hw_addr[0]); } @@ -917,33 +860,20 @@ static void wq_netinfo(struct work_struct *wq_obj) */ static void wq_clear_halt(struct work_struct *wq_obj) { - struct buf_anchor *anchor; - struct most_dev *mdev; - struct mbo *mbo; - struct urb *urb; - unsigned int channel; - unsigned long flags; + struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj); + struct most_dev *mdev = clear_work->mdev; + unsigned int channel = clear_work->channel; + int pipe = clear_work->pipe; - anchor = to_buf_anchor(wq_obj); - urb = anchor->urb; - mbo = urb->context; - mdev = to_mdev(mbo->ifp); - channel = mbo->hdm_channel_id; - - if (usb_clear_halt(urb->dev, urb->pipe)) + mutex_lock(&mdev->io_mutex); + most_stop_enqueue(&mdev->iface, channel); + free_anchored_buffers(mdev, channel, MBO_E_INVAL); + if (usb_clear_halt(mdev->usb_device, pipe)) dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); - usb_free_urb(urb); - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_del(&anchor->list); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - - if (likely(mbo->complete)) - mbo->complete(mbo); - if (mdev->conf[channel].direction & MOST_CH_TX) - most_resume_enqueue(&mdev->iface, channel); - - kfree(anchor); + mdev->is_channel_healthy[channel] = true; + most_resume_enqueue(&mdev->iface, channel); + mutex_unlock(&mdev->io_mutex); } /** @@ -958,7 +888,9 @@ static const struct file_operations hdm_usb_fops = { */ static struct usb_device_id usbid[] = { { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), }, - { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_INIC), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), }, { } /* Terminating entry */ }; @@ -970,6 +902,10 @@ static struct usb_device_id usbid[] = { struct most_dci_attribute most_dci_attr_##_name = \ __ATTR(_name, S_IRUGO | S_IWUSR, show_value, store_value) +#define MOST_DCI_WO_ATTR(_name) \ + struct most_dci_attribute most_dci_attr_##_name = \ + __ATTR(_name, S_IWUSR, NULL, store_value) + /** * struct most_dci_attribute - to access the attributes of a dci object * @attr: attributes of a dci object @@ -1046,45 +982,68 @@ static void most_dci_release(struct kobject *kobj) kfree(dci_obj); } +struct regs { + const char *name; + u16 reg; +}; + +static const struct regs ro_regs[] = { + { "ni_state", DRCI_REG_NI_STATE }, + { "packet_bandwidth", DRCI_REG_PACKET_BW }, + { "node_address", DRCI_REG_NODE_ADDR }, + { "node_position", DRCI_REG_NODE_POS }, +}; + +static const struct regs rw_regs[] = { + { "mep_filter", DRCI_REG_MEP_FILTER }, + { "mep_hash0", DRCI_REG_HASH_TBL0 }, + { "mep_hash1", DRCI_REG_HASH_TBL1 }, + { "mep_hash2", DRCI_REG_HASH_TBL2 }, + { "mep_hash3", DRCI_REG_HASH_TBL3 }, + { "mep_eui48_hi", DRCI_REG_HW_ADDR_HI }, + { "mep_eui48_mi", DRCI_REG_HW_ADDR_MI }, + { "mep_eui48_lo", DRCI_REG_HW_ADDR_LO }, +}; + +static int get_stat_reg_addr(const struct regs *regs, int size, + const char *name, u16 *reg_addr) +{ + int i; + + for (i = 0; i < size; i++) { + if (!strcmp(name, regs[i].name)) { + *reg_addr = regs[i].reg; + return 0; + } + } + return -EFAULT; +} + +#define get_static_reg_addr(regs, name, reg_addr) \ + get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr) + static ssize_t show_value(struct most_dci_obj *dci_obj, struct most_dci_attribute *attr, char *buf) { - u16 tmp_val; + const char *name = attr->attr.name; + u16 val; u16 reg_addr; int err; - if (!strcmp(attr->attr.name, "ni_state")) - reg_addr = DRCI_REG_NI_STATE; - else if (!strcmp(attr->attr.name, "packet_bandwidth")) - reg_addr = DRCI_REG_PACKET_BW; - else if (!strcmp(attr->attr.name, "node_address")) - reg_addr = DRCI_REG_NODE_ADDR; - else if (!strcmp(attr->attr.name, "node_position")) - reg_addr = DRCI_REG_NODE_POS; - else if (!strcmp(attr->attr.name, "mep_filter")) - reg_addr = DRCI_REG_MEP_FILTER; - else if (!strcmp(attr->attr.name, "mep_hash0")) - reg_addr = DRCI_REG_HASH_TBL0; - else if (!strcmp(attr->attr.name, "mep_hash1")) - reg_addr = DRCI_REG_HASH_TBL1; - else if (!strcmp(attr->attr.name, "mep_hash2")) - reg_addr = DRCI_REG_HASH_TBL2; - else if (!strcmp(attr->attr.name, "mep_hash3")) - reg_addr = DRCI_REG_HASH_TBL3; - else if (!strcmp(attr->attr.name, "mep_eui48_hi")) - reg_addr = DRCI_REG_HW_ADDR_HI; - else if (!strcmp(attr->attr.name, "mep_eui48_mi")) - reg_addr = DRCI_REG_HW_ADDR_MI; - else if (!strcmp(attr->attr.name, "mep_eui48_lo")) - reg_addr = DRCI_REG_HW_ADDR_LO; - else - return -EIO; + if (!strcmp(name, "arb_address")) + return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr); - err = drci_rd_reg(dci_obj->usb_device, reg_addr, &tmp_val); + if (!strcmp(name, "arb_value")) + reg_addr = dci_obj->reg_addr; + else if (get_static_reg_addr(ro_regs, name, ®_addr) && + get_static_reg_addr(rw_regs, name, ®_addr)) + return -EFAULT; + + err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val); if (err < 0) return err; - return snprintf(buf, PAGE_SIZE, "%04x\n", tmp_val); + return snprintf(buf, PAGE_SIZE, "%04x\n", val); } static ssize_t store_value(struct most_dci_obj *dci_obj, @@ -1093,31 +1052,28 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, { u16 val; u16 reg_addr; - int err; + const char *name = attr->attr.name; + int err = kstrtou16(buf, 16, &val); - if (!strcmp(attr->attr.name, "mep_filter")) - reg_addr = DRCI_REG_MEP_FILTER; - else if (!strcmp(attr->attr.name, "mep_hash0")) - reg_addr = DRCI_REG_HASH_TBL0; - else if (!strcmp(attr->attr.name, "mep_hash1")) - reg_addr = DRCI_REG_HASH_TBL1; - else if (!strcmp(attr->attr.name, "mep_hash2")) - reg_addr = DRCI_REG_HASH_TBL2; - else if (!strcmp(attr->attr.name, "mep_hash3")) - reg_addr = DRCI_REG_HASH_TBL3; - else if (!strcmp(attr->attr.name, "mep_eui48_hi")) - reg_addr = DRCI_REG_HW_ADDR_HI; - else if (!strcmp(attr->attr.name, "mep_eui48_mi")) - reg_addr = DRCI_REG_HW_ADDR_MI; - else if (!strcmp(attr->attr.name, "mep_eui48_lo")) - reg_addr = DRCI_REG_HW_ADDR_LO; - else - return -EIO; - - err = kstrtou16(buf, 16, &val); if (err) return err; + if (!strcmp(name, "arb_address")) { + dci_obj->reg_addr = val; + return count; + } + + if (!strcmp(name, "arb_value")) { + reg_addr = dci_obj->reg_addr; + } else if (!strcmp(name, "sync_ep")) { + u16 ep = val; + + reg_addr = DRCI_REG_BASE + DRCI_COMMAND + ep * 16; + val = 1; + } else if (get_static_reg_addr(ro_regs, name, ®_addr)) { + return -EFAULT; + } + err = drci_wr_reg(dci_obj->usb_device, reg_addr, val); if (err < 0) return err; @@ -1129,6 +1085,7 @@ static MOST_DCI_RO_ATTR(ni_state); static MOST_DCI_RO_ATTR(packet_bandwidth); static MOST_DCI_RO_ATTR(node_address); static MOST_DCI_RO_ATTR(node_position); +static MOST_DCI_WO_ATTR(sync_ep); static MOST_DCI_ATTR(mep_filter); static MOST_DCI_ATTR(mep_hash0); static MOST_DCI_ATTR(mep_hash1); @@ -1137,6 +1094,8 @@ static MOST_DCI_ATTR(mep_hash3); static MOST_DCI_ATTR(mep_eui48_hi); static MOST_DCI_ATTR(mep_eui48_mi); static MOST_DCI_ATTR(mep_eui48_lo); +static MOST_DCI_ATTR(arb_address); +static MOST_DCI_ATTR(arb_value); /** * most_dci_def_attrs - array of default attribute files of the dci object @@ -1146,6 +1105,7 @@ static struct attribute *most_dci_def_attrs[] = { &most_dci_attr_packet_bandwidth.attr, &most_dci_attr_node_address.attr, &most_dci_attr_node_position.attr, + &most_dci_attr_sync_ep.attr, &most_dci_attr_mep_filter.attr, &most_dci_attr_mep_hash0.attr, &most_dci_attr_mep_hash1.attr, @@ -1154,6 +1114,8 @@ static struct attribute *most_dci_def_attrs[] = { &most_dci_attr_mep_eui48_hi.attr, &most_dci_attr_mep_eui48_mi.attr, &most_dci_attr_mep_eui48_lo.attr, + &most_dci_attr_arb_address.attr, + &most_dci_attr_arb_value.attr, NULL, }; @@ -1176,10 +1138,9 @@ static struct kobj_type most_dci_ktype = { static struct most_dci_obj *create_most_dci_obj(struct kobject *parent) { - struct most_dci_obj *most_dci; + struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); int retval; - most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); if (!most_dci) return NULL; @@ -1216,21 +1177,17 @@ static void destroy_most_dci_obj(struct most_dci_obj *p) static int hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) { + struct usb_host_interface *usb_iface_desc = interface->cur_altsetting; + struct usb_device *usb_dev = interface_to_usbdev(interface); + struct device *dev = &usb_dev->dev; + struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); unsigned int i; unsigned int num_endpoints; struct most_channel_capability *tmp_cap; - struct most_dev *mdev; - struct usb_device *usb_dev; - struct device *dev; - struct usb_host_interface *usb_iface_desc; struct usb_endpoint_descriptor *ep_desc; int ret = 0; int err; - usb_iface_desc = interface->cur_altsetting; - usb_dev = interface_to_usbdev(interface); - dev = &usb_dev->dev; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) goto exit_ENOMEM; @@ -1276,9 +1233,9 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) if (!mdev->ep_address) goto exit_free2; - mdev->anchor_list = - kcalloc(num_endpoints, sizeof(*mdev->anchor_list), GFP_KERNEL); - if (!mdev->anchor_list) + mdev->busy_urbs = + kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL); + if (!mdev->busy_urbs) goto exit_free3; tmp_cap = mdev->cap; @@ -1297,21 +1254,21 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE; tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE; tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | - MOST_CH_ISOC_AVP | MOST_CH_SYNC; + MOST_CH_ISOC | MOST_CH_SYNC; if (usb_endpoint_dir_in(ep_desc)) tmp_cap->direction = MOST_CH_RX; else tmp_cap->direction = MOST_CH_TX; tmp_cap++; - INIT_LIST_HEAD(&mdev->anchor_list[i]); - spin_lock_init(&mdev->anchor_list_lock[i]); + init_usb_anchor(&mdev->busy_urbs[i]); + spin_lock_init(&mdev->channel_lock[i]); err = drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep_desc->bEndpointAddress * 16, 1); if (err < 0) - pr_warn("DCI Sync for EP %02x failed", - ep_desc->bEndpointAddress); + dev_warn(dev, "DCI Sync for EP %02x failed", + ep_desc->bEndpointAddress); } dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n", le16_to_cpu(usb_dev->descriptor.idVendor), @@ -1332,7 +1289,9 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) } mutex_lock(&mdev->io_mutex); - if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_INIC) { + if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || + le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 || + le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) { /* this increments the reference count of the instance * object of the core */ @@ -1351,7 +1310,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) return 0; exit_free4: - kfree(mdev->anchor_list); + kfree(mdev->busy_urbs); exit_free3: kfree(mdev->ep_address); exit_free2: @@ -1379,9 +1338,8 @@ exit_ENOMEM: */ static void hdm_disconnect(struct usb_interface *interface) { - struct most_dev *mdev; + struct most_dev *mdev = usb_get_intfdata(interface); - mdev = usb_get_intfdata(interface); mutex_lock(&mdev->io_mutex); usb_set_intfdata(interface, NULL); mdev->usb_device = NULL; @@ -1393,7 +1351,7 @@ static void hdm_disconnect(struct usb_interface *interface) destroy_most_dci_obj(mdev->dci); most_deregister_interface(&mdev->iface); - kfree(mdev->anchor_list); + kfree(mdev->busy_urbs); kfree(mdev->cap); kfree(mdev->conf); kfree(mdev->ep_address); diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 7c619feb12d3..329109c0024f 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -33,7 +33,7 @@ #define STRING_SIZE 80 static struct class *most_class; -static struct device *class_glue_dir; +static struct device *core_dev; static struct ida mdev_id; static int dummy_num_buffers; @@ -51,6 +51,7 @@ struct most_c_obj { u16 channel_id; bool is_poisoned; struct mutex start_mutex; + struct mutex nq_mutex; /* nq thread synchronization */ int is_starving; struct most_interface *iface; struct most_inst_obj *inst; @@ -82,10 +83,13 @@ struct most_inst_obj { static const struct { int most_ch_data_type; char *name; -} ch_data_type[] = { { MOST_CH_CONTROL, "control\n" }, +} ch_data_type[] = { + { MOST_CH_CONTROL, "control\n" }, { MOST_CH_ASYNC, "async\n" }, { MOST_CH_SYNC, "sync\n" }, - { MOST_CH_ISOC_AVP, "isoc_avp\n"} }; + { MOST_CH_ISOC, "isoc\n"}, + { MOST_CH_ISOC, "isoc_avp\n"}, +}; #define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) @@ -260,11 +264,11 @@ static ssize_t show_available_directions(struct most_c_obj *c, strcpy(buf, ""); if (c->iface->channel_vector[i].direction & MOST_CH_RX) - strcat(buf, "dir_rx "); + strcat(buf, "rx "); if (c->iface->channel_vector[i].direction & MOST_CH_TX) - strcat(buf, "dir_tx "); + strcat(buf, "tx "); strcat(buf, "\n"); - return strlen(buf) + 1; + return strlen(buf); } static ssize_t show_available_datatypes(struct most_c_obj *c, @@ -280,10 +284,10 @@ static ssize_t show_available_datatypes(struct most_c_obj *c, strcat(buf, "async "); if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC) strcat(buf, "sync "); - if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC_AVP) - strcat(buf, "isoc_avp "); + if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC) + strcat(buf, "isoc "); strcat(buf, "\n"); - return strlen(buf) + 1; + return strlen(buf); } static @@ -391,9 +395,9 @@ static ssize_t show_set_direction(struct most_c_obj *c, char *buf) { if (c->cfg.direction & MOST_CH_TX) - return snprintf(buf, PAGE_SIZE, "dir_tx\n"); + return snprintf(buf, PAGE_SIZE, "tx\n"); else if (c->cfg.direction & MOST_CH_RX) - return snprintf(buf, PAGE_SIZE, "dir_rx\n"); + return snprintf(buf, PAGE_SIZE, "rx\n"); return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } @@ -404,8 +408,12 @@ static ssize_t store_set_direction(struct most_c_obj *c, { if (!strcmp(buf, "dir_rx\n")) { c->cfg.direction = MOST_CH_RX; + } else if (!strcmp(buf, "rx\n")) { + c->cfg.direction = MOST_CH_RX; } else if (!strcmp(buf, "dir_tx\n")) { c->cfg.direction = MOST_CH_TX; + } else if (!strcmp(buf, "tx\n")) { + c->cfg.direction = MOST_CH_TX; } else { pr_info("WARN: invalid attribute settings\n"); return -EINVAL; @@ -847,7 +855,23 @@ static ssize_t show_add_link(struct most_aim_obj *aim_obj, struct most_aim_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->add_link); + struct most_c_obj *c; + struct most_inst_obj *i; + int offs = 0; + + list_for_each_entry(i, &instance_list, list) { + list_for_each_entry(c, &i->channel_list, list) { + if (c->aim0.ptr == aim_obj->driver || + c->aim1.ptr == aim_obj->driver) { + offs += snprintf(buf + offs, PAGE_SIZE - offs, + "%s:%s\n", + kobject_name(&i->kobj), + kobject_name(&c->kobj)); + } + } + } + + return offs; } /** @@ -1131,18 +1155,18 @@ static inline void trash_mbo(struct mbo *mbo) spin_unlock_irqrestore(&c->fifo_lock, flags); } -static struct mbo *get_hdm_mbo(struct most_c_obj *c) +static bool hdm_mbo_ready(struct most_c_obj *c) { - unsigned long flags; - struct mbo *mbo; + bool empty; - spin_lock_irqsave(&c->fifo_lock, flags); - if (c->enqueue_halt || list_empty(&c->halt_fifo)) - mbo = NULL; - else - mbo = list_pop_mbo(&c->halt_fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); - return mbo; + if (c->enqueue_halt) + return false; + + spin_lock_irq(&c->fifo_lock); + empty = list_empty(&c->halt_fifo); + spin_unlock_irq(&c->fifo_lock); + + return !empty; } static void nq_hdm_mbo(struct mbo *mbo) @@ -1160,20 +1184,32 @@ static int hdm_enqueue_thread(void *data) { struct most_c_obj *c = data; struct mbo *mbo; + int ret; typeof(c->iface->enqueue) enqueue = c->iface->enqueue; while (likely(!kthread_should_stop())) { wait_event_interruptible(c->hdm_fifo_wq, - (mbo = get_hdm_mbo(c)) || + hdm_mbo_ready(c) || kthread_should_stop()); - if (unlikely(!mbo)) + mutex_lock(&c->nq_mutex); + spin_lock_irq(&c->fifo_lock); + if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) { + spin_unlock_irq(&c->fifo_lock); + mutex_unlock(&c->nq_mutex); continue; + } + + mbo = list_pop_mbo(&c->halt_fifo); + spin_unlock_irq(&c->fifo_lock); if (c->cfg.direction == MOST_CH_RX) mbo->buffer_length = c->cfg.buffer_size; - if (unlikely(enqueue(mbo->ifp, mbo->hdm_channel_id, mbo))) { + ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo); + mutex_unlock(&c->nq_mutex); + + if (unlikely(ret)) { pr_err("hdm enqueue failed\n"); nq_hdm_mbo(mbo); c->hdm_enqueue_task = NULL; @@ -1294,17 +1330,14 @@ _exit: /** * most_submit_mbo - submits an MBO to fifo * @mbo: pointer to the MBO - * */ -int most_submit_mbo(struct mbo *mbo) +void most_submit_mbo(struct mbo *mbo) { - if (unlikely((!mbo) || (!mbo->context))) { - pr_err("Bad MBO or missing channel reference\n"); - return -EINVAL; - } + if (WARN_ONCE(!mbo || !mbo->context, + "bad mbo or missing channel reference\n")) + return; nq_hdm_mbo(mbo); - return 0; } EXPORT_SYMBOL_GPL(most_submit_mbo); @@ -1468,10 +1501,8 @@ static void most_read_completion(struct mbo *mbo) return; } - if (atomic_sub_and_test(1, &c->mbo_nq_level)) { - pr_info("WARN: rx device out of buffers\n"); + if (atomic_sub_and_test(1, &c->mbo_nq_level)) c->is_starving = 1; - } if (c->aim0.refs && c->aim0.ptr->rx_completion && c->aim0.ptr->rx_completion(mbo) == 0) @@ -1761,6 +1792,7 @@ struct kobject *most_register_interface(struct most_interface *iface) init_completion(&c->cleanup); atomic_set(&c->mbo_ref, 0); mutex_init(&c->start_mutex); + mutex_init(&c->nq_mutex); list_add_tail(&c->list, &inst->channel_list); } pr_info("registered new MOST device mdev%d (%s)\n", @@ -1826,8 +1858,12 @@ void most_stop_enqueue(struct most_interface *iface, int id) { struct most_c_obj *c = get_channel_by_iface(iface, id); - if (likely(c)) - c->enqueue_halt = true; + if (!c) + return; + + mutex_lock(&c->nq_mutex); + c->enqueue_halt = true; + mutex_unlock(&c->nq_mutex); } EXPORT_SYMBOL_GPL(most_stop_enqueue); @@ -1843,9 +1879,12 @@ void most_resume_enqueue(struct most_interface *iface, int id) { struct most_c_obj *c = get_channel_by_iface(iface, id); - if (unlikely(!c)) + if (!c) return; + + mutex_lock(&c->nq_mutex); c->enqueue_halt = false; + mutex_unlock(&c->nq_mutex); wake_up_interruptible(&c->hdm_fifo_wq); } @@ -1879,22 +1918,19 @@ static int __init most_init(void) goto exit_class; } - class_glue_dir = - device_create(most_class, NULL, 0, NULL, "mostcore"); - if (IS_ERR(class_glue_dir)) { - err = PTR_ERR(class_glue_dir); + core_dev = device_create(most_class, NULL, 0, NULL, "mostcore"); + if (IS_ERR(core_dev)) { + err = PTR_ERR(core_dev); goto exit_driver; } - most_aim_kset = - kset_create_and_add("aims", NULL, &class_glue_dir->kobj); + most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj); if (!most_aim_kset) { err = -ENOMEM; goto exit_class_container; } - most_inst_kset = - kset_create_and_add("devices", NULL, &class_glue_dir->kobj); + most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj); if (!most_inst_kset) { err = -ENOMEM; goto exit_driver_kset; diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h index 60e018e499ef..5f8339bd046f 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/mostcore/mostcore.h @@ -56,7 +56,7 @@ enum most_channel_direction { enum most_channel_data_type { MOST_CH_CONTROL = 1 << 0, MOST_CH_ASYNC = 1 << 1, - MOST_CH_ISOC_AVP = 1 << 2, + MOST_CH_ISOC = 1 << 2, MOST_CH_SYNC = 1 << 5, }; @@ -112,7 +112,7 @@ struct most_channel_capability { u16 buffer_size_packet; u16 num_buffers_streaming; u16 buffer_size_streaming; - char *name_suffix; + const char *name_suffix; }; /** @@ -287,7 +287,7 @@ struct kobject *most_register_interface(struct most_interface *iface); * @intf_instance Pointer to the interface instance description. */ void most_deregister_interface(struct most_interface *iface); -int most_submit_mbo(struct mbo *mbo); +void most_submit_mbo(struct mbo *mbo); /** * most_stop_enqueue - prevents core from enqueing MBOs diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 99445d0fcf9c..552a7dcbf50b 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -192,7 +192,7 @@ static int xlr_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) return phy_ethtool_sset(phydev, ecmd); } -static struct ethtool_ops xlr_ethtool_ops = { +static const struct ethtool_ops xlr_ethtool_ops = { .get_settings = xlr_get_settings, .set_settings = xlr_set_settings, }; @@ -269,16 +269,6 @@ static void xlr_make_tx_desc(struct nlm_fmn_msg *msg, unsigned long addr, msg->msg3 = 0; } -static void __maybe_unused xlr_wakeup_queue(unsigned long dev) -{ - struct net_device *ndev = (struct net_device *)dev; - struct xlr_net_priv *priv = netdev_priv(ndev); - struct phy_device *phydev = xlr_get_phydev(priv); - - if (phydev->link) - netif_tx_wake_queue(netdev_get_tx_queue(ndev, priv->wakeup_q)); -} - static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) { @@ -413,7 +403,7 @@ static struct rtnl_link_stats64 *xlr_get_stats64(struct net_device *ndev, return stats; } -static struct net_device_ops xlr_netdev_ops = { +static const struct net_device_ops xlr_netdev_ops = { .ndo_open = xlr_net_open, .ndo_stop = xlr_net_stop, .ndo_start_xmit = xlr_net_start_xmit, diff --git a/drivers/staging/octeon-usb/Kconfig b/drivers/staging/octeon-usb/Kconfig index 16ea17ff3fd2..0b8f1d9c7056 100644 --- a/drivers/staging/octeon-usb/Kconfig +++ b/drivers/staging/octeon-usb/Kconfig @@ -6,5 +6,5 @@ config OCTEON_USB Networks' products in the Octeon family. To compile this driver as a module, choose M here. The module - will be called octeon-usb. + will be called octeon-hcd. diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 17442b3ed849..9a7858a300fd 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -3292,7 +3292,6 @@ static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf) spin_lock_irqsave(&usb->lock, flags); port_status = cvmx_usb_get_status(usb); spin_unlock_irqrestore(&usb->lock, flags); - buf[0] = 0; buf[0] = port_status.connect_change << 1; return buf[0] != 0; diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 1fde9c824948..691e4a51ace4 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -168,6 +168,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev) phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, PHY_INTERFACE_MODE_GMII); + of_node_put(phy_node); if (!phydev) return -ENODEV; diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 48846dffc8e1..4e7304210bb9 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -117,7 +117,10 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) cvmx_helper_link_info_t link_info; bool status_change; - link_info = cvmx_helper_link_autoconf(priv->port); + link_info = cvmx_helper_link_get(priv->port); + if (priv->link_info != link_info.u64 && + cvmx_helper_link_set(priv->port, link_info)) + link_info.u64 = priv->link_info; status_change = priv->link_info != link_info.u64; priv->link_info = link_info.u64; diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index a10fe3af9a9c..f0900d1c4d7b 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -43,21 +43,27 @@ #include -static struct napi_struct cvm_oct_napi; +static atomic_t oct_rx_ready = ATOMIC_INIT(0); + +static struct oct_rx_group { + int irq; + int group; + struct napi_struct napi; +} oct_rx_group[16]; /** * cvm_oct_do_interrupt - interrupt handler. - * @cpl: Interrupt number. Unused - * @dev_id: Cookie to identify the device. Unused + * @irq: Interrupt number. + * @napi_id: Cookie to identify the NAPI instance. * * The interrupt occurs whenever the POW has packets in our group. * */ -static irqreturn_t cvm_oct_do_interrupt(int cpl, void *dev_id) +static irqreturn_t cvm_oct_do_interrupt(int irq, void *napi_id) { /* Disable the IRQ and start napi_poll. */ - disable_irq_nosync(OCTEON_IRQ_WORKQ0 + pow_receive_group); - napi_schedule(&cvm_oct_napi); + disable_irq_nosync(irq); + napi_schedule(napi_id); return IRQ_HANDLED; } @@ -143,14 +149,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) return 0; } -/** - * cvm_oct_napi_poll - the NAPI poll function. - * @napi: The NAPI instance, or null if called from cvm_oct_poll_controller - * @budget: Maximum number of packets to receive. - * - * Returns the number of packets processed. - */ -static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) +static int cvm_oct_poll(struct oct_rx_group *rx_group, int budget) { const int coreid = cvmx_get_core_num(); u64 old_group_mask; @@ -172,13 +171,13 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { old_group_mask = cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid), - 1ull << pow_receive_group); + BIT(rx_group->group)); cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */ } else { old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid)); cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), (old_group_mask & ~0xFFFFull) | - 1 << pow_receive_group); + BIT(rx_group->group)); } if (USE_ASYNC_IOBDMA) { @@ -203,15 +202,15 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) if (!work) { if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { cvmx_write_csr(CVMX_SSO_WQ_IQ_DIS, - 1ull << pow_receive_group); + BIT(rx_group->group)); cvmx_write_csr(CVMX_SSO_WQ_INT, - 1ull << pow_receive_group); + BIT(rx_group->group)); } else { union cvmx_pow_wq_int wq_int; wq_int.u64 = 0; - wq_int.s.iq_dis = 1 << pow_receive_group; - wq_int.s.wq_int = 1 << pow_receive_group; + wq_int.s.iq_dis = BIT(rx_group->group); + wq_int.s.wq_int = BIT(rx_group->group); cvmx_write_csr(CVMX_POW_WQ_INT, wq_int.u64); } break; @@ -410,10 +409,28 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) } cvm_oct_rx_refill_pool(0); - if (rx_count < budget && napi) { + return rx_count; +} + +/** + * cvm_oct_napi_poll - the NAPI poll function. + * @napi: The NAPI instance. + * @budget: Maximum number of packets to receive. + * + * Returns the number of packets processed. + */ +static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) +{ + struct oct_rx_group *rx_group = container_of(napi, struct oct_rx_group, + napi); + int rx_count; + + rx_count = cvm_oct_poll(rx_group, budget); + + if (rx_count < budget) { /* No more work */ napi_complete(napi); - enable_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group); + enable_irq(rx_group->irq); } return rx_count; } @@ -427,7 +444,17 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) */ void cvm_oct_poll_controller(struct net_device *dev) { - cvm_oct_napi_poll(NULL, 16); + int i; + + if (!atomic_read(&oct_rx_ready)) + return; + + for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { + if (!(pow_receive_groups & BIT(i))) + continue; + + cvm_oct_poll(&oct_rx_group[i], 16); + } } #endif @@ -446,54 +473,80 @@ void cvm_oct_rx_initialize(void) if (!dev_for_napi) panic("No net_devices were allocated."); - netif_napi_add(dev_for_napi, &cvm_oct_napi, cvm_oct_napi_poll, - rx_napi_weight); - napi_enable(&cvm_oct_napi); + for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { + int ret; - /* Register an IRQ handler to receive POW interrupts */ - i = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, - cvm_oct_do_interrupt, 0, "Ethernet", cvm_oct_device); + if (!(pow_receive_groups & BIT(i))) + continue; - if (i) - panic("Could not acquire Ethernet IRQ %d\n", - OCTEON_IRQ_WORKQ0 + pow_receive_group); + netif_napi_add(dev_for_napi, &oct_rx_group[i].napi, + cvm_oct_napi_poll, rx_napi_weight); + napi_enable(&oct_rx_group[i].napi); - disable_irq_nosync(OCTEON_IRQ_WORKQ0 + pow_receive_group); + oct_rx_group[i].irq = OCTEON_IRQ_WORKQ0 + i; + oct_rx_group[i].group = i; - /* Enable POW interrupt when our port has at least one packet */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { - union cvmx_sso_wq_int_thrx int_thr; - union cvmx_pow_wq_int_pc int_pc; + /* Register an IRQ handler to receive POW interrupts */ + ret = request_irq(oct_rx_group[i].irq, cvm_oct_do_interrupt, 0, + "Ethernet", &oct_rx_group[i].napi); + if (ret) + panic("Could not acquire Ethernet IRQ %d\n", + oct_rx_group[i].irq); - int_thr.u64 = 0; - int_thr.s.tc_en = 1; - int_thr.s.tc_thr = 1; - cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), - int_thr.u64); + disable_irq_nosync(oct_rx_group[i].irq); - int_pc.u64 = 0; - int_pc.s.pc_thr = 5; - cvmx_write_csr(CVMX_SSO_WQ_INT_PC, int_pc.u64); - } else { - union cvmx_pow_wq_int_thrx int_thr; - union cvmx_pow_wq_int_pc int_pc; + /* Enable POW interrupt when our port has at least one packet */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { + union cvmx_sso_wq_int_thrx int_thr; + union cvmx_pow_wq_int_pc int_pc; - int_thr.u64 = 0; - int_thr.s.tc_en = 1; - int_thr.s.tc_thr = 1; - cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), - int_thr.u64); + int_thr.u64 = 0; + int_thr.s.tc_en = 1; + int_thr.s.tc_thr = 1; + cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(i), int_thr.u64); - int_pc.u64 = 0; - int_pc.s.pc_thr = 5; - cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64); + int_pc.u64 = 0; + int_pc.s.pc_thr = 5; + cvmx_write_csr(CVMX_SSO_WQ_INT_PC, int_pc.u64); + } else { + union cvmx_pow_wq_int_thrx int_thr; + union cvmx_pow_wq_int_pc int_pc; + + int_thr.u64 = 0; + int_thr.s.tc_en = 1; + int_thr.s.tc_thr = 1; + cvmx_write_csr(CVMX_POW_WQ_INT_THRX(i), int_thr.u64); + + int_pc.u64 = 0; + int_pc.s.pc_thr = 5; + cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64); + } + + /* Schedule NAPI now. This will indirectly enable the + * interrupt. + */ + napi_schedule(&oct_rx_group[i].napi); } - - /* Schedule NAPI now. This will indirectly enable the interrupt. */ - napi_schedule(&cvm_oct_napi); + atomic_inc(&oct_rx_ready); } void cvm_oct_rx_shutdown(void) { - netif_napi_del(&cvm_oct_napi); + int i; + + for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { + if (!(pow_receive_groups & BIT(i))) + continue; + + /* Disable POW interrupt */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(i), 0); + else + cvmx_write_csr(CVMX_POW_WQ_INT_THRX(i), 0); + + /* Free the interrupt handler */ + free_irq(oct_rx_group[i].irq, cvm_oct_device); + + netif_napi_del(&oct_rx_group[i].napi); + } } diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h index 45f024bc5e33..617da8037a4d 100644 --- a/drivers/staging/octeon/ethernet-util.h +++ b/drivers/staging/octeon/ethernet-util.h @@ -32,12 +32,13 @@ static inline void *cvm_oct_get_buffer_ptr(union cvmx_buf_ptr packet_ptr) */ static inline int INTERFACE(int ipd_port) { - int interface = cvmx_helper_get_interface_num(ipd_port); + int interface; + if (ipd_port == CVMX_PIP_NUM_INPUT_PORTS) + return 10; + interface = cvmx_helper_get_interface_num(ipd_port); if (interface >= 0) return interface; - else if (ipd_port == CVMX_PIP_NUM_INPUT_PORTS) - return 10; panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port); } diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 45d576361319..d02e3e31ed29 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include @@ -35,17 +37,19 @@ #include #include #include - +#include #include #include +#define OCTEON_MAX_MTU 65392 + static int num_packet_buffers = 1024; module_param(num_packet_buffers, int, 0444); MODULE_PARM_DESC(num_packet_buffers, "\n" "\tNumber of packet buffers to allocate and store in the\n" "\tFPA. By default, 1024 packet buffers are used.\n"); -int pow_receive_group = 15; +static int pow_receive_group = 15; module_param(pow_receive_group, int, 0444); MODULE_PARM_DESC(pow_receive_group, "\n" "\tPOW group to receive packets from. All ethernet hardware\n" @@ -53,6 +57,15 @@ MODULE_PARM_DESC(pow_receive_group, "\n" "\tgroup. Also any other software can submit packets to this\n" "\tgroup for the kernel to process."); +static int receive_group_order; +module_param(receive_group_order, int, 0444); +MODULE_PARM_DESC(receive_group_order, "\n" + "\tOrder (0..4) of receive groups to take into use. Ethernet hardware\n" + "\twill be configured to send incoming packets to multiple POW\n" + "\tgroups. pow_receive_group parameter is ignored when multiple\n" + "\tgroups are taken into use and groups are allocated starting\n" + "\tfrom 0. By default, a single group is used.\n"); + int pow_send_group = -1; module_param(pow_send_group, int, 0644); MODULE_PARM_DESC(pow_send_group, "\n" @@ -86,6 +99,8 @@ int rx_napi_weight = 32; module_param(rx_napi_weight, int, 0444); MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter."); +/* Mask indicating which receive groups are in use. */ +int pow_receive_groups; /* * cvm_oct_poll_queue_stopping - flag to indicate polling should stop. @@ -237,21 +252,22 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) { struct octeon_ethernet *priv = netdev_priv(dev); int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) - int vlan_bytes = 4; +#if IS_ENABLED(CONFIG_VLAN_8021Q) + int vlan_bytes = VLAN_HLEN; #else int vlan_bytes = 0; #endif + int mtu_overhead = ETH_HLEN + ETH_FCS_LEN + vlan_bytes; /* * Limit the MTU to make sure the ethernet packets are between * 64 bytes and 65535 bytes. */ - if ((new_mtu + 14 + 4 + vlan_bytes < 64) || - (new_mtu + 14 + 4 + vlan_bytes > 65392)) { + if ((new_mtu + mtu_overhead < VLAN_ETH_ZLEN) || + (new_mtu + mtu_overhead > OCTEON_MAX_MTU)) { pr_err("MTU must be between %d and %d.\n", - 64 - 14 - 4 - vlan_bytes, 65392 - 14 - 4 - vlan_bytes); + VLAN_ETH_ZLEN - mtu_overhead, + OCTEON_MAX_MTU - mtu_overhead); return -EINVAL; } dev->mtu = new_mtu; @@ -259,8 +275,9 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { + int index = INDEX(priv->port); /* Add ethernet header and FCS, and VLAN if configured. */ - int max_packet = new_mtu + 14 + 4 + vlan_bytes; + int max_packet = new_mtu + mtu_overhead; if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { @@ -275,7 +292,7 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) union cvmx_pip_frm_len_chkx frm_len_chk; frm_len_chk.u64 = 0; - frm_len_chk.s.minlen = 64; + frm_len_chk.s.minlen = VLAN_ETH_ZLEN; frm_len_chk.s.maxlen = max_packet; cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), frm_len_chk.u64); @@ -300,12 +317,12 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev) union cvmx_gmxx_prtx_cfg gmx_cfg; struct octeon_ethernet *priv = netdev_priv(dev); int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { union cvmx_gmxx_rxx_adr_ctl control; + int index = INDEX(priv->port); control.u64 = 0; control.s.bcst = 1; /* Allow broadcast MAC addresses */ @@ -352,7 +369,6 @@ static int cvm_oct_set_mac_filter(struct net_device *dev) struct octeon_ethernet *priv = netdev_priv(dev); union cvmx_gmxx_prtx_cfg gmx_cfg; int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != @@ -360,6 +376,7 @@ static int cvm_oct_set_mac_filter(struct net_device *dev) int i; u8 *ptr = dev->dev_addr; u64 mac = 0; + int index = INDEX(priv->port); for (i = 0; i < 6; i++) mac = (mac << 8) | (u64)ptr[i]; @@ -477,6 +494,8 @@ int cvm_oct_common_open(struct net_device *dev, gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); gmx_cfg.s.en = 1; + if (octeon_has_feature(OCTEON_FEATURE_PKND)) + gmx_cfg.s.pknd = priv->port; cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); if (octeon_is_simulation()) @@ -508,8 +527,10 @@ void cvm_oct_link_poll(struct net_device *dev) if (link_info.u64 == priv->link_info) return; - link_info = cvmx_helper_link_autoconf(priv->port); - priv->link_info = link_info.u64; + if (cvmx_helper_link_set(priv->port, link_info)) + link_info.u64 = priv->link_info; + else + priv->link_info = link_info.u64; if (link_info.s.link_up) { if (!netif_carrier_ok(dev)) @@ -647,6 +668,16 @@ static struct device_node *cvm_oct_node_for_port(struct device_node *pip, return np; } +static void cvm_set_rgmii_delay(struct device_node *np, int iface, int port) +{ + u32 delay_value; + + if (!of_property_read_u32(np, "rx-delay", &delay_value)) + cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value); + if (!of_property_read_u32(np, "tx-delay", &delay_value)) + cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, iface), delay_value); +} + static int cvm_oct_probe(struct platform_device *pdev) { int num_interfaces; @@ -663,11 +694,18 @@ static int cvm_oct_probe(struct platform_device *pdev) return -EINVAL; } - cvm_oct_configure_common_hw(); cvmx_helper_initialize_packet_io_global(); + if (receive_group_order) { + if (receive_group_order > 4) + receive_group_order = 4; + pow_receive_groups = (1 << (1 << receive_group_order)) - 1; + } else { + pow_receive_groups = BIT(pow_receive_group); + } + /* Change the input group for all ports before input is enabled */ num_interfaces = cvmx_helper_get_number_of_interfaces(); for (interface = 0; interface < num_interfaces; interface++) { @@ -681,7 +719,37 @@ static int cvm_oct_probe(struct platform_device *pdev) pip_prt_tagx.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); - pip_prt_tagx.s.grp = pow_receive_group; + + if (receive_group_order) { + int tag_mask; + + /* We support only 16 groups at the moment, so + * always disable the two additional "hidden" + * tag_mask bits on CN68XX. + */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + pip_prt_tagx.u64 |= 0x3ull << 44; + + tag_mask = ~((1 << receive_group_order) - 1); + pip_prt_tagx.s.grptagbase = 0; + pip_prt_tagx.s.grptagmask = tag_mask; + pip_prt_tagx.s.grptag = 1; + pip_prt_tagx.s.tag_mode = 0; + pip_prt_tagx.s.inc_prt_flag = 1; + pip_prt_tagx.s.ip6_dprt_flag = 1; + pip_prt_tagx.s.ip4_dprt_flag = 1; + pip_prt_tagx.s.ip6_sprt_flag = 1; + pip_prt_tagx.s.ip4_sprt_flag = 1; + pip_prt_tagx.s.ip6_dst_flag = 1; + pip_prt_tagx.s.ip4_dst_flag = 1; + pip_prt_tagx.s.ip6_src_flag = 1; + pip_prt_tagx.s.ip4_src_flag = 1; + pip_prt_tagx.s.grp = 0; + } else { + pip_prt_tagx.s.grptag = 0; + pip_prt_tagx.s.grp = pow_receive_group; + } + cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), pip_prt_tagx.u64); } @@ -703,7 +771,6 @@ static int cvm_oct_probe(struct platform_device *pdev) if ((pow_send_group != -1)) { struct net_device *dev; - pr_info("\tConfiguring device for POW only access\n"); dev = alloc_etherdev(sizeof(struct octeon_ethernet)); if (dev) { /* Initialize the device private structure. */ @@ -806,6 +873,8 @@ static int cvm_oct_probe(struct platform_device *pdev) case CVMX_HELPER_INTERFACE_MODE_GMII: dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; strcpy(dev->name, "eth%d"); + cvm_set_rgmii_delay(priv->of_node, interface, + port_index); break; } @@ -842,17 +911,8 @@ static int cvm_oct_remove(struct platform_device *pdev) { int port; - /* Disable POW interrupt */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) - cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), 0); - else - cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); - cvmx_ipd_disable(); - /* Free the interrupt handler */ - free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device); - atomic_inc_return(&cvm_oct_poll_queue_stopping); cancel_delayed_work_sync(&cvm_oct_rx_refill_work); @@ -876,7 +936,6 @@ static int cvm_oct_remove(struct platform_device *pdev) } } - cvmx_pko_shutdown(); cvmx_ipd_free_ptr(); diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index d533aefe085a..9c6852d61c0d 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -72,7 +72,7 @@ void cvm_oct_link_poll(struct net_device *dev); extern int always_use_pow; extern int pow_send_group; -extern int pow_receive_group; +extern int pow_receive_groups; extern char pow_send_list[]; extern struct net_device *cvm_oct_device[]; extern atomic_t cvm_oct_poll_queue_stopping; diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c index 6a4d379c16a3..1e23ef15b263 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c +++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c @@ -49,7 +49,7 @@ static void dcon_clear_irq(void) static int dcon_was_irq(void) { - u_int8_t tmp; + u8 tmp; /* irq status will appear in PMIO_Rx50[6] on gpio12 */ tmp = inb(VX855_GPI_STATUS_CHG); diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index a5755358cc5d..553e8d50352f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -78,9 +78,9 @@ static void update_BCNTIM(struct adapter *padapter) /* update TIM IE */ p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_); - if (p != NULL && tim_ielen > 0) { + if (p && tim_ielen > 0) { tim_ielen += 2; - premainder_ie = p+tim_ielen; + premainder_ie = p + tim_ielen; tim_ie_offset = (int)(p - pie); remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; @@ -98,7 +98,7 @@ static void update_BCNTIM(struct adapter *padapter) _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)); - if (p != NULL) + if (p) offset += tmp_len+2; /* DS Parameter Set IE, len = 3 */ @@ -183,10 +183,10 @@ void rtw_add_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork, i += (pIE->Length + 2); } - if (p != NULL && ielen > 0) { + if (p && ielen > 0) { ielen += 2; - premainder_ie = p+ielen; + premainder_ie = p + ielen; ie_offset = (int)(p - pie); @@ -195,7 +195,7 @@ void rtw_add_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork, if (bmatch) dst_ie = p; else - dst_ie = p+ielen; + dst_ie = p + ielen; } if (remainder_ielen > 0) { @@ -232,10 +232,10 @@ void rtw_remove_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork, p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_); - if (p != NULL && ielen > 0) { + if (p && ielen > 0) { ielen += 2; - premainder_ie = p+ielen; + premainder_ie = p + ielen; ie_offset = (int)(p - pie); @@ -385,8 +385,8 @@ void expire_timeout_chk(struct adapter *padapter) updated = ap_free_sta(padapter, psta, true, 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) && - padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME/pstapriv->asoc_list_cnt/2)) { + if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) && + padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2)) { DBG_88E("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__, (psta->hwaddr), psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, @@ -470,7 +470,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) /* b/g mode ra_bitmap */ for (i = 0; i < sizeof(psta->bssrateset); i++) { if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f); + tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f); } /* n mode ra_bitmap */ if (psta_ht->ht_option) { @@ -481,8 +481,8 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) limit = 8;/* 1R */ for (i = 0; i < limit; i++) { - if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8)) - tx_ra_bitmap |= BIT(i+12); + if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8)) + tx_ra_bitmap |= BIT(i + 12); } /* max short GI rate */ @@ -507,19 +507,19 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) psta->wireless_mode = sta_band; raid = networktype_to_raid(sta_band); - init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f; + init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f; if (psta->aid < NUM_STA) { u8 arg = 0; - arg = psta->mac_id&0x1f; + arg = psta->mac_id & 0x1f; arg |= BIT(7);/* support entry 2~31 */ if (shortGIrate) arg |= BIT(5); - tx_ra_bitmap |= ((raid<<28)&0xf0000000); + tx_ra_bitmap |= ((raid << 28) & 0xf0000000); DBG_88E("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = 0x%x\n", __func__, psta->mac_id, raid, tx_ra_bitmap, arg); @@ -573,7 +573,7 @@ static void update_bmc_sta(struct adapter *padapter) /* b/g mode ra_bitmap */ for (i = 0; i < supportRateNum; i++) { if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f); + tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f); } if (pcur_network->Configuration.DSConfig > 14) { @@ -587,7 +587,7 @@ static void update_bmc_sta(struct adapter *padapter) } raid = networktype_to_raid(network_type); - init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f; + init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f; /* ap mode */ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true); @@ -597,7 +597,7 @@ static void update_bmc_sta(struct adapter *padapter) arg = psta->mac_id&0x1f; arg |= BIT(7); - tx_ra_bitmap |= ((raid<<28)&0xf0000000); + tx_ra_bitmap |= ((raid << 28) & 0xf0000000); DBG_88E("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg); /* bitmap[0:27] = tx_rate_bitmap */ @@ -636,7 +636,7 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; struct ht_priv *phtpriv_sta = &psta->htpriv; - psta->mac_id = psta->aid+1; + psta->mac_id = psta->aid + 1; DBG_88E("%s\n", __func__); /* ap mode */ @@ -658,11 +658,15 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; /* check if sta support s Short GI */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) + if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info & + phtpriv_ap->ht_cap.cap_info) & + (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) phtpriv_sta->sgi = true; /* bwmode */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) { + if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info & + phtpriv_ap->ht_cap.cap_info) & + IEEE80211_HT_CAP_SUP_WIDTH) { phtpriv_sta->bwmode = pmlmeext->cur_bwmode; phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; } @@ -702,12 +706,12 @@ static void update_hw_ht_param(struct adapter *padapter) /* handle A-MPDU parameter field */ /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing + ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k + ampdu_params_info [4:2]:Min MPDU Start Spacing */ - max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03; + max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03; - min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2; + min_MPDU_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2; rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing)); @@ -716,7 +720,7 @@ static void update_hw_ht_param(struct adapter *padapter) /* */ /* Config SM Power Save setting */ /* */ - pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2; + pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2; if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); } @@ -746,7 +750,7 @@ static 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 */ @@ -799,7 +803,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf) /* set channel, bwmode */ p = rtw_get_ie((pnetwork->IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(struct ndis_802_11_fixed_ie))); if (p && ie_len) { - pht_info = (struct HT_info_element *)(p+2); + pht_info = (struct HT_info_element *)(p + 2); if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) { /* switch to the 40M Hz mode */ @@ -930,15 +934,15 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); /* get supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if (p != NULL) { - memcpy(supportRate, p+2, ie_len); + if (p) { + memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } /* get ext_supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_); - if (p != NULL) { - memcpy(supportRate+supportRateNum, p+2, ie_len); + if (p) { + memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; } @@ -966,7 +970,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { - if (rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ @@ -985,8 +989,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) { p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); - if ((p) && (!memcmp(p+2, OUI1, 4))) { - if (rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, + if ((p) && (!memcmp(p + 2, OUI1, 4))) { + if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; @@ -1010,10 +1014,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) { p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &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 */ @@ -1032,7 +1036,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) (pbss_network->IELength - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { u8 rf_type; - struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2); + struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2); pHT_caps_ie = p; ht_cap = true; @@ -1042,7 +1046,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2)); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2)); else pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); @@ -1050,8 +1054,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); if (rf_type == RF_1T1R) { - pht_cap->supp_mcs_set[0] = 0xff; - pht_cap->supp_mcs_set[1] = 0x0; + pht_cap->mcs.rx_mask[0] = 0xff; + pht_cap->mcs.rx_mask[1] = 0x0; } memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); } @@ -1143,7 +1147,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr)); - if ((NUM_ACL-1) < pacl_list->num) + if ((NUM_ACL - 1) < pacl_list->num) return -1; spin_lock_bh(&(pacl_node_q->lock)); @@ -1422,7 +1426,8 @@ static int rtw_ht_operation_update(struct adapter *padapter) if (pmlmepriv->num_sta_no_ht || (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) new_op_mode = OP_MODE_MIXED; - else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH) && + else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & + IEEE80211_HT_CAP_SUP_WIDTH) && pmlmepriv->num_sta_ht_20mhz) new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; else if (pmlmepriv->olbc_ht) @@ -1552,7 +1557,7 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) } if (psta->flags & WLAN_STA_HT) { - u16 ht_capab = psta->htpriv.ht_cap.cap_info; + u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); DBG_88E("HT: STA %pM HT Capabilities Info: 0x%04x\n", (psta->hwaddr), ht_capab); @@ -1710,40 +1715,6 @@ u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, return beacon_updated; } -int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset) -{ - struct list_head *phead, *plist; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) - return 0; - - DBG_88E(FUNC_NDEV_FMT" with ch:%u, offset:%u\n", - FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset); - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - plist = phead->next; - - /* for each sta in asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - plist = plist->next; - - issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset); - psta->expire_to = min_t(unsigned int, pstapriv->expire_to * 2, 5); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset); - - return 0; -} - int rtw_sta_flush(struct adapter *padapter) { struct list_head *phead, *plist; @@ -1856,9 +1827,6 @@ void start_ap_mode(struct adapter *padapter) pmlmepriv->wps_probe_resp_ie = NULL; pmlmepriv->wps_assoc_resp_ie = NULL; - pmlmepriv->p2p_beacon_ie = NULL; - pmlmepriv->p2p_probe_resp_ie = NULL; - /* for ACL */ INIT_LIST_HEAD(&(pacl_list->acl_node_q.queue)); pacl_list->num = 0; diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 77485235c615..f1f4788dbd86 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -27,8 +27,8 @@ No irqsave is necessary. int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) { - sema_init(&(pcmdpriv->cmd_queue_sema), 0); - sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0); + init_completion(&pcmdpriv->cmd_queue_comp); + init_completion(&pcmdpriv->terminate_cmdthread_comp); _rtw_init_queue(&(pcmdpriv->cmd_queue)); return _SUCCESS; @@ -85,7 +85,7 @@ static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) /* To decide allow or not */ if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) && (!pcmdpriv->padapter->registrypriv.usbss_enable)) { - if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) { + if (cmd_obj->cmdcode == _Set_Drv_Extra_CMD_) { struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf; if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID) @@ -93,7 +93,7 @@ static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) } } - if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) + if (cmd_obj->cmdcode == _SetChannelPlan_CMD_) bAllow = true; if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) || @@ -122,7 +122,7 @@ u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj); if (res == _SUCCESS) - up(&pcmdpriv->cmd_queue_sema); + complete(&pcmdpriv->cmd_queue_comp); exit: @@ -162,12 +162,12 @@ int rtw_cmd_thread(void *context) allow_signal(SIGTERM); pcmdpriv->cmdthd_running = true; - up(&pcmdpriv->terminate_cmdthread_sema); + complete(&pcmdpriv->terminate_cmdthread_comp); RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n")); while (1) { - if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) + if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp)) break; if (padapter->bDriverStopped || @@ -234,7 +234,7 @@ _next: rtw_free_cmd_obj(pcmd); } - up(&pcmdpriv->terminate_cmdthread_sema); + complete(&pcmdpriv->terminate_cmdthread_comp); complete_and_exit(NULL, 0); @@ -271,7 +271,7 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__)); - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); + init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_); /* psurveyPara->bsslimit = 48; */ psurveyPara->scan_mode = pmlmepriv->scan_mode; @@ -305,8 +305,6 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, res = rtw_enqueue_cmd(pcmdpriv, ph2c); if (res == _SUCCESS) { - pmlmepriv->scan_start_time = jiffies; - mod_timer(&pmlmepriv->scan_to_timer, jiffies + msecs_to_jiffies(SCANNING_TIMEOUT)); @@ -491,7 +489,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ INIT_LIST_HEAD(&pcmd->list); - pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ + pcmd->cmdcode = _JoinBss_CMD_; pcmd->parmbuf = (unsigned char *)psecnetwork; pcmd->rsp = NULL; pcmd->rspsz = 0; @@ -670,13 +668,13 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) u8 res = _SUCCESS; - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (!ph2c) { res = _FAIL; goto exit; } - paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_KERNEL); + paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC); if (!paddbareq_parm) { kfree(ph2c); res = _FAIL; @@ -686,7 +684,7 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) paddbareq_parm->tid = tid; memcpy(paddbareq_parm->addr, addr, ETH_ALEN); - init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); + init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, _AddBAReq_CMD_); /* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */ @@ -724,7 +722,7 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) pdrvextra_cmd_parm->type_size = 0; pdrvextra_cmd_parm->pbuf = (u8 *)padapter; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ @@ -767,7 +765,7 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue) goto exit; } - init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan)); + init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, _SetChannelPlan_CMD_); res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); } else { /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ @@ -936,7 +934,7 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) pdrvextra_cmd_parm->type_size = lps_ctrl_type; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); } else { @@ -978,7 +976,7 @@ u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time) pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID; pdrvextra_cmd_parm->type_size = min_time; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); exit: @@ -1020,7 +1018,7 @@ u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue) pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID; pdrvextra_cmd_parm->type_size = antenna; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); } else { @@ -1048,7 +1046,7 @@ u8 rtw_ps_cmd(struct adapter *padapter) pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); return rtw_enqueue_cmd(pcmdpriv, ppscmd); } @@ -1119,7 +1117,7 @@ u8 rtw_chk_hi_queue_cmd(struct adapter *padapter) pdrvextra_cmd_parm->type_size = 0; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); exit: diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c index db5c952ac852..60d8c7b9f458 100644 --- a/drivers/staging/rtl8188eu/core/rtw_debug.c +++ b/drivers/staging/rtl8188eu/core/rtw_debug.c @@ -138,144 +138,6 @@ int proc_set_read_reg(struct file *file, const char __user *buffer, return count; } -int proc_get_fwstate(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - int len = 0; - - len += snprintf(page + len, count - len, "fwstate=0x%x\n", get_fwstate(pmlmepriv)); - - *eof = 1; - return len; -} - -int proc_get_sec_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - int len = 0; - - len += snprintf(page + len, count - len, "auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n", - psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm, - psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus); - - *eof = 1; - return len; -} - -int proc_get_mlmext_state(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - int len = 0; - - len += snprintf(page + len, count - len, "pmlmeinfo->state=0x%x\n", pmlmeinfo->state); - - *eof = 1; - return len; -} - -int proc_get_qos_option(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - int len = 0; - - len += snprintf(page + len, count - len, "qos_option=%d\n", pmlmepriv->qospriv.qos_option); - - *eof = 1; - return len; -} - -int proc_get_ht_option(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - int len = 0; - - len += snprintf(page + len, count - len, "ht_option=%d\n", pmlmepriv->htpriv.ht_option); - *eof = 1; - return len; -} - -int proc_get_rf_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - int len = 0; - - len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offset=%d\n", - pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); - *eof = 1; - return len; -} - -int proc_get_ap_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct sta_info *psta; - struct net_device *dev = data; - 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; - int len = 0; - - psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); - if (psta) { - int i; - struct recv_reorder_ctrl *preorder_ctrl; - - len += snprintf(page + len, count - len, "SSID=%s\n", cur_network->network.Ssid.Ssid); - len += snprintf(page + len, count - len, "sta's macaddr:%pM\n", psta->hwaddr); - len += snprintf(page + len, count - len, "cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); - len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self); - len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); - len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); - len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); - len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); - len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); - - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - if (preorder_ctrl->enable) - len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", i, preorder_ctrl->indicate_seq); - } - } else { - len += snprintf(page + len, count - len, "can't get sta's macaddr, cur_network's macaddr: %pM\n", cur_network->network.MacAddress); - } - - *eof = 1; - return len; -} - int proc_get_adapter_state(char *page, char **start, off_t offset, int count, int *eof, void *data) @@ -291,599 +153,6 @@ int proc_get_adapter_state(char *page, char **start, return len; } -int proc_get_trx_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct recv_priv *precvpriv = &padapter->recvpriv; - int len = 0; - - len += snprintf(page + len, count - len, "free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d, free_ext_xmitbuf_cnt=%d, free_recvframe_cnt=%d\n", - pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt, precvpriv->free_recvframe_cnt); - len += snprintf(page + len, count - len, "rx_urb_pending_cn=%d\n", precvpriv->rx_pending_cnt); - - *eof = 1; - return len; -} - -int proc_get_mac_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= MAC REG =======\n"); - - for (i = 0x0; i < 0x300; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - - *eof = 1; - return len; -} - -int proc_get_mac_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= MAC REG =======\n"); - memset(page, 0, count); - for (i = 0x300; i < 0x600; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - - *eof = 1; - return len; -} - -int proc_get_mac_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= MAC REG =======\n"); - - for (i = 0x600; i < 0x800; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - - *eof = 1; - return len; -} - -int proc_get_bb_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= BB REG =======\n"); - for (i = 0x800; i < 0xB00; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_bb_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= BB REG =======\n"); - for (i = 0xB00; i < 0xE00; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_bb_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= BB REG =======\n"); - for (i = 0xE00; i < 0x1000; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_rf_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1, path; - u32 value; - - len += snprintf(page + len, count - len, "\n======= RF REG =======\n"); - path = 1; - len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path); - for (i = 0; i < 0xC0; i++) { - value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x ", i); - len += snprintf(page + len, count - len, " 0x%08x ", value); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_rf_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1, path; - u32 value; - - len += snprintf(page + len, count - len, "\n======= RF REG =======\n"); - path = 1; - len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path); - for (i = 0xC0; i < 0x100; i++) { - value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x ", i); - len += snprintf(page + len, count - len, " 0x%08x ", value); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_rf_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1, path; - u32 value; - - len += snprintf(page + len, count - len, "\n======= RF REG =======\n"); - path = 2; - len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path); - for (i = 0; i < 0xC0; i++) { - value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x ", i); - len += snprintf(page + len, count - len, " 0x%08x ", value); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - - *eof = 1; - return len; -} - - -int proc_get_rf_reg_dump4(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1, path; - u32 value; - - len += snprintf(page + len, count - len, "\n======= RF REG =======\n"); - path = 2; - len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path); - for (i = 0xC0; i < 0x100; i++) { - value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x ", i); - len += snprintf(page + len, count - len, " 0x%08x ", value); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - - - -int proc_get_rx_signal(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - - len = snprintf(page + len, count, - "rssi:%d\n" - "rxpwdb:%d\n" - "signal_strength:%u\n" - "signal_qual:%u\n" - "noise:%u\n", - padapter->recvpriv.rssi, - padapter->recvpriv.rxpwdb, - padapter->recvpriv.signal_strength, - padapter->recvpriv.signal_qual, - padapter->recvpriv.noise - ); - - *eof = 1; - return len; -} - -int proc_set_rx_signal(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 is_signal_dbg; - s32 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 = clamp(signal_strength, 0, 100); - - padapter->recvpriv.is_signal_dbg = is_signal_dbg; - padapter->recvpriv.signal_strength_dbg = signal_strength; - - if (is_signal_dbg) - DBG_88E("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength); - else - DBG_88E("set %s\n", "HW_SIGNAL_STRENGTH"); - } - return count; -} - -int proc_get_ht_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - int len = 0; - - if (pregpriv) - len += snprintf(page + len, count - len, - "%d\n", - pregpriv->ht_enable - ); - *eof = 1; - return len; -} - -int proc_set_ht_enable(struct file *file, const char __user *buffer, - unsigned long count, 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]; - s32 mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (pregpriv) { - pregpriv->ht_enable = mode; - pr_info("ht_enable=%d\n", pregpriv->ht_enable); - } - } - - return count; -} - -int proc_get_cbw40_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - int len = 0; - - if (pregpriv) - len += snprintf(page + len, count - len, - "%d\n", - pregpriv->cbw40_enable - ); - - *eof = 1; - return len; -} - -int proc_set_cbw40_enable(struct file *file, const char __user *buffer, - unsigned long count, 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]; - s32 mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (pregpriv) { - pregpriv->cbw40_enable = mode; - pr_info("cbw40_enable=%d\n", mode); - } - } - return count; -} - -int proc_get_ampdu_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - int len = 0; - - if (pregpriv) - len += snprintf(page + len, count - len, - "%d\n", - pregpriv->ampdu_enable - ); - - *eof = 1; - return len; -} - -int proc_set_ampdu_enable(struct file *file, const char __user *buffer, - unsigned long count, 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]; - s32 mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (pregpriv) { - pregpriv->ampdu_enable = mode; - pr_info("ampdu_enable=%d\n", mode); - } - } - return count; -} - -int proc_get_two_path_rssi(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - int len = 0; - - if (padapter) - len += snprintf(page + len, count - len, - "%d %d\n", - padapter->recvpriv.RxRssi[0], - padapter->recvpriv.RxRssi[1] - ); - - *eof = 1; - return len; -} - -int proc_get_rx_stbc(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - int len = 0; - - if (pregpriv) - len += snprintf(page + len, count - len, - "%d\n", - pregpriv->rx_stbc - ); - - *eof = 1; - return len; -} - -int proc_set_rx_stbc(struct file *file, const char __user *buffer, - unsigned long count, 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 = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (pregpriv) { - pregpriv->rx_stbc = mode; - netdev_info(dev, "rx_stbc=%d\n", mode); - } - } - return count; -} - -int proc_get_rssi_disp(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - *eof = 1; - return 0; -} - -int proc_set_rssi_disp(struct file *file, const char __user *buffer, - unsigned long count, 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_88E("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_88E("invalid set_rssi_disp parameter!\n"); - return count; - } - - if (enable) { - DBG_88E("Turn On Rx RSSI Display Function\n"); - padapter->bRxRSSIDisplay = enable; - } else { - DBG_88E("Turn Off Rx RSSI Display Function\n"); - padapter->bRxRSSIDisplay = 0; - } - } - return count; -} - -#ifdef CONFIG_88EU_AP_MODE - -int proc_get_all_sta_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct sta_info *psta; - struct net_device *dev = data; - 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; - int len = 0; - - - len += snprintf(page + len, count - len, "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 = phead->next; - - while (phead != plist) { - psta = container_of(plist, struct sta_info, hash_list); - - plist = plist->next; - - len += snprintf(page + len, count - len, "sta's macaddr: %pM\n", psta->hwaddr); - len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self); - len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); - len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); - len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); - len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); - len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); - len += snprintf(page + len, count - len, "sleepq_len=%d\n", psta->sleepq_len); - len += snprintf(page + len, count - len, "capability=0x%x\n", psta->capability); - len += snprintf(page + len, count - len, "flags=0x%x\n", psta->flags); - len += snprintf(page + len, count - len, "wpa_psk=0x%x\n", psta->wpa_psk); - len += snprintf(page + len, count - len, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher); - len += snprintf(page + len, count - len, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher); - len += snprintf(page + len, count - len, "qos_info=0x%x\n", psta->qos_info); - len += snprintf(page + len, count - len, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy); - - for (j = 0; j < 16; j++) { - preorder_ctrl = &psta->recvreorder_ctrl[j]; - if (preorder_ctrl->enable) - len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq); - } - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - - *eof = 1; - return len; -} -#endif - int proc_get_best_channel(char *page, char **start, off_t offset, int count, int *eof, void *data) diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index fbce1f7e68ca..16cc7706a1e6 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -317,69 +317,6 @@ void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _si } } -/* Do not support BT */ -void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut) -{ - switch (type) { - case TYPE_EFUSE_MAX_SECTION: - { - u8 *pMax_section; - pMax_section = pOut; - *pMax_section = EFUSE_MAX_SECTION_88E; - } - break; - case TYPE_EFUSE_REAL_CONTENT_LEN: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; - } - break; - case TYPE_EFUSE_CONTENT_LEN_BANK: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; - } - break; - case TYPE_AVAILABLE_EFUSE_BYTES_BANK: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - case TYPE_EFUSE_MAP_LEN: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = (u16)EFUSE_MAP_LEN_88E; - } - break; - case TYPE_EFUSE_PROTECT_BYTES_BANK: - { - u8 *pu1Tmp; - pu1Tmp = pOut; - *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - default: - { - u8 *pu1Tmp; - pu1Tmp = pOut; - *pu1Tmp = 0; - } - break; - } -} - u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data) { u16 tmpaddr = 0; @@ -483,14 +420,11 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) u8 hoffset = 0, hworden = 0; u8 tmpidx = 0; u8 tmpdata[8]; - u8 max_section = 0; u8 tmp_header = 0; - EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section); - if (!data) return false; - if (offset > max_section) + if (offset > EFUSE_MAX_SECTION_88E) return false; memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); @@ -591,12 +525,12 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) { bool bRet = false; - u16 efuse_addr = *pAddr, efuse_max_available_len = 0; + u16 efuse_addr = *pAddr; + u16 efuse_max_available_len = + EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E; u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0; u8 repeatcnt = 0; - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); - while (efuse_addr < efuse_max_available_len) { pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F; efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); @@ -769,12 +703,11 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u bool bRet = false; u8 i, efuse_data = 0, cur_header = 0; u8 matched_wden = 0, badworden = 0; - u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0; + u16 startAddr = 0; + u16 efuse_max_available_len = + EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E; struct pgpkt curPkt; - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max); - rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr); startAddr %= EFUSE_REAL_CONTENT_LEN; @@ -846,12 +779,7 @@ hal_EfusePgCheckAvailableAddr( u8 efuseType ) { - u16 efuse_max_available_len = 0; - - /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */ - EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len); - - if (Efuse_GetCurrentSize(pAdapter) >= efuse_max_available_len) + if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) return false; return true; } @@ -977,13 +905,9 @@ void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata) */ static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse) { - u16 mapLen = 0; - Efuse_PowerSwitch(pAdapter, false, true); - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse); + efuse_ReadEFuse(pAdapter, efuseType, 0, EFUSE_MAP_LEN_88E, Efuse); Efuse_PowerSwitch(pAdapter, false, false); } @@ -996,12 +920,9 @@ void EFUSE_ShadowMapUpdate( u8 efuseType) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen); if (pEEPROM->bautoload_fail_flag) - memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen); + memset(pEEPROM->efuse_eeprom_data, 0xFF, EFUSE_MAP_LEN_88E); else Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data); } diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 0b0d78fe83ed..914c4923421b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -155,59 +155,6 @@ u8 *rtw_set_ie return pbuf + len + 2; } -inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, - u8 new_ch, u8 ch_switch_cnt) -{ - u8 ie_data[3]; - - ie_data[0] = ch_switch_mode; - ie_data[1] = new_ch; - ie_data[2] = ch_switch_cnt; - return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); -} - -inline u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset) -{ - if (ch_offset == SCN) - return HAL_PRIME_CHNL_OFFSET_DONT_CARE; - else if (ch_offset == SCA) - return HAL_PRIME_CHNL_OFFSET_UPPER; - else if (ch_offset == SCB) - return HAL_PRIME_CHNL_OFFSET_LOWER; - - return HAL_PRIME_CHNL_OFFSET_DONT_CARE; -} - -inline u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset) -{ - if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - return SCN; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - return SCB; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - return SCA; - - return SCN; -} - -inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset) -{ - return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len); -} - -inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, - u8 flags, u16 reason, u16 precedence) -{ - u8 ie_data[6]; - - ie_data[0] = ttl; - ie_data[1] = flags; - *(u16 *)(ie_data + 2) = cpu_to_le16(reason); - *(u16 *)(ie_data + 4) = cpu_to_le16(precedence); - - return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len); -} - /*---------------------------------------------------------------------------- index: the information element id index, limit is the limit for search -----------------------------------------------------------------------------*/ @@ -236,97 +183,6 @@ u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit) return NULL; } -/** - * rtw_get_ie_ex - Search specific IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE - * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE - * - * Returns: The address of the specific IE found, or NULL - */ -u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen) -{ - uint cnt; - u8 *target_ie = NULL; - - - if (ielen) - *ielen = 0; - - if (!in_ie || in_len <= 0) - return target_ie; - - cnt = 0; - - while (cnt < in_len) { - if (eid == in_ie[cnt] && (!oui || !memcmp(&in_ie[cnt + 2], oui, oui_len))) { - target_ie = &in_ie[cnt]; - - if (ie) - memcpy(ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (ielen) - *ielen = in_ie[cnt + 1] + 2; - - break; - } else { - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - } - return target_ie; -} - -/** - * rtw_ies_remove_ie - Find matching IEs and remove - * @ies: Address of IEs to search - * @ies_len: Pointer of length of ies, will update to new length - * @offset: The offset to start scarch - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * - * Returns: _SUCCESS: ies is updated, _FAIL: not updated - */ -int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len) -{ - int ret = _FAIL; - u8 *target_ie; - u32 target_ielen; - u8 *start; - uint search_len; - - if (!ies || !ies_len || *ies_len <= offset) - goto exit; - - start = ies + offset; - search_len = *ies_len - offset; - - while (1) { - target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen); - if (target_ie && target_ielen) { - u8 buf[MAX_IE_SZ] = {0}; - u8 *remain_ies = target_ie + target_ielen; - uint remain_len = search_len - (remain_ies - start); - - memcpy(buf, remain_ies, remain_len); - memcpy(target_ie, buf, remain_len); - *ies_len = *ies_len - target_ielen; - ret = _SUCCESS; - - start = target_ie; - search_len = remain_len; - } else { - break; - } - } -exit: - return ret; -} - void rtw_set_supported_rate(u8 *SupportedRates, uint mode) { @@ -1096,43 +952,6 @@ void rtw_macaddr_cfg(u8 *mac_addr) DBG_88E("rtw_macaddr_cfg MAC Address = %pM\n", (mac_addr)); } -void dump_ies(u8 *buf, u32 buf_len) -{ - u8 *pos = buf; - u8 id, len; - - while (pos - buf <= buf_len) { - id = *pos; - len = *(pos + 1); - - DBG_88E("%s ID:%u, LEN:%u\n", __func__, id, len); - dump_wps_ie(pos, len); - - pos += (2 + len); - } -} - -void dump_wps_ie(u8 *ie, u32 ie_len) -{ - u8 *pos = ie; - u16 id; - u16 len; - u8 *wps_ie; - uint wps_ielen; - - wps_ie = rtw_get_wps_ie(ie, ie_len, NULL, &wps_ielen); - if (wps_ie != ie || wps_ielen == 0) - return; - - pos += 6; - while (pos - ie < ie_len) { - id = get_unaligned_be16(pos); - len = get_unaligned_be16(pos + 2); - DBG_88E("%s ID:0x%04x, LEN:%u\n", __func__, id, len); - pos += (4 + len); - } -} - /* Baron adds to avoid FreeBSD warning */ int ieee80211_is_empty_essid(const char *essid, int essid_len) { @@ -1223,7 +1042,6 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork) __le16 le_tmp; u16 wpa_len = 0, rsn_len = 0; struct HT_info_element *pht_info = NULL; - struct rtw_ieee80211_ht_cap *pht_cap = NULL; unsigned int len; unsigned char *p; @@ -1259,10 +1077,12 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork) /* parsing HT_CAP_IE */ p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); if (p && len > 0) { - pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); - pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info; + struct ieee80211_ht_cap *ht_cap = + (struct ieee80211_ht_cap *)(p + 2); + + pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(ht_cap->cap_info); } else { - pnetwork->BcnInfo.ht_cap_info = 0; + pnetwork->BcnInfo.ht_cap_info = 0; } /* parsing HT_INFO_IE */ p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); @@ -1335,58 +1155,3 @@ u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsign } return max_rate; } - -int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action) -{ - const u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr); - u16 fc; - u8 c, a = 0; - - fc = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)frame)->frame_ctl); - - if ((fc & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE)) != - (RTW_IEEE80211_FTYPE_MGMT | RTW_IEEE80211_STYPE_ACTION)) - return false; - - c = frame_body[0]; - - switch (c) { - case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */ - break; - default: - a = frame_body[1]; - } - - if (category) - *category = c; - if (action) - *action = a; - - return true; -} - -static const char *_action_public_str[] = { - "ACT_PUB_BSSCOEXIST", - "ACT_PUB_DSE_ENABLE", - "ACT_PUB_DSE_DEENABLE", - "ACT_PUB_DSE_REG_LOCATION", - "ACT_PUB_EXT_CHL_SWITCH", - "ACT_PUB_DSE_MSR_REQ", - "ACT_PUB_DSE_MSR_RPRT", - "ACT_PUB_MP", - "ACT_PUB_DSE_PWR_CONSTRAINT", - "ACT_PUB_VENDOR", - "ACT_PUB_GAS_INITIAL_REQ", - "ACT_PUB_GAS_INITIAL_RSP", - "ACT_PUB_GAS_COMEBACK_REQ", - "ACT_PUB_GAS_COMEBACK_RSP", - "ACT_PUB_TDLS_DISCOVERY_RSP", - "ACT_PUB_LOCATION_TRACK", - "ACT_PUB_RSVD", -}; - -const char *action_public_str(u8 action) -{ - action = min_t(u8, action, ACT_PUBLIC_MAX); - return _action_public_str[action]; -} diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index f85a6abec3a3..6ed23f4db38c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -14,7 +14,6 @@ ******************************************************************************/ #define _RTW_IOCTL_SET_C_ - #include #include #include @@ -570,10 +569,8 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) struct registry_priv *pregistrypriv = &adapter->registrypriv; struct mlme_priv *pmlmepriv = &adapter->mlmepriv; struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - struct rtw_ieee80211_ht_cap *pht_capie; u8 rf_type = 0; u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0; - u16 mcs_rate = 0; u32 ht_ielen = 0; if (adapter->registrypriv.mp_mode == 1) { @@ -588,15 +585,11 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N|WIRELESS_11_5N)) { p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12); if (p && ht_ielen > 0) { - pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2); - - memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); - /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */ bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0; - short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; - short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; + short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; + short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); max_rate = rtw_mcs_rate( @@ -604,7 +597,7 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) bw_40MHz & (pregistrypriv->cbw40_enable), short_GI_20, short_GI_40, - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate + pmlmeinfo->HT_caps.mcs.rx_mask ); } } else { diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 1456499b84bf..ee2dcd05010f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -52,8 +52,6 @@ int rtw_init_mlme_priv(struct adapter *padapter) _rtw_init_queue(&(pmlmepriv->free_bss_pool)); _rtw_init_queue(&(pmlmepriv->scanned_queue)); - set_scanned_network_val(pmlmepriv, 0); - memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network))); @@ -100,12 +98,6 @@ void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len); rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len); rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len); - - rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len); } #else void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) @@ -143,8 +135,6 @@ struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) pnetwork->aid = 0; pnetwork->join_res = 0; - pmlmepriv->num_of_scanned++; - exit: spin_unlock_bh(&free_queue->lock); @@ -175,7 +165,6 @@ static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network * spin_lock_bh(&free_queue->lock); list_del_init(&(pnetwork->list)); list_add_tail(&(pnetwork->list), &(free_queue->queue)); - pmlmepriv->num_of_scanned--; spin_unlock_bh(&free_queue->lock); } @@ -189,7 +178,6 @@ void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network * return; list_del_init(&(pnetwork->list)); list_add_tail(&(pnetwork->list), get_list_head(free_queue)); - pmlmepriv->num_of_scanned--; } /* @@ -271,7 +259,6 @@ void rtw_generate_random_ibss(u8 *pibss) pibss[3] = (u8)(curtime & 0xff);/* p[0]; */ pibss[4] = (u8)((curtime>>8) & 0xff);/* p[1]; */ pibss[5] = (u8)((curtime>>16) & 0xff);/* p[2]; */ - return; } u8 *rtw_get_capability_from_ie(u8 *ie) @@ -569,7 +556,6 @@ static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network * void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf) { RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_evet\n")); - return; } @@ -732,7 +718,6 @@ static void free_scanqueue(struct mlme_priv *pmlmepriv) list_del_init(plist); list_add_tail(plist, &free_queue->queue); plist = ptemp; - pmlmepriv->num_of_scanned--; } spin_unlock_bh(&free_queue->lock); @@ -1935,7 +1920,6 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ u32 ielen, out_len; enum ht_cap_ampdu_factor max_rx_ampdu_factor; unsigned char *p; - struct rtw_ieee80211_ht_cap ht_capie; unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; @@ -1948,6 +1932,8 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ p = rtw_get_ie(in_ie+12, _HT_CAPABILITY_IE_, &ielen, in_len-12); if (p && ielen > 0) { + struct ieee80211_ht_cap ht_cap; + if (pqospriv->qos_option == 0) { out_len = *pout_len; rtw_set_ie(out_ie+out_len, _VENDOR_SPECIFIC_IE_, @@ -1958,33 +1944,33 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ out_len = *pout_len; - memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap)); + memset(&ht_cap, 0, sizeof(struct ieee80211_ht_cap)); - ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | - IEEE80211_HT_CAP_DSSSCCK40; + ht_cap.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_TX_STBC | + IEEE80211_HT_CAP_DSSSCCK40); rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset); rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz); /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing + ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k + ampdu_params_info [4:2]:Min MPDU Start Spacing */ rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); - ht_capie.ampdu_params_info = (max_rx_ampdu_factor&0x03); + ht_cap.ampdu_params_info = max_rx_ampdu_factor & 0x03; if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_) - ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2)); + ht_cap.ampdu_params_info |= IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2); else - ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); - + ht_cap.ampdu_params_info |= IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00; rtw_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_, - sizeof(struct rtw_ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len); + sizeof(struct ieee80211_ht_cap), + (unsigned char *)&ht_cap, pout_len); phtpriv->ht_option = true; @@ -2000,9 +1986,6 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ /* the function is > passive_level (in critical_section) */ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) { - u8 *p, max_ampdu_sz; - int len; - struct rtw_ieee80211_ht_cap *pht_capie; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv = &pmlmepriv->htpriv; struct registry_priv *pregistrypriv = &padapter->registrypriv; @@ -2027,34 +2010,21 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) phtpriv->ampdu_enable = true; } - - /* check Max Rx A-MPDU Size */ - len = 0; - p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_CAPABILITY_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie)); - if (p && len > 0) { - pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2); - max_ampdu_sz = pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR; - max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */ - phtpriv->rx_ampdu_maxlen = max_ampdu_sz; - } - len = 0; - p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_ADD_INFO_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie)); - /* update cur_bwmode & cur_ch_offset */ if ((pregistrypriv->cbw40_enable) && - (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & BIT(1)) && + (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & BIT(1)) && (pmlmeinfo->HT_info.infos[0] & BIT(2))) { int i; u8 rf_type; - padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); + rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); /* update the MCS rates */ for (i = 0; i < 16; i++) { if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R)) - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i]; + ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i]; else - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i]; + ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_2R[i]; } /* switch to the 40M Hz mode according to the AP */ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; @@ -2072,7 +2042,7 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) } /* Config SM Power Save setting */ - pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2; + pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2; if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 7f32b39e5869..fb13df586441 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -320,7 +320,7 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned int rate_len; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); @@ -347,22 +347,22 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, bc_addr); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); /* pmlmeext->mgnt_seq++; */ SetFrameSubType(pframe, WIFI_BEACON); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { int len_diff; @@ -377,8 +377,8 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) ); pframe += (cur_network->IELength+len_diff); pattrib->pktlen += (cur_network->IELength+len_diff); - wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, - pattrib->pktlen-sizeof(struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); + wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, + pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); if (wps_ie && wps_ielen > 0) rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); if (sr != 0) @@ -461,7 +461,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned char *mac, *bssid; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); @@ -488,22 +488,22 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; mac = myid(&(padapter->eeprompriv)); bssid = cur_network->MacAddress; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr2, mac); + ether_addr_copy(pwlanhdr->addr3, bssid); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(fctrl, WIFI_PROBERSP); - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = pattrib->hdrlen; pframe += pattrib->hdrlen; @@ -609,7 +609,7 @@ static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pss struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned char *mac; unsigned char bssrate[NumRates]; @@ -633,31 +633,31 @@ static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pss memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; mac = myid(&(padapter->eeprompriv)); - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; if (da) { /* unicast probe request frame */ - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr3, da, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr3, da); } else { /* broadcast probe request frame */ - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, bc_addr); + ether_addr_copy(pwlanhdr->addr3, bc_addr); } - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr2, mac); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_PROBEREQ); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); if (pssid) pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen)); @@ -745,7 +745,7 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned int val32; u16 val16; @@ -769,25 +769,27 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_AUTH); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); if (psta) {/* for AP mode */ #ifdef CONFIG_88EU_AP_MODE - memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, psta->hwaddr); + ether_addr_copy(pwlanhdr->addr2, + myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, + myid(&(padapter->eeprompriv))); /* setting auth algo number */ @@ -825,9 +827,9 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, } else { __le32 le_tmp32; __le16 le_tmp16; - memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress); + ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); /* setting auth algo number */ val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ @@ -866,7 +868,7 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, SetPrivacy(fctrl); - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); pattrib->encrypt = _WEP40_; @@ -889,7 +891,7 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type) { struct xmit_frame *pmgntframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; struct pkt_attrib *pattrib; unsigned char *pbuf, *pframe; unsigned short val; @@ -916,14 +918,15 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); - memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr); + ether_addr_copy((void *)GetAddr2Ptr(pwlanhdr), + myid(&(padapter->eeprompriv))); + ether_addr_copy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); @@ -933,7 +936,7 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, else return; - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen += pattrib->hdrlen; pframe += pattrib->hdrlen; @@ -1017,7 +1020,7 @@ static void issue_assocreq(struct adapter *padapter) struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe, *p; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned int i, j, ie_len, index = 0; unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates]; @@ -1040,20 +1043,20 @@ static void issue_assocreq(struct adapter *padapter) memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ASSOCREQ); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); /* caps */ @@ -1132,23 +1135,23 @@ static void issue_assocreq(struct adapter *padapter) if (padapter->mlmepriv.htpriv.ht_option) { p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie))); if ((p != NULL) && (!(is_ap_in_tkip(padapter)))) { - memcpy(&(pmlmeinfo->HT_caps), (p + 2), sizeof(struct HT_caps_element)); + memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct ieee80211_ht_cap)); /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */ if (pregpriv->cbw40_enable == 0) - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1))); + pmlmeinfo->HT_caps.cap_info &= cpu_to_le16(~(BIT(6) | BIT(1))); else - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1)); + pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(BIT(1)); /* todo: disable SM power save mode */ - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c); + pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x000c); rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); switch (rf_type) { case RF_1T1R: if (pregpriv->rx_stbc) - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */ - memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16); + pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */ + memcpy((u8 *)&pmlmeinfo->HT_caps.mcs, MCS_rate_1R, 16); break; case RF_2T2R: case RF_1T2R: @@ -1157,9 +1160,9 @@ static void issue_assocreq(struct adapter *padapter) ((pmlmeext->cur_wireless_mode & WIRELESS_11_24N) && (pregpriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */ (pregpriv->wifi_spec == 1)) { DBG_88E("declare supporting RX STBC\n"); - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */ + pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */ } - memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R, 16); + memcpy(&pmlmeinfo->HT_caps.mcs, MCS_rate_2R, 16); break; } pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); @@ -1212,7 +1215,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; struct xmit_priv *pxmitpriv; struct mlme_ext_priv *pmlmeext; @@ -1239,9 +1242,9 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) @@ -1252,16 +1255,16 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned if (power_mode) SetPwrMgt(fctrl); - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_DATA_NULL); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); pattrib->last_txcmdsz = pattrib->pktlen; @@ -1332,7 +1335,7 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned short *qc; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); @@ -1359,9 +1362,9 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) @@ -1380,16 +1383,16 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 SetAckpolicy(qc, pattrib->ack_policy); - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos); + pframe += sizeof(struct ieee80211_qos_hdr); + pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); pattrib->last_txcmdsz = pattrib->pktlen; @@ -1457,7 +1460,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); @@ -1478,21 +1481,21 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_DEAUTH); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); le_tmp = cpu_to_le16(reason); pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, &le_tmp, @@ -1559,66 +1562,6 @@ exit: return ret; } -void issue_action_spct_ch_switch(struct adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - - - DBG_88E(FUNC_NDEV_FMT" ra =%pM, ch:%u, offset:%u\n", - FUNC_NDEV_ARG(padapter->pnetdev), ra, new_ch, ch_offset); - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; - - fctrl = &(pwlanhdr->frame_ctl); - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */ - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */ - memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */ - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - /* category, action */ - { - u8 category, action; - category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT; - action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH; - - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - } - - pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0); - pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen), - hal_ch_offset_to_secondary_ch_offset(ch_offset)); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status) { @@ -1633,7 +1576,7 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; u8 *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); @@ -1656,21 +1599,21 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, raddr); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ACTION); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); @@ -1779,7 +1722,7 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; struct wlan_network *pnetwork = NULL; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); @@ -1815,21 +1758,21 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, cur_network->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, cur_network->MacAddress); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ACTION); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); @@ -2112,7 +2055,7 @@ static u8 collect_bss_info(struct adapter *padapter, struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr); + len = packet_len - sizeof(struct ieee80211_hdr_3addr); if (len > MAX_IE_SZ) return _FAIL; @@ -2142,7 +2085,7 @@ static u8 collect_bss_info(struct adapter *padapter, /* below is to copy the information element */ bssid->IELength = len; - memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength); + memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); /* get the signal strength in dBM.raw data */ bssid->Rssi = precv_frame->attrib.phy_info.recvpower; @@ -2219,7 +2162,7 @@ static u8 collect_bss_info(struct adapter *padapter, if (subtype == WIFI_PROBEREQ) { /* FIXME */ bssid->InfrastructureMode = Ndis802_11Infrastructure; - memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); + ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe)); bssid->Privacy = 1; return _SUCCESS; } @@ -2231,10 +2174,10 @@ static u8 collect_bss_info(struct adapter *padapter, if (val16 & BIT(0)) { bssid->InfrastructureMode = Ndis802_11Infrastructure; - memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); + ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe)); } else { bssid->InfrastructureMode = Ndis802_11IBSS; - memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); + ether_addr_copy(bssid->MacAddress, GetAddr3Ptr(pframe)); } if (val16 & BIT(4)) @@ -2249,10 +2192,10 @@ static u8 collect_bss_info(struct adapter *padapter, struct mlme_priv *pmlmepriv = &padapter->mlmepriv; p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset); if (p && len > 0) { - struct HT_caps_element *pHT_caps; - pHT_caps = (struct HT_caps_element *)(p + 2); + struct ieee80211_ht_cap *pHT_caps = + (struct ieee80211_ht_cap *)(p + 2); - if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info)&BIT(14)) + if (le16_to_cpu(pHT_caps->cap_info) & BIT(14)) pmlmepriv->num_FortyMHzIntolerant++; } else { pmlmepriv->num_sta_no_ht++; @@ -2684,7 +2627,7 @@ static unsigned int OnBeacon(struct adapter *padapter, } /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr)); + pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr)); /* update TSF Value */ update_TSF(pmlmeext, pframe, len); @@ -3296,13 +3239,15 @@ static unsigned int OnAssocReq(struct adapter *padapter, } /* save HT capabilities in the sta object */ - memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap)); - if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) { + memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); + if (elems.ht_capabilities && + elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) { pstat->flags |= WLAN_STA_HT; pstat->flags |= WLAN_STA_WME; - memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap)); + memcpy(&pstat->htpriv.ht_cap, + elems.ht_capabilities, sizeof(struct ieee80211_ht_cap)); } else { pstat->flags &= ~WLAN_STA_HT; } @@ -3639,7 +3584,7 @@ static unsigned int on_action_spct(struct adapter *padapter, struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); u8 category; u8 action; @@ -3713,7 +3658,7 @@ static unsigned int OnAction_back(struct adapter *padapter, if (psta == NULL) return _SUCCESS; - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); category = frame_body[0]; if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */ @@ -3800,7 +3745,7 @@ static unsigned int on_action_public_p2p(struct recv_frame *precv_frame) u8 *pframe = precv_frame->rx_data; u8 *frame_body; u8 dialogToken = 0; - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); dialogToken = frame_body[7]; @@ -3814,7 +3759,7 @@ static unsigned int on_action_public_vendor(struct recv_frame *precv_frame) { unsigned int ret = _FAIL; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); if (!memcmp(frame_body + 2, P2P_OUI, 4)) ret = on_action_public_p2p(precv_frame); @@ -3826,7 +3771,7 @@ static unsigned int on_action_public_default(struct recv_frame *precv_frame, u8 { unsigned int ret = _FAIL; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); u8 token; token = frame_body[2]; @@ -3845,7 +3790,7 @@ static unsigned int on_action_public(struct adapter *padapter, { unsigned int ret = _FAIL; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); u8 category, action; /* check RA matches or not */ @@ -3917,7 +3862,7 @@ static unsigned int OnAction(struct adapter *padapter, unsigned char *frame_body; u8 *pframe = precv_frame->rx_data; - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); category = frame_body[0]; @@ -4295,7 +4240,7 @@ void report_survey_event(struct adapter *padapter, INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4304,7 +4249,7 @@ void report_survey_event(struct adapter *padapter, pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct survey_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); + pc2h_evt_hdr->ID = _Survey_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); @@ -4345,7 +4290,7 @@ void report_surveydone_event(struct adapter *padapter) INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4354,7 +4299,7 @@ void report_surveydone_event(struct adapter *padapter) pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct surveydone_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); + pc2h_evt_hdr->ID = _SurveyDone_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); @@ -4389,7 +4334,7 @@ void report_join_res(struct adapter *padapter, int res) INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4398,7 +4343,7 @@ void report_join_res(struct adapter *padapter, int res) pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct joinbss_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); + pc2h_evt_hdr->ID = _JoinBss_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); @@ -4440,7 +4385,7 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4449,11 +4394,11 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct stadel_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); + pc2h_evt_hdr->ID = _DelSTA_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN); + ether_addr_copy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr); memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); @@ -4493,7 +4438,7 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4502,11 +4447,11 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct stassoc_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); + pc2h_evt_hdr->ID = _AddSTA_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN); + ether_addr_copy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr); padd_sta_evt->cam_id = cam_idx; DBG_88E("report_add_sta_event: add STA\n"); @@ -4537,7 +4482,7 @@ void update_sta_info(struct adapter *padapter, struct sta_info *psta) psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; - if (support_short_GI(padapter, &(pmlmeinfo->HT_caps))) + if (support_short_GI(padapter, &pmlmeinfo->HT_caps)) psta->htpriv.sgi = true; psta->qos_option = true; @@ -4904,7 +4849,7 @@ void survey_timer_hdl(unsigned long data) goto exit_survey_timer_hdl; } - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); + init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_); rtw_enqueue_cmd(pcmdpriv, ph2c); } @@ -5480,7 +5425,7 @@ u8 set_tx_beacon_cmd(struct adapter *padapter) pmlmeinfo->hidden_ssid_mode); ptxBeacon_parm->IELength += len_diff; - init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon)); + init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, _TX_Beacon_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index 59c6d8ab60f6..0b70fe7d3b72 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -38,7 +38,7 @@ static int rtw_hw_suspend(struct adapter *padapter) LeaveAllPowerSaveMode(padapter); DBG_88E("==> rtw_hw_suspend\n"); - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; /* s1. */ if (pnetdev) { @@ -73,7 +73,7 @@ static int rtw_hw_suspend(struct adapter *padapter) pwrpriv->rf_pwrstate = rf_off; pwrpriv->bips_processing = false; - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); return 0; @@ -90,12 +90,12 @@ static int rtw_hw_resume(struct adapter *padapter) /* system resume */ DBG_88E("==> rtw_hw_resume\n"); - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; rtw_reset_drv_sw(padapter); if (pm_netdev_open(pnetdev, false) != 0) { - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); goto error_exit; } @@ -113,7 +113,7 @@ static int rtw_hw_resume(struct adapter *padapter) pwrpriv->rf_pwrstate = rf_on; pwrpriv->bips_processing = false; - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); return 0; @@ -138,7 +138,7 @@ void ips_enter(struct adapter *padapter) return; } - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; @@ -159,7 +159,7 @@ void ips_enter(struct adapter *padapter) } pwrpriv->bips_processing = false; - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); } int ips_leave(struct adapter *padapter) @@ -171,7 +171,7 @@ int ips_leave(struct adapter *padapter) int keyid; - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) { pwrpriv->bips_processing = true; @@ -205,7 +205,7 @@ int ips_leave(struct adapter *padapter) pwrpriv->bpower_saving = false; } - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); return result; } @@ -504,7 +504,7 @@ void rtw_init_pwrctrl_priv(struct adapter *padapter) { struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - _init_pwrlock(&pwrctrlpriv->lock); + mutex_init(&pwrctrlpriv->mutex_lock); pwrctrlpriv->rf_pwrstate = rf_on; pwrctrlpriv->ips_enter_cnts = 0; pwrctrlpriv->ips_leave_cnts = 0; diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 977bb2532c3e..b87cbbbee054 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -39,7 +39,7 @@ static u8 rtw_rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -void rtw_signal_stat_timer_hdl(unsigned long data); +static void rtw_signal_stat_timer_hdl(unsigned long data); void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) { @@ -73,7 +73,7 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) if (!precvpriv->pallocated_frame_buf) return _FAIL; - precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ); + precvpriv->precv_frame_buf = PTR_ALIGN(precvpriv->pallocated_frame_buf, RXFRAME_ALIGN_SZ); precvframe = (struct recv_frame *)precvpriv->precv_frame_buf; @@ -2088,7 +2088,7 @@ _recv_entry_drop: return ret; } -void rtw_signal_stat_timer_hdl(unsigned long data) +static void rtw_signal_stat_timer_hdl(unsigned long data) { struct adapter *adapter = (struct adapter *)data; struct recv_priv *recvpriv = &adapter->recvpriv; diff --git a/drivers/staging/rtl8188eu/core/rtw_rf.c b/drivers/staging/rtl8188eu/core/rtw_rf.c index 3fc1a8fd367c..e47be87fb402 100644 --- a/drivers/staging/rtl8188eu/core/rtw_rf.c +++ b/drivers/staging/rtl8188eu/core/rtw_rf.c @@ -19,7 +19,6 @@ #include #include - struct ch_freq { u32 channel; u32 frequency; diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 442a614a3726..85bb441a7214 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -233,7 +233,6 @@ void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe) &crc, &payload[length-4])); } } - return; } /* 3 ===== TKIP related ===== */ diff --git a/drivers/staging/rtl8188eu/core/rtw_sreset.c b/drivers/staging/rtl8188eu/core/rtw_sreset.c index 13a5bf4730ab..a198c5779d50 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sreset.c +++ b/drivers/staging/rtl8188eu/core/rtw_sreset.c @@ -16,18 +16,16 @@ #include #include -void sreset_init_value(struct adapter *padapter) +void rtw_hal_sreset_init(struct adapter *padapter) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; + struct sreset_priv *psrtpriv = &padapter->HalData->srestpriv; psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS; } u8 sreset_get_wifi_status(struct adapter *padapter) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; + struct sreset_priv *psrtpriv = &padapter->HalData->srestpriv; u8 status = WIFI_STATUS_SUCCESS; u32 val32 = 0; @@ -54,6 +52,5 @@ u8 sreset_get_wifi_status(struct adapter *padapter) void sreset_set_wifi_error_status(struct adapter *padapter, u32 status) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - pHalData->srestpriv.Wifi_Error_Status = status; + padapter->HalData->srestpriv.Wifi_Error_Status = status; } diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 4410fe8d7c68..2a65ac702129 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -341,9 +341,6 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigne { u8 center_ch; - if (padapter->bNotifyChannelChange) - DBG_88E("[%s] ch = %d, offset = %d, bwmode = %d\n", __func__, channel, channel_offset, bwmode); - if ((bwmode == HT_CHANNEL_WIDTH_20) || (channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) { /* SelectChannel(padapter, channel); */ @@ -716,6 +713,7 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv = &pmlmepriv->htpriv; + u8 *HT_cap = (u8 *)(&pmlmeinfo->HT_caps); if (pIE == NULL) return; @@ -728,20 +726,20 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) for (i = 0; i < (pIE->Length); i++) { if (i != 2) { /* Got the endian issue here. */ - pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]); + HT_cap[i] &= (pIE->data[i]); } else { /* modify from fw by Thomas 2010/11/17 */ - if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3)) + if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x3) > (pIE->data[i] & 0x3)) max_AMPDU_len = pIE->data[i] & 0x3; else - max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3; + max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x3; - if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c)) - min_MPDU_spacing = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c; + if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) > (pIE->data[i] & 0x1c)) + min_MPDU_spacing = pmlmeinfo->HT_caps.ampdu_params_info & 0x1c; else min_MPDU_spacing = pIE->data[i] & 0x1c; - pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing; + pmlmeinfo->HT_caps.ampdu_params_info = max_AMPDU_len | min_MPDU_spacing; } } @@ -750,9 +748,9 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) /* update the MCS rates */ for (i = 0; i < 16; i++) { if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R)) - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i]; + ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i]; else - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i]; + ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_2R[i]; } } @@ -798,9 +796,9 @@ void HTOnAssocRsp(struct adapter *padapter) AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k AMPDU_para [4:2]:Min MPDU Start Spacing */ - max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03; + max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03; - min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2; + min_MPDU_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2; rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing)); @@ -872,7 +870,6 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) u32 wpa_ielen = 0; u8 *pbssid = GetAddr3Ptr(pframe); struct HT_info_element *pht_info = NULL; - struct rtw_ieee80211_ht_cap *pht_cap = NULL; u32 bcn_channel; unsigned short ht_cap_info; unsigned char ht_info_infos_0; @@ -881,7 +878,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) if (is_client_associated_to_ap(Adapter) == false) return true; - len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr); + len = packet_len - sizeof(struct ieee80211_hdr_3addr); if (len > MAX_IE_SZ) { DBG_88E("%s IE too long for survey event\n", __func__); @@ -907,14 +904,16 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) /* below is to copy the information element */ bssid->IELength = len; - memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength); + memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); /* check bw and channel offset */ /* parsing HT_CAP_IE */ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); if (p && len > 0) { - pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); - ht_cap_info = pht_cap->cap_info; + struct ieee80211_ht_cap *ht_cap = + (struct ieee80211_ht_cap *)(p + 2); + + ht_cap_info = le16_to_cpu(ht_cap->cap_info); } else { ht_cap_info = 0; } @@ -1243,16 +1242,17 @@ unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz) return mask; } -unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps) +unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps) { unsigned int mask = 0; - mask = (pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20); + mask = (pHT_caps->mcs.rx_mask[0] << 12) | + (pHT_caps->mcs.rx_mask[1] << 20); return mask; } -int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps) +int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *pHT_caps) { unsigned char bit_offset; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; @@ -1266,7 +1266,7 @@ int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps) bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40) ? 6 : 5; - if (__le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & (0x1 << bit_offset)) + if (__le16_to_cpu(pHT_caps->cap_info) & (0x1 << bit_offset)) return _SUCCESS; else return _FAIL; @@ -1508,7 +1508,7 @@ void update_wireless_mode(struct adapter *padapter) SIFS_Timer = 0x0a0a0808;/* 0x0808 -> for CCK, 0x0a0a -> for OFDM */ /* change this value if having IOT issues. */ - padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer); + rtw_hal_set_hwreg(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer); if (pmlmeext->cur_wireless_mode & WIRELESS_11B) update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB); @@ -1584,7 +1584,7 @@ void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len) u8 *pIE; __le32 *pbuf; - pIE = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + pIE = pframe + sizeof(struct ieee80211_hdr_3addr); pbuf = (__le32 *)pIE; pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1)); diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index e0a5567f5942..0f8b8e0bffdf 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -57,8 +57,6 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */ spin_lock_init(&pxmitpriv->lock); - sema_init(&pxmitpriv->xmit_sema, 0); - sema_init(&pxmitpriv->terminate_xmitthread_sema, 0); /* Please insert all the queue initializaiton using _rtw_init_queue below @@ -88,7 +86,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) res = _FAIL; goto exit; } - pxmitpriv->pxmit_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_frame_buf), 4); + pxmitpriv->pxmit_frame_buf = PTR_ALIGN(pxmitpriv->pallocated_frame_buf, 4); /* pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - */ /* ((size_t) (pxmitpriv->pallocated_frame_buf) &3); */ @@ -126,7 +124,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) goto exit; } - pxmitpriv->pxmitbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmitbuf), 4); + pxmitpriv->pxmitbuf = PTR_ALIGN(pxmitpriv->pallocated_xmitbuf, 4); /* pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - */ /* ((size_t) (pxmitpriv->pallocated_xmitbuf) &3); */ @@ -144,9 +142,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) if (res == _FAIL) { msleep(10); res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - if (res == _FAIL) { + if (res == _FAIL) goto exit; - } } pxmitbuf->flags = XMIT_VO_QUEUE; @@ -168,7 +165,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) goto exit; } - pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4); + pxmitpriv->pxmit_extbuf = PTR_ALIGN(pxmitpriv->pallocated_xmit_extbuf, 4); pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; @@ -199,8 +196,6 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitpriv->txirp_cnt = 1; - sema_init(&(pxmitpriv->tx_retevt), 0); - /* per AC pending irp */ pxmitpriv->beq_cnt = 0; pxmitpriv->bkq_cnt = 0; @@ -252,9 +247,8 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) pxmitbuf++; } - if (pxmitpriv->pallocated_xmit_extbuf) { + if (pxmitpriv->pallocated_xmit_extbuf) vfree(pxmitpriv->pallocated_xmit_extbuf); - } rtw_free_hwxmits(padapter); @@ -408,7 +402,7 @@ static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) _rtw_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr)); /* user_prio = (ntohs(ip_hdr.tos) >> 5) & 0x3; */ user_prio = ip_hdr.tos >> 5; - } else if (pattrib->ether_type == 0x888e) { + } else if (pattrib->ether_type == ETH_P_PAE) { /* "When priority processing of data frames is supported, */ /* a STA's SME should send EAPOL-Key frames at the highest priority." */ user_prio = 7; @@ -457,14 +451,14 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p pattrib->pktlen = pktfile.pkt_len; - if (ETH_P_IP == pattrib->ether_type) { + if (pattrib->ether_type == ETH_P_IP) { /* The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time */ /* to prevent DHCP protocol fail */ u8 tmp[24]; _rtw_pktfile_read(&pktfile, &tmp[0], 24); pattrib->dhcp_pkt = 0; if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */ - if (ETH_P_IP == pattrib->ether_type) {/* IP header */ + if (pattrib->ether_type == ETH_P_IP) {/* IP header */ if (((tmp[21] == 68) && (tmp[23] == 67)) || ((tmp[21] == 67) && (tmp[23] == 68))) { /* 68 : UDP BOOTP client */ @@ -475,15 +469,15 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p } } } - } else if (0x888e == pattrib->ether_type) { + } else if (pattrib->ether_type == ETH_P_PAE) { DBG_88E_LEVEL(_drv_info_, "send eapol packet\n"); } - if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) + if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) rtw_set_scan_deny(padapter, 3000); /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */ - if ((pattrib->ether_type == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) + if ((pattrib->ether_type == ETH_P_ARP) || (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1); bmcast = IS_MCAST(pattrib->ra); @@ -515,8 +509,6 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p } pattrib->ack_policy = 0; - /* get ether_hdr_len */ - pattrib->pkt_hdrlen = ETH_HLEN;/* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */ pattrib->hdrlen = WLAN_HDR_A3_LEN; pattrib->subtype = WIFI_DATA_TYPE; @@ -539,8 +531,8 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p pattrib->encrypt = 0; - if ((pattrib->ether_type != 0x888e) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\npsta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != 0x888e\n", pattrib->ether_type)); + if ((pattrib->ether_type != ETH_P_PAE) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { + RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\npsta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != ETH_P_PAE\n", pattrib->ether_type)); res = _FAIL; goto exit; } @@ -769,13 +761,13 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr { u16 *qc; - struct rtw_ieee80211_hdr *pwlanhdr = (struct rtw_ieee80211_hdr *)hdr; + struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; u8 qos_option = false; int res = _SUCCESS; - __le16 *fctrl = &pwlanhdr->frame_ctl; + __le16 *fctrl = &pwlanhdr->frame_control; struct sta_info *psta; @@ -785,11 +777,10 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr if (pattrib->psta) { psta = pattrib->psta; } else { - if (bmcst) { + if (bmcst) psta = rtw_get_bcmc_stainfo(padapter); - } else { + else psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); - } } memset(hdr, 0, WLANHDR_OFFSET); @@ -999,7 +990,7 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct } _rtw_open_pktfile(pkt, &pktfile); - _rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen); + _rtw_pktfile_read(&pktfile, NULL, ETH_HLEN); frg_inx = 0; frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */ @@ -1054,9 +1045,8 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct mpdu_len -= llc_sz; } - if ((pattrib->icv_len > 0) && (pattrib->bswenc)) { + if ((pattrib->icv_len > 0) && (pattrib->bswenc)) mpdu_len -= pattrib->icv_len; - } if (bmcst) { /* don't do fragment to broadcat/multicast packets */ @@ -1560,11 +1550,10 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) int res = _SUCCESS; - if (pattrib->psta) { + if (pattrib->psta) psta = pattrib->psta; - } else { + else psta = rtw_get_stainfo(pstapriv, pattrib->ra); - } if (psta == NULL) { res = _FAIL; @@ -1658,16 +1647,6 @@ u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe) return addr; } -static void do_queue_select(struct adapter *padapter, struct pkt_attrib *pattrib) -{ - u8 qsel; - - qsel = pattrib->priority; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("### do_queue_select priority=%d , qsel = %d\n", pattrib->priority, qsel)); - - pattrib->qsel = qsel; -} - /* * The main transmit(tx) entry * @@ -1700,7 +1679,7 @@ s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt) rtw_led_control(padapter, LED_CTL_TX); - do_queue_select(padapter, &pxmitframe->attrib); + pxmitframe->attrib.qsel = pxmitframe->attrib.priority; #ifdef CONFIG_88EU_AP_MODE spin_lock_bh(&pxmitpriv->lock); diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c index cce1ea259b76..134fa6c595a8 100644 --- a/drivers/staging/rtl8188eu/hal/bb_cfg.c +++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c @@ -498,7 +498,7 @@ static u32 array_phy_reg_pg_8188e[] = { static void store_pwrindex_offset(struct adapter *adapter, u32 regaddr, u32 bitmask, u32 data) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapter); + struct hal_data_8188e *hal_data = adapter->HalData; u32 * const power_level_offset = hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt]; @@ -518,8 +518,7 @@ static void store_pwrindex_offset(struct adapter *adapter, power_level_offset[4] = data; if (regaddr == rTxAGC_A_Mcs15_Mcs12) { power_level_offset[5] = data; - if (hal_data->rf_type == RF_1T1R) - hal_data->pwrGroupCnt++; + hal_data->pwrGroupCnt++; } if (regaddr == rTxAGC_B_Rate18_06) power_level_offset[8] = data; @@ -537,8 +536,6 @@ static void store_pwrindex_offset(struct adapter *adapter, power_level_offset[12] = data; if (regaddr == rTxAGC_B_Mcs15_Mcs12) { power_level_offset[13] = data; - if (hal_data->rf_type != RF_1T1R) - hal_data->pwrGroupCnt++; } } @@ -588,11 +585,10 @@ static bool config_bb_with_pgheader(struct adapter *adapt) static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapter); struct bb_reg_def *reg[4]; - reg[RF_PATH_A] = &hal_data->PHYRegDef[RF_PATH_A]; - reg[RF_PATH_B] = &hal_data->PHYRegDef[RF_PATH_B]; + reg[RF_PATH_A] = &adapter->HalData->PHYRegDef[RF_PATH_A]; + reg[RF_PATH_B] = &adapter->HalData->PHYRegDef[RF_PATH_B]; reg[RF_PATH_A]->rfintfs = rFPGA0_XAB_RFInterfaceSW; reg[RF_PATH_B]->rfintfs = rFPGA0_XAB_RFInterfaceSW; @@ -652,13 +648,12 @@ static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *adapter) static bool config_parafile(struct adapter *adapt) { struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(adapt); - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); set_baseband_phy_config(adapt); /* If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */ if (!eeprom->bautoload_fail_flag) { - hal_data->pwrGroupCnt = 0; + adapt->HalData->pwrGroupCnt = 0; config_bb_with_pgheader(adapt); } set_baseband_agc_config(adapt); @@ -668,7 +663,6 @@ static bool config_parafile(struct adapter *adapt) bool rtl88eu_phy_bb_config(struct adapter *adapt) { int rtstatus = true; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); u32 regval; u8 crystal_cap; @@ -688,7 +682,7 @@ bool rtl88eu_phy_bb_config(struct adapter *adapt) rtstatus = config_parafile(adapt); /* write 0x24[16:11] = 0x24[22:17] = crystal_cap */ - crystal_cap = hal_data->CrystalCap & 0x3F; + crystal_cap = adapt->HalData->CrystalCap & 0x3F; phy_set_bb_reg(adapt, REG_AFE_XTAL_CTRL, 0x7ff800, (crystal_cap | (crystal_cap << 6))); diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 085f0fbd0c43..a11c7b4254f6 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -17,62 +17,6 @@ #include #include #include -#include - -void rtw_hal_chip_configure(struct adapter *adapt) -{ - if (adapt->HalFunc.intf_chip_configure) - adapt->HalFunc.intf_chip_configure(adapt); -} - -void rtw_hal_read_chip_info(struct adapter *adapt) -{ - if (adapt->HalFunc.read_adapter_info) - adapt->HalFunc.read_adapter_info(adapt); -} - -void rtw_hal_read_chip_version(struct adapter *adapt) -{ - if (adapt->HalFunc.read_chip_version) - adapt->HalFunc.read_chip_version(adapt); -} - -void rtw_hal_def_value_init(struct adapter *adapt) -{ - if (adapt->HalFunc.init_default_value) - adapt->HalFunc.init_default_value(adapt); -} - -void rtw_hal_free_data(struct adapter *adapt) -{ - if (adapt->HalFunc.free_hal_data) - adapt->HalFunc.free_hal_data(adapt); -} - -void rtw_hal_dm_init(struct adapter *adapt) -{ - if (adapt->HalFunc.dm_init) - adapt->HalFunc.dm_init(adapt); -} - -void rtw_hal_sw_led_init(struct adapter *adapt) -{ - if (adapt->HalFunc.InitSwLeds) - adapt->HalFunc.InitSwLeds(adapt); -} - -void rtw_hal_sw_led_deinit(struct adapter *adapt) -{ - if (adapt->HalFunc.DeInitSwLeds) - adapt->HalFunc.DeInitSwLeds(adapt); -} - -u32 rtw_hal_power_on(struct adapter *adapt) -{ - if (adapt->HalFunc.hal_power_on) - return adapt->HalFunc.hal_power_on(adapt); - return _FAIL; -} uint rtw_hal_init(struct adapter *adapt) { @@ -80,15 +24,13 @@ uint rtw_hal_init(struct adapter *adapt) adapt->hw_init_completed = false; - status = adapt->HalFunc.hal_init(adapt); + status = rtl8188eu_hal_init(adapt); if (status == _SUCCESS) { adapt->hw_init_completed = true; if (adapt->registrypriv.notch_filter == 1) rtw_hal_notch_filter(adapt, 1); - - rtw_hal_reset_security_engine(adapt); } else { adapt->hw_init_completed = false; DBG_88E("rtw_hal_init: hal__init fail\n"); @@ -104,7 +46,7 @@ uint rtw_hal_deinit(struct adapter *adapt) { uint status = _SUCCESS; - status = adapt->HalFunc.hal_deinit(adapt); + status = rtl8188eu_hal_deinit(adapt); if (status == _SUCCESS) adapt->hw_init_completed = false; @@ -114,92 +56,6 @@ uint rtw_hal_deinit(struct adapter *adapt) return status; } -void rtw_hal_set_hwreg(struct adapter *adapt, u8 variable, u8 *val) -{ - if (adapt->HalFunc.SetHwRegHandler) - adapt->HalFunc.SetHwRegHandler(adapt, variable, val); -} - -void rtw_hal_get_hwreg(struct adapter *adapt, u8 variable, u8 *val) -{ - if (adapt->HalFunc.GetHwRegHandler) - adapt->HalFunc.GetHwRegHandler(adapt, variable, val); -} - -u8 rtw_hal_get_def_var(struct adapter *adapt, - enum hal_def_variable var, void *val) -{ - if (adapt->HalFunc.GetHalDefVarHandler) - return adapt->HalFunc.GetHalDefVarHandler(adapt, var, val); - return _FAIL; -} - -void rtw_hal_set_odm_var(struct adapter *adapt, - enum hal_odm_variable var, void *val1, - bool set) -{ - if (adapt->HalFunc.SetHalODMVarHandler) - adapt->HalFunc.SetHalODMVarHandler(adapt, var, - val1, set); -} - -u32 rtw_hal_inirp_init(struct adapter *adapt) -{ - u32 rst = _FAIL; - - if (adapt->HalFunc.inirp_init) - rst = adapt->HalFunc.inirp_init(adapt); - else - DBG_88E(" %s HalFunc.inirp_init is NULL!!!\n", __func__); - return rst; -} - -u32 rtw_hal_inirp_deinit(struct adapter *adapt) -{ - if (adapt->HalFunc.inirp_deinit) - return adapt->HalFunc.inirp_deinit(adapt); - - return _FAIL; -} - -s32 rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - if (adapt->HalFunc.hal_xmit) - return adapt->HalFunc.hal_xmit(adapt, pxmitframe); - - return false; -} - -s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) -{ - s32 ret = _FAIL; - - if (adapt->HalFunc.mgnt_xmit) - ret = adapt->HalFunc.mgnt_xmit(adapt, pmgntframe); - return ret; -} - -s32 rtw_hal_init_xmit_priv(struct adapter *adapt) -{ - if (adapt->HalFunc.init_xmit_priv) - return adapt->HalFunc.init_xmit_priv(adapt); - return _FAIL; -} - -s32 rtw_hal_init_recv_priv(struct adapter *adapt) -{ - if (adapt->HalFunc.init_recv_priv) - return adapt->HalFunc.init_recv_priv(adapt); - - return _FAIL; -} - -void rtw_hal_free_recv_priv(struct adapter *adapt) -{ - if (adapt->HalFunc.free_recv_priv) - adapt->HalFunc.free_recv_priv(adapt); -} - void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) { struct mlme_priv *pmlmepriv = &(adapt->mlmepriv); @@ -215,86 +71,6 @@ void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) add_RATid(adapt, psta, 0);/* todo: based on rssi_level*/ #endif } else { - if (adapt->HalFunc.UpdateRAMaskHandler) - adapt->HalFunc.UpdateRAMaskHandler(adapt, mac_id, - rssi_level); + UpdateHalRAMask8188EUsb(adapt, mac_id, rssi_level); } } - -void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, - u8 rssi_level) -{ - if (adapt->HalFunc.Add_RateATid) - adapt->HalFunc.Add_RateATid(adapt, bitmap, arg, - rssi_level); -} - -u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rfpath, - u32 regaddr, u32 bitmask) -{ - u32 data = 0; - - if (adapt->HalFunc.read_rfreg) - data = adapt->HalFunc.read_rfreg(adapt, rfpath, regaddr, - bitmask); - return data; -} - -void rtw_hal_set_bwmode(struct adapter *adapt, - enum ht_channel_width bandwidth, u8 offset) -{ - if (adapt->HalFunc.set_bwmode_handler) - adapt->HalFunc.set_bwmode_handler(adapt, bandwidth, - offset); -} - -void rtw_hal_set_chan(struct adapter *adapt, u8 channel) -{ - if (adapt->HalFunc.set_channel_handler) - adapt->HalFunc.set_channel_handler(adapt, channel); -} - -void rtw_hal_dm_watchdog(struct adapter *adapt) -{ - if (adapt->HalFunc.hal_dm_watchdog) - adapt->HalFunc.hal_dm_watchdog(adapt); -} - -void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) -{ - if (adapt->HalFunc.SetBeaconRelatedRegistersHandler) - adapt->HalFunc.SetBeaconRelatedRegistersHandler(adapt); -} - -u8 rtw_hal_antdiv_before_linked(struct adapter *adapt) -{ - if (adapt->HalFunc.AntDivBeforeLinkHandler) - return adapt->HalFunc.AntDivBeforeLinkHandler(adapt); - return false; -} - -void rtw_hal_antdiv_rssi_compared(struct adapter *adapt, - struct wlan_bssid_ex *dst, - struct wlan_bssid_ex *src) -{ - if (adapt->HalFunc.AntDivCompareHandler) - adapt->HalFunc.AntDivCompareHandler(adapt, dst, src); -} - -void rtw_hal_sreset_init(struct adapter *adapt) -{ - if (adapt->HalFunc.sreset_init_value) - adapt->HalFunc.sreset_init_value(adapt); -} - -void rtw_hal_notch_filter(struct adapter *adapter, bool enable) -{ - if (adapter->HalFunc.hal_notch_filter) - adapter->HalFunc.hal_notch_filter(adapter, enable); -} - -void rtw_hal_reset_security_engine(struct adapter *adapter) -{ - if (adapter->HalFunc.hal_reset_security_engine) - adapter->HalFunc.hal_reset_security_engine(adapter); -} diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 57a127501694..d983a8029f4c 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -226,150 +226,6 @@ void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm) odm_EdcaTurboCheck(pDM_Odm); } -/* Init /.. Fixed HW value. Only init time. */ -void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u32 Value) -{ - /* This section is used for init value */ - switch (CmnInfo) { - /* Fixed ODM value. */ - case ODM_CMNINFO_ABILITY: - pDM_Odm->SupportAbility = (u32)Value; - break; - case ODM_CMNINFO_PLATFORM: - pDM_Odm->SupportPlatform = (u8)Value; - break; - case ODM_CMNINFO_INTERFACE: - pDM_Odm->SupportInterface = (u8)Value; - break; - case ODM_CMNINFO_MP_TEST_CHIP: - pDM_Odm->bIsMPChip = (u8)Value; - break; - case ODM_CMNINFO_IC_TYPE: - pDM_Odm->SupportICType = Value; - break; - case ODM_CMNINFO_CUT_VER: - pDM_Odm->CutVersion = (u8)Value; - break; - case ODM_CMNINFO_RF_TYPE: - pDM_Odm->RFType = (u8)Value; - break; - case ODM_CMNINFO_RF_ANTENNA_TYPE: - pDM_Odm->AntDivType = (u8)Value; - break; - case ODM_CMNINFO_BOARD_TYPE: - pDM_Odm->BoardType = (u8)Value; - break; - case ODM_CMNINFO_EXT_LNA: - pDM_Odm->ExtLNA = (u8)Value; - break; - case ODM_CMNINFO_EXT_PA: - pDM_Odm->ExtPA = (u8)Value; - break; - case ODM_CMNINFO_EXT_TRSW: - pDM_Odm->ExtTRSW = (u8)Value; - break; - case ODM_CMNINFO_PATCH_ID: - pDM_Odm->PatchID = (u8)Value; - break; - case ODM_CMNINFO_BINHCT_TEST: - pDM_Odm->bInHctTest = (bool)Value; - break; - case ODM_CMNINFO_BWIFI_TEST: - pDM_Odm->bWIFITest = (bool)Value; - break; - case ODM_CMNINFO_SMART_CONCURRENT: - pDM_Odm->bDualMacSmartConcurrent = (bool)Value; - break; - /* To remove the compiler warning, must add an empty default statement to handle the other values. */ - default: - /* do nothing */ - break; - } - - /* Tx power tracking BB swing table. */ - /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ - pDM_Odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ - pDM_Odm->BbSwingIdxOfdmCurrent = 12; - pDM_Odm->BbSwingFlagOfdm = false; -} - -void ODM_CmnInfoHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, void *pValue) -{ - /* */ - /* Hook call by reference pointer. */ - /* */ - switch (CmnInfo) { - /* Dynamic call by reference pointer. */ - case ODM_CMNINFO_MAC_PHY_MODE: - pDM_Odm->pMacPhyMode = (u8 *)pValue; - break; - case ODM_CMNINFO_TX_UNI: - pDM_Odm->pNumTxBytesUnicast = (u64 *)pValue; - break; - case ODM_CMNINFO_RX_UNI: - pDM_Odm->pNumRxBytesUnicast = (u64 *)pValue; - break; - case ODM_CMNINFO_WM_MODE: - pDM_Odm->pWirelessMode = (u8 *)pValue; - break; - case ODM_CMNINFO_BAND: - pDM_Odm->pBandType = (u8 *)pValue; - break; - case ODM_CMNINFO_SEC_CHNL_OFFSET: - pDM_Odm->pSecChOffset = (u8 *)pValue; - break; - case ODM_CMNINFO_SEC_MODE: - pDM_Odm->pSecurity = (u8 *)pValue; - break; - case ODM_CMNINFO_BW: - pDM_Odm->pBandWidth = (u8 *)pValue; - break; - case ODM_CMNINFO_CHNL: - pDM_Odm->pChannel = (u8 *)pValue; - break; - case ODM_CMNINFO_DMSP_GET_VALUE: - pDM_Odm->pbGetValueFromOtherMac = (bool *)pValue; - break; - case ODM_CMNINFO_BUDDY_ADAPTOR: - pDM_Odm->pBuddyAdapter = (struct adapter **)pValue; - break; - case ODM_CMNINFO_DMSP_IS_MASTER: - pDM_Odm->pbMasterOfDMSP = (bool *)pValue; - break; - case ODM_CMNINFO_SCAN: - pDM_Odm->pbScanInProcess = (bool *)pValue; - break; - case ODM_CMNINFO_POWER_SAVING: - pDM_Odm->pbPowerSaving = (bool *)pValue; - break; - case ODM_CMNINFO_ONE_PATH_CCA: - pDM_Odm->pOnePathCCA = (u8 *)pValue; - break; - case ODM_CMNINFO_DRV_STOP: - pDM_Odm->pbDriverStopped = (bool *)pValue; - break; - case ODM_CMNINFO_PNP_IN: - pDM_Odm->pbDriverIsGoingToPnpSetPowerSleep = (bool *)pValue; - break; - case ODM_CMNINFO_INIT_ON: - pDM_Odm->pinit_adpt_in_progress = (bool *)pValue; - break; - case ODM_CMNINFO_ANT_TEST: - pDM_Odm->pAntennaTest = (u8 *)pValue; - break; - case ODM_CMNINFO_NET_CLOSED: - pDM_Odm->pbNet_closed = (bool *)pValue; - break; - case ODM_CMNINFO_MP_MODE: - pDM_Odm->mp_mode = (u8 *)pValue; - break; - /* To remove the compiler warning, must add an empty default statement to handle the other values. */ - default: - /* do nothing */ - break; - } -} - void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u16 Index, void *pValue) { /* Hook call by reference pointer. */ @@ -385,46 +241,6 @@ void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info } } -/* Update Band/CHannel/.. The values are dynamic but non-per-packet. */ -void ODM_CmnInfoUpdate(struct odm_dm_struct *pDM_Odm, u32 CmnInfo, u64 Value) -{ - /* */ - /* This init variable may be changed in run time. */ - /* */ - switch (CmnInfo) { - case ODM_CMNINFO_ABILITY: - pDM_Odm->SupportAbility = (u32)Value; - break; - case ODM_CMNINFO_RF_TYPE: - pDM_Odm->RFType = (u8)Value; - break; - case ODM_CMNINFO_WIFI_DIRECT: - pDM_Odm->bWIFI_Direct = (bool)Value; - break; - case ODM_CMNINFO_WIFI_DISPLAY: - pDM_Odm->bWIFI_Display = (bool)Value; - break; - case ODM_CMNINFO_LINK: - pDM_Odm->bLinked = (bool)Value; - break; - case ODM_CMNINFO_RSSI_MIN: - pDM_Odm->RSSI_Min = (u8)Value; - break; - case ODM_CMNINFO_DBG_COMP: - pDM_Odm->DebugComponents = Value; - break; - case ODM_CMNINFO_DBG_LEVEL: - pDM_Odm->DebugLevel = (u32)Value; - break; - case ODM_CMNINFO_RA_THRESHOLD_HIGH: - pDM_Odm->RateAdaptive.HighRSSIThresh = (u8)Value; - break; - case ODM_CMNINFO_RA_THRESHOLD_LOW: - pDM_Odm->RateAdaptive.LowRSSIThresh = (u8)Value; - break; - } -} - void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm) { struct adapter *adapter = pDM_Odm->Adapter; @@ -469,7 +285,6 @@ void odm_CmnInfoInit_Debug(struct odm_dm_struct *pDM_Odm) ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportInterface=%d\n", pDM_Odm->SupportInterface)); ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportICType=0x%x\n", pDM_Odm->SupportICType)); ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CutVersion=%d\n", pDM_Odm->CutVersion)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RFType=%d\n", pDM_Odm->RFType)); ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("BoardType=%d\n", pDM_Odm->BoardType)); ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtLNA=%d\n", pDM_Odm->ExtLNA)); ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtPA=%d\n", pDM_Odm->ExtPA)); @@ -947,37 +762,21 @@ u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, u32 ra_mask, u break; case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G): case (ODM_WM_A|ODM_WM_B|ODM_WM_G|ODM_WM_N24G): - if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) { - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x000f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x000ff000; - } else { - if (*(pDM_Odm->pBandWidth) == ODM_BW40M) - rate_bitmap = 0x000ff015; - else - rate_bitmap = 0x000ff005; - } + if (rssi_level == DM_RATR_STA_HIGH) { + rate_bitmap = 0x000f0000; + } else if (rssi_level == DM_RATR_STA_MIDDLE) { + rate_bitmap = 0x000ff000; } else { - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x0f8f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x0f8ff000; - } else { - if (*(pDM_Odm->pBandWidth) == ODM_BW40M) - rate_bitmap = 0x0f8ff015; - else - rate_bitmap = 0x0f8ff005; - } + if (*(pDM_Odm->pBandWidth) == ODM_BW40M) + rate_bitmap = 0x000ff015; + else + rate_bitmap = 0x000ff005; } break; default: /* case WIRELESS_11_24N: */ /* case WIRELESS_11_5N: */ - if (pDM_Odm->RFType == RF_1T2R) - rate_bitmap = 0x000fffff; - else - rate_bitmap = 0x0fffffff; + rate_bitmap = 0x0fffffff; break; } @@ -1096,8 +895,7 @@ bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate void odm_DynamicTxPowerInit(struct odm_dm_struct *pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; pdmpriv->bDynamicTxPowerEnable = false; pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal; pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; @@ -1122,8 +920,7 @@ void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm) static void FindMinimumRSSI(struct adapter *pAdapter) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; + struct dm_priv *pdmpriv = &pAdapter->HalData->dmpriv; /* 1 1.Unconditionally set RSSI */ pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; @@ -1132,8 +929,7 @@ static void FindMinimumRSSI(struct adapter *pAdapter) void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; int i; int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff; u8 sta_cnt = 0; @@ -1162,7 +958,7 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) for (i = 0; i < sta_cnt; i++) { if (PWDB_rssi[i] != 0) { - ODM_RA_SetRSSI_8188E(&pHalData->odmpriv, + ODM_RA_SetRSSI_8188E(&Adapter->HalData->odmpriv, PWDB_rssi[i] & 0xFF, (PWDB_rssi[i] >> 16) & 0xFF); } @@ -1179,8 +975,7 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0; FindMinimumRSSI(Adapter); - ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, - pdmpriv->MinUndecoratedPWDBForDM); + Adapter->HalData->odmpriv.RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM; } /* 3============================================================ */ @@ -1290,7 +1085,6 @@ void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm) u64 cur_tx_bytes = 0; u64 cur_rx_bytes = 0; u8 bbtchange = false; - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv); struct recv_priv *precvpriv = &(Adapter->recvpriv); struct registry_priv *pregpriv = &Adapter->registrypriv; @@ -1344,7 +1138,8 @@ void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm) /* Turn Off EDCA turbo here. */ /* Restore original EDCA according to the declaration of AP. */ if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) { - usb_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE); + usb_write32(Adapter, REG_EDCA_BE_PARAM, + Adapter->HalData->AcParam_BE); pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; } } diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index a83bbea9be93..5192ef70bcfc 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -65,8 +65,7 @@ static u32 rf_serial_read(struct adapter *adapt, enum rf_radio_path rfpath, u32 offset) { u32 ret = 0; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath]; + struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath]; u32 tmplong, tmplong2; u8 rfpi_enable = 0; @@ -110,15 +109,14 @@ static void rf_serial_write(struct adapter *adapt, u32 data) { u32 data_and_addr = 0; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath]; + struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath]; offset &= 0xff; data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff; phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr); } -u32 phy_query_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, +u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path, u32 reg_addr, u32 bit_mask) { u32 original_value, readback_value, bit_shift; @@ -147,14 +145,11 @@ void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u8 index = (channel - 1); u8 TxCount = 0, path_nums; - if ((RF_1T2R == hal_data->rf_type) || (RF_1T1R == hal_data->rf_type)) - path_nums = 1; - else - path_nums = 2; + path_nums = 1; for (TxCount = 0; TxCount < path_nums; TxCount++) { if (TxCount == RF_PATH_A) { @@ -183,7 +178,7 @@ static void phy_power_index_check(struct adapter *adapt, u8 channel, u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; hal_data->CurrentCckTxPwrIdx = cck_pwr[0]; hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0]; @@ -211,7 +206,7 @@ void phy_set_tx_power_level(struct adapter *adapt, u8 channel) static void phy_set_bw_mode_callback(struct adapter *adapt) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u8 reg_bw_opmode; u8 reg_prsr_rsc; @@ -274,10 +269,10 @@ static void phy_set_bw_mode_callback(struct adapter *adapt) rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW); } -void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth, +void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth, unsigned char offset) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW; hal_data->CurrentChannelBW = bandwidth; @@ -293,10 +288,7 @@ static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) { u8 rf_path; u32 param1, param2; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - - if (adapt->bNotifyChannelChange) - DBG_88E("[%s] ch = %d\n", __func__, channel); + struct hal_data_8188e *hal_data = adapt->HalData; phy_set_tx_power_level(adapt, channel); @@ -310,9 +302,9 @@ static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) } } -void phy_sw_chnl(struct adapter *adapt, u8 channel) +void rtw_hal_set_chan(struct adapter *adapt, u8 channel) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u8 tmpchannel = hal_data->CurrentChannel; if (hal_data->rf_chip == RF_PSEUDO_11N) @@ -407,7 +399,7 @@ static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm) void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset; u8 thermal_avg_count = 0; u32 thermal_avg = 0; @@ -439,7 +431,7 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317; - thermal_val = (u8)phy_query_rf_reg(adapt, RF_PATH_A, + thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_T_METER_88E, 0xfc00); if (is2t) @@ -632,8 +624,7 @@ static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB) { u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp; u8 result = 0x00; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; /* 1 Get TXIMR setting */ /* modify RXIQK mode table */ @@ -737,8 +728,7 @@ static u8 phy_path_b_iqk(struct adapter *adapt) { u32 regeac, regeb4, regebc, regec4, regecc; u8 result = 0x00; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; /* One shot, path B LOK & IQK */ phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002); @@ -954,17 +944,11 @@ static bool simularity_compare(struct adapter *adapt, s32 resulta[][8], u8 c1, u8 c2) { u32 i, j, diff, sim_bitmap = 0, bound; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ bool result = true; s32 tmp1 = 0, tmp2 = 0; - if ((dm_odm->RFType == ODM_2T2R) || (dm_odm->RFType == ODM_2T3R) || - (dm_odm->RFType == ODM_2T4R)) - bound = 8; - else - bound = 4; + bound = 4; for (i = 0; i < bound; i++) { if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) { @@ -1033,8 +1017,7 @@ static bool simularity_compare(struct adapter *adapt, s32 resulta[][8], static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8], u8 t, bool is2t) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; u32 i; u8 path_a_ok, path_b_ok; u32 adda_reg[IQK_ADDA_REG_NUM] = { @@ -1232,12 +1215,12 @@ static void phy_lc_calibrate(struct adapter *adapt, bool is2t) if ((tmpreg&0x70) != 0) { /* 1. Read original RF mode */ /* Path-A */ - rf_a_mode = phy_query_rf_reg(adapt, RF_PATH_A, RF_AC, + rf_a_mode = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_AC, bMask12Bits); /* Path-B */ if (is2t) - rf_b_mode = phy_query_rf_reg(adapt, RF_PATH_B, RF_AC, + rf_b_mode = rtw_hal_read_rfreg(adapt, RF_PATH_B, RF_AC, bMask12Bits); /* 2. Set RF mode = standby mode */ @@ -1252,7 +1235,7 @@ static void phy_lc_calibrate(struct adapter *adapt, bool is2t) } /* 3. Read RF reg18 */ - lc_cal = phy_query_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits); + lc_cal = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits); /* 4. Set LC calibration begin bit15 */ phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits, @@ -1279,8 +1262,7 @@ static void phy_lc_calibrate(struct adapter *adapt, bool is2t) void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; s32 result[4][8]; u8 i, final, chn_index; bool pathaok, pathbok; @@ -1295,7 +1277,7 @@ void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) rOFDM0_RxIQExtAnta}; bool is2t; - is2t = (dm_odm->RFType == ODM_2T2R) ? true : false; + is2t = false; if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION)) return; @@ -1391,7 +1373,7 @@ void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) (reg_ec4 == 0)); } - chn_index = get_right_chnl_for_iqk(hal_data->CurrentChannel); + chn_index = get_right_chnl_for_iqk(adapt->HalData->CurrentChannel); if (final < 4) { for (i = 0; i < IQK_Matrix_REG_NUM; i++) @@ -1407,8 +1389,7 @@ void rtl88eu_phy_lc_calibrate(struct adapter *adapt) { bool singletone = false, carrier_sup = false; u32 timeout = 2000, timecount = 0; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION)) return; @@ -1422,12 +1403,7 @@ void rtl88eu_phy_lc_calibrate(struct adapter *adapt) dm_odm->RFCalibrateInfo.bLCKInProgress = true; - if (dm_odm->RFType == ODM_2T2R) { - phy_lc_calibrate(adapt, true); - } else { - /* For 88C 1T1R */ - phy_lc_calibrate(adapt, false); - } + phy_lc_calibrate(adapt, false); dm_odm->RFCalibrateInfo.bLCKInProgress = false; } diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c index 1596274eefc5..2f3edf0f850a 100644 --- a/drivers/staging/rtl8188eu/hal/rf.c +++ b/drivers/staging/rtl8188eu/hal/rf.c @@ -22,7 +22,7 @@ void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt, enum ht_channel_width bandwidth) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; switch (bandwidth) { case HT_CHANNEL_WIDTH_20: @@ -44,7 +44,7 @@ void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt, void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; struct dm_priv *pdmpriv = &hal_data->dmpriv; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; u32 tx_agc[2] = {0, 0}, tmpval = 0, pwrtrac_value; @@ -129,7 +129,6 @@ static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm, u8 *pwr_level_bw20, u8 *pwr_level_bw40, u8 channel, u32 *ofdmbase, u32 *mcs_base) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); u32 powerbase0, powerbase1; u8 i, powerlevel[2]; @@ -140,9 +139,9 @@ static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm, (powerbase0<<8) | powerbase0; *(ofdmbase+i) = powerbase0; } - for (i = 0; i < hal_data->NumTotalRFPath; i++) { + for (i = 0; i < adapt->HalData->NumTotalRFPath; i++) { /* Check HT20 to HT40 diff */ - if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + if (adapt->HalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) powerlevel[i] = pwr_level_bw20[i]; else powerlevel[i] = pwr_level_bw40[i]; @@ -156,7 +155,7 @@ static void get_rx_power_val_by_reg(struct adapter *adapt, u8 channel, u8 index, u32 *powerbase0, u32 *powerbase1, u32 *out_val) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; struct dm_priv *pdmpriv = &hal_data->dmpriv; u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit; s8 pwr_diff = 0; @@ -286,7 +285,6 @@ void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt, u8 *pwr_level_bw20, u8 *pwr_level_bw40, u8 channel) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); u32 write_val[2], powerbase0[2], powerbase1[2], pwrtrac_value; u8 direction; u8 index = 0; @@ -294,8 +292,8 @@ void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt, getpowerbase88e(adapt, pwr_level_ofdm, pwr_level_bw20, pwr_level_bw40, channel, &powerbase0[0], &powerbase1[0]); - rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 0, &direction, - &pwrtrac_value); + rtl88eu_dm_txpower_track_adjust(&adapt->HalData->odmpriv, 0, + &direction, &pwrtrac_value); for (index = 0; index < 6; index++) { get_rx_power_val_by_reg(adapt, channel, index, diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 453f9e729067..dde64417e66a 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -19,7 +19,7 @@ static bool check_condition(struct adapter *adapt, const u32 condition) { - struct odm_dm_struct *odm = &GET_HAL_DATA(adapt)->odmpriv; + struct odm_dm_struct *odm = &adapt->HalData->odmpriv; u32 _board = odm->BoardType; u32 _platform = odm->SupportPlatform; u32 _interface = odm->SupportInterface; @@ -228,7 +228,7 @@ static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt) static bool rf6052_conf_para(struct adapter *adapt) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; u8 rfpath; bool rtstatus = true; @@ -299,12 +299,9 @@ static bool rf6052_conf_para(struct adapter *adapt) static bool rtl88e_phy_rf6052_config(struct adapter *adapt) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; - if (hal_data->rf_type == RF_1T1R) - hal_data->NumTotalRFPath = 1; - else - hal_data->NumTotalRFPath = 2; + hal_data->NumTotalRFPath = 1; return rf6052_conf_para(adapt); } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 2422c0297a50..d0f59b7836f1 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -60,7 +60,6 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p u8 h2c_box_num; u32 msgbox_addr; u32 msgbox_ex_addr; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); u8 cmd_idx, ext_cmd_len; u32 h2c_cmd = 0; u32 h2c_cmd_ex = 0; @@ -81,7 +80,7 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p /* pay attention to if race condition happened in H2C cmd setting. */ do { - h2c_box_num = haldata->LastHMEBoxNum; + h2c_box_num = adapt->HalData->LastHMEBoxNum; if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) { DBG_88E(" fw read cmd failed...\n"); @@ -110,7 +109,8 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p } bcmd_down = true; - haldata->LastHMEBoxNum = (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS; + adapt->HalData->LastHMEBoxNum = + (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS; } while ((!bcmd_down) && (retry_cnts--)); @@ -126,9 +126,9 @@ exit: /* bitmap[28:31]= Rate Adaptive id */ /* arg[0:4] = macid */ /* arg[5] = Short GI */ -void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level) +void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level) { - struct hal_data_8188e *haldata = GET_HAL_DATA(pAdapter); + struct odm_dm_struct *odmpriv = &pAdapter->HalData->odmpriv; u8 macid, init_rate, raid, shortGIrate = false; @@ -138,7 +138,7 @@ void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi bitmap &= 0x0fffffff; if (rssi_level != DM_RATR_STA_INIT) - bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, macid, bitmap, rssi_level); + bitmap = ODM_Get_Rate_Bitmap(odmpriv, macid, bitmap, rssi_level); bitmap |= ((raid<<28)&0xf0000000); @@ -156,7 +156,7 @@ void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi DBG_88E("%s=> mac_id:%d, raid:%d, ra_bitmap=0x%x, shortGIrate=0x%02x\n", __func__, macid, raid, bitmap, shortGIrate); - ODM_RA_UpdateRateInfo_8188E(&(haldata->odmpriv), macid, raid, bitmap, shortGIrate); + ODM_RA_UpdateRateInfo_8188E(odmpriv, macid, raid, bitmap, shortGIrate); } void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode) @@ -219,7 +219,7 @@ void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt) static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) { - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; u32 rate_len, pktlen; struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); @@ -227,20 +227,20 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, bc_addr); + ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); SetFrameSubType(pframe, WIFI_BEACON); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pktlen = sizeof(struct ieee80211_hdr_3addr); /* timestamp will be inserted by hardware */ pframe += 8; @@ -304,16 +304,16 @@ _ConstructBeacon: static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) { - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); __le16 *fctrl; struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; /* Frame control. */ - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; SetPwrMgt(fctrl); SetFrameSubType(pframe, WIFI_PSPOLL); @@ -322,10 +322,10 @@ static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) SetDuration(pframe, (pmlmeinfo->aid | 0xc000)); /* BSSID. */ - memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress); /* TA. */ - memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv))); *pLength = 16; } @@ -338,7 +338,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, u8 bEosp, u8 bForcePowerSave) { - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; u32 pktlen; struct mlme_priv *pmlmepriv = &adapt->mlmepriv; @@ -347,9 +347,9 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &pwlanhdr->frame_ctl; + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; if (bForcePowerSave) SetPwrMgt(fctrl); @@ -357,40 +357,40 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, switch (cur_network->network.InfrastructureMode) { case Ndis802_11Infrastructure: SetToDs(fctrl); - memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress); + ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, StaAddr); break; case Ndis802_11APMode: SetFrDs(fctrl); - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, pnetwork->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&(adapt->eeprompriv)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, pnetwork->MacAddress); + ether_addr_copy(pwlanhdr->addr3, myid(&(adapt->eeprompriv))); break; case Ndis802_11IBSS: default: - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); break; } SetSeqNum(pwlanhdr, 0); if (bQoS) { - struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr; + struct ieee80211_qos_hdr *pwlanqoshdr; SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); - pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe; - SetPriority(&pwlanqoshdr->qc, AC); - SetEOSP(&pwlanqoshdr->qc, bEosp); + pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe; + SetPriority(&pwlanqoshdr->qos_ctrl, AC); + SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp); - pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos); + pktlen = sizeof(struct ieee80211_qos_hdr); } else { SetFrameSubType(pframe, WIFI_DATA_NULL); - pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct ieee80211_hdr_3addr); } *pLength = pktlen; @@ -398,7 +398,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID) { - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; u8 *mac, *bssid; u32 pktlen; @@ -406,21 +406,21 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; mac = myid(&(adapt->eeprompriv)); bssid = cur_network->MacAddress; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, mac); + ether_addr_copy(pwlanhdr->addr3, bssid); SetSeqNum(pwlanhdr, 0); SetFrameSubType(fctrl, WIFI_PROBERSP); - pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct ieee80211_hdr_3addr); pframe += pktlen; if (cur_network->IELength > MAX_IE_SZ) @@ -445,7 +445,6 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u /* 2009.10.15 by tynli. */ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) { - struct hal_data_8188e *haldata; struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; struct xmit_priv *pxmitpriv; @@ -467,7 +466,6 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) return; } - haldata = GET_HAL_DATA(adapt); pxmitpriv = &adapt->xmitpriv; pmlmeext = &adapt->mlmeextpriv; pmlmeinfo = &pmlmeext->mlmext_info; @@ -487,7 +485,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) if (PageNeed == 1) PageNeed += 1; PageNum += PageNeed; - haldata->FwRsvdPageStartOffset = PageNum; + adapt->HalData->FwRsvdPageStartOffset = PageNum; BufIndex += PageNeed*128; @@ -554,7 +552,7 @@ exit: void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); bool bSendBeacon = false; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 81f2931876f8..d04b7fbb71e1 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -42,43 +42,33 @@ static void dm_InitGPIOSetting(struct adapter *Adapter) /* */ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); + struct hal_data_8188e *hal_data = Adapter->HalData; struct dm_priv *pdmpriv = &hal_data->dmpriv; struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); - u8 cut_ver; /* Init Value */ memset(dm_odm, 0, sizeof(*dm_odm)); dm_odm->Adapter = Adapter; + dm_odm->SupportPlatform = ODM_CE; + dm_odm->SupportICType = ODM_RTL8188E; + dm_odm->CutVersion = ODM_CUT_A; + dm_odm->bIsMPChip = hal_data->VersionID.ChipType == NORMAL_CHIP; + dm_odm->PatchID = hal_data->CustomerID; + dm_odm->bWIFITest = Adapter->registrypriv.wifi_spec; - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PLATFORM, ODM_CE); + dm_odm->AntDivType = hal_data->TRxAntDivType; - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8188E); - - cut_ver = ODM_CUT_A; - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_CUT_VER, cut_ver); - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_MP_TEST_CHIP, hal_data->VersionID.ChipType == NORMAL_CHIP ? true : false); - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PATCH_ID, hal_data->CustomerID); - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec); - - - if (hal_data->rf_type == RF_1T1R) - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R); - else if (hal_data->rf_type == RF_2T2R) - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R); - else if (hal_data->rf_type == RF_1T2R) - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R); - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType); + /* Tx power tracking BB swing table. */ + /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ + dm_odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ + dm_odm->BbSwingIdxOfdmCurrent = 12; + dm_odm->BbSwingFlagOfdm = false; pdmpriv->InitODMFlag = ODM_RF_CALIBRATION | ODM_RF_TX_PWR_TRACK; - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag); + dm_odm->SupportAbility = pdmpriv->InitODMFlag; } static void Update_ODM_ComInfo_88E(struct adapter *Adapter) @@ -86,7 +76,7 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); + struct hal_data_8188e *hal_data = Adapter->HalData; struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); struct dm_priv *pdmpriv = &hal_data->dmpriv; int i; @@ -109,20 +99,26 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) ODM_RF_TX_PWR_TRACK; } - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag); + dm_odm->SupportAbility = pdmpriv->InitODMFlag; - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_TX_UNI, &(Adapter->xmitpriv.tx_bytes)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_RX_UNI, &(Adapter->recvpriv.rx_bytes)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_WM_MODE, &(pmlmeext->cur_wireless_mode)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SEC_CHNL_OFFSET, &(hal_data->nCur40MhzPrimeSC)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SEC_MODE, &(Adapter->securitypriv.dot11PrivacyAlgrthm)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_BW, &(hal_data->CurrentChannelBW)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_CHNL, &(hal_data->CurrentChannel)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_NET_CLOSED, &(Adapter->net_closed)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_MP_MODE, &(Adapter->registrypriv.mp_mode)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SCAN, &(pmlmepriv->bScanInProcess)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_POWER_SAVING, &(pwrctrlpriv->bpower_saving)); - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType); + dm_odm->pNumTxBytesUnicast = &Adapter->xmitpriv.tx_bytes; + dm_odm->pNumRxBytesUnicast = &Adapter->recvpriv.rx_bytes; + dm_odm->pWirelessMode = &pmlmeext->cur_wireless_mode; + dm_odm->pSecChOffset = &hal_data->nCur40MhzPrimeSC; + dm_odm->pSecurity = (u8 *)&Adapter->securitypriv.dot11PrivacyAlgrthm; + dm_odm->pBandWidth = (u8 *)&hal_data->CurrentChannelBW; + dm_odm->pChannel = &hal_data->CurrentChannel; + dm_odm->pbNet_closed = (bool *)&Adapter->net_closed; + dm_odm->mp_mode = &Adapter->registrypriv.mp_mode; + dm_odm->pbScanInProcess = (bool *)&pmlmepriv->bScanInProcess; + dm_odm->pbPowerSaving = (bool *)&pwrctrlpriv->bpower_saving; + dm_odm->AntDivType = hal_data->TRxAntDivType; + + /* Tx power tracking BB swing table. */ + /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ + dm_odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ + dm_odm->BbSwingIdxOfdmCurrent = 12; + dm_odm->BbSwingFlagOfdm = false; for (i = 0; i < NUM_STA; i++) ODM_CmnInfoPtrArrayHook(dm_odm, ODM_CMNINFO_STA_STATUS, i, NULL); @@ -130,23 +126,19 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) void rtl8188e_InitHalDm(struct adapter *Adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &hal_data->dmpriv; - struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; + struct odm_dm_struct *dm_odm = &(Adapter->HalData->odmpriv); dm_InitGPIOSetting(Adapter); pdmpriv->DM_Type = DM_Type_ByDriver; pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE; Update_ODM_ComInfo_88E(Adapter); ODM_DMInit(dm_odm); - Adapter->fix_rate = 0xFF; } -void rtl8188e_HalDmWatchDog(struct adapter *Adapter) +void rtw_hal_dm_watchdog(struct adapter *Adapter) { - bool fw_ps_awake = true; u8 hw_init_completed = false; - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); struct mlme_priv *pmlmepriv = NULL; u8 bLinked = false; @@ -155,13 +147,6 @@ void rtl8188e_HalDmWatchDog(struct adapter *Adapter) if (!hw_init_completed) goto skip_dm; - rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&fw_ps_awake)); - - /* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */ - /* modifed by thomas. 2011.06.11. */ - if (Adapter->wdinfo.p2p_ps_mode) - fw_ps_awake = false; - /* ODM */ pmlmepriv = &Adapter->mlmepriv; @@ -175,19 +160,18 @@ void rtl8188e_HalDmWatchDog(struct adapter *Adapter) bLinked = true; } - ODM_CmnInfoUpdate(&hal_data->odmpriv, ODM_CMNINFO_LINK, bLinked); - ODM_DMWatchdog(&hal_data->odmpriv); + Adapter->HalData->odmpriv.bLinked = bLinked; + ODM_DMWatchdog(&Adapter->HalData->odmpriv); skip_dm: /* Check GPIO to determine current RF on/off and Pbc status. */ /* Check Hardware Radio ON/OFF or not */ return; } -void rtl8188e_init_dm_priv(struct adapter *Adapter) +void rtw_hal_dm_init(struct adapter *Adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &hal_data->dmpriv; - struct odm_dm_struct *podmpriv = &hal_data->odmpriv; + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; + struct odm_dm_struct *podmpriv = &Adapter->HalData->odmpriv; memset(pdmpriv, 0, sizeof(struct dm_priv)); Init_ODM_ComInfo_88E(Adapter); @@ -196,11 +180,9 @@ void rtl8188e_init_dm_priv(struct adapter *Adapter) /* Add new function to reset the state of antenna diversity before link. */ /* Compare RSSI for deciding antenna */ -void AntDivCompare8188E(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src) +void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); - - if (0 != hal_data->AntDivCfg) { + if (0 != Adapter->HalData->AntDivCfg) { /* select optimum_antenna for before linked =>For antenna diversity */ if (dst->Rssi >= src->Rssi) {/* keep org parameter */ src->Rssi = dst->Rssi; @@ -210,15 +192,14 @@ void AntDivCompare8188E(struct adapter *Adapter, struct wlan_bssid_ex *dst, stru } /* Add new function to reset the state of antenna diversity before link. */ -u8 AntDivBeforeLink8188E(struct adapter *Adapter) +u8 rtw_hal_antdiv_before_linked(struct adapter *Adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv; struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table; struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); /* Condition that does not need to use antenna diversity. */ - if (hal_data->AntDivCfg == 0) + if (Adapter->HalData->AntDivCfg == 0) return false; if (check_fwstate(pmlmepriv, _FW_LINKED)) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 0b444fd3e550..385bc2f56f2f 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -108,28 +108,24 @@ void _8051Reset88E(struct adapter *padapter) void rtl8188e_InitializeFirmwareVars(struct adapter *padapter) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - /* Init Fw LPS related. */ padapter->pwrctrlpriv.bFwCurrentInPSMode = false; /* Init H2C counter. by tynli. 2009.12.09. */ - pHalData->LastHMEBoxNum = 0; + padapter->HalData->LastHMEBoxNum = 0; } -static void rtl8188e_free_hal_data(struct adapter *padapter) +void rtw_hal_free_data(struct adapter *padapter) { kfree(padapter->HalData); padapter->HalData = NULL; } -static void ReadChipVersion8188E(struct adapter *padapter) +void rtw_hal_read_chip_version(struct adapter *padapter) { u32 value32; struct HAL_VERSION ChipVersion; - struct hal_data_8188e *pHalData; - - pHalData = GET_HAL_DATA(padapter); + struct hal_data_8188e *pHalData = padapter->HalData; value32 = usb_read32(padapter, REG_SYS_CFG); ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP); @@ -139,16 +135,13 @@ static void ReadChipVersion8188E(struct adapter *padapter) dump_chip_info(ChipVersion); pHalData->VersionID = ChipVersion; - pHalData->rf_type = RF_1T1R; pHalData->NumTotalRFPath = 1; - - MSG_88E("RF_Type is %x!!\n", pHalData->rf_type); } -static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet) +void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); - struct odm_dm_struct *podmpriv = &pHalData->odmpriv; + struct odm_dm_struct *podmpriv = &Adapter->HalData->odmpriv; + switch (eVariable) { case HAL_ODM_STA_INFO: { @@ -165,17 +158,17 @@ static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable } break; case HAL_ODM_P2P_STATE: - ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet); + podmpriv->bWIFI_Direct = bSet; break; case HAL_ODM_WIFI_DISPLAY_STATE: - ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet); + podmpriv->bWIFI_Display = bSet; break; default: break; } } -static void hal_notch_filter_8188e(struct adapter *adapter, bool enable) +void rtw_hal_notch_filter(struct adapter *adapter, bool enable) { if (enable) { DBG_88E("Enable notch filter\n"); @@ -185,32 +178,6 @@ static void hal_notch_filter_8188e(struct adapter *adapter, bool enable) usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) & ~BIT(1)); } } -void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) -{ - pHalFunc->free_hal_data = &rtl8188e_free_hal_data; - - pHalFunc->dm_init = &rtl8188e_init_dm_priv; - - pHalFunc->read_chip_version = &ReadChipVersion8188E; - - pHalFunc->set_bwmode_handler = &phy_set_bw_mode; - pHalFunc->set_channel_handler = &phy_sw_chnl; - - pHalFunc->hal_dm_watchdog = &rtl8188e_HalDmWatchDog; - - pHalFunc->Add_RateATid = &rtl8188e_Add_RateATid; - - pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E; - pHalFunc->AntDivCompareHandler = &AntDivCompare8188E; - pHalFunc->read_rfreg = &phy_query_rf_reg; - - pHalFunc->sreset_init_value = &sreset_init_value; - pHalFunc->sreset_get_wifi_status = &sreset_get_wifi_status; - - pHalFunc->SetHalODMVarHandler = &rtl8188e_SetHalODMVar; - - pHalFunc->hal_notch_filter = &hal_notch_filter_8188e; -} /* */ /* */ @@ -501,7 +468,7 @@ void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoL void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); + struct hal_data_8188e *pHalData = padapter->HalData; struct txpowerinfo24g pwrInfo24G; u8 rfPath, ch, group; u8 bIn24G, TxCount; @@ -553,7 +520,7 @@ void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool Auto void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); + struct hal_data_8188e *pHalData = pAdapter->HalData; if (!AutoLoadFail) { pHalData->CrystalCap = hwinfo[EEPROM_XTAL_88E]; @@ -567,7 +534,7 @@ void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoa void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); + struct hal_data_8188e *pHalData = pAdapter->HalData; if (!AutoLoadFail) pHalData->BoardType = (hwinfo[EEPROM_RF_BOARD_OPTION_88E] @@ -579,7 +546,7 @@ void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoL void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); + struct hal_data_8188e *pHalData = padapter->HalData; if (!AutoLoadFail) { pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_88E]; @@ -606,7 +573,7 @@ void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool Auto void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); + struct hal_data_8188e *pHalData = padapter->HalData; if (!AutoLoadFail) { pHalData->EEPROMCustomerID = hwinfo[EEPROM_CUSTOMERID_88E]; @@ -619,7 +586,7 @@ void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool Auto void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); + struct hal_data_8188e *pHalData = pAdapter->HalData; struct registry_priv *registry_par = &pAdapter->registrypriv; if (!AutoLoadFail) { @@ -652,7 +619,7 @@ void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); + struct hal_data_8188e *pHalData = Adapter->HalData; /* ThermalMeter from EEPROM */ if (!AutoloadFail) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index f110c961df70..fa2cfd5768de 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -57,10 +57,9 @@ static void process_link_qual(struct adapter *padapter, signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num; } -void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe) +void rtl8188e_process_phy_info(struct adapter *padapter, + struct recv_frame *precvframe) { - struct recv_frame *precvframe = prframe; - /* Check RSSI */ process_rssi(padapter, precvframe); /* Check EVM */ @@ -140,7 +139,6 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, { struct adapter *padapter = precvframe->adapter; struct rx_pkt_attrib *pattrib = &precvframe->attrib; - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); struct odm_phy_status_info *pPHYInfo = (struct odm_phy_status_info *)(&pattrib->phy_info); u8 *wlanhdr; struct odm_per_pkt_info pkt_info; @@ -181,7 +179,8 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, pkt_info.StationID = psta->mac_id; pkt_info.Rate = pattrib->mcs_rate; - ODM_PhyStatusQuery(&pHalData->odmpriv, pPHYInfo, (u8 *)pphy_status, &(pkt_info)); + ODM_PhyStatusQuery(&padapter->HalData->odmpriv, pPHYInfo, + (u8 *)pphy_status, &(pkt_info)); precvframe->psta = NULL; if (pkt_info.bPacketMatchBSSID && diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index d9e677ef8f84..780666a755ee 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -40,14 +40,13 @@ void SwLedOn(struct adapter *padapter, struct LED_871x *pLed) void SwLedOff(struct adapter *padapter, struct LED_871x *pLed) { u8 LedCfg; - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); if (padapter->bSurpriseRemoved || padapter->bDriverStopped) goto exit; LedCfg = usb_read8(padapter, REG_LEDCFG2);/* 0x4E */ - if (pHalData->bLedOpenDrain) { + if (padapter->HalData->bLedOpenDrain) { /* Open-drain arrangement for controlling the LED) */ LedCfg &= 0x90; /* Set to software control. */ usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3))); @@ -66,21 +65,20 @@ exit: /* Description: */ /* Initialize all LED_871x objects. */ -void rtl8188eu_InitSwLeds(struct adapter *padapter) +void rtw_hal_sw_led_init(struct adapter *padapter) { struct led_priv *pledpriv = &(padapter->ledpriv); - struct hal_data_8188e *haldata = GET_HAL_DATA(padapter); pledpriv->bRegUseLed = true; pledpriv->LedControlHandler = LedControl8188eu; - haldata->bLedOpenDrain = true; + padapter->HalData->bLedOpenDrain = true; InitLed871x(padapter, &(pledpriv->SwLed0)); } /* Description: */ /* DeInitialize all LED_819xUsb objects. */ -void rtl8188eu_DeInitSwLeds(struct adapter *padapter) +void rtw_hal_sw_led_deinit(struct adapter *padapter) { struct led_priv *ledpriv = &(padapter->ledpriv); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index 255d6f215091..d0495a16ff79 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -13,6 +13,7 @@ * ******************************************************************************/ #define _RTL8188EU_RECV_C_ +#include #include #include #include @@ -23,7 +24,7 @@ #include -int rtl8188eu_init_recv_priv(struct adapter *padapter) +int rtw_hal_init_recv_priv(struct adapter *padapter) { struct recv_priv *precvpriv = &padapter->recvpriv; int i, res = _SUCCESS; @@ -72,6 +73,7 @@ int rtl8188eu_init_recv_priv(struct adapter *padapter) MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL); if (pskb) { + kmemleak_not_leak(pskb); pskb->dev = padapter->pnetdev; tmpaddr = (size_t)pskb->data; alignm = tmpaddr & (RECVBUFF_ALIGN_SZ-1); @@ -87,7 +89,7 @@ exit: return res; } -void rtl8188eu_free_recv_priv(struct adapter *padapter) +void rtw_hal_free_recv_priv(struct adapter *padapter) { int i; struct recv_buf *precvbuf; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index ec21d8c82eba..85650b2663ec 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -21,7 +21,7 @@ #include #include -s32 rtl8188eu_init_xmit_priv(struct adapter *adapt) +s32 rtw_hal_init_xmit_priv(struct adapter *adapt) { struct xmit_priv *pxmitpriv = &adapt->xmitpriv; @@ -33,11 +33,7 @@ s32 rtl8188eu_init_xmit_priv(struct adapter *adapt) static u8 urb_zero_packet_chk(struct adapter *adapt, int sz) { - u8 set_tx_desc_offset; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - set_tx_desc_offset = (((sz + TXDESC_SIZE) % haldata->UsbBulkOutSize) == 0) ? 1 : 0; - - return set_tx_desc_offset; + return !((sz + TXDESC_SIZE) % adapt->HalData->UsbBulkOutSize); } static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc) @@ -175,7 +171,7 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag u8 data_rate, pwr_status, offset; struct adapter *adapt = pxmitframe->padapter; struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct odm_dm_struct *odmpriv = &adapt->HalData->odmpriv; struct tx_desc *ptxdesc = (struct tx_desc *)pmem; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); @@ -259,12 +255,12 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */ if (pattrib->ht_en) { - if (ODM_RA_GetShortGI_8188E(&haldata->odmpriv, pattrib->mac_id)) + if (ODM_RA_GetShortGI_8188E(odmpriv, pattrib->mac_id)) ptxdesc->txdw5 |= cpu_to_le32(SGI);/* SGI */ } - data_rate = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, pattrib->mac_id); + data_rate = ODM_RA_GetDecisionRate_8188E(odmpriv, pattrib->mac_id); ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F); - pwr_status = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, pattrib->mac_id); + pwr_status = ODM_RA_GetHwPwrStatus_8188E(odmpriv, pattrib->mac_id); ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT); } else { /* EAP data packet and ARP packet and DHCP. */ @@ -332,8 +328,7 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */ } - rtl88eu_dm_set_tx_ant_by_tx_info(&haldata->odmpriv, pmem, - pattrib->mac_id); + rtl88eu_dm_set_tx_ant_by_tx_info(odmpriv, pmem, pattrib->mac_id); rtl8188eu_cal_txdesc_chksum(ptxdesc); _dbg_dump_tx_info(adapt, pxmitframe->frame_tag, ptxdesc); @@ -387,7 +382,7 @@ static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe) } ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe); - inner_ret = usb_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf); + inner_ret = usb_write_port(adapt, ff_hwaddr, w_sz, pxmitbuf); rtw_count_tx_stats(adapt, pxmitframe, sz); @@ -424,11 +419,11 @@ static u32 xmitframe_need_length(struct xmit_frame *pxmitframe) return len; } -s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pfirstframe = NULL; + struct xmit_buf *pxmitbuf; /* aggregate variable */ struct hw_xmit *phwxmit; @@ -441,7 +436,7 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp u32 pbuf_tail; /* last pkt tail */ u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */ - u32 bulksize = haldata->UsbBulkOutSize; + u32 bulksize = adapt->HalData->UsbBulkOutSize; u8 desc_cnt; u32 bulkptr; @@ -450,12 +445,9 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n")); - /* check xmitbuffer is ok */ - if (pxmitbuf == NULL) { - pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); - if (pxmitbuf == NULL) - return false; - } + pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); + if (pxmitbuf == NULL) + return false; /* 3 1. pick up first frame */ rtw_free_xmitframe(pxmitpriv, pxmitframe); @@ -565,7 +557,7 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp if (pbuf < bulkptr) { desc_cnt++; - if (desc_cnt == haldata->UsbTxAggDescNum) + if (desc_cnt == adapt->HalData->UsbTxAggDescNum) break; } else { desc_cnt = 0; @@ -594,7 +586,7 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp /* 3 4. write xmit buffer to USB FIFO */ ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe); - usb_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf); + usb_write_port(adapt, ff_hwaddr, pbuf_tail, pxmitbuf); /* 3 5. update statisitc */ pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE); @@ -607,24 +599,12 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp return true; } -static s32 xmitframe_direct(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - s32 res; - - res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); - if (res == _SUCCESS) - rtw_dump_xframe(adapt, pxmitframe); - else - DBG_88E("==> %s xmitframe_coalsece failed\n", __func__); - return res; -} - /* * Return * true dump packet directly * false enqueue packet */ -static s32 pre_xmitframe(struct adapter *adapt, struct xmit_frame *pxmitframe) +s32 rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) { s32 res; struct xmit_buf *pxmitbuf = NULL; @@ -650,7 +630,12 @@ static s32 pre_xmitframe(struct adapter *adapt, struct xmit_frame *pxmitframe) pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; - if (xmitframe_direct(adapt, pxmitframe) != _SUCCESS) { + res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); + + if (res == _SUCCESS) { + rtw_dump_xframe(adapt, pxmitframe); + } else { + DBG_88E("==> %s xmitframe_coalsece failed\n", __func__); rtw_free_xmitbuf(pxmitpriv, pxmitbuf); rtw_free_xmitframe(pxmitpriv, pxmitframe); } @@ -674,20 +659,10 @@ enqueue: return false; } -s32 rtl8188eu_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) +s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) { struct xmit_priv *xmitpriv = &adapt->xmitpriv; rtl88eu_mon_xmit_hook(adapt->pmondev, pmgntframe, xmitpriv->frag_len); return rtw_dump_xframe(adapt, pmgntframe); } - -/* - * Return - * true dump packet directly ok - * false temporary can't transmit packets to hardware - */ -s32 rtl8188eu_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - return pre_xmitframe(adapt, pxmitframe); -} diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 363f3a34ddce..7692ca495ee5 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -21,14 +21,13 @@ #include #include #include -#include #include #define HAL_BB_ENABLE 1 static void _ConfigNormalChipOutEP_8188E(struct adapter *adapt, u8 NumOutPipe) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; switch (NumOutPipe) { case 3: @@ -51,13 +50,12 @@ static void _ConfigNormalChipOutEP_8188E(struct adapter *adapt, u8 NumOutPipe) static bool HalUsbSetQueuePipeMapping8188EUsb(struct adapter *adapt, u8 NumInPipe, u8 NumOutPipe) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); bool result = false; _ConfigNormalChipOutEP_8188E(adapt, NumOutPipe); /* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */ - if (haldata->OutEpNumber == 1) { + if (adapt->HalData->OutEpNumber == 1) { if (NumInPipe != 1) return result; } @@ -69,9 +67,9 @@ static bool HalUsbSetQueuePipeMapping8188EUsb(struct adapter *adapt, u8 NumInPip return result; } -static void rtl8188eu_interface_configure(struct adapter *adapt) +void rtw_hal_chip_configure(struct adapter *adapt) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapt); if (pdvobjpriv->ishighspeed) @@ -94,12 +92,11 @@ static void rtl8188eu_interface_configure(struct adapter *adapt) pdvobjpriv->RtNumInPipes, pdvobjpriv->RtNumOutPipes); } -static u32 rtl8188eu_InitPowerOn(struct adapter *adapt) +u32 rtw_hal_power_on(struct adapter *adapt) { u16 value16; /* HW Power on sequence */ - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - if (haldata->bMacPwrCtrlOn) + if (adapt->HalData->bMacPwrCtrlOn) return _SUCCESS; if (!rtl88eu_pwrseqcmdparsing(adapt, PWR_CUT_ALL_MSK, @@ -119,7 +116,7 @@ static u32 rtl8188eu_InitPowerOn(struct adapter *adapt) /* for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */ usb_write16(adapt, REG_CR, value16); - haldata->bMacPwrCtrlOn = true; + adapt->HalData->bMacPwrCtrlOn = true; return _SUCCESS; } @@ -129,18 +126,17 @@ static void _InitInterrupt(struct adapter *Adapter) { u32 imr, imr_ex; u8 usb_opt; - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); /* HISR write one to clear */ usb_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF); /* HIMR - */ imr = IMR_PSTIMEOUT_88E | IMR_TBDER_88E | IMR_CPWM_88E | IMR_CPWM2_88E; usb_write32(Adapter, REG_HIMR_88E, imr); - haldata->IntrMask[0] = imr; + Adapter->HalData->IntrMask[0] = imr; imr_ex = IMR_TXERR_88E | IMR_RXERR_88E | IMR_TXFOVW_88E | IMR_RXFOVW_88E; usb_write32(Adapter, REG_HIMRE_88E, imr_ex); - haldata->IntrMask[1] = imr_ex; + Adapter->HalData->IntrMask[1] = imr_ex; /* REG_USB_SPECIAL_OPTION - BIT(4) */ /* 0; Use interrupt endpoint to upload interrupt pkt */ @@ -157,7 +153,6 @@ static void _InitInterrupt(struct adapter *Adapter) static void _InitQueueReservedPage(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); struct registry_priv *pregistrypriv = &Adapter->registrypriv; u32 numHQ = 0; u32 numLQ = 0; @@ -168,14 +163,14 @@ static void _InitQueueReservedPage(struct adapter *Adapter) bool bWiFiConfig = pregistrypriv->wifi_spec; if (bWiFiConfig) { - if (haldata->OutEpQueueSel & TX_SELE_HQ) + if (Adapter->HalData->OutEpQueueSel & TX_SELE_HQ) numHQ = 0x29; - if (haldata->OutEpQueueSel & TX_SELE_LQ) + if (Adapter->HalData->OutEpQueueSel & TX_SELE_LQ) numLQ = 0x1C; /* NOTE: This step shall be proceed before writing REG_RQPN. */ - if (haldata->OutEpQueueSel & TX_SELE_NQ) + if (Adapter->HalData->OutEpQueueSel & TX_SELE_NQ) numNQ = 0x1C; value8 = (u8)_NPQ(numNQ); usb_write8(Adapter, REG_RQPN_NPQ, value8); @@ -225,10 +220,9 @@ static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ, static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - u16 value = 0; - switch (haldata->OutEpQueueSel) { + + switch (Adapter->HalData->OutEpQueueSel) { case TX_SELE_HQ: value = QUEUE_HIGH; break; @@ -247,13 +241,12 @@ static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter) static void _InitNormalChipTwoOutEpPriority(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); struct registry_priv *pregistrypriv = &Adapter->registrypriv; u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; u16 valueHi = 0; u16 valueLow = 0; - switch (haldata->OutEpQueueSel) { + switch (Adapter->HalData->OutEpQueueSel) { case (TX_SELE_HQ | TX_SELE_LQ): valueHi = QUEUE_HIGH; valueLow = QUEUE_LOW; @@ -313,9 +306,7 @@ static void _InitNormalChipThreeOutEpPriority(struct adapter *Adapter) static void _InitQueuePriority(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - - switch (haldata->OutEpNumber) { + switch (Adapter->HalData->OutEpNumber) { case 1: _InitNormalChipOneOutEpPriority(Adapter); break; @@ -357,7 +348,7 @@ static void _InitDriverInfoSize(struct adapter *Adapter, u8 drvInfoSize) static void _InitWMACSetting(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; haldata->ReceiveConfig = RCR_AAP | RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA | RCR_CBSSID_BCN | @@ -456,7 +447,7 @@ static void _InitRetryFunction(struct adapter *Adapter) */ static void usb_AggSettingTxUpdate(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; u32 value32; if (Adapter->registrypriv.wifi_spec) @@ -492,7 +483,7 @@ usb_AggSettingRxUpdate( struct adapter *Adapter ) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; u8 valueDMA; u8 valueUSB; @@ -566,8 +557,6 @@ usb_AggSettingRxUpdate( static void InitUsbAggregationSetting(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - /* Tx aggregation setting */ usb_AggSettingTxUpdate(Adapter); @@ -575,12 +564,12 @@ static void InitUsbAggregationSetting(struct adapter *Adapter) usb_AggSettingRxUpdate(Adapter); /* 201/12/10 MH Add for USB agg mode dynamic switch. */ - haldata->UsbRxHighSpeedMode = false; + Adapter->HalData->UsbRxHighSpeedMode = false; } static void _InitBeaconParameters(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; usb_write16(Adapter, REG_BCN_CTRL, 0x1010); @@ -622,7 +611,7 @@ enum { static void _InitAntenna_Selection(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; if (haldata->AntDivCfg == 0) return; @@ -672,13 +661,13 @@ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt) return rfpowerstate; } /* HalDetectPwrDownMode */ -static u32 rtl8188eu_hal_init(struct adapter *Adapter) +u32 rtl8188eu_hal_init(struct adapter *Adapter) { u8 value8 = 0; u16 value16; u8 txpktbuf_bndy; u32 status = _SUCCESS; - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; struct registry_priv *pregistrypriv = &Adapter->registrypriv; unsigned long init_start_time = jiffies; @@ -702,7 +691,7 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter) } HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON); - status = rtl8188eu_InitPowerOn(Adapter); + status = rtw_hal_power_on(Adapter); if (status == _FAIL) { RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("Failed to init power on!\n")); goto exit; @@ -810,8 +799,8 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter) usb_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */ /* Keep RfRegChnlVal for later use. */ - haldata->RfRegChnlVal[0] = phy_query_rf_reg(Adapter, (enum rf_radio_path)0, RF_CHNLBW, bRFRegOffsetMask); - haldata->RfRegChnlVal[1] = phy_query_rf_reg(Adapter, (enum rf_radio_path)1, RF_CHNLBW, bRFRegOffsetMask); + haldata->RfRegChnlVal[0] = rtw_hal_read_rfreg(Adapter, (enum rf_radio_path)0, RF_CHNLBW, bRFRegOffsetMask); + haldata->RfRegChnlVal[1] = rtw_hal_read_rfreg(Adapter, (enum rf_radio_path)1, RF_CHNLBW, bRFRegOffsetMask); HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_TURN_ON_BLOCK); _BBTurnOnBlock(Adapter); @@ -905,7 +894,6 @@ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END); static void CardDisableRTL8188EU(struct adapter *Adapter) { u8 val8; - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("CardDisableRTL8188EU\n")); @@ -958,7 +946,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) 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 */ - haldata->bMacPwrCtrlOn = false; + Adapter->HalData->bMacPwrCtrlOn = false; Adapter->bFWReady = false; } @@ -972,7 +960,7 @@ static void rtl8192cu_hw_power_down(struct adapter *adapt) usb_write16(adapt, REG_APS_FSMCO, 0x8812); } -static u32 rtl8188eu_hal_deinit(struct adapter *Adapter) +u32 rtl8188eu_hal_deinit(struct adapter *Adapter) { DBG_88E("==> %s\n", __func__); @@ -994,7 +982,7 @@ static u32 rtl8188eu_hal_deinit(struct adapter *Adapter) return _SUCCESS; } -static unsigned int rtl8188eu_inirp_init(struct adapter *Adapter) +u32 rtw_hal_inirp_init(struct adapter *Adapter) { u8 i; struct recv_buf *precvbuf; @@ -1029,17 +1017,6 @@ exit: return status; } -static unsigned int rtl8188eu_inirp_deinit(struct adapter *Adapter) -{ - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("\n ===> usb_rx_deinit\n")); - - usb_read_port_cancel(Adapter); - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("\n <=== usb_rx_deinit\n")); - - return _SUCCESS; -} - /* */ /* */ /* EEPROM/EFUSE Content Parsing */ @@ -1047,7 +1024,7 @@ static unsigned int rtl8188eu_inirp_deinit(struct adapter *Adapter) /* */ static void Hal_EfuseParsePIDVID_8188EU(struct adapter *adapt, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; if (!AutoLoadFail) { /* VID, PID */ @@ -1132,12 +1109,10 @@ static void _ReadPROMContent( static void _ReadRFType(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - - haldata->rf_chip = RF_6052; + Adapter->HalData->rf_chip = RF_6052; } -static void _ReadAdapterInfo8188EU(struct adapter *Adapter) +void rtw_hal_read_chip_info(struct adapter *Adapter) { unsigned long start = jiffies; @@ -1157,7 +1132,7 @@ static void rtl8192cu_trigger_gpio_0(struct adapter *adapt) static void ResumeTxBeacon(struct adapter *adapt) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; /* 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. */ @@ -1171,7 +1146,7 @@ static void ResumeTxBeacon(struct adapter *adapt) static void StopTxBeacon(struct adapter *adapt) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; /* 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. */ @@ -1276,9 +1251,9 @@ static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg)&(~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); } -static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) +void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; struct dm_priv *pdmpriv = &haldata->dmpriv; struct odm_dm_struct *podmpriv = &haldata->odmpriv; @@ -1426,17 +1401,8 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) /* enable update TSF */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); } - if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); - } else { - if (Adapter->in_cta_test) { - u32 v = usb_read32(Adapter, REG_RCR); - v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */ - usb_write32(Adapter, REG_RCR, v); - } else { - 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: @@ -1449,13 +1415,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) /* enable to rx data frame.Accept all data frame */ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); - if (Adapter->in_cta_test) { - u32 v = usb_read32(Adapter, REG_RCR); - v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */ - usb_write32(Adapter, REG_RCR, v); - } else { - 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; @@ -1525,9 +1485,6 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) case HW_VAR_SEC_CFG: usb_write8(Adapter, REG_SECCFG, *((u8 *)val)); break; - case HW_VAR_DM_FLAG: - podmpriv->SupportAbility = *((u8 *)val); - break; case HW_VAR_DM_FUNC_OP: if (val[0]) podmpriv->BK_SupportAbility = podmpriv->SupportAbility; @@ -1793,14 +1750,11 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) } } -static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) +void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - struct odm_dm_struct *podmpriv = &haldata->odmpriv; - switch (variable) { case HW_VAR_BASIC_RATE: - *((u16 *)(val)) = haldata->BasicRateSet; + *((u16 *)(val)) = Adapter->HalData->BasicRateSet; case HW_VAR_TXPAUSE: val[0] = usb_read8(Adapter, REG_TXPAUSE); break; @@ -1808,11 +1762,8 @@ static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */ val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false; break; - case HW_VAR_DM_FLAG: - val[0] = podmpriv->SupportAbility; - break; case HW_VAR_RF_TYPE: - val[0] = haldata->rf_type; + val[0] = RF_1T1R; break; case HW_VAR_FWLPS_RF_ON: { @@ -1833,13 +1784,13 @@ static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) } break; case HW_VAR_CURRENT_ANTENNA: - val[0] = haldata->CurAntenna; + val[0] = Adapter->HalData->CurAntenna; break; case HW_VAR_EFUSE_BYTES: /* To get EFUE total used bytes, added by Roger, 2008.12.22. */ - *((u16 *)(val)) = haldata->EfuseUsedBytes; + *((u16 *)(val)) = Adapter->HalData->EfuseUsedBytes; break; case HW_VAR_APFM_ON_MAC: - *val = haldata->bMacPwrCtrlOn; + *val = Adapter->HalData->bMacPwrCtrlOn; break; case HW_VAR_CHK_HI_QUEUE_EMPTY: *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION)&0x0000ff00) == 0) ? true : false; @@ -1853,14 +1804,13 @@ static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) /* Description: */ /* Query setting of specified variable. */ /* */ -static u8 -GetHalDefVar8188EUsb( +u8 rtw_hal_get_def_var( struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue ) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; u8 bResult = _SUCCESS; switch (eVariable) { @@ -1948,7 +1898,7 @@ GetHalDefVar8188EUsb( return bResult; } -static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) +void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) { u8 init_rate = 0; u8 networkType, raid; @@ -1956,7 +1906,7 @@ static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_l u8 shortGIrate = false; int supportRateNum = 0; struct sta_info *psta; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct odm_dm_struct *odmpriv = &adapt->HalData->odmpriv; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; @@ -1995,7 +1945,7 @@ static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_l break; } - rate_bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, mac_id, mask, rssi_level); + rate_bitmap = ODM_Get_Rate_Bitmap(odmpriv, mac_id, mask, rssi_level); DBG_88E("%s => mac_id:%d, networkType:0x%02x, mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n", __func__, mac_id, networkType, mask, rssi_level, rate_bitmap); @@ -2003,15 +1953,14 @@ static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_l init_rate = get_highest_rate_idx(mask)&0x3f; - ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv, mac_id, - raid, mask, shortGIrate); + ODM_RA_UpdateRateInfo_8188E(odmpriv, mac_id, raid, mask, shortGIrate); /* set ra_id */ psta->raid = raid; psta->init_rate = init_rate; } -static void SetBeaconRelatedRegisters8188EUsb(struct adapter *adapt) +void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) { u32 value32; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; @@ -2045,13 +1994,12 @@ static void SetBeaconRelatedRegisters8188EUsb(struct adapter *adapt) usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg) | BIT(1)); } -static void rtl8188eu_init_default_value(struct adapter *adapt) +void rtw_hal_def_value_init(struct adapter *adapt) { - struct hal_data_8188e *haldata; + struct hal_data_8188e *haldata = adapt->HalData; struct pwrctrl_priv *pwrctrlpriv; u8 i; - haldata = GET_HAL_DATA(adapt); pwrctrlpriv = &adapt->pwrctrlpriv; /* init default value */ @@ -2067,43 +2015,3 @@ static void rtl8188eu_init_default_value(struct adapter *adapt) for (i = 0; i < HP_THERMAL_NUM; i++) haldata->odmpriv.RFCalibrateInfo.ThermalValue_HP[i] = 0; } - -void rtl8188eu_set_hal_ops(struct adapter *adapt) -{ - struct hal_ops *halfunc = &adapt->HalFunc; - - - adapt->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL); - if (!adapt->HalData) - DBG_88E("cant not alloc memory for HAL DATA\n"); - - halfunc->hal_power_on = rtl8188eu_InitPowerOn; - halfunc->hal_init = &rtl8188eu_hal_init; - halfunc->hal_deinit = &rtl8188eu_hal_deinit; - - halfunc->inirp_init = &rtl8188eu_inirp_init; - halfunc->inirp_deinit = &rtl8188eu_inirp_deinit; - - halfunc->init_xmit_priv = &rtl8188eu_init_xmit_priv; - - halfunc->init_recv_priv = &rtl8188eu_init_recv_priv; - halfunc->free_recv_priv = &rtl8188eu_free_recv_priv; - halfunc->InitSwLeds = &rtl8188eu_InitSwLeds; - halfunc->DeInitSwLeds = &rtl8188eu_DeInitSwLeds; - - halfunc->init_default_value = &rtl8188eu_init_default_value; - halfunc->intf_chip_configure = &rtl8188eu_interface_configure; - halfunc->read_adapter_info = &_ReadAdapterInfo8188EU; - - halfunc->SetHwRegHandler = &SetHwReg8188EU; - halfunc->GetHwRegHandler = &GetHwReg8188EU; - halfunc->GetHalDefVarHandler = &GetHalDefVar8188EUsb; - - halfunc->UpdateRAMaskHandler = &UpdateHalRAMask8188EUsb; - halfunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188EUsb; - - halfunc->hal_xmit = &rtl8188eu_hal_xmit; - halfunc->mgnt_xmit = &rtl8188eu_mgnt_xmit; - - rtl8188e_set_hal_ops(halfunc); -} diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h index 8990748a1919..0976a761b280 100644 --- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h +++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h @@ -158,24 +158,6 @@ struct bb_reg_def { * Path A and B */ }; -struct ant_sel_ofdm { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 OFDM_TXSC:2; - u32 reserved:2; -}; - -struct ant_sel_cck { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - /*------------------------------Define structure----------------------------*/ diff --git a/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h b/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h deleted file mode 100644 index dbb55247b0c6..000000000000 --- a/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. 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 for -* more details. -* -******************************************************************************/ - -#ifndef __INC_FW_8188E_HW_IMG_H -#define __INC_FW_8188E_HW_IMG_H - - -/****************************************************************************** -* FW_AP.TXT -******************************************************************************/ -/****************************************************************************** -* FW_WoWLAN.TXT -******************************************************************************/ -#define ArrayLength_8188E_FW_WoWLAN 15764 -extern const u8 Array_8188E_FW_WoWLAN[ArrayLength_8188E_FW_WoWLAN]; - -#endif diff --git a/drivers/staging/rtl8188eu/include/basic_types.h b/drivers/staging/rtl8188eu/include/basic_types.h index 2c1676d2ac6e..69c4d49f43ab 100644 --- a/drivers/staging/rtl8188eu/include/basic_types.h +++ b/drivers/staging/rtl8188eu/include/basic_types.h @@ -137,8 +137,4 @@ value to host byte ordering.*/ ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ ) -/* Get the N-bytes aligment offset from the current length */ -#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ - (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) - #endif /* __BASIC_TYPES_H__ */ diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 55506a7da1a4..32326fd1dd24 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -53,30 +53,17 @@ #define SPEC_DEV_ID_ASSIGN_IFNAME BIT(5) struct registry_priv { - u8 chip_version; - u8 rfintfs; - u8 lbkmode; - u8 hci; struct ndis_802_11_ssid ssid; - u8 network_mode; /* infra, ad-hoc, auto */ u8 channel;/* ad-hoc support requirement */ u8 wireless_mode;/* A, B, G, auto */ - u8 scan_mode;/* active, passive */ - u8 radio_enable; u8 preamble;/* long, short, auto */ u8 vrtl_carrier_sense;/* Enable, Disable, Auto */ u8 vcs_type;/* RTS/CTS, CTS-to-self */ u16 rts_thresh; u16 frag_thresh; - u8 adhoc_tx_pwr; - u8 soft_ap; u8 power_mgnt; u8 ips_mode; u8 smart_ps; - u8 long_retry_lmt; - u8 short_retry_lmt; - u16 busy_thresh; - u8 ack_policy; u8 mp_mode; u8 software_encrypt; u8 software_decrypt; @@ -84,11 +71,6 @@ struct registry_priv { /* UAPSD */ u8 wmm_enable; u8 uapsd_enable; - u8 uapsd_max_sp; - u8 uapsd_acbk_en; - u8 uapsd_acbe_en; - u8 uapsd_acvi_en; - u8 uapsd_acvo_en; struct wlan_bssid_ex dev_network; @@ -97,10 +79,6 @@ struct registry_priv { u8 ampdu_enable;/* for tx */ u8 rx_stbc; u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */ - u8 lowrate_two_xmit; - - u8 rf_config; - u8 low_power; u8 wifi_spec;/* !turbo_mode */ @@ -112,9 +90,6 @@ struct registry_priv { u8 usbss_enable;/* 0:disable,1:enable */ u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */ - u8 hwpwrp_detect;/* 0:disable,1:enable */ - - u8 hw_wps_pbc;/* 0:disable,1:enable */ u8 max_roaming_times; /* the max number driver will try */ @@ -129,12 +104,6 @@ struct registry_priv { bool monitor_enable; }; -/* For registry parameters */ -#define RGTRY_OFT(field) ((u32)offsetof(struct registry_priv, field)) -#define RGTRY_SZ(field) sizeof(((struct registry_priv *)0)->field) -#define BSSID_OFT(field) ((u32)offsetofT(struct wlan_bssid_ex, field)) -#define BSSID_SZ(field) sizeof(((struct wlan_bssid_ex *)0)->field) - #define MAX_CONTINUAL_URB_ERR 4 struct dvobj_priv { @@ -149,16 +118,11 @@ struct dvobj_priv { u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */ /*-------- below is for USB INTERFACE --------*/ - - u8 nr_endpoint; u8 ishighspeed; u8 RtNumInPipes; u8 RtNumOutPipes; - int ep_num[5]; /* endpoint number */ struct mutex usb_vendor_req_mutex; - u8 *usb_vendor_req_buf; - struct usb_interface *pusbintf; struct usb_device *pusbdev; }; @@ -184,14 +148,7 @@ struct adapter { struct eeprom_priv eeprompriv; struct led_priv ledpriv; -#ifdef CONFIG_88EU_AP_MODE - struct hostapd_priv *phostapdpriv; -#endif - - struct wifidirect_info wdinfo; - - void *HalData; - struct hal_ops HalFunc; + struct hal_data_8188e *HalData; s32 bDriverStopped; s32 bSurpriseRemoved; @@ -199,20 +156,11 @@ struct adapter { u8 hw_init_completed; void *cmdThread; - void *evtThread; void (*intf_start)(struct adapter *adapter); void (*intf_stop)(struct adapter *adapter); struct net_device *pnetdev; struct net_device *pmondev; - /* used by rtw_rereg_nd_name related function */ - struct rereg_nd_name_data { - struct net_device *old_pnetdev; - char old_ifname[IFNAMSIZ]; - u8 old_ips_mode; - u8 old_bRegUseLed; - } rereg_nd_name_priv; - int bup; struct net_device_stats stats; struct iw_statistics iwstats; @@ -223,23 +171,12 @@ struct adapter { u8 bReadPortCancel; u8 bWritePortCancel; u8 bRxRSSIDisplay; - /* The driver will show up the desired channel number - * when this flag is 1. */ - u8 bNotifyChannelChange; struct mutex hw_init_mutex; - - spinlock_t br_ext_lock; - - u8 fix_rate; - - unsigned char in_cta_test; }; #define adapter_to_dvobj(adapter) (adapter->dvobj) -int rtw_handle_dualmac(struct adapter *adapter, bool init); - static inline u8 *myid(struct eeprom_priv *peepriv) { return peepriv->mac_addr; diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index eaf939bd4103..fa032b0c12ff 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -58,7 +58,6 @@ enum hw_variables { HW_VAR_SEC_CFG, HW_VAR_BCN_VALID, HW_VAR_RF_TYPE, - HW_VAR_DM_FLAG, HW_VAR_DM_FUNC_OP, HW_VAR_DM_FUNC_SET, HW_VAR_DM_FUNC_CLR, @@ -139,81 +138,6 @@ enum hal_intf_ps_func { HAL_MAX_ID, }; -struct hal_ops { - u32 (*hal_power_on)(struct adapter *padapter); - u32 (*hal_init)(struct adapter *padapter); - u32 (*hal_deinit)(struct adapter *padapter); - - void (*free_hal_data)(struct adapter *padapter); - - u32 (*inirp_init)(struct adapter *padapter); - u32 (*inirp_deinit)(struct adapter *padapter); - - s32 (*init_xmit_priv)(struct adapter *padapter); - - s32 (*init_recv_priv)(struct adapter *padapter); - void (*free_recv_priv)(struct adapter *padapter); - - void (*InitSwLeds)(struct adapter *padapter); - void (*DeInitSwLeds)(struct adapter *padapter); - - void (*dm_init)(struct adapter *padapter); - void (*read_chip_version)(struct adapter *padapter); - - void (*init_default_value)(struct adapter *padapter); - - void (*intf_chip_configure)(struct adapter *padapter); - - void (*read_adapter_info)(struct adapter *padapter); - - s32 (*interrupt_handler)(struct adapter *padapter); - - void (*set_bwmode_handler)(struct adapter *padapter, - enum ht_channel_width Bandwidth, - u8 Offset); - void (*set_channel_handler)(struct adapter *padapter, u8 channel); - - void (*hal_dm_watchdog)(struct adapter *padapter); - - void (*SetHwRegHandler)(struct adapter *padapter, u8 variable, - u8 *val); - void (*GetHwRegHandler)(struct adapter *padapter, u8 variable, - u8 *val); - - u8 (*GetHalDefVarHandler)(struct adapter *padapter, - enum hal_def_variable eVariable, - void *pValue); - - void (*SetHalODMVarHandler)(struct adapter *padapter, - enum hal_odm_variable eVariable, - void *pValue1, bool bSet); - - void (*UpdateRAMaskHandler)(struct adapter *padapter, - u32 mac_id, u8 rssi_level); - void (*SetBeaconRelatedRegistersHandler)(struct adapter *padapter); - - void (*Add_RateATid)(struct adapter *adapter, u32 bitmap, u8 arg, - u8 rssi_level); - - u8 (*AntDivBeforeLinkHandler)(struct adapter *adapter); - void (*AntDivCompareHandler)(struct adapter *adapter, - struct wlan_bssid_ex *dst, - struct wlan_bssid_ex *src); - s32 (*hal_xmit)(struct adapter *padapter, - struct xmit_frame *pxmitframe); - s32 (*mgnt_xmit)(struct adapter *padapter, - struct xmit_frame *pmgntframe); - u32 (*read_rfreg)(struct adapter *padapter, - enum rf_radio_path eRFPath, u32 RegAddr, - u32 BitMask); - - void (*sreset_init_value)(struct adapter *padapter); - u8 (*sreset_get_wifi_status)(struct adapter *padapter); - - void (*hal_notch_filter)(struct adapter *adapter, bool enable); - void (*hal_reset_security_engine)(struct adapter *adapter); -}; - enum rt_eeprom_type { EEPROM_93C46, EEPROM_93C56, @@ -235,6 +159,9 @@ enum hardware_type { #define is_boot_from_eeprom(adapter) (adapter->eeprompriv.EepromOrEfuse) +void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level); +u32 rtl8188eu_hal_deinit(struct adapter *Adapter); +u32 rtl8188eu_hal_init(struct adapter *Adapter); void rtw_hal_def_value_init(struct adapter *padapter); void rtw_hal_free_data(struct adapter *padapter); @@ -262,7 +189,7 @@ void rtw_hal_set_odm_var(struct adapter *padapter, bool bSet); u32 rtw_hal_inirp_init(struct adapter *padapter); -u32 rtw_hal_inirp_deinit(struct adapter *padapter); +void rtw_hal_inirp_deinit(struct adapter *padapter); s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe); s32 rtw_hal_mgnt_xmit(struct adapter *padapter, @@ -270,7 +197,7 @@ s32 rtw_hal_mgnt_xmit(struct adapter *padapter, s32 rtw_hal_init_xmit_priv(struct adapter *padapter); -s32 rtw_hal_init_recv_priv(struct adapter *padapter); +int rtw_hal_init_recv_priv(struct adapter *padapter); void rtw_hal_free_recv_priv(struct adapter *padapter); void rtw_hal_update_ra_mask(struct adapter *padapter, u32 mac_id, u8 level); @@ -296,7 +223,6 @@ void rtw_hal_antdiv_rssi_compared(struct adapter *padapter, void rtw_hal_sreset_init(struct adapter *padapter); void rtw_hal_notch_filter(struct adapter *adapter, bool enable); -void rtw_hal_reset_security_engine(struct adapter *adapter); void indicate_wx_scan_complete_event(struct adapter *padapter); u8 rtw_do_join(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index d8284c84f09c..fc58621368c1 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -239,7 +239,7 @@ struct ieee_param { u16 capability; int flags; u8 tx_supp_rates[16]; - struct rtw_ieee80211_ht_cap ht_cap; + struct ieee80211_ht_cap ht_cap; } add_sta; struct { u8 reserved[2];/* for set max_num_sta */ @@ -264,7 +264,7 @@ struct sta_data { u32 sta_set; u8 tx_supp_rates[16]; u32 tx_supp_rates_len; - struct rtw_ieee80211_ht_cap ht_cap; + struct ieee80211_ht_cap ht_cap; u64 rx_pkts; u64 rx_bytes; u64 rx_drops; @@ -291,62 +291,6 @@ struct sta_data { /* this is stolen from ipw2200 driver */ #define IEEE_IBSS_MAC_HASH_SIZE 31 -struct ieee_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num; - u16 frag_num; - unsigned long packet_time; - struct list_head list; -}; - -struct rtw_ieee80211_hdr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; -} __packed; - -struct rtw_ieee80211_hdr_3addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; -} __packed; - -struct rtw_ieee80211_hdr_qos { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; - u16 qc; -} __packed; - -struct rtw_ieee80211_hdr_3addr_qos { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u16 qc; -} __packed; - -struct eapol { - u8 snap[6]; - u16 ethertype; - u8 version; - u8 type; - u16 length; -} __packed; - enum eap_type { EAP_PACKET = 0, EAPOL_START, @@ -552,83 +496,12 @@ struct ieee80211_snap_hdr { #define IEEE80211_NUM_CCK_RATES 4 #define IEEE80211_OFDM_SHIFT_MASK_A 4 -/* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. Not setting these will not cause - * any adverse affects. */ -struct ieee80211_rx_stats { - /* u32 mac_time[2]; */ - s8 rssi; - u8 signal; - u8 noise; - u8 received_channel; - u16 rate; /* in 100 kbps */ - /* u8 control; */ - u8 mask; - u8 freq; - u16 len; -}; - /* IEEE 802.11 requires that STA supports concurrent reception of at least * three fragmented frames. This define can be increased to support more * concurrent frames, but it should be noted that each entry can consume about * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ #define IEEE80211_FRAG_CACHE_LEN 4 -struct ieee80211_frag_entry { - u32 first_frag_time; - uint seq; - uint last_frag; - uint qos; /* jackson */ - uint tid; /* jackson */ - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - -struct ieee80211_stats { - uint tx_unicast_frames; - uint tx_multicast_frames; - uint tx_fragments; - uint tx_unicast_octets; - uint tx_multicast_octets; - uint tx_deferred_transmissions; - uint tx_single_retry_frames; - uint tx_multiple_retry_frames; - uint tx_retry_limit_exceeded; - uint tx_discards; - uint rx_unicast_frames; - uint rx_multicast_frames; - uint rx_fragments; - uint rx_unicast_octets; - uint rx_multicast_octets; - uint rx_fcs_errors; - uint rx_discards_no_buffer; - uint tx_discards_wrong_sa; - uint rx_discards_undecryptable; - uint rx_message_in_msg_fragments; - uint rx_message_in_bad_msg_fragments; -}; - -struct ieee80211_softmac_stats { - uint rx_ass_ok; - uint rx_ass_err; - uint rx_probe_rq; - uint tx_probe_rs; - uint tx_beacons; - uint rx_auth_rq; - uint rx_auth_rs_ok; - uint rx_auth_rs_err; - uint tx_auth_rq; - uint no_auth_rs; - uint no_ass_rs; - uint tx_ass_rq; - uint rx_ass_rq; - uint tx_probe_rq; - uint reassoc; - uint swtxstop; - uint swtxawake; -}; - #define SEC_KEY_1 (1<<0) #define SEC_KEY_2 (1<<1) #define SEC_KEY_3 (1<<2) @@ -648,42 +521,6 @@ struct ieee80211_softmac_stats { #define WEP_KEYS 4 #define WEP_KEY_LEN 13 -struct ieee80211_security { - u16 active_key:2, - enabled:1, - auth_mode:2, - auth_algo:4, - unicast_uses_group:1; - u8 key_sizes[WEP_KEYS]; - u8 keys[WEP_KEYS][WEP_KEY_LEN]; - u8 level; - u16 flags; -} __packed; - -/* - - 802.11 data frame from AP - - ,-------------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `-------------------------------------------------------------------' - -Total: 28-2340 bytes - -*/ - -struct ieee80211_header_data { - u16 frame_ctl; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; -}; - #define BEACON_PROBE_SSID_ID_POSITION 12 /* Management Frame Information Element Types */ @@ -700,81 +537,9 @@ struct ieee80211_header_data { #define MFIE_TYPE_RATES_EX 50 #define MFIE_TYPE_GENERIC 221 -struct ieee80211_info_element_hdr { - u8 id; - u8 len; -} __packed; - -struct ieee80211_info_element { - u8 id; - u8 len; - u8 data[0]; -} __packed; - -/* - * These are the data types that can make up management packets - * - u16 auth_algorithm; - u16 auth_sequence; - u16 beacon_interval; - u16 capability; - u8 current_ap[ETH_ALEN]; - u16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __packed; - u32 time_stamp[2]; - u16 reason; - u16 status; -*/ - #define IEEE80211_DEFAULT_TX_ESSID "Penguin" #define IEEE80211_DEFAULT_BASIC_RATE 10 -struct ieee80211_authentication { - struct ieee80211_header_data header; - u16 algorithm; - u16 transaction; - u16 status; - /* struct ieee80211_info_element_hdr info_element; */ -} __packed; - -struct ieee80211_probe_response { - struct ieee80211_header_data header; - u32 time_stamp[2]; - u16 beacon_interval; - u16 capability; - struct ieee80211_info_element info_element; -} __packed; - -struct ieee80211_probe_request { - struct ieee80211_header_data header; -} __packed; - -struct ieee80211_assoc_request_frame { - struct rtw_ieee80211_hdr_3addr header; - u16 capability; - u16 listen_interval; - struct ieee80211_info_element_hdr info_element; -} __packed; - -struct ieee80211_assoc_response_frame { - struct rtw_ieee80211_hdr_3addr header; - u16 capability; - u16 status; - u16 aid; -} __packed; - -struct ieee80211_txb { - u8 nr_frags; - u8 encrypted; - u16 reserved; - u16 frag_size; - u16 payload_size; - struct sk_buff *fragments[0]; -}; - - /* SWEEP TABLE ENTRIES NUMBER*/ #define MAX_SWEEP_TAB_ENTRIES 42 #define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 @@ -872,11 +637,6 @@ static inline int is_broadcast_mac_addr(const u8 *addr) #define CFG_IEEE80211_RESERVE_FCS (1<<0) #define CFG_IEEE80211_COMPUTE_FCS (1<<1) -struct tx_pending { - int frag; - struct ieee80211_txb *txb; -}; - #define MAXTID 16 #define IEEE_A (1<<0) @@ -1096,20 +856,8 @@ enum secondary_ch_offset { SCA = 1, /* secondary channel above */ SCB = 3, /* secondary channel below */ }; -u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset); -u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset); -u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, - u8 new_ch, u8 ch_switch_cnt); -u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, - u8 secondary_ch_offset); -u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, - u8 flags, u16 reason, u16 precedence); u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit); -u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, - u8 oui_len, u8 *ie, uint *ielen); -int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, - u8 eid, u8 *oui, u8 oui_len); void rtw_set_supported_rate(u8 *SupportedRates, uint mode); @@ -1133,19 +881,6 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content); -/** - * for_each_ie - iterate over continuous IEs - * @ie: - * @buf: - * @buf_len: - */ -#define for_each_ie(ie, buf, buf_len) \ - for (ie = (void *)buf; (((u8 *)ie) - ((u8 *)buf) + 1) < buf_len; \ - ie = (void *)(((u8 *)ie) + *(((u8 *)ie)+1) + 2)) - -void dump_ies(u8 *buf, u32 buf_len); -void dump_wps_ie(u8 *ie, u32 ie_len); - uint rtw_get_rateset_len(u8 *rateset); struct registry_priv; @@ -1167,8 +902,4 @@ void rtw_macaddr_cfg(u8 *mac_addr); u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate); -int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, - u8 *action); -const char *action_public_str(u8 action); - #endif /* IEEE80211_H */ diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index dbebf17f36d3..805f52e108b2 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -315,22 +315,6 @@ enum odm_ability { ODM_PSD2AFH = 0x00000800 }; -/* 2011/20/20 MH For MP driver RT_WLAN_STA = struct sta_info */ -/* Please declare below ODM relative info in your STA info structure. */ - -struct odm_sta_info { - /* Driver Write */ - bool bUsed; /* record the sta status link or not? */ - u8 IOTPeer; /* Enum value. HT_IOT_PEER_E */ - - /* ODM Write */ - /* 1 PHY_STATUS_INFO */ - u8 RSSI_Path[4]; /* */ - u8 RSSI_Ave; - u8 RXEVM[4]; - u8 RXSNR[4]; -}; - /* 2011/10/20 MH Define Common info enum for all team. */ enum odm_common_info_def { @@ -740,8 +724,6 @@ struct odm_dm_struct { u32 SupportICType; /* Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */ u8 CutVersion; - /* RF Type 4T4R/3T3R/2T2R/1T2R/1T1R/... */ - u8 RFType; /* Board Type Normal/HighPower/MiniCard/SLIM/Combo/. = 0/1/2/3/4/. */ u8 BoardType; /* with external LNA NO/Yes = 0/1 */ diff --git a/drivers/staging/rtl8188eu/include/osdep_intf.h b/drivers/staging/rtl8188eu/include/osdep_intf.h index 54fca79827e3..dbd7dc4f87dd 100644 --- a/drivers/staging/rtl8188eu/include/osdep_intf.h +++ b/drivers/staging/rtl8188eu/include/osdep_intf.h @@ -34,7 +34,6 @@ int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname); struct net_device *rtw_init_netdev(struct adapter *padapter); u16 rtw_recv_select_queue(struct sk_buff *skb); -void rtw_proc_remove_one(struct net_device *dev); int pm_netdev_open(struct net_device *pnetdev, u8 bnormal); void rtw_ips_dev_unload(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 5475956c5ee5..9047b6dec9ed 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,7 +44,6 @@ #include #include #include -#include /* Necessary because we use the proc fs */ #include /* for struct tasklet_struct */ #include #include @@ -78,16 +77,12 @@ u8 *_rtw_malloc(u32 sz); void *rtw_malloc2d(int h, int w, int size); -u32 _rtw_down_sema(struct semaphore *sema); - void _rtw_init_queue(struct __queue *pqueue); struct rtw_netdev_priv_indicator { void *priv; - u32 sizeof_priv; }; -struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, - void *old_priv); +struct net_device *rtw_alloc_etherdev_with_old_priv(void *old_priv); #define rtw_netdev_priv(netdev) \ (((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv) diff --git a/drivers/staging/rtl8188eu/include/phy.h b/drivers/staging/rtl8188eu/include/phy.h index 9a9ab82a8ed3..cd387e998574 100644 --- a/drivers/staging/rtl8188eu/include/phy.h +++ b/drivers/staging/rtl8188eu/include/phy.h @@ -11,17 +11,13 @@ bool rtl88eu_phy_bb_config(struct adapter *adapt); u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask); void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data); -u32 phy_query_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, +u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path, u32 reg_addr, u32 bit_mask); void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, u32 reg_addr, u32 bit_mask, u32 data); void phy_set_tx_power_level(struct adapter *adapt, u8 channel); -void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth, - unsigned char offset); -void phy_sw_chnl(struct adapter *adapt, u8 channel); - void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type, u8 *dir, u32 *out_write); diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h index cad31587c30a..7550d58f6b5b 100644 --- a/drivers/staging/rtl8188eu/include/recv_osdep.h +++ b/drivers/staging/rtl8188eu/include/recv_osdep.h @@ -26,13 +26,9 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv); s32 rtw_recv_entry(struct recv_frame *precv_frame); int rtw_recv_indicatepkt(struct adapter *adapter, struct recv_frame *recv_frame); -void rtw_recv_returnpacket(struct net_device *cnxt, struct sk_buff *retpkt); void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup); -int rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter); -void rtw_free_recv_priv(struct recv_priv *precvpriv); - void rtw_os_recv_resource_alloc(struct recv_frame *recvfr); int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h index 4d7d804658c2..042b4ec656c8 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h @@ -49,12 +49,6 @@ enum RTL8188E_H2C_CMD_ID { H2C_RESET_TSF = 0xc0, }; -struct cmd_msg_parm { - u8 eid; /* element id */ - u8 sz; /* sz */ - u8 buf[6]; -}; - enum { PWRS }; @@ -67,15 +61,6 @@ struct setpwrmode_parm { u8 PwrState;/* AllON(0x0c),RFON(0x04),RFOFF(0x00) */ }; -struct H2C_SS_RFOFF_PARAM { - u8 ROFOn; /* 1: on, 0:off */ - u16 gpio_period; /* unit: 1024 us */ -} __packed; - -struct joinbssrpt_parm { - u8 OpMode; /* RT_MEDIA_STATUS */ -}; - struct rsvdpage_loc { u8 LocProbeRsp; u8 LocPsPoll; @@ -84,26 +69,9 @@ struct rsvdpage_loc { u8 LocBTQosNull; }; -struct P2P_PS_Offload_t { - u8 Offload_En:1; - u8 role:1; /* 1: Owner, 0: Client */ - u8 CTWindow_En:1; - u8 NoA0_En:1; - u8 NoA1_En:1; - u8 AllStaSleep:1; /* Only valid in Owner */ - u8 discovery:1; - u8 rsvd:1; -}; - -struct P2P_PS_CTWPeriod_t { - u8 CTWPeriod; /* TU */ -}; - /* host message to firmware cmd */ void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode); void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus); -void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg, - u8 rssi_level); void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h index 4190112a50bf..c0ffd98d7617 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h @@ -45,12 +45,9 @@ struct dm_priv { u8 PowerIndex_backup[6]; }; -void rtl8188e_init_dm_priv(struct adapter *adapt); void rtl8188e_InitHalDm(struct adapter *adapt); -void rtl8188e_HalDmWatchDog(struct adapter *adapt); void AntDivCompare8188E(struct adapter *adapt, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src); -u8 AntDivBeforeLink8188E(struct adapter *adapt); #endif diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 9dd5c293a54b..7c81e3f3d12e 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -202,7 +202,6 @@ struct hal_data_8188e { /* rf_ctrl */ u8 rf_chip; - u8 rf_type; u8 NumTotalRFPath; u8 BoardType; @@ -351,10 +350,6 @@ struct hal_data_8188e { u8 UsbRxAggPageTimeout; }; -#define GET_HAL_DATA(__pAdapter) \ - ((struct hal_data_8188e *)((__pAdapter)->HalData)) -#define GET_RF_TYPE(priv) (GET_HAL_DATA(priv)->rf_type) - /* rtl8188e_hal_init.c */ void _8051Reset88E(struct adapter *padapter); void rtl8188e_InitializeFirmwareVars(struct adapter *padapter); @@ -385,8 +380,6 @@ void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, void Hal_ReadPowerSavingMode88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail); -void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc); - /* register */ void rtl8188e_start_thread(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_led.h b/drivers/staging/rtl8188eu/include/rtl8188e_led.h index fca6d8c81e90..d1ad6aa8c1e0 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_led.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_led.h @@ -22,8 +22,6 @@ /* */ /* Interface to manipulate LED objects. */ /* */ -void rtl8188eu_InitSwLeds(struct adapter *padapter); -void rtl8188eu_DeInitSwLeds(struct adapter *padapter); void SwLedOn(struct adapter *padapter, struct LED_871x *pLed); void SwLedOff(struct adapter *padapter, struct LED_871x *pLed); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h index 54048bc826e5..80832a5f0732 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h @@ -51,12 +51,11 @@ enum rx_packet_type { }; #define INTERRUPT_MSG_FORMAT_LEN 60 -s32 rtl8188eu_init_recv_priv(struct adapter *padapter); -void rtl8188eu_free_recv_priv(struct adapter *padapter); void rtl8188eu_recv_hdl(struct adapter *padapter, struct recv_buf *precvbuf); void rtl8188eu_recv_tasklet(void *priv); void rtl8188e_query_rx_phy_status(struct recv_frame *fr, struct phy_stat *phy); -void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe); +void rtl8188e_process_phy_info(struct adapter *padapter, + struct recv_frame *prframe); void update_recvframe_phyinfo_88e(struct recv_frame *fra, struct phy_stat *phy); void update_recvframe_attrib_88e(struct recv_frame *fra, struct recv_stat *stat); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h index 65a63df2077f..66205b782721 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h @@ -154,14 +154,11 @@ struct txrpt_ccx_88e { void rtl8188e_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull); s32 rtl8188eu_init_xmit_priv(struct adapter *padapter); -s32 rtl8188eu_hal_xmit(struct adapter *padapter, struct xmit_frame *frame); -s32 rtl8188eu_mgnt_xmit(struct adapter *padapter, struct xmit_frame *frame); s32 rtl8188eu_xmit_buf_handler(struct adapter *padapter); #define hal_xmit_handler rtl8188eu_xmit_buf_handler void rtl8188eu_xmit_tasklet(void *priv); s32 rtl8188eu_xmitframe_complete(struct adapter *padapter, - struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); + struct xmit_priv *pxmitpriv); void dump_txrpt_ccx_88e(void *buf); void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf); diff --git a/drivers/staging/rtl8188eu/include/rtw_ap.h b/drivers/staging/rtl8188eu/include/rtw_ap.h index b820684bc3fe..e8dd6d4407aa 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ap.h +++ b/drivers/staging/rtl8188eu/include/rtw_ap.h @@ -50,7 +50,6 @@ void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta); u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, bool active, u16 reason); int rtw_sta_flush(struct adapter *padapter); -int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset); void start_ap_mode(struct adapter *padapter); void stop_ap_mode(struct adapter *padapter); #endif /* end of CONFIG_88EU_AP_MODE */ diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h index 08ca59217cb7..18a6530c9dde 100644 --- a/drivers/staging/rtl8188eu/include/rtw_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h @@ -39,8 +39,8 @@ struct cmd_obj { }; struct cmd_priv { - struct semaphore cmd_queue_sema; - struct semaphore terminate_cmdthread_sema; + struct completion cmd_queue_comp; + struct completion terminate_cmdthread_comp; struct __queue cmd_queue; u8 cmdthd_running; struct adapter *padapter; @@ -209,34 +209,6 @@ struct set_assocsta_rsp { u8 rsvd[3]; }; -/* - Caller Ad-Hoc/AP - - Command mode - - This is to force fw to del an sta_data entry per driver's request - - FW will invalidate the cam entry associated with it. - -*/ -struct del_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -/* -Caller Mode: AP/Ad-HoC(M) - -Notes: To notify fw that given staid has changed its power state - -Command Mode - -*/ -struct setstapwrstate_parm { - u8 staid; - u8 status; - u8 hwaddr[6]; -}; - /* Notes: This command is used for H2C/C2H loopback testing @@ -312,8 +284,6 @@ struct SetChannelPlan_param { u8 channel_plan; }; -#define GEN_CMD_CODE(cmd) cmd ## _CMD_ - /* Result: @@ -376,42 +346,42 @@ struct _cmd_callback { }; enum rtw_h2c_cmd { - GEN_CMD_CODE(_JoinBss), - GEN_CMD_CODE(_DisConnect), - GEN_CMD_CODE(_CreateBss), - GEN_CMD_CODE(_SetOpMode), - GEN_CMD_CODE(_SiteSurvey), - GEN_CMD_CODE(_SetAuth), - GEN_CMD_CODE(_SetKey), - GEN_CMD_CODE(_SetStaKey), - GEN_CMD_CODE(_SetAssocSta), - GEN_CMD_CODE(_AddBAReq), - GEN_CMD_CODE(_SetChannel), - GEN_CMD_CODE(_TX_Beacon), - GEN_CMD_CODE(_Set_MLME_EVT), - GEN_CMD_CODE(_Set_Drv_Extra), - GEN_CMD_CODE(_SetChannelPlan), + _JoinBss_CMD_, + _DisConnect_CMD_, + _CreateBss_CMD_, + _SetOpMode_CMD_, + _SiteSurvey_CMD_, + _SetAuth_CMD_, + _SetKey_CMD_, + _SetStaKey_CMD_, + _SetAssocSta_CMD_, + _AddBAReq_CMD_, + _SetChannel_CMD_, + _TX_Beacon_CMD_, + _Set_MLME_EVT_CMD_, + _Set_Drv_Extra_CMD_, + _SetChannelPlan_CMD_, MAX_H2CCMD }; #ifdef _RTW_CMD_C_ static struct _cmd_callback rtw_cmd_callback[] = { - {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback}, - {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, - {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback}, - {GEN_CMD_CODE(_SetOpMode), NULL}, - {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, - {GEN_CMD_CODE(_SetAuth), NULL}, - {GEN_CMD_CODE(_SetKey), NULL}, - {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback}, - {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback}, - {GEN_CMD_CODE(_AddBAReq), NULL}, - {GEN_CMD_CODE(_SetChannel), NULL}, - {GEN_CMD_CODE(_TX_Beacon), NULL}, - {GEN_CMD_CODE(_Set_MLME_EVT), NULL}, - {GEN_CMD_CODE(_Set_Drv_Extra), NULL}, - {GEN_CMD_CODE(_SetChannelPlan), NULL}, + {_JoinBss_CMD_, &rtw_joinbss_cmd_callback}, + {_DisConnect_CMD_, &rtw_disassoc_cmd_callback}, + {_CreateBss_CMD_, &rtw_createbss_cmd_callback}, + {_SetOpMode_CMD_, NULL}, + {_SiteSurvey_CMD_, &rtw_survey_cmd_callback}, + {_SetAuth_CMD_, NULL}, + {_SetKey_CMD_, NULL}, + {_SetStaKey_CMD_, &rtw_setstaKey_cmdrsp_callback}, + {_SetAssocSta_CMD_, &rtw_setassocsta_cmdrsp_callback}, + {_AddBAReq_CMD_, NULL}, + {_SetChannel_CMD_, NULL}, + {_TX_Beacon_CMD_, NULL}, + {_Set_MLME_EVT_CMD_, NULL}, + {_Set_Drv_Extra_CMD_, NULL}, + {_SetChannelPlan_CMD_, NULL}, }; #endif diff --git a/drivers/staging/rtl8188eu/include/rtw_debug.h b/drivers/staging/rtl8188eu/include/rtw_debug.h index 7ed4cada7efa..95590a1a7b1b 100644 --- a/drivers/staging/rtl8188eu/include/rtw_debug.h +++ b/drivers/staging/rtl8188eu/include/rtw_debug.h @@ -129,133 +129,12 @@ int proc_get_read_reg(char *page, char **start, int proc_set_read_reg(struct file *file, const char __user *buffer, unsigned long count, void *data); -int proc_get_fwstate(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_sec_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_mlmext_state(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_qos_option(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_ht_option(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_rf_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_ap_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - int proc_get_adapter_state(char *page, char **start, off_t offset, int count, int *eof, void *data); -int proc_get_trx_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_mac_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_mac_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_mac_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_bb_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_bb_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_bb_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rf_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rf_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rf_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rf_reg_dump4(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -#ifdef CONFIG_88EU_AP_MODE - -int proc_get_all_sta_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -#endif - int proc_get_best_channel(char *page, char **start, off_t offset, int count, int *eof, void *data); -int proc_get_rx_signal(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_rx_signal(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_ht_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_ht_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_cbw40_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_cbw40_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_ampdu_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_ampdu_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_rx_stbc(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_rx_stbc(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_two_path_rssi(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rssi_disp(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_rssi_disp(struct file *file, const char __user *buffer, - unsigned long count, void *data); - #endif /* __RTW_DEBUG_H__ */ diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h index 9bfb10c302b5..168c12d3c0b4 100644 --- a/drivers/staging/rtl8188eu/include/rtw_efuse.h +++ b/drivers/staging/rtl8188eu/include/rtw_efuse.h @@ -34,16 +34,6 @@ #define EFUSE_WIFI 0 #define EFUSE_BT 1 -enum _EFUSE_DEF_TYPE { - TYPE_EFUSE_MAX_SECTION = 0, - TYPE_EFUSE_REAL_CONTENT_LEN = 1, - TYPE_AVAILABLE_EFUSE_BYTES_BANK = 2, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL = 3, - TYPE_EFUSE_MAP_LEN = 4, - TYPE_EFUSE_PROTECT_BYTES_BANK = 5, - TYPE_EFUSE_CONTENT_LEN_BANK = 6, -}; - /* E-Fuse */ #define EFUSE_MAP_SIZE 512 #define EFUSE_MAX_SIZE 256 @@ -95,8 +85,6 @@ struct efuse_hal { }; u8 Efuse_CalculateWordCnts(u8 word_en); -void EFUSE_GetEfuseDefinition(struct adapter *adapt, u8 type, u8 type1, - void *out); u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data); u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data); diff --git a/drivers/staging/rtl8188eu/include/rtw_event.h b/drivers/staging/rtl8188eu/include/rtw_event.h index 5c34e567d341..1c5ebde97091 100644 --- a/drivers/staging/rtl8188eu/include/rtw_event.h +++ b/drivers/staging/rtl8188eu/include/rtw_event.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include /* @@ -71,12 +71,6 @@ struct stadel_event { int mac_id; }; -struct addba_event { - unsigned int tid; -}; - -#define GEN_EVT_CODE(event) event ## _EVT_ - struct fwevent { u32 parmsize; void (*event_callback)(struct adapter *dev, u8 *pbuf); @@ -84,21 +78,6 @@ struct fwevent { #define C2HEVENT_SZ 32 -struct event_node { - unsigned char *node; - unsigned char evt_code; - unsigned short evt_sz; - int *caller_ff_tail; - int caller_ff_sz; -}; - -struct c2hevent_queue { - int head; - int tail; - struct event_node nodes[C2HEVENT_SZ]; - unsigned char seq; -}; - #define NETWORK_QUEUE_SZ 4 struct network_queue { diff --git a/drivers/staging/rtl8188eu/include/rtw_ht.h b/drivers/staging/rtl8188eu/include/rtw_ht.h index b45483fd069f..d842eade7f57 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ht.h +++ b/drivers/staging/rtl8188eu/include/rtw_ht.h @@ -15,16 +15,11 @@ #ifndef _RTW_HT_H_ #define _RTW_HT_H_ -#include -#include "wifi.h" +#include struct ht_priv { u32 ht_option; u32 ampdu_enable;/* for enable Tx A-MPDU */ - u32 tx_amsdu_enable;/* for enable Tx A-MSDU */ - u32 tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */ - u32 rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, - * updated when join_callback. */ u8 bwmode;/* */ u8 ch_offset;/* PRIME_CHNL_OFFSET */ u8 sgi;/* short GI */ @@ -33,7 +28,7 @@ struct ht_priv { u8 agg_enable_bitmap; u8 candidate_tid_bitmap; - struct rtw_ieee80211_ht_cap ht_cap; + struct ieee80211_ht_cap ht_cap; }; #endif /* _RTL871X_HT_H_ */ diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl.h b/drivers/staging/rtl8188eu/include/rtw_ioctl.h index 3a652df4b26c..a6b1c854a061 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ioctl.h +++ b/drivers/staging/rtl8188eu/include/rtw_ioctl.h @@ -69,15 +69,6 @@ enum oid_type { SET_OID }; -struct oid_funs_node { - unsigned int oid_start; /* the starting number for OID */ - unsigned int oid_end; /* the ending number for OID */ - struct oid_obj_priv *node_array; - unsigned int array_sz; /* the size of node_array */ - int query_counter; /* count the number of query hits for this segment */ - int set_counter; /* count the number of set hits for this segment */ -}; - struct oid_par_priv { void *adapter_context; NDIS_OID oid; @@ -89,12 +80,6 @@ struct oid_par_priv { u32 dbg; }; -struct oid_obj_priv { - unsigned char dbg; /* 0: without OID debug message - * 1: with OID debug message */ - int (*oidfuns)(struct oid_par_priv *poid_par_priv); -}; - #if defined(_RTW_MP_IOCTL_C_) static int oid_null_function(struct oid_par_priv *poid_par_priv) { return NDIS_STATUS_SUCCESS; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 5d8bce0f58db..9434b869c5e9 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -301,12 +301,10 @@ struct mlme_priv { u8 *nic_hdl; - u8 not_indic_disco; struct list_head *pscanned; struct __queue free_bss_pool; struct __queue scanned_queue; u8 *free_bss_buf; - u32 num_of_scanned; struct ndis_802_11_ssid assoc_ssid; u8 assoc_bssid[6]; @@ -318,10 +316,8 @@ struct mlme_priv { struct timer_list assoc_timer; uint assoc_by_bssid; - uint assoc_by_rssi; struct timer_list scan_to_timer; /* driver itself handles scan_timeout status. */ - u32 scan_start_time; /* used to evaluate the time spent in scanning */ struct qos_priv qospriv; @@ -387,17 +383,6 @@ struct mlme_priv { u32 wps_probe_resp_ie_len; u32 wps_assoc_resp_ie_len; - u8 *p2p_beacon_ie; - u8 *p2p_probe_req_ie; - u8 *p2p_probe_resp_ie; - u8 *p2p_go_probe_resp_ie; /* for GO */ - u8 *p2p_assoc_req_ie; - - u32 p2p_beacon_ie_len; - u32 p2p_probe_req_ie_len; - u32 p2p_probe_resp_ie_len; - u32 p2p_go_probe_resp_ie_len; /* for GO */ - u32 p2p_assoc_req_ie_len; spinlock_t bcn_update_lock; u8 update_bcn; #endif /* if defined (CONFIG_88EU_AP_MODE) */ @@ -500,27 +485,6 @@ static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state) spin_unlock_bh(&pmlmepriv->lock); } -static inline void up_scanned_network(struct mlme_priv *pmlmepriv) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned++; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void down_scanned_network(struct mlme_priv *pmlmepriv) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned--; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv, int val) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned = val; - spin_unlock_bh(&pmlmepriv->lock); -} - u16 rtw_get_capability(struct wlan_bssid_ex *bss); void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 27382ff24a84..1b1caaf583c9 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -349,7 +349,7 @@ struct mlme_ext_info { struct ADDBA_request ADDBA_req; struct WMM_para_element WMM_param; - struct HT_caps_element HT_caps; + struct ieee80211_ht_cap HT_caps; struct HT_info_element HT_info; struct wlan_bssid_ex network;/* join network or bss_network, * if in ap mode, it is the same @@ -529,12 +529,12 @@ int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, void update_sta_info(struct adapter *padapter, struct sta_info *psta); unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz); unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz); -unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps); +unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps); void Update_RA_Entry(struct adapter *padapter, u32 mac_id); void set_sta_rate(struct adapter *padapter, struct sta_info *psta); unsigned char get_highest_rate_idx(u32 mask); -int support_short_GI(struct adapter *padapter, struct HT_caps_element *caps); +int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *caps); unsigned int is_ap_in_tkip(struct adapter *padapter); unsigned int is_ap_in_wep(struct adapter *padapter); unsigned int should_forbid_n_rate(struct adapter *padapter); @@ -562,8 +562,6 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms); int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason); -void issue_action_spct_ch_switch(struct adapter *padapter, u8 *ra, u8 new_ch, - u8 ch_offset); unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr); unsigned int send_beacon(struct adapter *padapter); @@ -627,27 +625,24 @@ u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf); u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf); u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf); -#define GEN_DRV_CMD_HANDLER(size, cmd) {size, &cmd ## _hdl}, -#define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd}, - #ifdef _RTW_CMD_C_ static struct cmd_hdl wlancmds[] = { - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), join_cmd_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), createbss_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), tx_beacon_hdl) - GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) - GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl) + {sizeof(struct wlan_bssid_ex), join_cmd_hdl}, + {sizeof(struct disconnect_parm), disconnect_hdl}, + {sizeof(struct wlan_bssid_ex), createbss_hdl}, + {sizeof(struct setopmode_parm), setopmode_hdl}, + {sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl}, + {sizeof(struct setauth_parm), setauth_hdl}, + {sizeof(struct setkey_parm), setkey_hdl}, + {sizeof(struct set_stakey_parm), set_stakey_hdl}, + {sizeof(struct set_assocsta_parm), NULL}, + {sizeof(struct addBaReq_parm), add_ba_hdl}, + {sizeof(struct set_ch_parm), set_ch_hdl}, + {sizeof(struct wlan_bssid_ex), tx_beacon_hdl}, + {0, mlme_evt_hdl}, + {0, rtw_drvextra_cmd_hdl}, + {sizeof(struct SetChannelPlan_param), set_chplan_hdl} }; #endif @@ -669,32 +664,32 @@ void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf); void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf); enum rtw_c2h_event { - GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ - GEN_EVT_CODE(_Read_BBREG), - GEN_EVT_CODE(_Read_RFREG), - GEN_EVT_CODE(_Read_EEPROM), - GEN_EVT_CODE(_Read_EFUSE), - GEN_EVT_CODE(_Read_CAM), /*5*/ - GEN_EVT_CODE(_Get_BasicRate), - GEN_EVT_CODE(_Get_DataRate), - GEN_EVT_CODE(_Survey), /*8*/ - GEN_EVT_CODE(_SurveyDone), /*9*/ + _Read_MACREG_EVT_ = 0, /*0*/ + _Read_BBREG_EVT_, + _Read_RFREG_EVT_, + _Read_EEPROM_EVT_, + _Read_EFUSE_EVT_, + _Read_CAM_EVT_, /*5*/ + _Get_BasicRate_EVT_, + _Get_DataRate_EVT_, + _Survey_EVT_, /*8*/ + _SurveyDone_EVT_, /*9*/ - GEN_EVT_CODE(_JoinBss), /*10*/ - GEN_EVT_CODE(_AddSTA), - GEN_EVT_CODE(_DelSTA), - GEN_EVT_CODE(_AtimDone), - GEN_EVT_CODE(_TX_Report), - GEN_EVT_CODE(_CCX_Report), /*15*/ - GEN_EVT_CODE(_DTM_Report), - GEN_EVT_CODE(_TX_Rate_Statistics), - GEN_EVT_CODE(_C2HLBK), - GEN_EVT_CODE(_FWDBG), - GEN_EVT_CODE(_C2HFEEDBACK), /*20*/ - GEN_EVT_CODE(_ADDBA), - GEN_EVT_CODE(_C2HBCN), - GEN_EVT_CODE(_ReportPwrState), /* filen: only for PCIE, USB */ - GEN_EVT_CODE(_CloseRF), /* filen: only for PCIE, + _JoinBss_EVT_, /*10*/ + _AddSTA_EVT_, + _DelSTA_EVT_, + _AtimDone_EVT_, + _TX_Report_EVT_, + _CCX_Report_EVT_, /*15*/ + _DTM_Report_EVT_, + _TX_Rate_Statistics_EVT_, + _C2HLBK_EVT_, + _FWDBG_EVT_, + _C2HFEEDBACK_EVT_, /*20*/ + _ADDBA_EVT_, + _C2HBCN_EVT_, + _ReportPwrState_EVT_, /* filen: only for PCIE, USB */ + _CloseRF_EVT_, /* filen: only for PCIE, * work around ASPM */ MAX_C2HEVT }; diff --git a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h index 9680e2eab62f..18a9e744fcbe 100644 --- a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h +++ b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h @@ -92,21 +92,6 @@ struct reportpwrstate_parm { unsigned short rsvd; }; -static inline void _init_pwrlock(struct semaphore *plock) -{ - sema_init(plock, 1); -} - -static inline void _enter_pwrlock(struct semaphore *plock) -{ - _rtw_down_sema(plock); -} - -static inline void _exit_pwrlock(struct semaphore *plock) -{ - up(plock); -} - #define LPS_DELAY_TIME 1*HZ /* 1 sec */ #define EXE_PWR_NONE 0x01 @@ -157,7 +142,7 @@ enum { /* for ips_mode */ }; struct pwrctrl_priv { - struct semaphore lock; + struct mutex mutex_lock; volatile u8 rpwm; /* requested power state for fw */ volatile u8 cpwm; /* fw current power state. updated when * 1. read from HCPWM 2. driver lowers power level */ diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index b0373b6216d6..49d973881a04 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -65,13 +65,6 @@ struct stainfo_rxcache { */ }; -struct smooth_rssi_data { - u32 elements[100]; /* array to store values */ - u32 index; /* index to current array to store */ - u32 total_num; /* num of valid elements */ - u32 total_val; /* sum of valid elements */ -}; - struct signal_stat { u8 update_req; /* used to indicate */ u8 avg_val; /* avg of valid elements */ @@ -246,7 +239,6 @@ struct recv_buf { struct recv_frame { struct list_head list; struct sk_buff *pkt; - struct sk_buff *pkt_newalloc; struct adapter *adapter; struct rx_pkt_attrib attrib; uint len; diff --git a/drivers/staging/rtl8188eu/include/rtw_security.h b/drivers/staging/rtl8188eu/include/rtw_security.h index ca1247bce6e3..2663e60bb6c6 100644 --- a/drivers/staging/rtl8188eu/include/rtw_security.h +++ b/drivers/staging/rtl8188eu/include/rtw_security.h @@ -164,12 +164,6 @@ struct security_priv { u8 bWepDefaultKeyIdxSet; }; -struct sha256_state { - u64 length; - u32 state[8], curlen; - u8 buf[64]; -}; - #define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst) \ do { \ switch (psecuritypriv->dot11AuthAlgrthm) { \ diff --git a/drivers/staging/rtl8188eu/include/rtw_sreset.h b/drivers/staging/rtl8188eu/include/rtw_sreset.h index ce027dfdecc5..4c4ccd564863 100644 --- a/drivers/staging/rtl8188eu/include/rtw_sreset.h +++ b/drivers/staging/rtl8188eu/include/rtw_sreset.h @@ -33,7 +33,6 @@ struct sreset_priv { #define WIFI_RX_HANG BIT(5) #define WIFI_IF_NOT_EXIST BIT(6) -void sreset_init_value(struct adapter *padapter); u8 sreset_get_wifi_status(struct adapter *padapter); void sreset_set_wifi_error_status(struct adapter *padapter, u32 status); diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h index a0853bab3edb..dd6b7a9a8d4a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h @@ -113,7 +113,6 @@ struct pkt_attrib { u8 dhcp_pkt; u16 ether_type; u16 seqnum; - u16 pkt_hdrlen; /* the original 802.3 pkt header len */ u16 hdrlen; /* the WLAN Header Len */ u32 pktlen; /* the original 802.3 pkt raw_data len (not include * ether_hdr data) */ @@ -256,15 +255,8 @@ struct hw_txqueue { int ac_tag; }; -struct agg_pkt_info { - u16 offset; - u16 pkt_len; -}; - struct xmit_priv { spinlock_t lock; - struct semaphore xmit_sema; - struct semaphore terminate_xmitthread_sema; struct __queue be_pending; struct __queue bk_pending; struct __queue vi_pending; @@ -289,7 +281,6 @@ struct xmit_priv { u8 wmm_para_seq[4];/* sequence for wmm ac parameter strength * from large to small. it's value is 0->vo, * 1->vi, 2->be, 3->bk. */ - struct semaphore tx_retevt;/* all tx return event; */ u8 txirp_cnt;/* */ struct tasklet_struct xmit_tasklet; /* per AC pending irp */ diff --git a/drivers/staging/rtl8188eu/include/usb_hal.h b/drivers/staging/rtl8188eu/include/usb_hal.h deleted file mode 100644 index b1bf07a9013e..000000000000 --- a/drivers/staging/rtl8188eu/include/usb_hal.h +++ /dev/null @@ -1,21 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __USB_HAL_H__ -#define __USB_HAL_H__ - -void rtl8188eu_set_hal_ops(struct adapter *padapter); -#define hal_set_hal_ops rtl8188eu_set_hal_ops - -#endif /* __USB_HAL_H__ */ diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h index 220733314f8b..78d9b6e035bf 100644 --- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h +++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h @@ -47,21 +47,6 @@ #define usb_read_interrupt_complete(purb, regs) \ usb_read_interrupt_complete(purb) -static inline u8 rtw_usb_bulk_size_boundary(struct adapter *padapter, - int buf_len) -{ - u8 rst = true; - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - - if (pdvobjpriv->ishighspeed) - rst = (0 == (buf_len) % USB_HIGH_SPEED_BULK_SIZE) ? - true : false; - else - rst = (0 == (buf_len) % USB_FULL_SPEED_BULK_SIZE) ? - true : false; - return rst; -} - unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr); u8 usb_read8(struct adapter *adapter, u32 addr); @@ -75,7 +60,7 @@ int usb_write8(struct adapter *adapter, u32 addr, u8 val); int usb_write16(struct adapter *adapter, u32 addr, u16 val); int usb_write32(struct adapter *adapter, u32 addr, u32 val); -u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); +u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, struct xmit_buf *pmem); void usb_write_port_cancel(struct adapter *adapter); #endif diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index e7c512183619..9e08e6842eca 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -508,22 +508,6 @@ struct rtw_ieee80211_bar { #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - /** - * struct rtw_ieee80211_ht_cap - HT capabilities - * - * This structure refers to "HT capabilities element" as - * described in 802.11n draft section 7.3.2.52 - */ - -struct rtw_ieee80211_ht_cap { - unsigned short cap_info; - unsigned char ampdu_params_info; - unsigned char supp_mcs_set[16]; - unsigned short extended_ht_cap_info; - unsigned int tx_BF_cap_info; - unsigned char antenna_selection_info; -} __packed; - /** * struct rtw_ieee80211_ht_cap - HT additional information * @@ -538,20 +522,6 @@ struct ieee80211_ht_addt_info { unsigned char basic_set[16]; } __packed; -struct HT_caps_element { - union { - struct { - __le16 HT_caps_info; - unsigned char AMPDU_para; - unsigned char MCS_rate[16]; - unsigned short HT_ext_caps; - unsigned int Beamforming_caps; - unsigned char ASEL_caps; - } HT_cap_element; - unsigned char HT_cap[26]; - } u; -} __packed; - struct HT_info_element { unsigned char primary_channel; unsigned char infos[5]; diff --git a/drivers/staging/rtl8188eu/include/wlan_bssdef.h b/drivers/staging/rtl8188eu/include/wlan_bssdef.h index 560966cd7dfe..e1931dd04da0 100644 --- a/drivers/staging/rtl8188eu/include/wlan_bssdef.h +++ b/drivers/staging/rtl8188eu/include/wlan_bssdef.h @@ -123,40 +123,10 @@ enum ndis_802_11_wep_status { #define NDIS_802_11_AI_RESFI_STATUSCODE 2 #define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 -struct ndis_802_11_ai_reqfi { - u16 Capabilities; - u16 ListenInterval; - unsigned char CurrentAPAddress[ETH_ALEN]; -}; - -struct ndis_802_11_ai_resfi { - u16 Capabilities; - u16 StatusCode; - u16 AssociationId; -}; - -struct ndis_802_11_assoc_info { - u32 Length; - u16 AvailableRequestFixedIEs; - struct ndis_802_11_ai_reqfi RequestFixedIEs; - u32 RequestIELength; - u32 OffsetRequestIEs; - u16 AvailableResponseFixedIEs; - struct ndis_802_11_ai_resfi ResponseFixedIEs; - u32 ResponseIELength; - u32 OffsetResponseIEs; -}; - enum ndis_802_11_reload_def { Ndis802_11ReloadWEPKeys }; -struct ndis_802_11_remove_key { - u32 Length; /* Length */ - u32 KeyIndex; - unsigned char BSSID[ETH_ALEN]; -}; - struct ndis_802_11_wep { u32 Length; /* Length of this structure */ u32 KeyIndex; /* 0 is the per-client key, @@ -165,12 +135,6 @@ struct ndis_802_11_wep { u8 KeyMaterial[16];/* variable len depending on above field */ }; -struct ndis_802_11_auth_req { - u32 Length; /* Length of structure */ - unsigned char Bssid[ETH_ALEN]; - u32 Flags; -}; - enum ndis_802_11_status_type { Ndis802_11StatusType_Authentication, Ndis802_11StatusType_MediaStreamMode, @@ -179,10 +143,6 @@ enum ndis_802_11_status_type { * an upper bound */ }; -struct ndis_802_11_status_ind { - enum ndis_802_11_status_type StatusType; -}; - /* mask for authentication/integrity fields */ #define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f #define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 @@ -193,21 +153,6 @@ struct ndis_802_11_status_ind { /* MIC check time, 60 seconds. */ #define MIC_CHECK_TIME 60000000 -struct ndis_802_11_auth_evt { - struct ndis_802_11_status_ind Status; - struct ndis_802_11_auth_req Request[1]; -}; - -struct ndis_802_11_test { - u32 Length; - u32 Type; - union { - struct ndis_802_11_auth_evt AuthenticationEvent; - NDIS_802_11_RSSI RssiTrigger; - } tt; -}; - - #ifndef Ndis802_11APMode #define Ndis802_11APMode (Ndis802_11InfrastructureMax+1) #endif @@ -297,32 +242,4 @@ enum UAPSD_MAX_SP { #define NUM_PRE_AUTH_KEY 16 #define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY -/* -* WPA2 -*/ - -struct pmkid_candidate { - unsigned char BSSID[ETH_ALEN]; - u32 Flags; -}; - -struct ndis_802_11_pmkid_list { - u32 Version; /* Version of the structure */ - u32 NumCandidates; /* No. of pmkid candidates */ - struct pmkid_candidate CandidateList[1]; -}; - -struct ndis_802_11_auth_encrypt { - enum ndis_802_11_auth_mode AuthModeSupported; - enum ndis_802_11_wep_status EncryptStatusSupported; -}; - -struct ndis_802_11_cap { - u32 Length; - u32 Version; - u32 NoOfPMKIDs; - u32 NoOfAuthEncryptPairsSupported; - struct ndis_802_11_auth_encrypt AuthenticationEncryptionSupported[1]; -}; - #endif /* ifndef WLAN_BSSDEF_H_ */ diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 5672f014cc46..4de9dbc93380 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -132,12 +132,15 @@ static char *translate_scan(struct adapter *padapter, p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12); if (p && ht_ielen > 0) { - struct rtw_ieee80211_ht_cap *pht_capie; + struct ieee80211_ht_cap *pht_capie; ht_cap = true; - pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2); - memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); - bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0; - short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; + pht_capie = (struct ieee80211_ht_cap *)(p + 2); + memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2); + bw_40MHz = !!(le16_to_cpu(pht_capie->cap_info) & + IEEE80211_HT_CAP_SUP_WIDTH); + short_GI = !!(le16_to_cpu(pht_capie->cap_info) & + (IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40)); } /* Add the protocol name */ @@ -400,7 +403,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, wep_key_len = wep_key_len <= 5 ? 5 : 13; wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial); pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len); - if (pwep == NULL) { + if (!pwep) { RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n")); goto exit; } @@ -441,7 +444,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); - if (psta == NULL) { + if (!psta) { ; } else { if (strcmp(param->u.crypt.alg, "none") != 0) @@ -476,7 +479,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, } } pbcmc_sta = rtw_get_bcmc_stainfo(padapter); - if (pbcmc_sta == NULL) { + if (!pbcmc_sta) { ; } else { /* Jeff: don't disable ieee8021x_blocked while clearing key */ @@ -502,9 +505,9 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie int group_cipher = 0, pairwise_cipher = 0; int ret = 0; - if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) { + if ((ielen > MAX_WPA_IE_LEN) || (!pie)) { _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - if (pie == NULL) + if (!pie) return ret; else return -EINVAL; @@ -512,7 +515,7 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie if (ielen) { buf = kmemdup(pie, ielen, GFP_KERNEL); - if (buf == NULL) { + if (!buf) { ret = -ENOMEM; goto exit; } @@ -1049,7 +1052,7 @@ static int rtw_wx_set_mlme(struct net_device *dev, struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); struct iw_mlme *mlme = (struct iw_mlme *)extra; - if (mlme == NULL) + if (!mlme) return -1; DBG_88E("%s\n", __func__); @@ -1896,7 +1899,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, param_len = sizeof(struct ieee_param) + pext->key_len; param = (struct ieee_param *)rtw_malloc(param_len); - if (param == NULL) + if (!param) return -1; memset(param, 0, param_len); @@ -2061,7 +2064,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) } param = (struct ieee_param *)rtw_malloc(p->length); - if (param == NULL) { + if (!param) { ret = -ENOMEM; goto out; } @@ -2254,13 +2257,13 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, } } - if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) { + if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) { /* todo:clear default encryption keys */ DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx); goto exit; } - if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) { + if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) { DBG_88E("r871x_set_encryption, crypt.alg = WEP\n"); wep_key_idx = param->u.crypt.idx; wep_key_len = param->u.crypt.key_len; @@ -2274,7 +2277,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, wep_key_len = wep_key_len <= 5 ? 5 : 13; wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial); pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len); - if (pwep == NULL) { + if (!pwep) { DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n"); goto exit; } @@ -2528,7 +2531,8 @@ static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) if (WLAN_STA_HT&flags) { psta->htpriv.ht_option = true; psta->qos_option = 1; - memcpy((void *)&psta->htpriv.ht_cap, (void *)¶m->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap)); + memcpy(&psta->htpriv.ht_cap, ¶m->u.add_sta.ht_cap, + sizeof(struct ieee80211_ht_cap)); } else { psta->htpriv.ht_option = false; } @@ -2624,7 +2628,8 @@ static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *par (psta->ht_20mhz_set << 5)); psta_data->tx_supp_rates_len = psta->bssratelen; memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen); - memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap)); + memcpy(&psta_data->ht_cap, + &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap)); psta_data->rx_pkts = psta->sta_stats.rx_data_pkts; psta_data->rx_bytes = psta->sta_stats.rx_bytes; psta_data->rx_drops = psta->sta_stats.rx_drops; @@ -2699,7 +2704,7 @@ static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, if (ie_len > 0) { pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len); pmlmepriv->wps_beacon_ie_len = ie_len; - if (pmlmepriv->wps_beacon_ie == NULL) { + if (!pmlmepriv->wps_beacon_ie) { DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); return -EINVAL; } @@ -2734,7 +2739,7 @@ static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *par if (ie_len > 0) { pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len); pmlmepriv->wps_probe_resp_ie_len = ie_len; - if (pmlmepriv->wps_probe_resp_ie == NULL) { + if (!pmlmepriv->wps_probe_resp_ie) { DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); return -EINVAL; } @@ -2764,7 +2769,7 @@ static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *par if (ie_len > 0) { pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len); pmlmepriv->wps_assoc_resp_ie_len = ie_len; - if (pmlmepriv->wps_assoc_resp_ie == NULL) { + if (!pmlmepriv->wps_assoc_resp_ie) { DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); return -EINVAL; } @@ -2866,7 +2871,7 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p) } param = (struct ieee_param *)rtw_malloc(p->length); - if (param == NULL) { + if (!param) { ret = -ENOMEM; goto out; } @@ -2976,7 +2981,7 @@ static int rtw_wx_set_priv(struct net_device *dev, pmlmepriv->wps_probe_req_ie = NULL; pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz); - if (pmlmepriv->wps_probe_req_ie == NULL) { + if (!pmlmepriv->wps_probe_req_ie) { pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); ret = -EINVAL; goto FREE_EXT; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index ae2caff030f1..40691f1ec507 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -23,8 +23,6 @@ #include #include -#include - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek Wireless Lan Driver"); MODULE_AUTHOR("Realtek Semiconductor Corp."); @@ -33,11 +31,7 @@ MODULE_VERSION(DRIVERVERSION); #define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */ /* module param defaults */ -static int rtw_chip_version; -static int rtw_rfintfs = HWPI; -static int rtw_lbkmode;/* RTL8712_AIR_TRX; */ /* Ndis802_11Infrastructure; infra, ad-hoc, auto */ -static int rtw_network_mode = Ndis802_11IBSS; static int rtw_channel = 1;/* ad-hoc support requirement */ static int rtw_wireless_mode = WIRELESS_11BG_24N; static int rtw_vrtl_carrier_sense = AUTO_VCS; @@ -45,9 +39,6 @@ static int rtw_vcs_type = RTS_CTS;/* */ static int rtw_rts_thresh = 2347;/* */ static int rtw_frag_thresh = 2346;/* */ static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */ -static int rtw_scan_mode = 1;/* active, passive */ -static int rtw_adhoc_tx_pwr = 1; -static int rtw_soft_ap; static int rtw_power_mgnt = 1; static int rtw_ips_mode = IPS_NORMAL; @@ -57,11 +48,6 @@ module_param(rtw_ips_mode, int, 0644); MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode"); static int rtw_debug = 1; -static int rtw_radio_enable = 1; -static int rtw_long_retry_lmt = 7; -static int rtw_short_retry_lmt = 7; -static int rtw_busy_thresh = 40; -static int rtw_ack_policy = NORMAL_ACK; static int rtw_software_encrypt; static int rtw_software_decrypt; @@ -70,11 +56,6 @@ static int rtw_acm_method;/* 0:By SW 1:By HW. */ static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */ static int rtw_uapsd_enable; -static int rtw_uapsd_max_sp = NO_LIMIT; -static int rtw_uapsd_acbk_en; -static int rtw_uapsd_acbe_en; -static int rtw_uapsd_acvi_en; -static int rtw_uapsd_acvo_en; static int rtw_ht_enable = 1; /* 0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */ @@ -89,11 +70,6 @@ static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */ static int rtw_rx_stbc = 1; static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */ -/* Use 2 path Tx to transmit MCS0~7 and legacy mode */ -static int rtw_lowrate_two_xmit = 1; - -static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */ -static int rtw_low_power; static int rtw_wifi_spec; static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX; @@ -111,10 +87,6 @@ static int rtw_enusbss;/* 0:disable, 1:enable */ static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */ -static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */ - -static int rtw_hw_wps_pbc = 1; - int rtw_mc2u_disable; static int rtw_80211d; @@ -132,32 +104,22 @@ char *rtw_initmac; module_param(rtw_initmac, charp, 0644); module_param(rtw_channel_plan, int, 0644); -module_param(rtw_chip_version, int, 0644); -module_param(rtw_rfintfs, int, 0644); -module_param(rtw_lbkmode, int, 0644); -module_param(rtw_network_mode, int, 0644); module_param(rtw_channel, int, 0644); module_param(rtw_wmm_enable, int, 0644); module_param(rtw_vrtl_carrier_sense, int, 0644); module_param(rtw_vcs_type, int, 0644); -module_param(rtw_busy_thresh, int, 0644); module_param(rtw_ht_enable, int, 0644); module_param(rtw_cbw40_enable, int, 0644); module_param(rtw_ampdu_enable, int, 0644); module_param(rtw_rx_stbc, int, 0644); module_param(rtw_ampdu_amsdu, int, 0644); -module_param(rtw_lowrate_two_xmit, int, 0644); -module_param(rtw_rf_config, int, 0644); module_param(rtw_power_mgnt, int, 0644); module_param(rtw_smart_ps, int, 0644); -module_param(rtw_low_power, int, 0644); module_param(rtw_wifi_spec, int, 0644); module_param(rtw_antdiv_cfg, int, 0644); module_param(rtw_antdiv_type, int, 0644); module_param(rtw_enusbss, int, 0644); module_param(rtw_hwpdn_mode, int, 0644); -module_param(rtw_hwpwrp_detect, int, 0644); -module_param(rtw_hw_wps_pbc, int, 0644); static uint rtw_max_roaming_times = 2; module_param(rtw_max_roaming_times, uint, 0644); @@ -185,361 +147,11 @@ MODULE_PARM_DESC(monitor_enable, "Enable monitor inferface (default: false)"); static int netdev_open(struct net_device *pnetdev); static int netdev_close(struct net_device *pnetdev); -/* dummy routines */ -void rtw_proc_remove_one(struct net_device *dev) -{ -} - -static void rtw_proc_init_one(struct net_device *dev) -{ -} - -#if 0 /* TODO: Convert these to /sys */ -static void rtw_proc_init_one(struct net_device *dev) -{ - struct proc_dir_entry *dir_dev = NULL; - struct proc_dir_entry *entry = NULL; - struct adapter *padapter = rtw_netdev_priv(dev); - u8 rf_type; - - if (rtw_proc == NULL) { - memcpy(rtw_proc_name, DRV_NAME, sizeof(DRV_NAME)); - - rtw_proc = create_proc_entry(rtw_proc_name, S_IFDIR, - init_net.proc_net); - if (rtw_proc == NULL) { - DBG_88E(KERN_ERR "Unable to create rtw_proc directory\n"); - return; - } - - entry = create_proc_read_entry("ver_info", S_IFREG | S_IRUGO, - rtw_proc, proc_get_drv_version, - dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - } - - if (padapter->dir_dev == NULL) { - padapter->dir_dev = create_proc_entry(dev->name, - S_IFDIR | S_IRUGO | S_IXUGO, - rtw_proc); - dir_dev = padapter->dir_dev; - if (dir_dev == NULL) { - if (rtw_proc_cnt == 0 && rtw_proc) { - remove_proc_entry(rtw_proc_name, init_net.proc_net); - rtw_proc = NULL; - } - - pr_info("Unable to create dir_dev directory\n"); - return; - } - } else { - return; - } - - rtw_proc_cnt++; - - entry = create_proc_read_entry("write_reg", S_IFREG | S_IRUGO, - dir_dev, proc_get_write_reg, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_write_reg; - - entry = create_proc_read_entry("read_reg", S_IFREG | S_IRUGO, - dir_dev, proc_get_read_reg, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_read_reg; - - - entry = create_proc_read_entry("fwstate", S_IFREG | S_IRUGO, - dir_dev, proc_get_fwstate, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("sec_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_sec_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("mlmext_state", S_IFREG | S_IRUGO, - dir_dev, proc_get_mlmext_state, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("qos_option", S_IFREG | S_IRUGO, - dir_dev, proc_get_qos_option, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("ht_option", S_IFREG | S_IRUGO, - dir_dev, proc_get_ht_option, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rf_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_rf_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("ap_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_ap_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("adapter_state", S_IFREG | S_IRUGO, - dir_dev, proc_getstruct adapter_state, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("trx_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_trx_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("mac_reg_dump1", S_IFREG | S_IRUGO, - dir_dev, proc_get_mac_reg_dump1, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("mac_reg_dump2", S_IFREG | S_IRUGO, - dir_dev, proc_get_mac_reg_dump2, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("mac_reg_dump3", S_IFREG | S_IRUGO, - dir_dev, proc_get_mac_reg_dump3, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("bb_reg_dump1", S_IFREG | S_IRUGO, - dir_dev, proc_get_bb_reg_dump1, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("bb_reg_dump2", S_IFREG | S_IRUGO, - dir_dev, proc_get_bb_reg_dump2, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("bb_reg_dump3", S_IFREG | S_IRUGO, - dir_dev, proc_get_bb_reg_dump3, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rf_reg_dump1", S_IFREG | S_IRUGO, - dir_dev, proc_get_rf_reg_dump1, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rf_reg_dump2", S_IFREG | S_IRUGO, - dir_dev, proc_get_rf_reg_dump2, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type)) { - entry = create_proc_read_entry("rf_reg_dump3", - S_IFREG | S_IRUGO, dir_dev, - proc_get_rf_reg_dump3, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rf_reg_dump4", - S_IFREG | S_IRUGO, dir_dev, - proc_get_rf_reg_dump4, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - } - -#ifdef CONFIG_88EU_AP_MODE - - entry = create_proc_read_entry("all_sta_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_all_sta_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } -#endif - - entry = create_proc_read_entry("best_channel", S_IFREG | S_IRUGO, - dir_dev, proc_get_best_channel, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rx_signal", S_IFREG | S_IRUGO, - dir_dev, proc_get_rx_signal, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_rx_signal; - entry = create_proc_read_entry("ht_enable", S_IFREG | S_IRUGO, - dir_dev, proc_get_ht_enable, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_ht_enable; - - entry = create_proc_read_entry("cbw40_enable", S_IFREG | S_IRUGO, - dir_dev, proc_get_cbw40_enable, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_cbw40_enable; - - entry = create_proc_read_entry("ampdu_enable", S_IFREG | S_IRUGO, - dir_dev, proc_get_ampdu_enable, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_ampdu_enable; - - entry = create_proc_read_entry("rx_stbc", S_IFREG | S_IRUGO, - dir_dev, proc_get_rx_stbc, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_rx_stbc; - - entry = create_proc_read_entry("path_rssi", S_IFREG | S_IRUGO, - dir_dev, proc_get_two_path_rssi, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry = create_proc_read_entry("rssi_disp", S_IFREG | S_IRUGO, - dir_dev, proc_get_rssi_disp, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_rssi_disp; -} - -void rtw_proc_remove_one(struct net_device *dev) -{ - struct proc_dir_entry *dir_dev = NULL; - struct adapter *padapter = rtw_netdev_priv(dev); - u8 rf_type; - - dir_dev = padapter->dir_dev; - padapter->dir_dev = NULL; - - if (dir_dev) { - remove_proc_entry("write_reg", dir_dev); - remove_proc_entry("read_reg", dir_dev); - remove_proc_entry("fwstate", dir_dev); - remove_proc_entry("sec_info", dir_dev); - remove_proc_entry("mlmext_state", dir_dev); - remove_proc_entry("qos_option", dir_dev); - remove_proc_entry("ht_option", dir_dev); - remove_proc_entry("rf_info", dir_dev); - remove_proc_entry("ap_info", dir_dev); - remove_proc_entry("adapter_state", dir_dev); - remove_proc_entry("trx_info", dir_dev); - remove_proc_entry("mac_reg_dump1", dir_dev); - remove_proc_entry("mac_reg_dump2", dir_dev); - remove_proc_entry("mac_reg_dump3", dir_dev); - remove_proc_entry("bb_reg_dump1", dir_dev); - remove_proc_entry("bb_reg_dump2", dir_dev); - remove_proc_entry("bb_reg_dump3", dir_dev); - remove_proc_entry("rf_reg_dump1", dir_dev); - remove_proc_entry("rf_reg_dump2", dir_dev); - rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type)) { - remove_proc_entry("rf_reg_dump3", dir_dev); - remove_proc_entry("rf_reg_dump4", dir_dev); - } -#ifdef CONFIG_88EU_AP_MODE - remove_proc_entry("all_sta_info", dir_dev); -#endif - - remove_proc_entry("best_channel", dir_dev); - remove_proc_entry("rx_signal", dir_dev); - remove_proc_entry("cbw40_enable", dir_dev); - remove_proc_entry("ht_enable", dir_dev); - remove_proc_entry("ampdu_enable", dir_dev); - remove_proc_entry("rx_stbc", dir_dev); - remove_proc_entry("path_rssi", dir_dev); - remove_proc_entry("rssi_disp", dir_dev); - remove_proc_entry(dev->name, rtw_proc); - dir_dev = NULL; - } else { - return; - } - rtw_proc_cnt--; - - if (rtw_proc_cnt == 0) { - if (rtw_proc) { - remove_proc_entry("ver_info", rtw_proc); - - remove_proc_entry(rtw_proc_name, init_net.proc_net); - rtw_proc = NULL; - } - } -} -#endif - static void loadparam(struct adapter *padapter, struct net_device *pnetdev) { struct registry_priv *registry_par = &padapter->registrypriv; GlobalDebugLevel = rtw_debug; - registry_par->chip_version = (u8)rtw_chip_version; - registry_par->rfintfs = (u8)rtw_rfintfs; - registry_par->lbkmode = (u8)rtw_lbkmode; - registry_par->network_mode = (u8)rtw_network_mode; memcpy(registry_par->ssid.Ssid, "ANY", 3); registry_par->ssid.SsidLength = 3; @@ -551,17 +163,9 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) registry_par->rts_thresh = (u16)rtw_rts_thresh; registry_par->frag_thresh = (u16)rtw_frag_thresh; registry_par->preamble = (u8)rtw_preamble; - registry_par->scan_mode = (u8)rtw_scan_mode; - registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr; - registry_par->soft_ap = (u8)rtw_soft_ap; registry_par->smart_ps = (u8)rtw_smart_ps; registry_par->power_mgnt = (u8)rtw_power_mgnt; registry_par->ips_mode = (u8)rtw_ips_mode; - registry_par->radio_enable = (u8)rtw_radio_enable; - registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt; - registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt; - registry_par->busy_thresh = (u16)rtw_busy_thresh; - registry_par->ack_policy = (u8)rtw_ack_policy; registry_par->mp_mode = 0; registry_par->software_encrypt = (u8)rtw_software_encrypt; registry_par->software_decrypt = (u8)rtw_software_decrypt; @@ -570,28 +174,18 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) /* UAPSD */ registry_par->wmm_enable = (u8)rtw_wmm_enable; registry_par->uapsd_enable = (u8)rtw_uapsd_enable; - registry_par->uapsd_max_sp = (u8)rtw_uapsd_max_sp; - registry_par->uapsd_acbk_en = (u8)rtw_uapsd_acbk_en; - registry_par->uapsd_acbe_en = (u8)rtw_uapsd_acbe_en; - registry_par->uapsd_acvi_en = (u8)rtw_uapsd_acvi_en; - registry_par->uapsd_acvo_en = (u8)rtw_uapsd_acvo_en; registry_par->ht_enable = (u8)rtw_ht_enable; registry_par->cbw40_enable = (u8)rtw_cbw40_enable; registry_par->ampdu_enable = (u8)rtw_ampdu_enable; registry_par->rx_stbc = (u8)rtw_rx_stbc; registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu; - registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit; - registry_par->rf_config = (u8)rtw_rf_config; - registry_par->low_power = (u8)rtw_low_power; registry_par->wifi_spec = (u8)rtw_wifi_spec; registry_par->channel_plan = (u8)rtw_channel_plan; registry_par->accept_addba_req = true; registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; registry_par->antdiv_type = (u8)rtw_antdiv_type; registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode; - registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect; - registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc; registry_par->max_roaming_times = (u8)rtw_max_roaming_times; @@ -732,7 +326,7 @@ struct net_device *rtw_init_netdev(struct adapter *old_padapter) RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+init_net_dev\n")); if (old_padapter != NULL) - pnetdev = rtw_alloc_etherdev_with_old_priv(sizeof(struct adapter), (void *)old_padapter); + pnetdev = rtw_alloc_etherdev_with_old_priv((void *)old_padapter); if (!pnetdev) return NULL; @@ -762,7 +356,7 @@ static int rtw_start_drv_threads(struct adapter *padapter) err = PTR_ERR(padapter->cmdThread); else /* wait for cmd_thread to run */ - _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); + wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp); return err; } @@ -772,9 +366,9 @@ void rtw_stop_drv_threads(struct adapter *padapter) RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_stop_drv_threads\n")); /* Below is to terminate rtw_cmd_thread & event_thread... */ - up(&padapter->cmdpriv.cmd_queue_sema); + complete(&padapter->cmdpriv.cmd_queue_comp); if (padapter->cmdThread) - _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); + wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp); } @@ -821,7 +415,6 @@ static u8 rtw_init_default_value(struct adapter *padapter) padapter->bReadPortCancel = false; padapter->bWritePortCancel = false; padapter->bRxRSSIDisplay = 0; - padapter->bNotifyChannelChange = 0; return _SUCCESS; } @@ -912,8 +505,6 @@ u8 rtw_init_drv_sw(struct adapter *padapter) rtw_hal_sreset_init(padapter); - spin_lock_init(&padapter->br_ext_lock); - exit: RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_init_drv_sw\n")); @@ -961,12 +552,6 @@ u8 rtw_free_drv_sw(struct adapter *padapter) RT_TRACE(_module_os_intfs_c_, _drv_info_, ("<== rtw_free_drv_sw\n")); - /* free the old_pnetdev */ - if (padapter->rereg_nd_name_priv.old_pnetdev) { - free_netdev(padapter->rereg_nd_name_priv.old_pnetdev); - padapter->rereg_nd_name_priv.old_pnetdev = NULL; - } - mutex_destroy(&padapter->hw_init_mutex); RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_free_drv_sw\n")); @@ -1013,7 +598,6 @@ static int _netdev_open(struct net_device *pnetdev) } if (padapter->intf_start) padapter->intf_start(padapter); - rtw_proc_init_one(pnetdev); rtw_led_control(padapter, LED_CTL_NO_LINK); diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 764250b4ba86..7cd2655f27fe 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -55,21 +55,13 @@ void *rtw_malloc2d(int h, int w, int size) return a; } -u32 _rtw_down_sema(struct semaphore *sema) -{ - if (down_interruptible(sema)) - return _FAIL; - return _SUCCESS; -} - void _rtw_init_queue(struct __queue *pqueue) { INIT_LIST_HEAD(&(pqueue->queue)); spin_lock_init(&(pqueue->lock)); } -struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, - void *old_priv) +struct net_device *rtw_alloc_etherdev_with_old_priv(void *old_priv) { struct net_device *pnetdev; struct rtw_netdev_priv_indicator *pnpi; @@ -80,7 +72,6 @@ struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, pnpi = netdev_priv(pnetdev); pnpi->priv = old_priv; - pnpi->sizeof_priv = sizeof_priv; RETURN: return pnetdev; diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c index 0c44914ea3e6..103cdb4ed073 100644 --- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c @@ -24,7 +24,6 @@ /* alloc os related resource in struct recv_frame */ void rtw_os_recv_resource_alloc(struct recv_frame *precvframe) { - precvframe->pkt_newalloc = NULL; precvframe->pkt = NULL; } diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 11d51a30170f..68e1e6bbe87f 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -25,9 +25,10 @@ #include #include -#include #include +#include "rtl8188e_hal.h" + #define USB_VENDER_ID_REALTEK 0x0bda /* DID_USB_v916_20130116 */ @@ -79,9 +80,8 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces; pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber; - pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints; - for (i = 0; i < pdvobjpriv->nr_endpoint; i++) { + for (i = 0; i < piface_desc->bNumEndpoints; i++) { int ep_num; pendp_desc = &phost_iface->endpoint[i].desc; @@ -98,7 +98,6 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) ep_num; pdvobjpriv->RtNumOutPipes++; } - pdvobjpriv->ep_num[i] = ep_num; } if (pusbd->speed == USB_SPEED_HIGH) @@ -107,13 +106,6 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) pdvobjpriv->ishighspeed = false; mutex_init(&pdvobjpriv->usb_vendor_req_mutex); - pdvobjpriv->usb_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE, GFP_KERNEL); - - if (!pdvobjpriv->usb_vendor_req_buf) { - usb_set_intfdata(usb_intf, NULL); - kfree(pdvobjpriv); - return NULL; - } usb_get_dev(pusbd); return pdvobjpriv; @@ -141,7 +133,6 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf) } } - kfree(dvobj->usb_vendor_req_buf); mutex_destroy(&dvobj->usb_vendor_req_mutex); kfree(dvobj); } @@ -238,7 +229,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) rtw_cancel_all_timer(padapter); LeaveAllPowerSaveMode(padapter); - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); /* s1. */ if (pnetdev) { netif_carrier_off(pnetdev); @@ -267,7 +258,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) rtw_free_network_queue(padapter, true); rtw_dev_unload(padapter); - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) rtw_indicate_scan_done(padapter, 1); @@ -298,18 +289,20 @@ static int rtw_resume_process(struct adapter *padapter) goto exit; } - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); rtw_reset_drv_sw(padapter); pwrpriv->bkeepfwalive = false; pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive); - if (pm_netdev_open(pnetdev, true) != 0) + if (pm_netdev_open(pnetdev, true) != 0) { + mutex_unlock(&pwrpriv->mutex_lock); goto exit; + } netif_device_attach(pnetdev); netif_carrier_on(pnetdev); - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); rtw_roaming(padapter, NULL); @@ -369,8 +362,9 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, padapter->pmondev = pmondev; } - /* step 2. hook HalFunc, allocate HalData */ - hal_set_hal_ops(padapter); + padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL); + if (!padapter->HalData) + DBG_88E("cant not alloc memory for HAL DATA\n"); padapter->intf_start = &usb_intf_start; padapter->intf_stop = &usb_intf_stop; @@ -456,11 +450,9 @@ static void rtw_usb_if1_deinit(struct adapter *if1) free_mlme_ap_info(if1); #endif - if (pnetdev) { - /* will call netdev_close() */ - unregister_netdev(pnetdev); - rtw_proc_remove_one(pnetdev); - } + if (pnetdev) + unregister_netdev(pnetdev); /* will call netdev_close() */ + rtl88eu_mon_deinit(if1->pmondev); rtw_cancel_all_timer(if1); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index ce1e1a135f1b..d0d591501b73 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -20,7 +20,7 @@ static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) { DBG_88E("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len); @@ -48,7 +48,7 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) struct sk_buff *pkt_copy = NULL; struct recv_frame *precvframe = NULL; struct rx_pkt_attrib *pattrib = NULL; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; struct recv_priv *precvpriv = &adapt->recvpriv; struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; @@ -251,7 +251,7 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i } /* Acquire IO memory for vendorreq */ - pIo_buf = dvobjpriv->usb_vendor_req_buf; + pIo_buf = kmalloc(MAX_USB_IO_CTL_SIZE, GFP_ATOMIC); if (pIo_buf == NULL) { DBG_88E("[%s] pIo_buf == NULL\n", __func__); @@ -285,8 +285,7 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i if (status == (-ESHUTDOWN) || status == -ENODEV) { adapt->bSurpriseRemoved = true; } else { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - haldata->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL; + adapt->HalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL; } } else { /* status != len && status >= 0 */ if (status > 0) { @@ -303,6 +302,8 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len) break; } + kfree(pIo_buf); + release_mutex: mutex_unlock(&dvobjpriv->usb_vendor_req_mutex); exit: @@ -434,10 +435,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) break; case -EPROTO: case -EOVERFLOW: - { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - haldata->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL; - } + adapt->HalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL; precvbuf->reuse = true; usb_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); break; @@ -525,7 +523,7 @@ u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *rmem) return ret; } -void usb_read_port_cancel(struct adapter *padapter) +void rtw_hal_inirp_deinit(struct adapter *padapter) { int i; struct recv_buf *precvbuf; @@ -691,7 +689,7 @@ check_completion: tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); } -u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) +u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, struct xmit_buf *xmitbuf) { unsigned long irqL; unsigned int pipe; @@ -700,8 +698,7 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) struct urb *purb = NULL; struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem; - struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; + struct xmit_frame *pxmitframe = (struct xmit_frame *)xmitbuf->priv_data; struct usb_device *pusbd = pdvobj->pusbdev; @@ -711,7 +708,7 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) (padapter->pwrctrlpriv.pnp_bstop_trx)) { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n")); - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); + rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); goto exit; } @@ -720,44 +717,44 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) switch (addr) { case VO_QUEUE_INX: pxmitpriv->voq_cnt++; - pxmitbuf->flags = VO_QUEUE_INX; + xmitbuf->flags = VO_QUEUE_INX; break; case VI_QUEUE_INX: pxmitpriv->viq_cnt++; - pxmitbuf->flags = VI_QUEUE_INX; + xmitbuf->flags = VI_QUEUE_INX; break; case BE_QUEUE_INX: pxmitpriv->beq_cnt++; - pxmitbuf->flags = BE_QUEUE_INX; + xmitbuf->flags = BE_QUEUE_INX; break; case BK_QUEUE_INX: pxmitpriv->bkq_cnt++; - pxmitbuf->flags = BK_QUEUE_INX; + xmitbuf->flags = BK_QUEUE_INX; break; case HIGH_QUEUE_INX: - pxmitbuf->flags = HIGH_QUEUE_INX; + xmitbuf->flags = HIGH_QUEUE_INX; break; default: - pxmitbuf->flags = MGT_QUEUE_INX; + xmitbuf->flags = MGT_QUEUE_INX; break; } spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - purb = pxmitbuf->pxmit_urb[0]; + purb = xmitbuf->pxmit_urb[0]; /* translate DMA FIFO addr to pipehandle */ pipe = ffaddr2pipehdl(pdvobj, addr); usb_fill_bulk_urb(purb, pusbd, pipe, - pxmitframe->buf_addr, /* pxmitbuf->pbuf */ + pxmitframe->buf_addr, /* xmitbuf->pbuf */ cnt, usb_write_port_complete, - pxmitbuf);/* context is pxmitbuf */ + xmitbuf);/* context is xmitbuf */ status = usb_submit_urb(purb, GFP_ATOMIC); if (status) { - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR); + rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR); DBG_88E("usb_write_port, status =%d\n", status); RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port(): usb_submit_urb, status =%x\n", status)); @@ -779,7 +776,7 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) exit: if (ret != _SUCCESS) - rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + rtw_free_xmitbuf(pxmitpriv, xmitbuf); return ret; } @@ -846,7 +843,7 @@ void rtl8188eu_xmit_tasklet(void *priv) break; } - ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv, NULL); + ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv); if (!ret) break; diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c index 221e2750652e..4b1b04e00715 100644 --- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c @@ -72,7 +72,7 @@ int rtw_os_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitb if (pxmitbuf->pallocated_buf == NULL) return _FAIL; - pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ); + pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ); pxmitbuf->dma_transfer_addr = 0; for (i = 0; i < 8; i++) { diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c index 4d8fb4158f6b..25725b158eca 100644 --- a/drivers/staging/rtl8192e/dot11d.c +++ b/drivers/staging/rtl8192e/dot11d.c @@ -51,9 +51,8 @@ void dot11d_init(struct rtllib_device *ieee) pDot11dInfo->State = DOT11D_STATE_NONE; pDot11dInfo->CountryIeLen = 0; memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); RESET_CIE_WATCHDOG(ieee); - } EXPORT_SYMBOL(dot11d_init); @@ -99,14 +98,13 @@ void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee) } EXPORT_SYMBOL(Dot11d_Channelmap); - void Dot11d_Reset(struct rtllib_device *ieee) { struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); u32 i; - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); for (i = 1; i <= 11; i++) (pDot11dInfo->channel_map)[i] = 1; for (i = 12; i <= 14; i++) @@ -123,8 +121,8 @@ void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, u8 i, j, NumTriples, MaxChnlNum; struct chnl_txpow_triple *pTriple; - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); MaxChnlNum = 0; NumTriples = (CoutryIeLen - 3) / 3; pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3); diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h index 735a199ebdcf..aac395f26652 100644 --- a/drivers/staging/rtl8192e/dot11d.h +++ b/drivers/staging/rtl8192e/dot11d.h @@ -47,8 +47,8 @@ struct rt_dot11d_info { u8 CountryIeSrcAddr[6]; u8 CountryIeWatchdog; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; - u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; + u8 channel_map[MAX_CHANNEL_NUMBER + 1]; + u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER + 1]; enum dot11d_state State; }; @@ -78,6 +78,7 @@ static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__pIeeeDev) { GET_CIE_WATCHDOG(__pIeeeDev) = 0; } + #define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev)) void dot11d_init(struct rtllib_device *dev); diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index ba64a4f1b3a8..8d6bca61e7aa 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -1487,8 +1487,8 @@ static void _rtl92e_query_rxphystatus( struct phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc; u8 *prxpkt; u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg; - char rx_pwr[4], rx_pwr_all = 0; - char rx_snrX, rx_evmX; + s8 rx_pwr[4], rx_pwr_all = 0; + s8 rx_snrX, rx_evmX; u8 evm, pwdb_all; u32 RSSI, total_rssi = 0; u8 is_cck_rate = 0; @@ -1613,7 +1613,7 @@ static void _rtl92e_query_rxphystatus( 2) - 110; tmp_rxsnr = pofdm_buf->rxsnr_X[i]; - rx_snrX = (char)(tmp_rxsnr); + rx_snrX = (s8)(tmp_rxsnr); rx_snrX /= 2; priv->stats.rxSNRdB[i] = (long)rx_snrX; @@ -1643,7 +1643,7 @@ static void _rtl92e_query_rxphystatus( for (i = 0; i < max_spatial_stream; i++) { tmp_rxevm = pofdm_buf->rxevm_X[i]; - rx_evmX = (char)(tmp_rxevm); + rx_evmX = (s8)(tmp_rxevm); rx_evmX /= 2; diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c index 29cefb599bab..d437a8efe933 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c @@ -11,7 +11,7 @@ * * Contact Information: * wlanfae -******************************************************************************/ + *****************************************************************************/ /*Created on 2008/11/18, 3: 7*/ #include "r8192E_hwimg.h" diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c index 5e3bbe5c3ca4..dde492261451 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c @@ -256,7 +256,7 @@ u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, return 0; if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter) return 0; - down(&priv->rf_sem); + mutex_lock(&priv->rf_mutex); if (priv->Rf_Mode == RF_OP_By_FW) { Original_Value = _rtl92e_phy_rf_fw_read(dev, eRFPath, RegAddr); udelay(200); @@ -265,7 +265,7 @@ u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, } BitShift = _rtl92e_calculate_bit_shift(BitMask); Readback_Value = (Original_Value & BitMask) >> BitShift; - up(&priv->rf_sem); + mutex_unlock(&priv->rf_mutex); return Readback_Value; } @@ -630,7 +630,7 @@ void rtl92e_set_tx_power(struct net_device *dev, u8 channel) { struct r8192_priv *priv = rtllib_priv(dev); u8 powerlevel = 0, powerlevelOFDM24G = 0; - char ant_pwr_diff; + s8 ant_pwr_diff; u32 u4RegValue; if (priv->epromtype == EEPROM_93C46) { diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c index 803c8b02a0c8..30f65af4d614 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c @@ -107,9 +107,9 @@ void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, __func__); return; } - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } } priv->rtllib->is_set_key = true; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 13a5ddc2bea5..4c30eea45f89 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -38,7 +38,7 @@ static int channels = 0x3fff; static char *ifname = "wlan%d"; -static struct rtl819x_ops rtl819xp_ops = { +static const struct rtl819x_ops rtl819xp_ops = { .nic_type = NIC_8192E, .get_eeprom_size = rtl92e_get_eeprom_size, .init_adapter_variable = rtl92e_init_variables, @@ -993,8 +993,8 @@ static void _rtl92e_init_priv_lock(struct r8192_priv *priv) spin_lock_init(&priv->irq_th_lock); spin_lock_init(&priv->rf_ps_lock); spin_lock_init(&priv->ps_lock); - sema_init(&priv->wx_sem, 1); - sema_init(&priv->rf_sem, 1); + mutex_init(&priv->wx_mutex); + mutex_init(&priv->rf_mutex); mutex_init(&priv->mutex); } @@ -1247,7 +1247,7 @@ static void _rtl92e_if_silent_reset(struct net_device *dev) RESET_START: - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); if (priv->rtllib->state == RTLLIB_LINKED) rtl92e_leisure_ps_leave(dev); @@ -1255,7 +1255,7 @@ RESET_START: if (priv->up) { netdev_info(dev, "%s():the driver is not up.\n", __func__); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return; } priv->up = 0; @@ -1277,14 +1277,14 @@ RESET_START: rtllib_stop_scan_syncro(ieee); if (ieee->state == RTLLIB_LINKED) { - SEM_DOWN_IEEE_WX(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); netdev_info(dev, "ieee->state is RTLLIB_LINKED\n"); rtllib_stop_send_beacons(priv->rtllib); del_timer_sync(&ieee->associate_timer); cancel_delayed_work(&ieee->associate_retry_wq); rtllib_stop_scan(ieee); netif_carrier_off(dev); - SEM_UP_IEEE_WX(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } else { netdev_info(dev, "ieee->state is NOT LINKED\n"); rtllib_softmac_stop_protocol(priv->rtllib, 0, true); @@ -1292,7 +1292,7 @@ RESET_START: rtl92e_dm_backup_state(dev); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__); @@ -1982,7 +1982,7 @@ void rtl92e_update_rx_statistics(struct r8192_priv *priv, weighting) / 6; } -u8 rtl92e_rx_db_to_percent(char antpower) +u8 rtl92e_rx_db_to_percent(s8 antpower) { if ((antpower <= -100) || (antpower >= 20)) return 0; @@ -1993,9 +1993,9 @@ u8 rtl92e_rx_db_to_percent(char antpower) } /* QueryRxPwrPercentage */ -u8 rtl92e_evm_db_to_percent(char value) +u8 rtl92e_evm_db_to_percent(s8 value) { - char ret_val; + s8 ret_val; ret_val = value; @@ -2179,9 +2179,9 @@ static int _rtl92e_open(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); int ret; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = _rtl92e_try_up(dev); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -2206,11 +2206,11 @@ static int _rtl92e_close(struct net_device *dev) rtllib_stop_scan(priv->rtllib); } - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = _rtl92e_down(dev, true); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; @@ -2242,11 +2242,11 @@ static void _rtl92e_restart(void *data) reset_wq); struct net_device *dev = priv->rtllib->dev; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); rtl92e_commit(dev); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); } static void _rtl92e_set_multicast(struct net_device *dev) @@ -2265,12 +2265,12 @@ static int _rtl92e_set_mac_adr(struct net_device *dev, void *mac) struct r8192_priv *priv = rtllib_priv(dev); struct sockaddr *addr = mac; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ether_addr_copy(dev->dev_addr, addr->sa_data); schedule_work(&priv->reset_wq); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -2287,7 +2287,7 @@ static int _rtl92e_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) struct iw_point *p = &wrq->u.data; struct ieee_param *ipw = NULL; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); switch (cmd) { case RTL_IOCTL_WPA_SUPPLICANT: @@ -2393,7 +2393,7 @@ static int _rtl92e_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } out: - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h index f627fdc15a58..babc0b3bce95 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h @@ -375,8 +375,8 @@ struct r8192_priv { struct tasklet_struct irq_tx_tasklet; struct tasklet_struct irq_prepare_beacon_tasklet; - struct semaphore wx_sem; - struct semaphore rf_sem; + struct mutex wx_mutex; + struct mutex rf_mutex; struct mutex mutex; struct rt_stats stats; @@ -503,8 +503,8 @@ struct r8192_priv { u32 Pwr_Track; u8 CCKPresentAttentuation_20Mdefault; u8 CCKPresentAttentuation_40Mdefault; - char CCKPresentAttentuation_difference; - char CCKPresentAttentuation; + s8 CCKPresentAttentuation_difference; + s8 CCKPresentAttentuation; long undecorated_smoothed_pwdb; u32 MCSTxPowerLevelOriginalOffset[6]; @@ -604,8 +604,8 @@ void rtl92e_update_rx_pkt_timestamp(struct net_device *dev, long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index); void rtl92e_update_rx_statistics(struct r8192_priv *priv, struct rtllib_rx_stats *pprevious_stats); -u8 rtl92e_evm_db_to_percent(char value); -u8 rtl92e_rx_db_to_percent(char antpower); +u8 rtl92e_evm_db_to_percent(s8 value); +u8 rtl92e_rx_db_to_percent(s8 antpower); void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats, struct rtllib_rx_stats *ptarget_stats); bool rtl92e_enable_nic(struct net_device *dev); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c index 98e4d88d0e73..aa4b015c3cc7 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c @@ -179,9 +179,9 @@ void rtl92e_ips_leave_wq(void *data) struct net_device *dev = ieee->dev; struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } void rtl92e_rtllib_ips_leave_wq(struct net_device *dev) @@ -209,9 +209,9 @@ void rtl92e_rtllib_ips_leave(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } static bool _rtl92e_ps_set_mode(struct net_device *dev, u8 rtPsMode) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index 70df6a1485d6..7413a100ca19 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -65,11 +65,11 @@ static int _rtl92e_wx_set_rate(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_rate(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -84,11 +84,11 @@ static int _rtl92e_wx_set_rts(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_rts(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -114,11 +114,11 @@ static int _rtl92e_wx_set_power(struct net_device *dev, __func__); return 0; } - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_power(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -142,11 +142,11 @@ static int _rtl92e_wx_set_rawtx(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_rawtx(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; @@ -158,12 +158,12 @@ static int _rtl92e_wx_force_reset(struct net_device *dev, { struct r8192_priv *priv = rtllib_priv(dev); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); RT_TRACE(COMP_DBG, "%s(): force reset ! extra is %d\n", __func__, *extra); priv->force_reset = *extra; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -177,7 +177,7 @@ static int _rtl92e_wx_adapter_power_status(struct net_device *dev, (&(priv->rtllib->PowerSaveControl)); struct rtllib_device *ieee = priv->rtllib; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); RT_TRACE(COMP_POWER, "%s(): %s\n", __func__, (*extra == 6) ? "DC power" : "AC power"); @@ -193,7 +193,7 @@ static int _rtl92e_wx_adapter_power_status(struct net_device *dev, ieee->ps = *extra; } - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -207,13 +207,13 @@ static int _rtl92e_wx_set_lps_awake_interval(struct net_device *dev, struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *) (&(priv->rtllib->PowerSaveControl)); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); netdev_info(dev, "%s(): set lps awake interval ! extra is %d\n", __func__, *extra); pPSC->RegMaxLPSAwakeIntvl = *extra; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -223,13 +223,13 @@ static int _rtl92e_wx_set_force_lps(struct net_device *dev, { struct r8192_priv *priv = rtllib_priv(dev); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); netdev_info(dev, "%s(): force LPS ! extra is %d (1 is open 0 is close)\n", __func__, *extra); priv->force_lps = *extra; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -266,7 +266,7 @@ static int _rtl92e_wx_set_mode(struct net_device *dev, if (priv->bHwRadioOff) return 0; rtState = priv->rtllib->eRFPowerState; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); if (wrqu->mode == IW_MODE_ADHOC || wrqu->mode == IW_MODE_MONITOR || ieee->bNetPromiscuousMode) { if (priv->rtllib->PowerSaveControl.bInactivePs) { @@ -275,21 +275,21 @@ static int _rtl92e_wx_set_mode(struct net_device *dev, RF_CHANGE_BY_IPS) { netdev_warn(dev, "%s(): RF is OFF.\n", __func__); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return -1; } netdev_info(dev, "=========>%s(): rtl92e_ips_leave\n", __func__); - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } } } ret = rtllib_wx_set_mode(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -425,7 +425,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, } } - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); priv->rtllib->FirstIe_InScan = true; @@ -436,15 +436,15 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, RF_CHANGE_BY_IPS) { netdev_warn(dev, "%s(): RF is OFF.\n", __func__); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return -1; } RT_TRACE(COMP_PS, "=========>%s(): rtl92e_ips_leave\n", __func__); - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } } rtllib_stop_scan(priv->rtllib); @@ -471,7 +471,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, ret = rtllib_wx_set_scan(priv->rtllib, a, wrqu, b); } - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -491,11 +491,11 @@ static int _rtl92e_wx_get_scan(struct net_device *dev, return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_get_scan(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -513,10 +513,10 @@ static int _rtl92e_wx_set_essid(struct net_device *dev, __func__); return 0; } - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_essid(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -528,11 +528,11 @@ static int _rtl92e_wx_get_essid(struct net_device *dev, int ret; struct r8192_priv *priv = rtllib_priv(dev); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_get_essid(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -545,12 +545,12 @@ static int _rtl92e_wx_set_nick(struct net_device *dev, if (wrqu->data.length > IW_ESSID_MAX_SIZE) return -E2BIG; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); wrqu->data.length = min_t(size_t, wrqu->data.length, sizeof(priv->nick)); memset(priv->nick, 0, sizeof(priv->nick)); memcpy(priv->nick, extra, wrqu->data.length); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -561,11 +561,11 @@ static int _rtl92e_wx_get_nick(struct net_device *dev, { struct r8192_priv *priv = rtllib_priv(dev); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); wrqu->data.length = strlen(priv->nick); memcpy(extra, priv->nick, wrqu->data.length); wrqu->data.flags = 1; /* active */ - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -579,11 +579,11 @@ static int _rtl92e_wx_set_freq(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_freq(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -644,11 +644,11 @@ static int _rtl92e_wx_set_wap(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_wap(priv->rtllib, info, awrq, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; @@ -698,14 +698,14 @@ static int _rtl92e_wx_set_enc(struct net_device *dev, return -ENETDOWN; priv->rtllib->wx_set_enc = 1; - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); - down(&priv->wx_sem); + mutex_unlock(&priv->rtllib->ips_mutex); + mutex_lock(&priv->wx_mutex); RT_TRACE(COMP_SEC, "Setting SW wep key"); ret = rtllib_wx_set_encode(priv->rtllib, info, wrqu, key); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); if (wrqu->encoding.flags & IW_ENCODE_DISABLED) { @@ -799,7 +799,7 @@ static int _rtl92e_wx_set_retry(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); if (wrqu->retry.flags & IW_RETRY_LIFETIME || wrqu->retry.disabled) { @@ -822,7 +822,7 @@ static int _rtl92e_wx_set_retry(struct net_device *dev, rtl92e_commit(dev); exit: - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return err; } @@ -875,7 +875,7 @@ static int _rtl92e_wx_set_sens(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); if (priv->rf_set_sens == NULL) { err = -1; /* we have not this support for this radio */ goto exit; @@ -886,7 +886,7 @@ static int _rtl92e_wx_set_sens(struct net_device *dev, err = -EINVAL; exit: - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return err; } @@ -902,12 +902,12 @@ static int _rtl92e_wx_set_encode_ext(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); priv->rtllib->wx_set_enc = 1; - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra); { @@ -969,7 +969,7 @@ static int _rtl92e_wx_set_encode_ext(struct net_device *dev, end_hw_sec: priv->rtllib->wx_set_enc = 0; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -985,9 +985,9 @@ static int _rtl92e_wx_set_auth(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_auth(priv->rtllib, info, &(data->param), extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -1003,9 +1003,9 @@ static int _rtl92e_wx_set_mlme(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_mlme(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -1020,9 +1020,9 @@ static int _rtl92e_wx_set_gen_ie(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_gen_ie(priv->rtllib, extra, data->data.length); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -1097,14 +1097,14 @@ static int _rtl92e_wx_get_promisc_mode(struct net_device *dev, struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); snprintf(extra, 45, "PromiscuousMode:%d, FilterSrcSTAFrame:%d", ieee->IntelPromiscuousModeInfo.bPromiscuousOn, ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame); wrqu->data.length = strlen(extra) + 1; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } diff --git a/drivers/staging/rtl8192e/rtl819x_Qos.h b/drivers/staging/rtl8192e/rtl819x_Qos.h index 463122db6d29..61da8f7475bb 100644 --- a/drivers/staging/rtl8192e/rtl819x_Qos.h +++ b/drivers/staging/rtl8192e/rtl819x_Qos.h @@ -169,9 +169,6 @@ union qos_tclas { } TYPE2_8021Q; }; -#define IsACValid(ac) ((ac >= 0 && ac <= 7) ? true : false) - - union aci_aifsn { u8 charData; diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c index 2c8a526773ed..a966a8e490ab 100644 --- a/drivers/staging/rtl8192e/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c @@ -306,6 +306,11 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr, pTsCommonInfo->TClasNum = TCLAS_Num; } +static bool IsACValid(unsigned int tid) +{ + return tid < 7; +} + bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs) { diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 776e179d5bfd..b895a537d3e4 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -521,7 +521,7 @@ enum wireless_mode { }; #ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ #endif /* ETH_P_PAE */ @@ -1651,9 +1651,9 @@ struct rtllib_device { short proto_started; short proto_stoppping; - struct semaphore wx_sem; - struct semaphore scan_sem; - struct semaphore ips_sem; + struct mutex wx_mutex; + struct mutex scan_mutex; + struct mutex ips_mutex; spinlock_t mgmt_tx_lock; spinlock_t beacon_lock; @@ -2212,7 +2212,5 @@ void rtllib_indicate_packets(struct rtllib_device *ieee, void HTUseDefaultSetting(struct rtllib_device *ieee); #define RT_ASOC_RETRY_LIMIT 5 u8 MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee); -#define SEM_DOWN_IEEE_WX(psem) down(psem) -#define SEM_UP_IEEE_WX(psem) up(psem) #endif /* RTLLIB_H */ diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c index f4f318abb299..9d5788e04dd5 100644 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ b/drivers/staging/rtl8192e/rtllib_module.c @@ -138,7 +138,7 @@ struct net_device *alloc_rtllib(int sizeof_priv) rtllib_softmac_init(ieee); ieee->pHTInfo = kzalloc(sizeof(struct rt_hi_throughput), GFP_KERNEL); - if (ieee->pHTInfo == NULL) + if (!ieee->pHTInfo) return NULL; HTUpdateDefaultSetting(ieee); diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 62154e3f4463..da74dc49b95e 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -276,8 +276,9 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee) } } -inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, - struct rtllib_device *ieee) +static inline void +softmac_ps_mgmt_xmit(struct sk_buff *skb, + struct rtllib_device *ieee) { short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; struct rtllib_hdr_3addr *header = @@ -513,7 +514,7 @@ static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) ieee->be_scan_inprogress = true; - down(&ieee->scan_sem); + mutex_lock(&ieee->scan_mutex); while (1) { do { @@ -566,7 +567,7 @@ out: if (IS_DOT11D_ENABLE(ieee)) DOT11D_ScanComplete(ieee); } - up(&ieee->scan_sem); + mutex_unlock(&ieee->scan_mutex); ieee->be_scan_inprogress = false; @@ -587,7 +588,7 @@ static void rtllib_softmac_scan_wq(void *data) if (rtllib_act_scanning(ieee, true)) return; - down(&ieee->scan_sem); + mutex_lock(&ieee->scan_mutex); if (ieee->eRFPowerState == eRfOff) { netdev_info(ieee->dev, @@ -618,7 +619,7 @@ static void rtllib_softmac_scan_wq(void *data) schedule_delayed_work(&ieee->softmac_scan_wq, msecs_to_jiffies(RTLLIB_SOFTMAC_SCAN_TIME)); - up(&ieee->scan_sem); + mutex_unlock(&ieee->scan_mutex); return; out: @@ -630,7 +631,7 @@ out1: ieee->actscanning = false; ieee->scan_watch_dog = 0; ieee->scanning_continue = 0; - up(&ieee->scan_sem); + mutex_unlock(&ieee->scan_mutex); } @@ -683,7 +684,7 @@ EXPORT_SYMBOL(rtllib_start_send_beacons); static void rtllib_softmac_stop_scan(struct rtllib_device *ieee) { - down(&ieee->scan_sem); + mutex_lock(&ieee->scan_mutex); ieee->scan_watch_dog = 0; if (ieee->scanning_continue == 1) { ieee->scanning_continue = 0; @@ -692,7 +693,7 @@ static void rtllib_softmac_stop_scan(struct rtllib_device *ieee) cancel_delayed_work_sync(&ieee->softmac_scan_wq); } - up(&ieee->scan_sem); + mutex_unlock(&ieee->scan_mutex); } void rtllib_stop_scan(struct rtllib_device *ieee) @@ -753,7 +754,7 @@ static void rtllib_start_scan(struct rtllib_device *ieee) } } -/* called with wx_sem held */ +/* called with wx_mutex held */ void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) { if (IS_DOT11D_ENABLE(ieee)) { @@ -770,8 +771,10 @@ void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) } EXPORT_SYMBOL(rtllib_start_scan_syncro); -inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon, - struct rtllib_device *ieee, int challengelen, u8 *daddr) +static inline struct sk_buff * +rtllib_authentication_req(struct rtllib_network *beacon, + struct rtllib_device *ieee, + int challengelen, u8 *daddr) { struct sk_buff *skb; struct rtllib_authentication *auth; @@ -1130,7 +1133,7 @@ static void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest) } -inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid) +static inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid) { int i = 0; @@ -1146,8 +1149,9 @@ inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid) return i; } -inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon, - struct rtllib_device *ieee) +static inline struct sk_buff * +rtllib_association_req(struct rtllib_network *beacon, + struct rtllib_device *ieee) { struct sk_buff *skb; struct rtllib_assoc_request_frame *hdr; @@ -1590,7 +1594,7 @@ static void rtllib_associate_procedure_wq(void *data) rtllib_stop_scan_syncro(ieee); if (ieee->rtllib_ips_leave != NULL) ieee->rtllib_ips_leave(ieee->dev); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->data_hard_stop) ieee->data_hard_stop(ieee->dev); @@ -1605,14 +1609,14 @@ static void rtllib_associate_procedure_wq(void *data) __func__); if (ieee->rtllib_ips_leave_wq != NULL) ieee->rtllib_ips_leave_wq(ieee->dev); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return; } ieee->associate_seq = 1; rtllib_associate_step1(ieee, ieee->current_network.bssid); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } inline void rtllib_softmac_new_net(struct rtllib_device *ieee, @@ -2209,8 +2213,9 @@ static void rtllib_process_action(struct rtllib_device *ieee, } } -inline int rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) +static inline int +rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) { u16 errcode; int aid; @@ -2344,8 +2349,9 @@ static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb) } } -inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) +static inline int +rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) { if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) { @@ -2361,7 +2367,8 @@ inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, return 0; } -inline int rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb) +static inline int +rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb) { struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data; u16 frame_ctl; @@ -2582,16 +2589,16 @@ static void rtllib_start_ibss_wq(void *data) struct rtllib_device, start_ibss_wq); /* iwconfig mode ad-hoc will schedule this and return * on the other hand this will block further iwconfig SET - * operations because of the wx_sem hold. + * operations because of the wx_mutex hold. * Anyway some most set operations set a flag to speed-up * (abort) this wq (when syncro scanning) before sleeping - * on the semaphore + * on the mutex */ if (!ieee->proto_started) { netdev_info(ieee->dev, "==========oh driver down return\n"); return; } - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->current_network.ssid_len == 0) { strcpy(ieee->current_network.ssid, RTLLIB_DEFAULT_TX_ESSID); @@ -2703,7 +2710,7 @@ static void rtllib_start_ibss_wq(void *data) netif_carrier_on(ieee->dev); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } inline void rtllib_start_ibss(struct rtllib_device *ieee) @@ -2711,7 +2718,7 @@ inline void rtllib_start_ibss(struct rtllib_device *ieee) schedule_delayed_work(&ieee->start_ibss_wq, msecs_to_jiffies(150)); } -/* this is called only in user context, with wx_sem held */ +/* this is called only in user context, with wx_mutex held */ static void rtllib_start_bss(struct rtllib_device *ieee) { unsigned long flags; @@ -2773,7 +2780,7 @@ static void rtllib_associate_retry_wq(void *data) struct rtllib_device, associate_retry_wq); unsigned long flags; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (!ieee->proto_started) goto exit; @@ -2806,7 +2813,7 @@ static void rtllib_associate_retry_wq(void *data) ieee->beinretry = false; exit: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } static struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee) @@ -2853,9 +2860,9 @@ void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag, u8 shutdown) { rtllib_stop_scan_syncro(ieee); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); rtllib_stop_protocol(ieee, shutdown); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } EXPORT_SYMBOL(rtllib_softmac_stop_protocol); @@ -2902,9 +2909,9 @@ void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown) void rtllib_softmac_start_protocol(struct rtllib_device *ieee, u8 mesh_flag) { - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); rtllib_start_protocol(ieee); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } EXPORT_SYMBOL(rtllib_softmac_start_protocol); @@ -3034,9 +3041,9 @@ void rtllib_softmac_init(struct rtllib_device *ieee) INIT_WORK_RSL(&ieee->wx_sync_scan_wq, (void *)rtllib_wx_sync_scan_wq, ieee); - sema_init(&ieee->wx_sem, 1); - sema_init(&ieee->scan_sem, 1); - sema_init(&ieee->ips_sem, 1); + mutex_init(&ieee->wx_mutex); + mutex_init(&ieee->scan_mutex); + mutex_init(&ieee->ips_mutex); spin_lock_init(&ieee->mgmt_tx_lock); spin_lock_init(&ieee->beacon_lock); @@ -3049,7 +3056,7 @@ void rtllib_softmac_init(struct rtllib_device *ieee) void rtllib_softmac_free(struct rtllib_device *ieee) { - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); kfree(ieee->pDot11dInfo); ieee->pDot11dInfo = NULL; del_timer_sync(&ieee->associate_timer); @@ -3064,7 +3071,7 @@ void rtllib_softmac_free(struct rtllib_device *ieee) cancel_work_sync(&ieee->associate_complete_wq); cancel_work_sync(&ieee->ips_leave_wq); cancel_work_sync(&ieee->wx_sync_scan_wq); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); tasklet_kill(&ieee->ps_task); } @@ -3397,8 +3404,9 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee, return ret; } -inline struct sk_buff *rtllib_disauth_skb(struct rtllib_network *beacon, - struct rtllib_device *ieee, u16 asRsn) +static inline struct sk_buff * +rtllib_disauth_skb(struct rtllib_network *beacon, + struct rtllib_device *ieee, u16 asRsn) { struct sk_buff *skb; struct rtllib_disauth *disauth; @@ -3423,8 +3431,9 @@ inline struct sk_buff *rtllib_disauth_skb(struct rtllib_network *beacon, return skb; } -inline struct sk_buff *rtllib_disassociate_skb(struct rtllib_network *beacon, - struct rtllib_device *ieee, u16 asRsn) +static inline struct sk_buff * +rtllib_disassociate_skb(struct rtllib_network *beacon, + struct rtllib_device *ieee, u16 asRsn) { struct sk_buff *skb; struct rtllib_disassoc *disass; @@ -3499,7 +3508,7 @@ int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p, struct ieee_param *param; int ret = 0; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (p->length < sizeof(struct ieee_param) || !p->pointer) { ret = -EINVAL; @@ -3543,7 +3552,7 @@ int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p, kfree(param); out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c index 61ed8b0413e4..5f1412fc410d 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c +++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c @@ -35,7 +35,7 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, int ret; struct iw_freq *fwrq = &wrqu->freq; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->iw_mode == IW_MODE_INFRA) { ret = 0; @@ -81,7 +81,7 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, ret = 0; out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_freq); @@ -146,7 +146,7 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee, rtllib_stop_scan_syncro(ieee); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); /* use ifconfig hw ether */ if (ieee->iw_mode == IW_MODE_MASTER) { ret = -1; @@ -185,7 +185,7 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee, if (ifup) rtllib_start_protocol(ieee); out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_wap); @@ -287,7 +287,7 @@ int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, int set_mode_status = 0; rtllib_stop_scan_syncro(ieee); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); switch (wrqu->mode) { case IW_MODE_MONITOR: case IW_MODE_ADHOC: @@ -322,7 +322,7 @@ int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, } out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return set_mode_status; } EXPORT_SYMBOL(rtllib_wx_set_mode); @@ -412,7 +412,7 @@ void rtllib_wx_sync_scan_wq(void *data) rtllib_wake_all_queues(ieee); out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } @@ -421,7 +421,7 @@ int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, { int ret = 0; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) { ret = -1; @@ -435,7 +435,7 @@ int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, } out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_scan); @@ -450,7 +450,7 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee, unsigned long flags; rtllib_stop_scan_syncro(ieee); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); proto_started = ieee->proto_started; @@ -492,7 +492,7 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee, if (proto_started) rtllib_start_protocol(ieee); out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_essid); @@ -514,7 +514,7 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee, int enable = (parms[0] > 0); short prev = ieee->raw_tx; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (enable) ieee->raw_tx = 1; @@ -536,7 +536,7 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee, netif_carrier_off(ieee->dev); } - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return 0; } @@ -575,7 +575,7 @@ int rtllib_wx_set_power(struct rtllib_device *ieee, return -1; } - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (wrqu->power.disabled) { RT_TRACE(COMP_DBG, "===>%s(): power disable\n", __func__); @@ -611,7 +611,7 @@ int rtllib_wx_set_power(struct rtllib_device *ieee, } exit: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } @@ -622,7 +622,7 @@ int rtllib_wx_get_power(struct rtllib_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->ps == RTLLIB_PS_DISABLED) { wrqu->power.disabled = 1; @@ -648,7 +648,7 @@ int rtllib_wx_get_power(struct rtllib_device *ieee, wrqu->power.flags |= IW_POWER_UNICAST_R; exit: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return 0; } diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 58fc70ec5f2f..78a3ad5b231f 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -1,31 +1,31 @@ /****************************************************************************** - - Copyright(c) 2003 - 2004 Intel Corporation. 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 for - more details. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - James P. Ketrenos - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -****************************************************************************** - - Few modifications for Realtek's Wi-Fi drivers by - Andrea Merello - - A special thanks goes to Realtek for their support ! - -******************************************************************************/ + * + * Copyright(c) 2003 - 2004 Intel Corporation. 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 for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + ***************************************************************************** + * + * Few modifications for Realtek's Wi-Fi drivers by + * Andrea Merello + * + * A special thanks goes to Realtek for their support ! + * + *****************************************************************************/ #include #include @@ -731,17 +731,19 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) if (qos_actived) { hdr_len = RTLLIB_3ADDR_LEN + 2; - /* in case we are a client verify acm is not set for this ac */ - while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { - netdev_info(ieee->dev, "skb->priority = %x\n", - skb->priority); - if (wme_downgrade_ac(skb)) - break; - netdev_info(ieee->dev, "converted skb->priority = %x\n", - skb->priority); - } + /* in case we are a client verify acm is not set for this ac */ + while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { + netdev_info(ieee->dev, "skb->priority = %x\n", + skb->priority); + if (wme_downgrade_ac(skb)) + break; + netdev_info(ieee->dev, "converted skb->priority = %x\n", + skb->priority); + } + qos_ctl |= skb->priority; header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID); + } else { hdr_len = RTLLIB_3ADDR_LEN; } @@ -981,6 +983,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) return 1; } + int rtllib_xmit(struct sk_buff *skb, struct net_device *dev) { memset(skb->cb, 0, sizeof(skb->cb)); diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c index 84e6272f28cd..b1500ee9a5cf 100644 --- a/drivers/staging/rtl8192e/rtllib_wx.c +++ b/drivers/staging/rtl8192e/rtllib_wx.c @@ -263,7 +263,7 @@ int rtllib_wx_get_scan(struct rtllib_device *ieee, int err = 0; netdev_dbg(ieee->dev, "Getting scan\n"); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); spin_lock_irqsave(&ieee->lock, flags); list_for_each_entry(network, &ieee->network_list, list) { @@ -287,7 +287,7 @@ int rtllib_wx_get_scan(struct rtllib_device *ieee, } spin_unlock_irqrestore(&ieee->lock, flags); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); wrqu->data.length = ev - extra; wrqu->data.flags = 0; @@ -689,7 +689,7 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee, if (ieee->state != RTLLIB_LINKED) return -ENOLINK; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); switch (mlme->cmd) { case IW_MLME_DEAUTH: @@ -716,11 +716,11 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee, ieee->current_network.ssid_len = 0; break; default: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return -EOPNOTSUPP; } - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return 0; } diff --git a/drivers/staging/rtl8192u/ieee80211/Makefile b/drivers/staging/rtl8192u/ieee80211/Makefile index b5d0c2eb045b..9e3f432e5355 100644 --- a/drivers/staging/rtl8192u/ieee80211/Makefile +++ b/drivers/staging/rtl8192u/ieee80211/Makefile @@ -1,7 +1,6 @@ NIC_SELECT = RTL8192U -ccflags-y := -I$(TOPDIR)/drivers/net/wireless -ccflags-y += -O2 +ccflags-y := -O2 ccflags-y += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX ieee80211-rsl-objs := ieee80211_rx.o \ diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 09e9499b7f9d..077ea13eb1e7 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -746,7 +746,7 @@ struct ieee80211_rx_stats { bool bisrxaggrsubframe; bool bPacketBeacon; //cosa add for rssi bool bToSelfBA; //cosa add for rssi - char cck_adc_pwdb[4]; //cosa add for rx path selection + s8 cck_adc_pwdb[4]; //cosa add for rx path selection u16 Seq_Num; }; @@ -1814,7 +1814,7 @@ struct ieee80211_device { u32 wpax_type_notify; //{added by David, 2006.9.26} /* QoS related flag */ - char init_wmmparam_flag; + s8 init_wmmparam_flag; /* set on initialization */ u8 qos_support; diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 051c2be842d0..89cbc077a48d 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -1027,7 +1027,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee, (PTS_COMMON_INFO *) &pRxTS, hdr->addr2, - (u8)Frame_QoSTID((u8 *)(skb->data)), + Frame_QoSTID((u8 *)(skb->data)), RX_DIR, true)) { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 49db1b75cd05..d7d85b3f19c4 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -284,7 +284,8 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee } } -inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) +static inline void +softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) { short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; @@ -320,7 +321,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i //dev_kfree_skb_any(skb);//edit by thomas } -inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) +static inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) { unsigned int len, rate_len; u8 *tag; @@ -640,8 +641,9 @@ void ieee80211_start_scan_syncro(struct ieee80211_device *ieee) } EXPORT_SYMBOL(ieee80211_start_scan_syncro); -inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon, - struct ieee80211_device *ieee, int challengelen) +static inline struct sk_buff * +ieee80211_authentication_req(struct ieee80211_network *beacon, + struct ieee80211_device *ieee, int challengelen) { struct sk_buff *skb; struct ieee80211_authentication *auth; @@ -806,7 +808,7 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d *(tag++) = 2; put_unaligned_le16(ieee->current_network.atim_window, - (u8 *)tag); + tag); tag+=2; } @@ -978,7 +980,9 @@ static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest) } -inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee) +static inline struct sk_buff * +ieee80211_association_req(struct ieee80211_network *beacon, + struct ieee80211_device *ieee) { struct sk_buff *skb; //unsigned long flags; @@ -3091,7 +3095,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, return ret; } -inline struct sk_buff *ieee80211_disassociate_skb( +static inline struct sk_buff *ieee80211_disassociate_skb( struct ieee80211_network *beacon, struct ieee80211_device *ieee, u8 asRsn) diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 28737ec65186..98fbb6ef484d 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -354,7 +354,7 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb) req = (struct rtl_80211_hdr_3addr *) skb->data; tag = (u8 *)req; - dst = (u8 *)(&req->addr2[0]); + dst = &req->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); pDialogToken = tag + 2; //category+action pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken @@ -452,7 +452,7 @@ int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb) } rsp = (struct rtl_80211_hdr_3addr *)skb->data; tag = (u8 *)rsp; - dst = (u8 *)(&rsp->addr2[0]); + dst = &rsp->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); pDialogToken = tag + 2; pStatusCode = (u16 *)(tag + 3); @@ -590,7 +590,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); delba = (struct rtl_80211_hdr_3addr *)skb->data; - dst = (u8 *)(&delba->addr2[0]); + dst = &delba->addr2[0]; pDelBaParamSet = (PDELBA_PARAM_SET)&delba->payload[2]; if(pDelBaParamSet->field.Initiator == 1) diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h index 821afc0ddac5..0b7b04ea0910 100644 --- a/drivers/staging/rtl8192u/r8192U.h +++ b/drivers/staging/rtl8192u/r8192U.h @@ -533,7 +533,7 @@ typedef struct _rt_9x_tx_rate_history { u32 ht_mcs[4][16]; } rt_tx_rahis_t, *prt_tx_rahis_t; typedef struct _RT_SMOOTH_DATA_4RF { - char elements[4][100]; /* array to store values */ + s8 elements[4][100]; /* array to store values */ u32 index; /* index to current array to store */ u32 TotalNum; /* num of valid elements */ u32 TotalVal[4]; /* sum of valid elements */ @@ -1031,7 +1031,7 @@ typedef struct r8192_priv { s8 cck_present_attentuation; u8 cck_present_attentuation_20Mdefault; u8 cck_present_attentuation_40Mdefault; - char cck_present_attentuation_difference; + s8 cck_present_attentuation_difference; bool btxpower_tracking; bool bcck_in_ch14; bool btxpowerdata_readfromEEPORM; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index dd0970facdf5..457eeb5f5239 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -114,9 +114,9 @@ static int channels = 0x3fff; -module_param(ifname, charp, S_IRUGO | S_IWUSR); -module_param(hwwep, int, S_IRUGO | S_IWUSR); -module_param(channels, int, S_IRUGO | S_IWUSR); +module_param(ifname, charp, 0644); +module_param(hwwep, int, 0644); +module_param(channels, int, 0644); MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default"); MODULE_PARM_DESC(hwwep, " Try to use hardware security support. "); @@ -922,47 +922,6 @@ void rtl8192_rtx_disable(struct net_device *dev) skb_queue_purge(&priv->skb_queue); } -inline u16 ieeerate2rtlrate(int rate) -{ - switch (rate) { - case 10: - return 0; - case 20: - return 1; - case 55: - return 2; - case 110: - return 3; - case 60: - return 4; - case 90: - return 5; - case 120: - return 6; - case 180: - return 7; - case 240: - return 8; - case 360: - return 9; - case 480: - return 10; - case 540: - return 11; - default: - return 3; - } -} - -static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540}; -inline u16 rtl8192_rate2rate(short rate) -{ - if (rate > 11) - return 0; - return rtl_rate[rate]; -} - - /* The prototype of rx_isr has changed since one version of Linux Kernel */ static void rtl8192_rx_isr(struct urb *urb) { @@ -1319,14 +1278,6 @@ void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate) } -inline u8 rtl8192_IsWirelessBMode(u16 rate) -{ - if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220)) - return 1; - else - return 0; -} - short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -1702,11 +1653,8 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) } if (bSend0Byte) { tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC); - if (!tx_urb_zero) { - RT_TRACE(COMP_ERR, - "can't alloc urb for zero byte\n"); + if (!tx_urb_zero) return -ENOMEM; - } usb_fill_bulk_urb(tx_urb_zero, udev, usb_sndbulkpipe(udev, idx_pipe), &zero, 0, tx_zero_isr, dev); @@ -4209,7 +4157,7 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer, * * Return: 0-100 percentage *---------------------------------------------------------------------------*/ -static u8 rtl819x_query_rxpwrpercentage(char antpower) +static u8 rtl819x_query_rxpwrpercentage(s8 antpower) { if ((antpower <= -100) || (antpower >= 20)) return 0; @@ -4220,9 +4168,9 @@ static u8 rtl819x_query_rxpwrpercentage(char antpower) } /* QueryRxPwrPercentage */ -static u8 rtl819x_evm_dbtopercentage(char value) +static u8 rtl819x_evm_dbtopercentage(s8 value) { - char ret_val; + s8 ret_val; ret_val = value; @@ -4297,8 +4245,8 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv, phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc; u8 *prxpkt; u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg; - char rx_pwr[4], rx_pwr_all = 0; - char rx_snrX, rx_evmX; + s8 rx_pwr[4], rx_pwr_all = 0; + s8 rx_snrX, rx_evmX; u8 evm, pwdb_all; u32 RSSI, total_rssi = 0; u8 is_cck_rate = 0; @@ -4423,7 +4371,7 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv, /* Get Rx snr value in DB */ tmp_rxsnr = pofdm_buf->rxsnr_X[i]; - rx_snrX = (char)(tmp_rxsnr); + rx_snrX = (s8)(tmp_rxsnr); rx_snrX /= 2; priv->stats.rxSNRdB[i] = (long)rx_snrX; @@ -4457,7 +4405,7 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv, for (i = 0; i < max_spatial_stream; i++) { tmp_rxevm = pofdm_buf->rxevm_X[i]; - rx_evmX = (char)(tmp_rxevm); + rx_evmX = (s8)(tmp_rxevm); /* Do not use shift operation like "rx_evmX >>= 1" * because the compiler of free build environment will @@ -4475,10 +4423,10 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv, */ pstats->SignalQuality = precord_stats->SignalQuality = - (u8)(evm & 0xff); + evm & 0xff; pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = - (u8)(evm & 0xff); + evm & 0xff; } @@ -5013,8 +4961,7 @@ static int rtl8192_usb_probe(struct usb_interface *intf, dev->netdev_ops = &rtl8192_netdev_ops; - dev->wireless_handlers = - (struct iw_handler_def *)&r8192_wx_handlers_def; + dev->wireless_handlers = &r8192_wx_handlers_def; dev->type = ARPHRD_ETHER; @@ -5222,7 +5169,8 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, } else { /* Key Material */ if (KeyContent) { - write_nic_dword(dev, WCAMI, (u32)(*(KeyContent + i - 2))); + write_nic_dword(dev, WCAMI, + *(KeyContent + i - 2)); write_nic_dword(dev, RWCAM, TargetCommand); } } diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 1e0e53c9c314..9209aad0515e 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -150,7 +150,7 @@ void deinit_hal_dm(struct net_device *dev) #ifdef USB_RX_AGGREGATION_SUPPORT void dm_CheckRxAggregation(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + struct r8192_priv *priv = ieee80211_priv(dev); PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; static unsigned long lastTxOkCnt; static unsigned long lastRxOkCnt; @@ -2346,7 +2346,7 @@ dm_CheckEdcaTurbo_EXIT: static void dm_init_ctstoself(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + struct r8192_priv *priv = ieee80211_priv(dev); priv->ieee80211->bCTSToSelfEnable = true; priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal; @@ -2354,7 +2354,7 @@ static void dm_init_ctstoself(struct net_device *dev) static void dm_ctstoself(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + struct r8192_priv *priv = ieee80211_priv(dev); PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; static unsigned long lastTxOkCnt; static unsigned long lastRxOkCnt; diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c index 8918654b44ed..5dc3b5b9bfff 100644 --- a/drivers/staging/rtl8712/ieee80211.c +++ b/drivers/staging/rtl8712/ieee80211.c @@ -145,7 +145,7 @@ static void set_supported_rate(u8 *rates, uint mode) case WIRELESS_11BG: memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); memcpy(rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); + IEEE80211_NUM_OFDM_RATESLEN); break; } } @@ -188,24 +188,24 @@ int r8712_generate_ie(struct registry_priv *pregistrypriv) ie += 2; /*SSID*/ ie = r8712_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, - pdev_network->Ssid.Ssid, &sz); + pdev_network->Ssid.Ssid, &sz); /*supported rates*/ set_supported_rate(pdev_network->rates, pregistrypriv->wireless_mode); rateLen = r8712_get_rateset_len(pdev_network->rates); if (rateLen > 8) { ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, 8, - pdev_network->rates, &sz); + pdev_network->rates, &sz); ie = r8712_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), - (pdev_network->rates + 8), &sz); + (pdev_network->rates + 8), &sz); } else ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, - rateLen, pdev_network->rates, &sz); + rateLen, pdev_network->rates, &sz); /*DS parameter set*/ ie = r8712_set_ie(ie, _DSSET_IE_, 1, - (u8 *)&(pdev_network->Configuration.DSConfig), &sz); + (u8 *)&(pdev_network->Configuration.DSConfig), &sz); /*IBSS Parameter Set*/ ie = r8712_set_ie(ie, _IBSS_PARA_IE_, 2, - (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); + (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); return sz; } @@ -220,8 +220,7 @@ unsigned char *r8712_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit) pbuf = r8712_get_ie(pbuf, _WPA_IE_ID_, &len, limit); if (pbuf) { /*check if oui matches...*/ - if (memcmp((pbuf + 2), wpa_oui_type, - sizeof(wpa_oui_type))) + if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type))) goto check_next_ie; /*check version...*/ memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16)); @@ -279,7 +278,7 @@ static int r8712_get_wpa2_cipher_suite(u8 *s) } int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher) + int *pairwise_cipher) { int i; int left, count; @@ -322,7 +321,7 @@ int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, } int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, - int *pairwise_cipher) + int *pairwise_cipher) { int i; int left, count; @@ -365,7 +364,7 @@ int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, } int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, - u8 *wpa_ie, u16 *wpa_len) + u8 *wpa_ie, u16 *wpa_len) { u8 authmode; u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; @@ -383,7 +382,7 @@ int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, } else { if (authmode == _WPA2_IE_ID_) { memcpy(rsn_ie, &in_ie[cnt], - in_ie[cnt + 1] + 2); + in_ie[cnt + 1] + 2); *rsn_len = in_ie[cnt + 1] + 2; cnt += in_ie[cnt + 1] + 2; /*get next*/ } else { diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index 57211f7e68a5..cbe4de05d26b 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -243,9 +243,9 @@ static u32 start_drv_threads(struct _adapter *padapter) void r8712_stop_drv_threads(struct _adapter *padapter) { /*Below is to terminate r8712_cmd_thread & event_thread...*/ - up(&padapter->cmdpriv.cmd_queue_sema); + complete(&padapter->cmdpriv.cmd_queue_comp); if (padapter->cmdThread) - _down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); + wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp); padapter->cmdpriv.cmd_seq = 1; } @@ -425,7 +425,7 @@ static int netdev_open(struct net_device *pnetdev) else netif_wake_queue(pnetdev); - if (video_mode) + if (video_mode) enable_video_mode(padapter, cbw40_enable); /* start driver mlme relation timer */ start_drv_timers(padapter); diff --git a/drivers/staging/rtl8712/osdep_intf.h b/drivers/staging/rtl8712/osdep_intf.h index aa0ec74af511..5d37e1f951cf 100644 --- a/drivers/staging/rtl8712/osdep_intf.h +++ b/drivers/staging/rtl8712/osdep_intf.h @@ -36,7 +36,7 @@ struct intf_priv { /* when in USB, IO is through interrupt in/out endpoints */ struct usb_device *udev; struct urb *piorw_urb; - struct semaphore io_retevt; + struct completion io_retevt_comp; }; int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index ad041c96fdb8..c9ea50daffff 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -57,13 +57,6 @@ struct __queue { spin_lock_init(&((pqueue)->lock)); \ } while (0) -static inline u32 _down_sema(struct semaphore *sema) -{ - if (down_interruptible(sema)) - return _FAIL; - return _SUCCESS; -} - static inline u32 end_of_queue_search(struct list_head *head, struct list_head *plist) { diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 735a0eadd98c..576c15d25a0f 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -60,7 +60,6 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, if (!precvbuf->purb) res = _FAIL; precvbuf->pskb = NULL; - precvbuf->reuse = false; precvbuf->pallocated_buf = NULL; precvbuf->pbuf = NULL; precvbuf->pdata = NULL; diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 13c018340ff2..9f61583af150 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -264,9 +264,9 @@ static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter, */ if (padapter->pwrctrlpriv.pwr_mode > PS_MODE_ACTIVE) { padapter->pwrctrlpriv.pwr_mode = PS_MODE_ACTIVE; - _enter_pwrlock(&(padapter->pwrctrlpriv.lock)); + mutex_lock(&padapter->pwrctrlpriv.mutex_lock); r8712_set_rpwm(padapter, PS_STATE_S4); - up(&(padapter->pwrctrlpriv.lock)); + mutex_unlock(&padapter->pwrctrlpriv.mutex_lock); } pcmd_r = pcmd; break; @@ -322,7 +322,7 @@ int r8712_cmd_thread(void *context) allow_signal(SIGTERM); while (1) { - if ((_down_sema(&(pcmdpriv->cmd_queue_sema))) == _FAIL) + if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp)) break; if (padapter->bDriverStopped || padapter->bSurpriseRemoved) break; @@ -395,10 +395,10 @@ _next: } if (pcmd->cmdcode == GEN_CMD_CODE(_SetPwrMode)) { if (padapter->pwrctrlpriv.bSleep) { - _enter_pwrlock(&(padapter-> - pwrctrlpriv.lock)); + mutex_lock(&padapter-> + pwrctrlpriv.mutex_lock); r8712_set_rpwm(padapter, PS_STATE_S2); - up(&padapter->pwrctrlpriv.lock); + mutex_unlock(&padapter->pwrctrlpriv.mutex_lock); } } r8712_free_cmd_obj(pcmd); @@ -420,7 +420,7 @@ _next: break; r8712_free_cmd_obj(pcmd); } while (1); - up(&pcmdpriv->terminate_cmdthread_sema); + complete(&pcmdpriv->terminate_cmdthread_comp); thread_exit(); } diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c index 76f60ba5ee9b..205298e23656 100644 --- a/drivers/staging/rtl8712/rtl8712_efuse.c +++ b/drivers/staging/rtl8712/rtl8712_efuse.c @@ -248,7 +248,7 @@ u8 r8712_efuse_pg_packet_read(struct _adapter *padapter, u8 offset, u8 *data) u8 tmpdata[PGPKT_DATA_SIZE]; u8 ret = true; - if (data == NULL) + if (!data) return false; if (offset > 0x0f) return false; diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c index 9055827cccf8..a8e237e480c9 100644 --- a/drivers/staging/rtl8712/rtl8712_led.c +++ b/drivers/staging/rtl8712/rtl8712_led.c @@ -43,7 +43,7 @@ #define LED_BLINK_LINK_INTERVAL_ALPHA 500 #define LED_BLINK_SCAN_INTERVAL_ALPHA 180 #define LED_BLINK_FASTER_INTERVAL_ALPHA 50 -#define LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA 5000 +#define LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA 5000 /*=========================================================================== * LED object. @@ -51,17 +51,19 @@ */ enum _LED_STATE_871x { LED_UNKNOWN = 0, - LED_ON = 1, - LED_OFF = 2, + LED_STATE_ON = 1, + LED_STATE_OFF = 2, LED_BLINK_NORMAL = 3, LED_BLINK_SLOWLY = 4, LED_POWER_ON_BLINK = 5, LED_SCAN_BLINK = 6, /* LED is blinking during scanning period, * the # of times to blink is depend on time - * for scanning. */ + * for scanning. + */ LED_NO_LINK_BLINK = 7, /* LED is blinking during no link state. */ LED_BLINK_StartToBlink = 8,/* Customized for Sercomm Printer - * Server case */ + * Server case + */ LED_BLINK_WPS = 9, /* LED is blinkg during WPS communication */ LED_TXRX_BLINK = 10, LED_BLINK_WPS_STOP = 11, /*for ALPHA */ @@ -92,7 +94,7 @@ static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed, nic = padapter->pnetdev; pLed->padapter = padapter; pLed->LedPin = LedPin; - pLed->CurrLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; pLed->bLedOn = false; pLed->bLedBlinkInProgress = false; pLed->BlinkTimes = 0; @@ -110,7 +112,8 @@ static void DeInitLed871x(struct LED_871x *pLed) { del_timer_sync(&pLed->BlinkTimer); /* We should reset bLedBlinkInProgress if we cancel - * the LedControlTimer, */ + * the LedControlTimer, + */ pLed->bLedBlinkInProgress = false; } @@ -208,7 +211,7 @@ static void SwLedBlink(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -248,10 +251,10 @@ static void SwLedBlink(struct LED_871x *pLed) pLed->bLedBlinkInProgress = false; } else { /* Assign LED state to toggle. */ - if (pLed->BlinkingLedState == LED_ON) - pLed->BlinkingLedState = LED_OFF; + if (pLed->BlinkingLedState == LED_STATE_ON) + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; /* Schedule a timer to toggle LED state. */ switch (pLed->CurrLedState) { @@ -288,7 +291,7 @@ static void SwLedBlink1(struct LED_871x *pLed) if (peeprompriv->CustomerID == RT_CID_819x_CAMEO) pLed = &(ledpriv->SwLed1); /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -312,17 +315,17 @@ static void SwLedBlink1(struct LED_871x *pLed) switch (pLed->CurrLedState) { case LED_BLINK_SLOWLY: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_BLINK_NORMAL: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); break; @@ -335,27 +338,27 @@ static void SwLedBlink1(struct LED_871x *pLed) pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -369,18 +372,18 @@ static void SwLedBlink1(struct LED_871x *pLed) pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } @@ -388,26 +391,26 @@ static void SwLedBlink1(struct LED_871x *pLed) pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; case LED_BLINK_WPS_STOP: /* WPS success */ - if (pLed->BlinkingLedState == LED_ON) { - pLed->BlinkingLedState = LED_OFF; + if (pLed->BlinkingLedState == LED_STATE_ON) { + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); bStopBlinking = false; } else { bStopBlinking = true; @@ -416,9 +419,9 @@ static void SwLedBlink1(struct LED_871x *pLed) pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } @@ -436,7 +439,7 @@ static void SwLedBlink2(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -447,20 +450,20 @@ static void SwLedBlink2(struct LED_871x *pLed) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; SwLedOff(padapter, pLed); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -471,20 +474,20 @@ static void SwLedBlink2(struct LED_871x *pLed) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; SwLedOff(padapter, pLed); } pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -501,7 +504,7 @@ static void SwLedBlink3(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else if (pLed->CurrLedState != LED_BLINK_WPS_STOP) @@ -513,22 +516,22 @@ static void SwLedBlink3(struct LED_871x *pLed) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedOn) SwLedOff(padapter, pLed); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -539,46 +542,46 @@ static void SwLedBlink3(struct LED_871x *pLed) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedOn) SwLedOff(padapter, pLed); } pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; case LED_BLINK_WPS_STOP: /*WPS success*/ - if (pLed->BlinkingLedState == LED_ON) { - pLed->BlinkingLedState = LED_OFF; + if (pLed->BlinkingLedState == LED_STATE_ON) { + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); bStopBlinking = false; } else { bStopBlinking = true; } if (bStopBlinking) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; SwLedOn(padapter, pLed); pLed->bLedWPSBlinkInProgress = false; } @@ -596,32 +599,32 @@ static void SwLedBlink4(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); if (!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN) { - pLed1->BlinkingLedState = LED_OFF; - pLed1->CurrLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; SwLedOff(padapter, pLed1); } switch (pLed->CurrLedState) { case LED_BLINK_SLOWLY: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_BLINK_StartToBlink: if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } @@ -634,17 +637,17 @@ static void SwLedBlink4(struct LED_871x *pLed) pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -657,37 +660,37 @@ static void SwLedBlink4(struct LED_871x *pLed) pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } break; case LED_BLINK_WPS_STOP: /*WPS authentication fail*/ if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; @@ -701,14 +704,14 @@ static void SwLedBlink4(struct LED_871x *pLed) } if (bStopBlinking) { pLed->BlinkTimes = 10; - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } @@ -724,7 +727,7 @@ static void SwLedBlink5(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -734,17 +737,17 @@ static void SwLedBlink5(struct LED_871x *pLed) if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -754,17 +757,17 @@ static void SwLedBlink5(struct LED_871x *pLed) if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -780,7 +783,7 @@ static void SwLedBlink6(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -790,25 +793,25 @@ static void SwLedBlink6(struct LED_871x *pLed) if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; @@ -827,7 +830,8 @@ static void BlinkTimerCallback(unsigned long data) struct LED_871x *pLed = (struct LED_871x *)data; /* This fixed the crash problem on Fedora 12 when trying to do the - * insmod;ifconfig up;rmmod commands. */ + * insmod;ifconfig up;rmmod commands. + */ if (pLed->padapter->bSurpriseRemoved || pLed->padapter->bDriverStopped) return; schedule_work(&pLed->BlinkWorkItem); @@ -908,9 +912,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } @@ -931,9 +935,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } @@ -961,9 +965,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -986,9 +990,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -1016,9 +1020,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1046,11 +1050,11 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS_STOP; if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } @@ -1063,15 +1067,15 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; @@ -1123,9 +1127,9 @@ static void SwLedControlMode2(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1142,17 +1146,17 @@ static void SwLedControlMode2(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_LINK: - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1178,8 +1182,8 @@ static void SwLedControlMode2(struct _adapter *padapter, pLed->bLedScanBlinkInProgress = false; } pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } @@ -1187,16 +1191,16 @@ static void SwLedControlMode2(struct _adapter *padapter, case LED_CTL_STOP_WPS: pLed->bLedWPSBlinkInProgress = false; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_STOP_WPS_FAIL: pLed->bLedWPSBlinkInProgress = false; - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; @@ -1204,15 +1208,15 @@ static void SwLedControlMode2(struct _adapter *padapter, case LED_CTL_START_TO_LINK: case LED_CTL_NO_LINK: if (!IS_LED_BLINKING(pLed)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1255,9 +1259,9 @@ static void SwLedControlMode3(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1273,9 +1277,9 @@ static void SwLedControlMode3(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -1283,8 +1287,8 @@ static void SwLedControlMode3(struct _adapter *padapter, case LED_CTL_LINK: if (IS_LED_WPS_BLINKING(pLed)) return; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1310,9 +1314,9 @@ static void SwLedControlMode3(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1326,11 +1330,11 @@ static void SwLedControlMode3(struct _adapter *padapter, } pLed->CurrLedState = LED_BLINK_WPS_STOP; if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } @@ -1340,23 +1344,23 @@ static void SwLedControlMode3(struct _adapter *padapter, del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_START_TO_LINK: case LED_CTL_NO_LINK: if (!IS_LED_BLINKING(pLed)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1390,8 +1394,8 @@ static void SwLedControlMode4(struct _adapter *padapter, if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_OFF; - pLed1->CurrLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); @@ -1411,11 +1415,11 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedStartToLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_StartToBlink; if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } @@ -1428,8 +1432,8 @@ static void SwLedControlMode4(struct _adapter *padapter, if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_OFF; - pLed1->CurrLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); @@ -1446,9 +1450,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } @@ -1472,9 +1476,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1493,9 +1497,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -1505,8 +1509,8 @@ static void SwLedControlMode4(struct _adapter *padapter, if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_OFF; - pLed1->CurrLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); @@ -1527,11 +1531,11 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } @@ -1545,9 +1549,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; @@ -1559,9 +1563,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); /*LED1 settings*/ @@ -1571,9 +1575,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed1->bLedWPSBlinkInProgress = true; pLed1->CurrLedState = LED_BLINK_WPS_STOP; if (pLed1->bLedOn) - pLed1->BlinkingLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; else - pLed1->BlinkingLedState = LED_ON; + pLed1->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; @@ -1585,9 +1589,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); /*LED1 settings*/ @@ -1598,15 +1602,15 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP; pLed1->BlinkTimes = 10; if (pLed1->bLedOn) - pLed1->BlinkingLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; else - pLed1->BlinkingLedState = LED_ON; + pLed1->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; @@ -1660,8 +1664,8 @@ static void SwLedControlMode5(struct _adapter *padapter, case LED_CTL_LINK: /* solid blue */ if (pLed->CurrLedState == LED_SCAN_BLINK) return; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; pLed->bLedBlinkInProgress = false; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); @@ -1679,9 +1683,9 @@ static void SwLedControlMode5(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1695,16 +1699,16 @@ static void SwLedControlMode5(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1731,8 +1735,8 @@ static void SwLedControlMode6(struct _adapter *padapter, case LED_CTL_SITE_SURVEY: if (IS_LED_WPS_BLINKING(pLed)) return; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; pLed->bLedBlinkInProgress = false; mod_timer(&(pLed->BlinkTimer), jiffies + msecs_to_jiffies(0)); break; @@ -1746,9 +1750,9 @@ static void SwLedControlMode6(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -1763,9 +1767,9 @@ static void SwLedControlMode6(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1776,14 +1780,14 @@ static void SwLedControlMode6(struct _adapter *padapter, del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index f25b34c7d115..66f0e0a35167 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -60,7 +60,7 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) _init_queue(&precvpriv->free_recv_buf_queue); precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC); - if (precvpriv->pallocated_recv_buf == NULL) + if (!precvpriv->pallocated_recv_buf) return _FAIL; precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 - ((addr_t) (precvpriv->pallocated_recv_buf) & 3); @@ -163,7 +163,8 @@ static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib, drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16; drvinfo_sz <<= 3; /*TODO: - * Offset 0 */ + * Offset 0 + */ pattrib->bdecrypted = ((le32_to_cpu(prxstat->rxdw0) & BIT(27)) >> 27) ? 0 : 1; pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) >> 14; @@ -210,7 +211,8 @@ static union recv_frame *recvframe_defrag(struct _adapter *adapter, curfragnum = 0; if (curfragnum != pfhdr->attrib.frag_num) { /*the first fragment number must be 0 - *free the whole queue*/ + *free the whole queue + */ r8712_free_recvframe(prframe, pfree_recv_queue); r8712_free_recvframe_queue(defrag_q, pfree_recv_queue); return NULL; @@ -224,18 +226,21 @@ static union recv_frame *recvframe_defrag(struct _adapter *adapter, /*check the fragment sequence (2nd ~n fragment frame) */ if (curfragnum != pnfhdr->attrib.frag_num) { /* the fragment number must increase (after decache) - * release the defrag_q & prframe */ + * release the defrag_q & prframe + */ r8712_free_recvframe(prframe, pfree_recv_queue); r8712_free_recvframe_queue(defrag_q, pfree_recv_queue); return NULL; } curfragnum++; /* copy the 2nd~n fragment frame's payload to the first fragment - * get the 2nd~last fragment frame's payload */ + * get the 2nd~last fragment frame's payload + */ wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; recvframe_pull(pnextrframe, wlanhdr_offset); /* append to first fragment frame's tail (if privacy frame, - * pull the ICV) */ + * pull the ICV) + */ recvframe_pull_tail(prframe, pfhdr->attrib.icv_len); memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len); recvframe_put(prframe, pnfhdr->len); @@ -269,7 +274,7 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, fragnum = pfhdr->attrib.frag_num; psta_addr = pfhdr->attrib.ta; psta = r8712_get_stainfo(pstapriv, psta_addr); - if (psta == NULL) + if (!psta) pdefrag_q = NULL; else pdefrag_q = &psta->sta_recvpriv.defrag_q; @@ -278,7 +283,8 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, prtnframe = precv_frame;/*isn't a fragment frame*/ if (ismfrag == 1) { /* 0~(n-1) fragment frame - * enqueue to defraf_g */ + * enqueue to defraf_g + */ if (pdefrag_q != NULL) { if (fragnum == 0) { /*the first fragment*/ @@ -294,7 +300,8 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, prtnframe = NULL; } else { /* can't find this ta's defrag_queue, so free this - * recv_frame */ + * recv_frame + */ r8712_free_recvframe(precv_frame, pfree_recv_queue); prtnframe = NULL; } @@ -302,7 +309,8 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, } if ((ismfrag == 0) && (fragnum != 0)) { /* the last fragment frame - * enqueue the last fragment */ + * enqueue the last fragment + */ if (pdefrag_q != NULL) { phead = &pdefrag_q->queue; list_add_tail(&pfhdr->list, phead); @@ -311,7 +319,8 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, prtnframe = precv_frame; } else { /* can't find this ta's defrag_queue, so free this - * recv_frame */ + * recv_frame + */ r8712_free_recvframe(precv_frame, pfree_recv_queue); prtnframe = NULL; } @@ -391,7 +400,8 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) { /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ + * replace EtherType + */ skb_pull(sub_skb, SNAP_SIZE); memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); @@ -530,7 +540,8 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, preorder_ctrl->indicate_seq = pattrib->seq_num; } /* Prepare indication list and indication. - * Check if there is any packet need indicate. */ + * Check if there is any packet need indicate. + */ while (!list_empty(phead)) { prframe = container_of(plist, union recv_frame, u.list); pattrib = &prframe->u.hdr.attrib; @@ -757,7 +768,8 @@ static void query_rx_phy_status(struct _adapter *padapter, /* Modify the RF RNA gain value to -40, -20, * -2, 14 by Jenyu's suggestion * Note: different RF with the different - * RNA gain. */ + * RNA gain. + */ case 0x3: rx_pwr_all = -40 - (pcck_buf->cck_agc_rpt & 0x3e); @@ -842,7 +854,8 @@ static void query_rx_phy_status(struct _adapter *padapter, total_rssi += rssi; } /* (2)PWDB, Average PWDB cacluated by hardware (for - * rate adaptive) */ + * rate adaptive) + */ rx_pwr_all = (((pphy_head[PHY_STAT_PWDB_ALL_SHT]) >> 1) & 0x7f) - 106; pwdb_all = query_rx_pwr_percentage(rx_pwr_all); @@ -870,7 +883,8 @@ static void query_rx_phy_status(struct _adapter *padapter, } /* UI BSS List signal strength(in percentage), make it good looking, * from 0~100. It is assigned to the BSS List in - * GetValueFromBeaconOrProbeRsp(). */ + * GetValueFromBeaconOrProbeRsp(). + */ if (bcck_rate) prframe->u.hdr.attrib.signal_strength = (u8)r8712_signal_scale_mapping(pwdb_all); @@ -985,15 +999,15 @@ int recv_func(struct _adapter *padapter, void *pcontext) } process_phy_info(padapter, prframe); prframe = r8712_decryptor(padapter, prframe); - if (prframe == NULL) { + if (!prframe) { retval = _FAIL; goto _exit_recv_func; } prframe = r8712_recvframe_chk_defrag(padapter, prframe); - if (prframe == NULL) + if (!prframe) goto _exit_recv_func; prframe = r8712_portctrl(padapter, prframe); - if (prframe == NULL) { + if (!prframe) { retval = _FAIL; goto _exit_recv_func; } @@ -1027,10 +1041,12 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) transfer_len = pskb->len; /* Test throughput with Netgear 3700 (No security) with Chariot 3T3R * pairs. The packet count will be a big number so that the containing - * packet will effect the Rx reordering. */ + * packet will effect the Rx reordering. + */ if (transfer_len < pkt_len) { /* In this case, it means the MAX_RECVBUF_SZ is too small to - * get the data from 8712u. */ + * get the data from 8712u. + */ return _FAIL; } do { @@ -1049,7 +1065,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01) shift_sz = 2; precvframe = r8712_alloc_recvframe(pfree_recv_queue); - if (precvframe == NULL) + if (!precvframe) goto _exit_recvbuf2recvframe; INIT_LIST_HEAD(&precvframe->u.hdr.list); precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/ @@ -1057,14 +1073,16 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) tmp_len = pkt_len + drvinfo_sz + RXDESC_SIZE; pkt_offset = (u16)round_up(tmp_len, 128); /* for first fragment packet, driver need allocate 1536 + - * drvinfo_sz + RXDESC_SIZE to defrag packet. */ + * drvinfo_sz + RXDESC_SIZE to defrag packet. + */ if ((mf == 1) && (frag == 0)) /*1658+6=1664, 1664 is 128 alignment.*/ alloc_sz = max_t(u16, tmp_len, 1658); else alloc_sz = tmp_len; /* 2 is for IP header 4 bytes alignment in QoS packet case. - * 4 is for skb->data 4 bytes alignment. */ + * 4 is for skb->data 4 bytes alignment. + */ alloc_sz += 6; pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz); if (pkt_copy) { diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h index fd9e3fc4c226..0b0c2730aac5 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.h +++ b/drivers/staging/rtl8712/rtl8712_recv.h @@ -61,7 +61,8 @@ struct recv_stat { struct phy_cck_rx_status { /* For CCK rate descriptor. This is a unsigned 8:1 variable. * LSB bit present 0.5. And MSB 7 bts present a signed value. - * Range from -64~+63.5. */ + * Range from -64~+63.5. + */ u8 adc_pwdb_X[4]; u8 sq_rpt; u8 cck_agc_rpt; @@ -103,7 +104,6 @@ struct recv_buf { struct _adapter *adapter; struct urb *purb; _pkt *pskb; - u8 reuse; u8 irp_pending; u32 transfer_len; uint len; @@ -116,13 +116,13 @@ struct recv_buf { }; /* - head -----> - data -----> - payload - tail -----> - end -----> - len = (unsigned int )(tail - data); -*/ + * head -----> + * data -----> + * payload + * tail -----> + * end -----> + * len = (unsigned int )(tail - data); + */ struct recv_frame_hdr { struct list_head list; _pkt *pkt; diff --git a/drivers/staging/rtl8712/rtl8712_spec.h b/drivers/staging/rtl8712/rtl8712_spec.h index af11b44b1140..51e042815cc9 100644 --- a/drivers/staging/rtl8712/rtl8712_spec.h +++ b/drivers/staging/rtl8712/rtl8712_spec.h @@ -83,7 +83,8 @@ #define CMD_ADDR_MAPPING_SHIFT 2 /*SDIO CMD ADDR MAPPING, *shift 2 bit for match - * offset[14:2]*/ + * offset[14:2] + */ /*Offset for SDIO LOCAL*/ #define OFFSET_SDIO_LOCAL 0x0FFF diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h index eed09c872fc9..2e66d28d6918 100644 --- a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h +++ b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h @@ -68,11 +68,13 @@ #define SYS_CLKSEL BIT(SYS_CLKSEL_SHT) /* System Clock 80MHz*/ #define PS_CLKSEL_SHT 1 #define PS_CLKSEL BIT(PS_CLKSEL_SHT) /*System power save - * clock select.*/ + * clock select. + */ #define CPU_CLKSEL_SHT 2 #define CPU_CLKSEL BIT(CPU_CLKSEL_SHT) /* System Clock select, * 1: AFE source, - * 0: System clock(L-Bus)*/ + * 0: System clock(L-Bus) + */ #define INT32K_EN_SHT 3 #define INT32K_EN BIT(INT32K_EN_SHT) #define MACSLP_SHT 4 @@ -85,10 +87,12 @@ #define RING_CLK_EN BIT(RING_CLK_EN_SHT) #define SWHW_SEL_SHT 14 #define SWHW_SEL BIT(SWHW_SEL_SHT) /* Load done, - * control path switch.*/ + * control path switch. + */ #define FWHW_SEL_SHT 15 #define FWHW_SEL BIT(FWHW_SEL_SHT) /* Sleep exit, - * control path switch.*/ + * control path switch. + */ /*9346CR*/ #define _VPDIDX_MSK 0xFF00 @@ -118,10 +122,12 @@ #define AFE_MISC_E32_EN BIT(AFE_MISC_E32_EN_SHT) #define AFE_MISC_MBEN_SHT 1 #define AFE_MISC_MBEN BIT(AFE_MISC_MBEN_SHT)/* Enable AFE Macro - * Block's Mbias.*/ + * Block's Mbias. + */ #define AFE_MISC_BGEN_SHT 0 #define AFE_MISC_BGEN BIT(AFE_MISC_BGEN_SHT)/* Enable AFE Macro - * Block's Bandgap.*/ + * Block's Bandgap. + */ /*--------------------------------------------------------------------------*/ @@ -149,10 +155,12 @@ /* EFUSE_CTRL*/ #define EF_FLAG BIT(31) /* Access Flag, Write:1; - * Read:0*/ + * Read:0 + */ #define EF_PGPD 0x70000000 /* E-fuse Program time*/ #define EF_RDT 0x0F000000 /* E-fuse read time: in the - * unit of cycle time*/ + * unit of cycle time + */ #define EF_PDN_EN BIT(19) /* EFuse Power down enable*/ #define ALD_EN BIT(18) /* Autoload Enable*/ #define EF_ADDR 0x0003FF00 /* Access Address*/ @@ -164,7 +172,8 @@ /* EFUSE_CLK_CTRL*/ #define EFUSE_CLK_EN BIT(1) /* E-Fuse Clock Enable*/ #define EFUSE_CLK_SEL BIT(0) /* E-Fuse Clock Select, - * 0:500K, 1:40M*/ + * 0:500K, 1:40M + */ #endif /*__RTL8712_SYSCFG_BITDEF_H__*/ diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 7e0b94503dfc..c4f03a602a2e 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -535,7 +535,8 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) * seqnum per tid. about usb using 4-endpoint, qsel points out * the correct mapping between AC&Endpoint, * the purpose is that correct mapping lets the MAC release - * the AC Queue list correctly. */ + * the AC Queue list correctly. + */ ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & 0x0fff0000); if ((pattrib->ether_type != 0x888e) && @@ -586,7 +587,8 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) * per tid. about usb using 4-endpoint, qsel points out the * correct mapping between AC&Endpoint, * the purpose is that correct mapping let the MAC releases - * the AC Queue list correctly. */ + * the AC Queue list correctly. + */ ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & 0x0fff0000); /* offset 16 */ @@ -627,7 +629,7 @@ int r8712_xmitframe_complete(struct _adapter *padapter, phwxmits = pxmitpriv->hwxmits; hwentry = pxmitpriv->hwxmit_entry; - if (pxmitbuf == NULL) { + if (!pxmitbuf) { pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv); if (!pxmitbuf) return false; @@ -686,7 +688,8 @@ int r8712_xmitframe_complete(struct _adapter *padapter, res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); /* always return ndis_packet after - * r8712_xmitframe_coalesce */ + * r8712_xmitframe_coalesce + */ r8712_xmit_complete(padapter, pxmitframe); } if (res == _SUCCESS) diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index aed03cfbb1ba..b7ee5e63af33 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -51,14 +51,14 @@ #include "mlme_osdep.h" /* -Caller and the r8712_cmd_thread can protect cmd_q by spin_lock. -No irqsave is necessary. -*/ + * Caller and the r8712_cmd_thread can protect cmd_q by spin_lock. + * No irqsave is necessary. + */ static sint _init_cmd_priv(struct cmd_priv *pcmdpriv) { - sema_init(&(pcmdpriv->cmd_queue_sema), 0); - sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0); + init_completion(&pcmdpriv->cmd_queue_comp); + init_completion(&pcmdpriv->terminate_cmdthread_comp); _init_queue(&(pcmdpriv->cmd_queue)); @@ -66,13 +66,13 @@ static sint _init_cmd_priv(struct cmd_priv *pcmdpriv) pcmdpriv->cmd_seq = 1; pcmdpriv->cmd_allocated_buf = kmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ, GFP_ATOMIC); - if (pcmdpriv->cmd_allocated_buf == NULL) + if (!pcmdpriv->cmd_allocated_buf) return _FAIL; pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((addr_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1)); pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC); - if (pcmdpriv->rsp_allocated_buf == NULL) + if (!pcmdpriv->rsp_allocated_buf) return _FAIL; pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((addr_t)(pcmdpriv->rsp_allocated_buf) & 3); @@ -88,7 +88,7 @@ static sint _init_evt_priv(struct evt_priv *pevtpriv) pevtpriv->event_seq = 0; pevtpriv->evt_allocated_buf = kmalloc(MAX_EVTSZ + 4, GFP_ATOMIC); - if (pevtpriv->evt_allocated_buf == NULL) + if (!pevtpriv->evt_allocated_buf) return _FAIL; pevtpriv->evt_buf = pevtpriv->evt_allocated_buf + 4 - ((addr_t)(pevtpriv->evt_allocated_buf) & 3); @@ -110,20 +110,20 @@ static void _free_cmd_priv(struct cmd_priv *pcmdpriv) } /* -Calling Context: - -_enqueue_cmd can only be called between kernel thread, -since only spin_lock is used. - -ISR/Call-Back functions can't call this sub-function. - -*/ + * Calling Context: + * + * _enqueue_cmd can only be called between kernel thread, + * since only spin_lock is used. + * + * ISR/Call-Back functions can't call this sub-function. + * + */ static sint _enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) { unsigned long irqL; - if (obj == NULL) + if (!obj) return _SUCCESS; spin_lock_irqsave(&queue->lock, irqL); list_add_tail(&obj->list, &queue->queue); @@ -172,7 +172,7 @@ u32 r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag) return _FAIL; res = _enqueue_cmd(&pcmdpriv->cmd_queue, obj); - up(&pcmdpriv->cmd_queue_sema); + complete(&pcmdpriv->cmd_queue_comp); return res; } @@ -181,7 +181,7 @@ u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) unsigned long irqL; struct __queue *queue; - if (obj == NULL) + if (!obj) return _SUCCESS; if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag) return _FAIL; @@ -189,7 +189,7 @@ u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) spin_lock_irqsave(&queue->lock, irqL); list_add_tail(&obj->list, &queue->queue); spin_unlock_irqrestore(&queue->lock, irqL); - up(&pcmdpriv->cmd_queue_sema); + complete(&pcmdpriv->cmd_queue_comp); return _SUCCESS; } @@ -211,11 +211,11 @@ void r8712_free_cmd_obj(struct cmd_obj *pcmd) } /* -r8712_sitesurvey_cmd(~) - ### NOTE:#### (!!!!) - MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, - YOU SHOULD HAVE LOCKED pmlmepriv->lock -*/ + * r8712_sitesurvey_cmd(~) + * ### NOTE:#### (!!!!) + * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, + * YOU SHOULD HAVE LOCKED pmlmepriv->lock + */ u8 r8712_sitesurvey_cmd(struct _adapter *padapter, struct ndis_802_11_ssid *pssid) { @@ -477,7 +477,7 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) } } psecnetwork = &psecuritypriv->sec_bss; - if (psecnetwork == NULL) { + if (!psecnetwork) { kfree(pcmd); return _FAIL; } @@ -491,8 +491,9 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1)); psecnetwork->IELength = 0; - /* If the driver wants to use the bssid to create the connection. - * If not, we copy the connecting AP's MAC address to it so that + /* + * If the driver wants to use the bssid to create the connection. + * If not, we copy the connecting AP's MAC address to it so that * the driver just has the bssid information for PMKIDList searching. */ if (!pmlmepriv->assoc_by_bssid) @@ -519,7 +520,8 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) } } if (pregistrypriv->ht_enable) { - /* For WEP mode, we will use the bg mode to do the connection + /* + * For WEP mode, we will use the bg mode to do the connection * to avoid some IOT issues, especially for Realtek 8192u * SoftAP. */ @@ -882,16 +884,16 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter, if (!psta) { psta = r8712_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); - if (psta == NULL) + if (!psta) goto createbss_cmd_fail; } r8712_indicate_connect(padapter); } else { pwlan = _r8712_alloc_network(pmlmepriv); - if (pwlan == NULL) { + if (!pwlan) { pwlan = r8712_get_oldest_wlan_network( &pmlmepriv->scanned_queue); - if (pwlan == NULL) + if (!pwlan) goto createbss_cmd_fail; pwlan->last_scanned = jiffies; } else @@ -904,8 +906,10 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter, (r8712_get_wlan_bssid_ex_sz(pnetwork))); if (pmlmepriv->fw_state & _FW_UNDER_LINKING) pmlmepriv->fw_state ^= _FW_UNDER_LINKING; - /* we will set _FW_LINKED when there is one more sat to - * join us (stassoc_event_callback) */ + /* + * we will set _FW_LINKED when there is one more sat to + * join us (stassoc_event_callback) + */ } createbss_cmd_fail: spin_unlock_irqrestore(&pmlmepriv->lock, irqL); @@ -921,7 +925,7 @@ void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct sta_info *psta = r8712_get_stainfo(pstapriv, psetstakey_rsp->addr); - if (psta == NULL) + if (!psta) goto exit; psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/ exit: @@ -941,7 +945,7 @@ void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, struct sta_info *psta = r8712_get_stainfo(pstapriv, passocsta_parm->addr); - if (psta == NULL) + if (!psta) return; psta->aid = psta->mac_id = passocsta_rsp->cam_id; spin_lock_irqsave(&pmlmepriv->lock, irqL); diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h index e4a2a50c85de..3284dcf2f1a9 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.h +++ b/drivers/staging/rtl8712/rtl871x_cmd.h @@ -50,8 +50,8 @@ struct cmd_obj { }; struct cmd_priv { - struct semaphore cmd_queue_sema; - struct semaphore terminate_cmdthread_sema; + struct completion cmd_queue_comp; + struct completion terminate_cmdthread_comp; struct __queue cmd_queue; u8 cmd_seq; u8 *cmd_buf; /*shall be non-paged, and 4 bytes aligned*/ @@ -185,10 +185,12 @@ struct setauth_parm { */ struct setkey_parm { u8 algorithm; /* encryption algorithm, could be none, wep40, - * TKIP, CCMP, wep104 */ + * TKIP, CCMP, wep104 + */ u8 keyid; u8 grpkey; /* 1: this is the grpkey for 802.1x. - * 0: this is the unicast key for 802.1x */ + * 0: this is the unicast key for 802.1x + */ u8 key[16]; /* this could be 40 or 104 */ }; @@ -215,15 +217,15 @@ struct SetMacAddr_param { }; /* -Caller Ad-Hoc/AP - -Command -Rsp(AID == CAMID) mode - -This is to force fw to add an sta_data entry per driver's request. - -FW will write an cam entry associated with it. - -*/ + * Caller Ad-Hoc/AP + * + * Command -Rsp(AID == CAMID) mode + * + * This is to force fw to add an sta_data entry per driver's request. + * + * FW will write an cam entry associated with it. + * + */ struct set_assocsta_parm { u8 addr[ETH_ALEN]; }; @@ -234,27 +236,27 @@ struct set_assocsta_rsp { }; /* - Caller Ad-Hoc/AP - - Command mode - - This is to force fw to del an sta_data entry per driver's request - - FW will invalidate the cam entry associated with it. - -*/ + * Caller Ad-Hoc/AP + * + * Command mode + * + * This is to force fw to del an sta_data entry per driver's request + * + * FW will invalidate the cam entry associated with it. + * + */ struct del_assocsta_parm { u8 addr[ETH_ALEN]; }; /* -Caller Mode: AP/Ad-HoC(M) - -Notes: To notify fw that given staid has changed its power state - -Command Mode - -*/ + * Caller Mode: AP/Ad-HoC(M) + * + * Notes: To notify fw that given staid has changed its power state + * + * Command Mode + * + */ struct setstapwrstate_parm { u8 staid; u8 status; @@ -262,25 +264,25 @@ struct setstapwrstate_parm { }; /* -Caller Mode: Any - -Notes: To setup the basic rate of RTL8711 - -Command Mode - -*/ + * Caller Mode: Any + * + * Notes: To setup the basic rate of RTL8711 + * + * Command Mode + * + */ struct setbasicrate_parm { u8 basicrates[NumRates]; }; /* -Caller Mode: Any - -Notes: To read the current basic rate - -Command-Rsp Mode - -*/ + * Caller Mode: Any + * + * Notes: To read the current basic rate + * + * Command-Rsp Mode + * + */ struct getbasicrate_parm { u32 rsvd; }; @@ -290,13 +292,13 @@ struct getbasicrate_rsp { }; /* -Caller Mode: Any - -Notes: To setup the data rate of RTL8711 - -Command Mode - -*/ + * Caller Mode: Any + * + * Notes: To setup the data rate of RTL8711 + * + * Command Mode + * + */ struct setdatarate_parm { u8 mac_id; u8 datarates[NumRates]; @@ -332,13 +334,13 @@ struct SetChannelPlan_param { }; /* -Caller Mode: Any - -Notes: To read the current data rate - -Command-Rsp Mode - -*/ + * Caller Mode: Any + * + * Notes: To read the current data rate + * + * Command-Rsp Mode + * + */ struct getdatarate_parm { u32 rsvd; @@ -349,36 +351,36 @@ struct getdatarate_rsp { /* -Caller Mode: Any -AP: AP can use the info for the contents of beacon frame -Infra: STA can use the info when sitesurveying -Ad-HoC(M): Like AP -Ad-HoC(C): Like STA - - -Notes: To set the phy capability of the NIC - -Command Mode - -*/ + * Caller Mode: Any + * AP: AP can use the info for the contents of beacon frame + * Infra: STA can use the info when sitesurveying + * Ad-HoC(M): Like AP + * Ad-HoC(C): Like STA + * + * + * Notes: To set the phy capability of the NIC + * + * Command Mode + * + */ /* -Caller Mode: Any - -Notes: To set the channel/modem/band -This command will be used when channel/modem/band is changed. - -Command Mode - -*/ + * Caller Mode: Any + * + * Notes: To set the channel/modem/band + * This command will be used when channel/modem/band is changed. + * + * Command Mode + * + */ /* -Caller Mode: Any - -Notes: To get the current setting of channel/modem/band - -Command-Rsp Mode - -*/ + * Caller Mode: Any + * + * Notes: To get the current setting of channel/modem/band + * + * Command-Rsp Mode + * + */ struct getphy_rsp { u8 rfchannel; u8 modem; @@ -428,58 +430,58 @@ struct getrfintfs_parm { }; /* - Notes: This command is used for H2C/C2H loopback testing - - mac[0] == 0 - ==> CMD mode, return H2C_SUCCESS. - The following condition must be ture under CMD mode - mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0; - s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7; - s2 == (b1 << 8 | b0); - - mac[0] == 1 - ==> CMD_RSP mode, return H2C_SUCCESS_RSP - - The rsp layout shall be: - rsp: parm: - mac[0] = mac[5]; - mac[1] = mac[4]; - mac[2] = mac[3]; - mac[3] = mac[2]; - mac[4] = mac[1]; - mac[5] = mac[0]; - s0 = s1; - s1 = swap16(s0); - w0 = swap32(w1); - b0 = b1 - s2 = s0 + s1 - b1 = b0 - w1 = w0 - - mac[0] == 2 - ==> CMD_EVENT mode, return H2C_SUCCESS - The event layout shall be: - event: parm: - mac[0] = mac[5]; - mac[1] = mac[4]; - mac[2] = event's sequence number, starting from 1 to parm's marc[3] - mac[3] = mac[2]; - mac[4] = mac[1]; - mac[5] = mac[0]; - s0 = swap16(s0) - event.mac[2]; - s1 = s1 + event.mac[2]; - w0 = swap32(w0); - b0 = b1 - s2 = s0 + event.mac[2] - b1 = b0 - w1 = swap32(w1) - event.mac[2]; - - parm->mac[3] is the total event counts that host requested. - - - event will be the same with the cmd's param. - -*/ + * Notes: This command is used for H2C/C2H loopback testing + * + * mac[0] == 0 + * ==> CMD mode, return H2C_SUCCESS. + * The following condition must be ture under CMD mode + * mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0; + * s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7; + * s2 == (b1 << 8 | b0); + * + * mac[0] == 1 + * ==> CMD_RSP mode, return H2C_SUCCESS_RSP + * + * The rsp layout shall be: + * rsp: parm: + * mac[0] = mac[5]; + * mac[1] = mac[4]; + * mac[2] = mac[3]; + * mac[3] = mac[2]; + * mac[4] = mac[1]; + * mac[5] = mac[0]; + * s0 = s1; + * s1 = swap16(s0); + * w0 = swap32(w1); + * b0 = b1 + * s2 = s0 + s1 + * b1 = b0 + * w1 = w0 + * + * mac[0] == 2 + * ==> CMD_EVENT mode, return H2C_SUCCESS + * The event layout shall be: + * event: parm: + * mac[0] = mac[5]; + * mac[1] = mac[4]; + * mac[2] = event's sequence number, starting from 1 to parm's marc[3] + * mac[3] = mac[2]; + * mac[4] = mac[1]; + * mac[5] = mac[0]; + * s0 = swap16(s0) - event.mac[2]; + * s1 = s1 + event.mac[2]; + * w0 = swap32(w0); + * b0 = b1 + * s2 = s0 + event.mac[2] + * b1 = b0 + * w1 = swap32(w1) - event.mac[2]; + * + * parm->mac[3] is the total event counts that host requested. + * + * + * event will be the same with the cmd's param. + * + */ /* CMD param Formart for DRV INTERNAL CMD HDL*/ struct drvint_cmd_parm { @@ -570,7 +572,8 @@ struct setpwrmode_parm { u8 bcn_rx_en; u8 bcn_pass_cnt; /* fw report one beacon information to * driver when it receives bcn_pass_cnt - * beacons. */ + * beacons. + */ u8 bcn_to; /* beacon TO (ms). ¡§=0¡¨ no limit.*/ u16 bcn_itv; u8 app_itv; /* only for VOIP mode. */ diff --git a/drivers/staging/rtl8712/rtl871x_ht.h b/drivers/staging/rtl8712/rtl871x_ht.h index 41872d937408..513f458ea07c 100644 --- a/drivers/staging/rtl8712/rtl871x_ht.h +++ b/drivers/staging/rtl8712/rtl871x_ht.h @@ -36,7 +36,8 @@ struct ht_priv { unsigned int tx_amsdu_enable;/*for enable Tx A-MSDU */ unsigned int tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */ unsigned int rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, - * updated when join_callback. */ + * updated when join_callback. + */ struct ieee80211_ht_cap ht_cap; }; diff --git a/drivers/staging/rtl8712/rtl871x_ioctl.h b/drivers/staging/rtl8712/rtl871x_ioctl.h index c9218be5bb4f..08bcb3b41bbd 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl.h +++ b/drivers/staging/rtl8712/rtl871x_ioctl.h @@ -68,7 +68,8 @@ struct oid_par_priv { struct oid_obj_priv { unsigned char dbg; /* 0: without OID debug message - * 1: with OID debug message */ + * 1: with OID debug message + */ uint (*oidfuns)(struct oid_par_priv *poid_par_priv); }; diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index e205adf24da2..475e7904fe45 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -1976,9 +1976,9 @@ static int r871x_get_ap_info(struct net_device *dev, if (pdata->length >= 32) { if (copy_from_user(data, pdata->pointer, 32)) return -EINVAL; - data[32] = 0; + data[32] = 0; } else { - return -EINVAL; + return -EINVAL; } spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL); phead = &queue->queue; diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index 56760cda8e89..0aaf2aab6dd0 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -140,7 +140,8 @@ u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid) ETH_ALEN)) { if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) goto _Abort_Set_BSSID; /* driver is in - * WIFI_ADHOC_MASTER_STATE */ + * WIFI_ADHOC_MASTER_STATE + */ } else { r8712_disassoc_cmd(padapter); if (check_fwstate(pmlmepriv, _FW_LINKED)) @@ -203,7 +204,8 @@ void r8712_set_802_11_ssid(struct _adapter *padapter, } } else { goto _Abort_Set_SSID; /* driver is in - * WIFI_ADHOC_MASTER_STATE */ + * WIFI_ADHOC_MASTER_STATE + */ } } } else { @@ -254,12 +256,14 @@ void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter, (*pold_state == Ndis802_11IBSS)) { /* will clr Linked_state before this function, * we must have checked whether issue dis-assoc_cmd or - * not */ + * not + */ r8712_ind_disconnect(padapter); } *pold_state = networktype; /* clear WIFI_STATION_STATE; WIFI_AP_STATE; WIFI_ADHOC_STATE; - * WIFI_ADHOC_MASTER_STATE */ + * WIFI_ADHOC_MASTER_STATE + */ _clr_fwstate_(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE); switch (networktype) { diff --git a/drivers/staging/rtl8712/rtl871x_led.h b/drivers/staging/rtl8712/rtl871x_led.h index eb612053a3dd..adfbc400a18d 100644 --- a/drivers/staging/rtl8712/rtl871x_led.h +++ b/drivers/staging/rtl8712/rtl871x_led.h @@ -72,14 +72,17 @@ enum LED_STRATEGY_871x { SW_LED_MODE0, /* SW control 1 LED via GPIO0. It is default option. */ SW_LED_MODE1, /* 2 LEDs, through LED0 and LED1. For ALPHA. */ SW_LED_MODE2, /* SW control 1 LED via GPIO0, - * custom for AzWave 8187 minicard. */ + * custom for AzWave 8187 minicard. + */ SW_LED_MODE3, /* SW control 1 LED via GPIO0, - * customized for Sercomm Printer Server case.*/ + * customized for Sercomm Printer Server case. + */ SW_LED_MODE4, /*for Edimax / Belkin*/ SW_LED_MODE5, /*for Sercomm / Belkin*/ SW_LED_MODE6, /*for WNC / Corega*/ HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different - * control modes, see MAC.CONFIG1 for details.)*/ + * control modes, see MAC.CONFIG1 for details.) + */ }; struct LED_871x { @@ -96,7 +99,8 @@ struct LED_871x { u8 bLedWPSBlinkInProgress; u32 BlinkTimes; /* No. times to toggle for blink.*/ u32 BlinkingLedState; /* Next state for blinking, - * either LED_ON or OFF.*/ + * either LED_ON or OFF. + */ struct timer_list BlinkTimer; /* Timer object for led blinking.*/ struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer */ @@ -115,7 +119,8 @@ struct led_priv { /*=========================================================================== * Interface to manipulate LED objects. - *===========================================================================*/ + *=========================================================================== + */ void r8712_InitSwLeds(struct _adapter *padapter); void r8712_DeInitSwLeds(struct _adapter *padapter); void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 772bf9fa9592..c1feef3da26c 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -403,7 +403,8 @@ static void update_scanned_network(struct _adapter *adapter, /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ + * with this beacon's information + */ if (end_of_queue_search(phead, plist)) { if (list_empty(&pmlmepriv->free_bss_pool.queue)) { /* If there are no more slots, expire the oldest */ @@ -926,7 +927,8 @@ void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf) if (psta != NULL) { /*the sta have been in sta_info_queue => do nothing *(between drv has received this event before and - * fw have not yet to set key to CAM_ENTRY) */ + * fw have not yet to set key to CAM_ENTRY) + */ return; } @@ -1171,7 +1173,8 @@ int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv) pmlmepriv->assoc_ssid.SsidLength))) { if (pmlmepriv->assoc_by_rssi) { /* if the ssid is the same, select the bss - * which has the max rssi*/ + * which has the max rssi + */ if (pnetwork_max_rssi) { if (pnetwork->network.Rssi > pnetwork_max_rssi->network.Rssi) @@ -1352,7 +1355,8 @@ static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid) i = -1; /* Could not find. */ } else { ; /* There is one Pre-Authentication Key for the - * specific BSSID. */ + * specific BSSID. + */ } return i; } @@ -1430,7 +1434,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, if (match) { if (sec_ie[0] == _WPA_IE_ID_) { /* parsing SSN IE to select required encryption - * algorithm, and set the bc/mc encryption algorithm */ + * algorithm, and set the bc/mc encryption algorithm + */ while (true) { /*check wpa_oui tag*/ if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) { @@ -1444,7 +1449,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, } if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) { /* get bc/mc encryption type (group - * key type)*/ + * key type) + */ switch (sec_ie[11]) { case 0x0: /*none*/ psecuritypriv->XGrpPrivacy = @@ -1482,7 +1488,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, } /*else the uncst_oui is match*/ } else { /*mixed mode, unicast_enc_type > 1*/ /*select the uncst_oui and remove - * the other uncst_oui*/ + * the other uncst_oui + */ cnt = sec_ie[12]; remove_cnt = (cnt - 1) * 4; sec_ie[12] = 0x01; @@ -1499,7 +1506,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, } if (authmode == _WPA2_IE_ID_) { /* parsing RSN IE to select required encryption - * algorithm, and set the bc/mc encryption algorithm */ + * algorithm, and set the bc/mc encryption algorithm + */ while (true) { if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) { /*IE Ver error*/ @@ -1543,7 +1551,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, } /*else the uncst_oui is match*/ } else { /*mixed mode, unicast_enc_type > 1*/ /*select the uncst_oui and remove the - * other uncst_oui*/ + * other uncst_oui + */ cnt = sec_ie[8]; remove_cnt = (cnt - 1) * 4; sec_ie[8] = 0x01; @@ -1667,7 +1676,8 @@ void r8712_joinbss_reset(struct _adapter *padapter) struct ht_priv *phtpriv = &pmlmepriv->htpriv; /* todo: if you want to do something io/reg/hw setting before join_bss, - * please add code here */ + * please add code here + */ phtpriv->ampdu_enable = false;/*reset to disabled*/ for (i = 0; i < 16; i++) phtpriv->baddbareq_issued[i] = false;/*reset it*/ diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index 61e0eb745d21..ddaaab058b2f 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -47,16 +47,20 @@ #define WIFI_ADHOC_MASTER_STATE 0x00000040 #define WIFI_UNDER_LINKING 0x00000080 #define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station - * is under site surveying*/ + * is under site surveying + */ #define WIFI_MP_STATE 0x00010000 #define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in cont. tx background*/ #define WIFI_MP_CTX_ST 0x00040000 /* in cont. tx with - * single-tone*/ + * single-tone + */ #define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in cont, tx - * background due to out of skb*/ + * background due to out of skb + */ #define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx*/ #define WIFI_MP_CTX_CCK_CS 0x00200000 /* in cont, tx with carrier - * suppression*/ + * suppression + */ #define WIFI_MP_LPBK_STATE 0x00400000 #define _FW_UNDER_LINKING WIFI_UNDER_LINKING diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c index 5e4fda1890f5..3c10a2c848c8 100644 --- a/drivers/staging/rtl8712/rtl871x_mp.c +++ b/drivers/staging/rtl8712/rtl871x_mp.c @@ -376,7 +376,8 @@ void r8712_SwitchBandwidth(struct _adapter *pAdapter) /* Use PHY_REG.txt default value. Do not need to change. * Correct the tx power for CCK rate in 40M. * Set Control channel to upper or lower. These settings are - * required only for 40MHz */ + * required only for 40MHz + */ set_bb_reg(pAdapter, rCCK0_System, bCCKSideBand, (HAL_PRIME_CHNL_OFFSET_DONT_CARE >> 1)); set_bb_reg(pAdapter, rOFDM1_LSTF, 0xC00, diff --git a/drivers/staging/rtl8712/rtl871x_mp.h b/drivers/staging/rtl8712/rtl871x_mp.h index 3f3b2e73b7d2..8df452e3e3ce 100644 --- a/drivers/staging/rtl8712/rtl871x_mp.h +++ b/drivers/staging/rtl8712/rtl871x_mp.h @@ -108,7 +108,8 @@ struct mp_priv { unsigned char network_macaddr[6]; /*Testing Flag*/ u32 mode;/*0 for normal type packet, - * 1 for loopback packet (16bytes TXCMD)*/ + * 1 for loopback packet (16bytes TXCMD) + */ sint prev_fw_state; u8 *pallocated_mp_xmitframe_buf; u8 *pmp_xmtframe_buf; diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h index 8dc898024e07..1102451a733d 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h @@ -158,28 +158,37 @@ static const struct oid_obj_priv oid_rtl_seg_81_80_00[] = { {1, oid_null_function}, /*0x05 OID_RT_PRO_SET_SCRAMBLER*/ {1, oid_null_function}, /*0x06 OID_RT_PRO_SET_FILTER_BB*/ {1, oid_null_function}, /*0x07 - * OID_RT_PRO_SET_MANUAL_DIVERS_BB*/ + * OID_RT_PRO_SET_MANUAL_DIVERS_BB + */ {1, oid_rt_pro_set_channel_direct_call_hdl}, /*0x08*/ {1, oid_null_function}, /*0x09 - * OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL*/ + * OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL + */ {1, oid_null_function}, /*0x0A - * OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL*/ + * OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL + */ {1, oid_rt_pro_set_continuous_tx_hdl}, /*0x0B - * OID_RT_PRO_SET_TX_CONTINUOUS_DIRECT_CALL*/ + * OID_RT_PRO_SET_TX_CONTINUOUS_DIRECT_CALL + */ {1, oid_rt_pro_set_single_carrier_tx_hdl}, /*0x0C - * OID_RT_PRO_SET_SINGLE_CARRIER_TX_CONTINUOUS*/ + * OID_RT_PRO_SET_SINGLE_CARRIER_TX_CONTINUOUS + */ {1, oid_null_function}, /*0x0D - * OID_RT_PRO_SET_TX_ANTENNA_BB*/ + * OID_RT_PRO_SET_TX_ANTENNA_BB + */ {1, oid_rt_pro_set_antenna_bb_hdl}, /*0x0E*/ {1, oid_null_function}, /*0x0F OID_RT_PRO_SET_CR_SCRAMBLER*/ {1, oid_null_function}, /*0x10 OID_RT_PRO_SET_CR_NEW_FILTER*/ {1, oid_rt_pro_set_tx_power_control_hdl}, /*0x11 - * OID_RT_PRO_SET_TX_POWER_CONTROL*/ + * OID_RT_PRO_SET_TX_POWER_CONTROL + */ {1, oid_null_function}, /*0x12 OID_RT_PRO_SET_CR_TX_CONFIG*/ {1, oid_null_function}, /*0x13 - * OID_RT_PRO_GET_TX_POWER_CONTROL*/ + * OID_RT_PRO_GET_TX_POWER_CONTROL + */ {1, oid_null_function}, /*0x14 - * OID_RT_PRO_GET_CR_SIGNAL_QUALITY*/ + * OID_RT_PRO_GET_CR_SIGNAL_QUALITY + */ {1, oid_null_function}, /*0x15 OID_RT_PRO_SET_CR_SETPOINT*/ {1, oid_null_function}, /*0x16 OID_RT_PRO_SET_INTEGRATOR*/ {1, oid_null_function}, /*0x17 OID_RT_PRO_SET_SIGNAL_QUALITY*/ @@ -203,13 +212,17 @@ static const struct oid_obj_priv oid_rtl_seg_81_80_20[] = { {1, oid_rt_pro_query_rx_packet_received_hdl}, /*0x26*/ {1, oid_rt_pro_query_rx_packet_crc32_error_hdl},/*0x27*/ {1, oid_null_function}, /*0x28 - *OID_RT_PRO_QUERY_CURRENT_ADDRESS*/ + *OID_RT_PRO_QUERY_CURRENT_ADDRESS + */ {1, oid_null_function}, /*0x29 - *OID_RT_PRO_QUERY_PERMANENT_ADDRESS*/ + *OID_RT_PRO_QUERY_PERMANENT_ADDRESS + */ {1, oid_null_function}, /*0x2A - *OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS*/ + *OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS + */ {1, oid_rt_pro_set_carrier_suppression_tx_hdl},/*0x2B - *OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX*/ + *OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX + */ {1, oid_null_function}, /*0x2C OID_RT_PRO_RECEIVE_PACKET*/ {1, oid_null_function}, /*0x2D OID_RT_PRO_WRITE_EEPROM_BYTE*/ {1, oid_null_function}, /*0x2E OID_RT_PRO_READ_EEPROM_BYTE*/ diff --git a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h index 2e9120a21a0b..11bcfb7bf77c 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h +++ b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h @@ -82,7 +82,8 @@ * 3. Page8(0x800) */ #define rFPGA0_RFMOD 0x800 /*RF mode & CCK TxSC RF - * BW Setting?? */ + * BW Setting?? + */ #define rFPGA0_TxInfo 0x804 /* Status report?? */ #define rFPGA0_PSDFunction 0x808 #define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ @@ -119,7 +120,8 @@ #define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting * RF-R/W protection - * for parameter4?? */ + * for parameter4?? + */ #define rFPGA0_AnalogParameter2 0x884 #define rFPGA0_AnalogParameter3 0x888 /* Useless now */ #define rFPGA0_AnalogParameter4 0x88c @@ -146,7 +148,8 @@ * 5. PageA(0xA00) * * Set Control channel to upper or lower. - * These settings are required only for 40MHz */ + * These settings are required only for 40MHz + */ #define rCCK0_System 0xa00 #define rCCK0_AFESetting 0xa04 /* Disable init gain now */ @@ -155,20 +158,23 @@ #define rCCK0_RxAGC1 0xa0c /* AGC default value, saturation level * Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. - * Not the same as 90 series */ + * Not the same as 90 series + */ #define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ #define rCCK0_RxHP 0xa14 #define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel - * estimation threshold */ + * estimation threshold + */ #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 0xa30-a4f - * channel report */ + * channel report + */ #define rCCK0_TRSSIReport 0xa50 #define rCCK0_RxReport 0xa54 /* 0xa57 */ #define rCCK0_FACounterLower 0xa5c /* 0xa5b */ @@ -193,11 +199,13 @@ #define rOFDM0_XDRxIQImbalance 0xc2c #define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD DM tune - * init gain */ + * 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 */ + * Short-GI + */ #define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ #define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ @@ -283,7 +291,8 @@ #define rTxAGC_Mcs15_Mcs12 0xe1c /* Analog- control in RX_WAIT_CCA : REG: EE0 - * [Analog- Power & Control Register] */ + * [Analog- Power & Control Register] + */ #define rRx_Wait_CCCA 0xe70 #define rAnapar_Ctrl_BB 0xee0 @@ -371,7 +380,8 @@ /* * Bit Mask * - * 1. Page1(0x100) */ + * 1. Page1(0x100) + */ #define bBBResetB 0x100 /* Useless now? */ #define bGlobalResetB 0x200 #define bOFDMTxStart 0x4 @@ -918,7 +928,8 @@ #define bPesudoNoiseState_D 0xffff0000 /* 7. RF Register - * Zebra1 */ + * Zebra1 + */ #define bZebra1_HSSIEnable 0x8 /* Useless */ #define bZebra1_TRxControl 0xc00 #define bZebra1_TRxGainSetting 0x07f diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index bf10d6db50e8..d464c136dd98 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -52,7 +52,8 @@ void r8712_set_rpwm(struct _adapter *padapter, u8 val8) pwrpriv->cpwm = val8; break; case PS_STATE_S2:/* only for USB normal powersave mode use, - * temp mark some code. */ + * temp mark some code. + */ case PS_STATE_S3: case PS_STATE_S4: pwrpriv->cpwm = val8; @@ -103,14 +104,14 @@ void r8712_cpwm_int_hdl(struct _adapter *padapter, if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80)) return; del_timer(&padapter->pwrctrlpriv.rpwm_check_timer); - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->cpwm = (preportpwrstate->state) & 0xf; if (pwrpriv->cpwm >= PS_STATE_S2) { if (pwrpriv->alives & CMD_ALIVE) - up(&(pcmdpriv->cmd_queue_sema)); + complete(&(pcmdpriv->cmd_queue_comp)); } pwrpriv->cpwm_tog = (preportpwrstate->state) & 0x80; - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); } static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, uint tag) @@ -141,10 +142,10 @@ static void SetPSModeWorkItemCallback(struct work_struct *work) struct _adapter *padapter = container_of(pwrpriv, struct _adapter, pwrctrlpriv); if (!pwrpriv->bSleep) { - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) r8712_set_rpwm(padapter, PS_STATE_S4); - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); } } @@ -155,11 +156,11 @@ static void rpwm_workitem_callback(struct work_struct *work) struct _adapter *padapter = container_of(pwrpriv, struct _adapter, pwrctrlpriv); if (pwrpriv->cpwm != pwrpriv->rpwm) { - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); r8712_read8(padapter, SDIO_HCPWM); pwrpriv->rpwm_retry = 1; r8712_set_rpwm(padapter, pwrpriv->rpwm); - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); } } @@ -175,7 +176,7 @@ void r8712_init_pwrctrl_priv(struct _adapter *padapter) struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv)); - sema_init(&pwrctrlpriv->lock, 1); + mutex_init(&pwrctrlpriv->mutex_lock); pwrctrlpriv->cpwm = PS_STATE_S4; pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE; pwrctrlpriv->smart_ps = 0; @@ -207,13 +208,13 @@ sint r8712_register_cmd_alive(struct _adapter *padapter) uint res = _SUCCESS; struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; - _enter_pwrlock(&pwrctrl->lock); + 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; } - up(&pwrctrl->lock); + mutex_unlock(&pwrctrl->mutex_lock); return res; } @@ -229,7 +230,7 @@ void r8712_unregister_cmd_alive(struct _adapter *padapter) { struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; - _enter_pwrlock(&pwrctrl->lock); + mutex_lock(&pwrctrl->mutex_lock); unregister_task_alive(pwrctrl, CMD_ALIVE); if ((pwrctrl->cpwm > PS_STATE_S2) && (pwrctrl->pwr_mode > PS_MODE_ACTIVE)) { @@ -239,5 +240,5 @@ void r8712_unregister_cmd_alive(struct _adapter *padapter) r8712_set_rpwm(padapter, PS_STATE_S0); } } - up(&pwrctrl->lock); + mutex_unlock(&pwrctrl->mutex_lock); } diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index dbfb55523545..c82fdf85d474 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -87,16 +87,12 @@ struct reportpwrstate_parm { unsigned short rsvd; }; -static inline void _enter_pwrlock(struct semaphore *plock) -{ - _down_sema(plock); -} - struct pwrctrl_priv { - struct semaphore lock; + struct mutex mutex_lock; /*volatile*/ u8 rpwm; /* requested power state for fw */ /* fw current power state. updated when 1. read from HCPWM or - * 2. driver lowers power level */ + * 2. driver lowers power level + */ /*volatile*/ u8 cpwm; /*volatile*/ u8 tog; /* toggling */ /*volatile*/ u8 cpwm_tog; /* toggling */ diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 23c143890252..cbd2e51ba42b 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -265,7 +265,8 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked - * only accept EAPOL frame */ + * only accept EAPOL frame + */ if (ether_type == 0x888e) { prtnframe = precv_frame; } else { @@ -277,7 +278,8 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, } else { /* allowed * check decryption status, and decrypt the - * frame if needed */ + * frame if needed + */ prtnframe = precv_frame; /* check is the EAPOL frame or not (Rekey) */ if (ether_type == 0x888e) { @@ -334,19 +336,22 @@ static sint sta2sta_data_frame(struct _adapter *adapter, sta_addr = pattrib->src; } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { /* For Station mode, sa and bssid should always be BSSID, - * and DA is my mac-address */ + * and DA is my mac-address + */ if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) return _FAIL; sta_addr = pattrib->bssid; } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { if (bmcast) { /* For AP mode, if DA == MCAST, then BSSID should - * be also MCAST */ + * be also MCAST + */ if (!IS_MCAST(pattrib->bssid)) return _FAIL; } else { /* not mc-frame */ /* For AP mode, if DA is non-MCAST, then it must be - * BSSID, and bssid == BSSID */ + * BSSID, and bssid == BSSID + */ if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) return _FAIL; sta_addr = pattrib->src; @@ -391,7 +396,8 @@ static sint ap2sta_data_frame(struct _adapter *adapter, if ((GetFrameSubType(ptr)) == WIFI_DATA_NULL) return _FAIL; /* drop QoS-SubType Data, including QoS NULL, - * excluding QoS-Data */ + * excluding QoS-Data + */ if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) { if (GetFrameSubType(ptr) & (BIT(4) | BIT(5) | BIT(6))) @@ -445,7 +451,8 @@ static sint sta2ap_data_frame(struct _adapter *adapter, if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* For AP mode, if DA is non-MCAST, then it must be BSSID, * and bssid == BSSID - * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR */ + * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR + */ if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) return _FAIL; *psta = r8712_get_stainfo(pstapriv, pattrib->src); @@ -619,7 +626,8 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_APPLETALK_AARP, 2))) || !memcmp(psnap, (void *)bridge_tunnel_header, SNAP_SIZE)) { /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ + * replace EtherType + */ bsnaphdr = true; } else { /* Leave Ethernet header part of hdr and full payload */ diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h index 77487bb9d3c0..f419943ad75d 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.h +++ b/drivers/staging/rtl8712/rtl871x_recv.h @@ -153,7 +153,8 @@ static inline u8 *get_recvframe_data(union recv_frame *precvframe) static inline u8 *recvframe_pull(union recv_frame *precvframe, sint sz) { /* used for extract sz bytes from rx_data, update rx_data and return - * the updated rx_data to the caller */ + * the updated rx_data to the caller + */ if (precvframe == NULL) return NULL; precvframe->u.hdr.rx_data += sz; @@ -169,7 +170,8 @@ static inline u8 *recvframe_put(union recv_frame *precvframe, sint sz) { /* used for append sz bytes from ptr to rx_tail, update rx_tail and * return the updated rx_tail to the caller - * after putting, rx_tail must be still larger than rx_end. */ + * after putting, rx_tail must be still larger than rx_end. + */ if (precvframe == NULL) return NULL; precvframe->u.hdr.rx_tail += sz; @@ -186,7 +188,8 @@ static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) /* rmv data from rx_tail (by yitsen) * used for extract sz bytes from rx_end, update rx_end and return the * updated rx_end to the caller - * after pulling, rx_end must be still larger than rx_data. */ + * after pulling, rx_end must be still larger than rx_data. + */ if (precvframe == NULL) return NULL; precvframe->u.hdr.rx_tail -= sz; diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h index 2295f0e64dc2..fa952e17975b 100644 --- a/drivers/staging/rtl8712/rtl871x_security.h +++ b/drivers/staging/rtl8712/rtl871x_security.h @@ -90,18 +90,23 @@ struct RT_PMKID_LIST { struct security_priv { u32 AuthAlgrthm; /* 802.11 auth, could be open, shared, - * 8021x and authswitch */ + * 8021x and authswitch + */ u32 PrivacyAlgrthm; /* This specify the privacy for shared - * auth. algorithm. */ + * auth. algorithm. + */ u32 PrivacyKeyIndex; /* this is only valid for legendary - * wep, 0~3 for key id. */ + * wep, 0~3 for key id. + */ union Keytype DefKey[4]; /* this is only valid for def. key */ u32 DefKeylen[4]; u32 XGrpPrivacy; /* This specify the privacy algthm. - * used for Grp key */ + * used for Grp key + */ u32 XGrpKeyid; /* key id used for Grp Key */ union Keytype XGrpKey[2]; /* 802.1x Group Key, for - * inx0 and inx1 */ + * inx0 and inx1 + */ union Keytype XGrptxmickey[2]; union Keytype XGrprxmickey[2]; union pn48 Grptxpn; /* PN48 used for Grp Key xmit. */ @@ -118,9 +123,11 @@ struct security_priv { s32 sw_encrypt; /* from registry_priv */ s32 sw_decrypt; /* from registry_priv */ s32 hw_decrypted; /* if the rx packets is hw_decrypted==false, - * it means the hw has not been ready. */ + * it means the hw has not been ready. + */ u32 ndisauthtype; /* keeps the auth_type & enc_status from upper - * layer ioctl(wpa_supplicant or wzc) */ + * layer ioctl(wpa_supplicant or wzc) + */ u32 ndisencryptstatus; struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */ struct NDIS_802_11_WEP ndiswep; @@ -136,7 +143,8 @@ struct security_priv { u32 btkip_countermeasure_time; /*------------------------------------------------------------------- * For WPA2 Pre-Authentication. - *------------------------------------------------------------------ */ + *------------------------------------------------------------------ + **/ struct RT_PMKID_LIST PMKIDList[NUM_PMKID_CACHE]; u8 PMKIDIndex; }; diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index e11ce2896893..e2d75e4c473f 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -188,7 +188,8 @@ void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta) _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv); _r8712_init_sta_recv_priv(&psta->sta_recvpriv); /* for A-MPDU Rx reordering buffer control, - * cancel reordering_ctrl_timer */ + * cancel reordering_ctrl_timer + */ for (i = 0; i < 16; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; del_timer(&preorder_ctrl->reordering_ctrl_timer); diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 99256baafd38..be38364c8a7c 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -204,7 +204,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, { /*If driver xmit ARP packet, driver can set ps mode to initial - * setting. It stands for getting DHCP or fix IP.*/ + * setting. It stands for getting DHCP or fix IP. + */ if (pattrib->ether_type == 0x0806) { if (padapter->pwrctrlpriv.pwr_mode != padapter->registrypriv.power_mgnt) { @@ -232,7 +233,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, if (pattrib->ether_type != 0x8712) return _FAIL; /* for mp storing the txcmd per packet, - * according to the info of txcmd to update pattrib */ + * according to the info of txcmd to update pattrib + */ /*get MP_TXDESC_SIZE bytes txcmd per packet*/ _r8712_pktfile_read(&pktfile, (u8 *)&txdesc, TXDESC_SIZE); memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); @@ -244,7 +246,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, if (pattrib->ether_type == ETH_P_IP) { /* The following is for DHCP and ARP packet, we use cck1M to * tx these packets and let LPS awake some time - * to prevent DHCP protocol fail */ + * to prevent DHCP protocol fail + */ u8 tmp[24]; _r8712_pktfile_read(&pktfile, &tmp[0], 24); @@ -255,7 +258,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, ((tmp[21] == 67) && (tmp[23] == 68))) { /* 68 : UDP BOOTP client * 67 : UDP BOOTP server - * Use low rate to send DHCP packet.*/ + * Use low rate to send DHCP packet. + */ pattrib->dhcp_pkt = 1; } } @@ -337,7 +341,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, else pattrib->bswenc = false; /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite - * some settings above.*/ + * some settings above. + */ if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) pattrib->priority = (txdesc.txdw1 >> QSEL_SHT) & 0x1f; return _SUCCESS; @@ -438,7 +443,8 @@ static sint xmitframe_addmic(struct _adapter *padapter, } r8712_secgetmic(&micdata, &(mic[0])); /* add mic code and add the mic code length in - * last_txcmdsz */ + * last_txcmdsz + */ memcpy(payload, &(mic[0]), 8); pattrib->last_txcmdsz += 8; payload = payload - pattrib->last_txcmdsz + 8; diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index a9633c3f73d0..d899d0c6d3a6 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -58,7 +58,8 @@ do { \ } while (0) /* Fixed the Big Endian bug when doing the Tx. - * The Linksys WRH54G will check this.*/ + * The Linksys WRH54G will check this. + */ #define TKIP_IV(pattrib_iv, txpn, keyidx)\ do { \ pattrib_iv[0] = txpn._byte_.TSC1;\ @@ -105,7 +106,8 @@ struct pkt_attrib { u16 seqnum; u16 ether_type; u16 pktlen; /* the original 802.3 pkt raw_data len - * (not include ether_hdr data) */ + * (not include ether_hdr data) + */ u16 last_txcmdsz; u8 pkt_hdrlen; /*the original 802.3 pkt header len*/ @@ -119,7 +121,8 @@ struct pkt_attrib { u8 priority; u8 encrypt; /* when 0 indicate no encrypt. when non-zero, - * indicate the encrypt algorithm*/ + * indicate the encrypt algorithm + */ u8 iv_len; u8 icv_len; unsigned char iv[8]; @@ -176,7 +179,8 @@ struct sta_xmit_priv { spinlock_t lock; sint option; sint apsd_setting; /* When bit mask is on, the associated edca - * queue supports APSD.*/ + * queue supports APSD. + */ struct tx_servq be_q; /* priority == 0,3 */ struct tx_servq bk_q; /* priority == 1,2*/ struct tx_servq vi_q; /*priority == 4,5*/ diff --git a/drivers/staging/rtl8712/usb_halinit.c b/drivers/staging/rtl8712/usb_halinit.c index ad21df16c2bd..0b159850f5a2 100644 --- a/drivers/staging/rtl8712/usb_halinit.c +++ b/drivers/staging/rtl8712/usb_halinit.c @@ -196,7 +196,8 @@ u8 r8712_usb_hal_bus_init(struct _adapter *padapter) msleep(20); /* Revised POS, */ /* Enable AFE Macro Block's Bandgap and Enable AFE Macro - * Block's Mbias */ + * Block's Mbias + */ r8712_write8(padapter, SPS0_CTRL + 1, 0x53); r8712_write8(padapter, SPS0_CTRL, 0x57); val8 = r8712_read8(padapter, AFE_MISC); diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index c1a0ca490546..897d4621a5ce 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -301,7 +301,8 @@ void rtl871x_intf_stop(struct _adapter *padapter) /*disable_hw_interrupt*/ if (!padapter->bSurpriseRemoved) { /*device still exists, so driver can do i/o operation - * TODO: */ + * TODO: + */ } /* cancel in irp */ @@ -368,7 +369,7 @@ static const struct device_type wlan_type = { * * notes: drv_init() is called when the bus driver has located a card for us * to support. We accept the new device by returning 0. -*/ + */ static int r871xu_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid) { @@ -611,7 +612,8 @@ error: } /* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() - * => how to recognize both */ + * => how to recognize both + */ static void r871xu_dev_remove(struct usb_interface *pusb_intf) { struct net_device *pnetdev = usb_get_intfdata(pusb_intf); @@ -635,12 +637,14 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) r8712_free_drv_sw(padapter); /* decrease the reference count of the usb device structure - * when disconnect */ + * when disconnect + */ usb_put_dev(udev); } /* If we didn't unplug usb dongle and remove/insert module, driver * fails on sitesurvey for the first time when device is up. - * Reset usb port for sitesurvey fail issue. */ + * Reset usb port for sitesurvey fail issue. + */ if (udev->state != USB_STATE_NOTATTACHED) usb_reset_device(udev); } diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c index 6f12345709c2..fc6bb0be2a28 100644 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ b/drivers/staging/rtl8712/usb_ops_linux.c @@ -50,7 +50,7 @@ uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv) pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC); if (!pintfpriv->piorw_urb) return _FAIL; - sema_init(&(pintfpriv->io_retevt), 0); + init_completion(&pintfpriv->io_retevt_comp); return _SUCCESS; } @@ -163,7 +163,7 @@ static void usb_write_mem_complete(struct urb *purb) else padapter->bSurpriseRemoved = true; } - up(&pintfpriv->io_retevt); + complete(&pintfpriv->io_retevt_comp); } void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) @@ -187,7 +187,7 @@ void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) wmem, cnt, usb_write_mem_complete, pio_queue); usb_submit_urb(piorw_urb, GFP_ATOMIC); - _down_sema(&pintfpriv->io_retevt); + wait_for_completion_interruptible(&pintfpriv->io_retevt_comp); } static void r8712_usb_read_port_complete(struct urb *purb) @@ -202,26 +202,23 @@ static void r8712_usb_read_port_complete(struct urb *purb) if (purb->status == 0) { /* SUCCESS */ if ((purb->actual_length > (MAX_RECVBUF_SZ)) || (purb->actual_length < RXDESC_SIZE)) { - precvbuf->reuse = true; r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); } else { + _pkt *pskb = precvbuf->pskb; + precvbuf->transfer_len = purb->actual_length; pbuf = (uint *)precvbuf->pbuf; isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff; if ((isevt & 0x1ff) == 0x1ff) { r8712_rxcmd_event_hdl(padapter, pbuf); - precvbuf->reuse = true; + skb_queue_tail(&precvpriv->rx_skb_queue, pskb); r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); } else { - _pkt *pskb = precvbuf->pskb; - skb_put(pskb, purb->actual_length); skb_queue_tail(&precvpriv->rx_skb_queue, pskb); tasklet_hi_schedule(&precvpriv->recv_tasklet); - precvbuf->pskb = NULL; - precvbuf->reuse = false; r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); } @@ -241,7 +238,6 @@ static void r8712_usb_read_port_complete(struct urb *purb) } /* Fall through. */ case -EPROTO: - precvbuf->reuse = true; r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); break; @@ -270,51 +266,43 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) struct usb_device *pusbd = pdvobj->pusbdev; if (adapter->bDriverStopped || adapter->bSurpriseRemoved || - adapter->pwrctrlpriv.pnp_bstop_trx) + adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf) return _FAIL; - if (precvbuf->reuse || !precvbuf->pskb) { - precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); - if (precvbuf->pskb != NULL) - precvbuf->reuse = true; + r8712_init_recvbuf(adapter, precvbuf); + /* Try to use skb from the free queue */ + precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); + + if (!precvbuf->pskb) { + precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, + MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); + if (!precvbuf->pskb) + return _FAIL; + tmpaddr = (addr_t)precvbuf->pskb->data; + alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); + skb_reserve(precvbuf->pskb, + (RECVBUFF_ALIGN_SZ - alignment)); + precvbuf->phead = precvbuf->pskb->head; + precvbuf->pdata = precvbuf->pskb->data; + precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); + precvbuf->pend = skb_end_pointer(precvbuf->pskb); + precvbuf->pbuf = precvbuf->pskb->data; + } else { /* skb is reused */ + precvbuf->phead = precvbuf->pskb->head; + precvbuf->pdata = precvbuf->pskb->data; + precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); + precvbuf->pend = skb_end_pointer(precvbuf->pskb); + precvbuf->pbuf = precvbuf->pskb->data; } - if (precvbuf != NULL) { - r8712_init_recvbuf(adapter, precvbuf); - /* re-assign for linux based on skb */ - if (!precvbuf->reuse || !precvbuf->pskb) { - precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, - MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); - if (!precvbuf->pskb) - return _FAIL; - tmpaddr = (addr_t)precvbuf->pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); - skb_reserve(precvbuf->pskb, - (RECVBUFF_ALIGN_SZ - alignment)); - precvbuf->phead = precvbuf->pskb->head; - precvbuf->pdata = precvbuf->pskb->data; - precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); - precvbuf->pend = skb_end_pointer(precvbuf->pskb); - precvbuf->pbuf = precvbuf->pskb->data; - } else { /* reuse skb */ - precvbuf->phead = precvbuf->pskb->head; - precvbuf->pdata = precvbuf->pskb->data; - precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); - precvbuf->pend = skb_end_pointer(precvbuf->pskb); - precvbuf->pbuf = precvbuf->pskb->data; - precvbuf->reuse = false; - } - purb = precvbuf->purb; - /* translate DMA FIFO addr to pipehandle */ - pipe = ffaddr2pipehdl(pdvobj, addr); - usb_fill_bulk_urb(purb, pusbd, pipe, - precvbuf->pbuf, MAX_RECVBUF_SZ, - r8712_usb_read_port_complete, - precvbuf); - err = usb_submit_urb(purb, GFP_ATOMIC); - if ((err) && (err != (-EPERM))) - ret = _FAIL; - } else { + purb = precvbuf->purb; + /* translate DMA FIFO addr to pipehandle */ + pipe = ffaddr2pipehdl(pdvobj, addr); + usb_fill_bulk_urb(purb, pusbd, pipe, + precvbuf->pbuf, MAX_RECVBUF_SZ, + r8712_usb_read_port_complete, + precvbuf); + err = usb_submit_urb(purb, GFP_ATOMIC); + if ((err) && (err != (-EPERM))) ret = _FAIL; - } return ret; } diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 7a352c45344f..b8af9656e6da 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -376,7 +376,8 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) /*----------------------------------------------------------------------------- Below is for the security related definition -------------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------- + */ #define _RESERVED_FRAME_TYPE_ 0 #define _SKB_FRAME_TYPE_ 2 #define _PRE_ALLOCMEM_ 1 @@ -420,7 +421,8 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) /* --------------------------------------------------------------------------- Below is the fixed elements... ------------------------------------------------------------------------------*/ + * --------------------------------------------------------------------------- + */ #define _AUTH_ALGM_NUM_ 2 #define _AUTH_SEQ_NUM_ 2 #define _BEACON_ITERVAL_ 2 @@ -448,20 +450,23 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) /*----------------------------------------------------------------------------- Below is the definition for 802.11i / 802.1x -------------------------------------------------------------------------------*/ + *------------------------------------------------------------------------------ + */ #define _IEEE8021X_MGT_ 1 /*WPA */ #define _IEEE8021X_PSK_ 2 /* WPA with pre-shared key */ /*----------------------------------------------------------------------------- Below is the definition for WMM -------------------------------------------------------------------------------*/ + *------------------------------------------------------------------------------ + */ #define _WMM_IE_Length_ 7 /* for WMM STA */ #define _WMM_Para_Element_Length_ 24 /*----------------------------------------------------------------------------- Below is the definition for 802.11n -------------------------------------------------------------------------------*/ + *------------------------------------------------------------------------------ + */ /* block-ack parameters */ #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 diff --git a/drivers/staging/rtl8712/wlan_bssdef.h b/drivers/staging/rtl8712/wlan_bssdef.h index fda5707c4acd..86a88b493a43 100644 --- a/drivers/staging/rtl8712/wlan_bssdef.h +++ b/drivers/staging/rtl8712/wlan_bssdef.h @@ -171,7 +171,8 @@ struct NDIS_802_11_REMOVE_KEY { struct NDIS_802_11_WEP { u32 Length; /* Length of this structure */ u32 KeyIndex; /* 0 is the per-client key, - * 1-N are the global keys */ + * 1-N are the global keys + */ u32 KeyLength; /* length of key in bytes */ u8 KeyMaterial[16]; /* variable length depending on above field */ }; @@ -194,7 +195,8 @@ struct wlan_network { struct list_head list; int network_type; /*refer to ieee80211.h for WIRELESS_11A/B/G */ int fixed; /* set to fixed when not to be removed asi - * site-surveying */ + * site-surveying + */ unsigned int last_scanned; /*timestamp for the network */ int aid; /*will only be valid when a BSS is joined. */ int join_res; diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c index 695f9b9fc749..4ee4136b5c28 100644 --- a/drivers/staging/rtl8712/xmit_linux.c +++ b/drivers/staging/rtl8712/xmit_linux.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "osdep_service.h" #include "drv_types.h" @@ -91,7 +92,8 @@ void r8712_set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) } else { /* "When priority processing of data frames is supported, * a STA's SME should send EAPOL-Key frames at the highest - * priority." */ + * priority." + */ if (pattrib->ether_type == 0x888e) UserPriority = 7; @@ -132,6 +134,7 @@ int r8712_xmit_resource_alloc(struct _adapter *padapter, netdev_err(padapter->pnetdev, "pxmitbuf->pxmit_urb[i] == NULL\n"); return _FAIL; } + kmemleak_not_leak(pxmitbuf->pxmit_urb[i]); } return _SUCCESS; } @@ -162,16 +165,16 @@ int r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev) struct _adapter *padapter = netdev_priv(pnetdev); struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - if (!r8712_if_up(padapter)) { + if (!r8712_if_up(padapter)) goto _xmit_entry_drop; - } + pxmitframe = r8712_alloc_xmitframe(pxmitpriv); - if (!pxmitframe) { + if (!pxmitframe) goto _xmit_entry_drop; - } - if ((!r8712_update_attrib(padapter, pkt, &pxmitframe->attrib))) { + + if ((!r8712_update_attrib(padapter, pkt, &pxmitframe->attrib))) goto _xmit_entry_drop; - } + padapter->ledpriv.LedControlHandler(padapter, LED_CTL_TX); pxmitframe->pkt = pkt; if (r8712_pre_xmit(padapter, pxmitframe)) { diff --git a/drivers/staging/rtl8723au/Kconfig b/drivers/staging/rtl8723au/Kconfig deleted file mode 100644 index 277c1ab69317..000000000000 --- a/drivers/staging/rtl8723au/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -config R8723AU - tristate "Realtek RTL8723AU Wireless LAN NIC driver (deprecated)" - depends on USB && WLAN && RFKILL - select WIRELESS_EXT - select WEXT_PRIV - select CFG80211 - default n - ---help--- - This option adds the Realtek RTL8723AU USB device such as found in - the Lenovo Yoga 13 tablet. If built as a module, it will be called r8723au. - - Note: This driver is deprecated and scheduled to be removed in a - future kernel release. Please use rtl8xxxu instead. - -if R8723AU - -config 8723AU_AP_MODE - bool "Realtek RTL8723AU AP mode" - default y - ---help--- - This option enables Access Point mode. Unless you know that your system - will never be used as an AP, or the target system has limited memory, - "Y" should be selected. - -config 8723AU_BT_COEXIST - bool "Realtek RTL8723AU BlueTooth Coexistence" - default y - ---help--- - This option enables icoexistence with BlueTooth communications for the r8723au driver. - Unless you know that this driver will never by used with BT, or the target system has - limited memory, "Y" should be selected. - -endif diff --git a/drivers/staging/rtl8723au/Makefile b/drivers/staging/rtl8723au/Makefile deleted file mode 100644 index 3e8989018a88..000000000000 --- a/drivers/staging/rtl8723au/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -r8723au-y := \ - core/rtw_cmd.o \ - core/rtw_efuse.o \ - core/rtw_ieee80211.o \ - core/rtw_mlme.o \ - core/rtw_mlme_ext.o \ - core/rtw_pwrctrl.o \ - core/rtw_recv.o \ - core/rtw_security.o \ - core/rtw_sreset.o \ - core/rtw_sta_mgt.o \ - core/rtw_xmit.o \ - core/rtw_wlan_util.o \ - hal/hal_com.o \ - hal/hal_intf.o \ - hal/Hal8723PwrSeq.o \ - hal/Hal8723UHWImg_CE.o \ - hal/HalDMOutSrc8723A_CE.o \ - hal/HalHWImg8723A_BB.o \ - hal/HalHWImg8723A_MAC.o \ - hal/HalHWImg8723A_RF.o \ - hal/HalPwrSeqCmd.o \ - hal/odm_RegConfig8723A.o \ - hal/odm_debug.o \ - hal/odm_interface.o \ - hal/odm_HWConfig.o \ - hal/odm.o \ - hal/rtl8723a_cmd.o \ - hal/rtl8723a_dm.o \ - hal/rtl8723a_hal_init.o \ - hal/rtl8723a_phycfg.o \ - hal/rtl8723a_rf6052.o \ - hal/rtl8723a_rxdesc.o \ - hal/rtl8723a_sreset.o \ - hal/rtl8723au_recv.o \ - hal/rtl8723au_xmit.o \ - hal/usb_halinit.o \ - hal/usb_ops_linux.o \ - os_dep/ioctl_cfg80211.o \ - os_dep/mlme_linux.o \ - os_dep/os_intfs.o \ - os_dep/recv_linux.o \ - os_dep/usb_intf.o \ - os_dep/usb_ops_linux.o \ - os_dep/xmit_linux.o - -r8723au-$(CONFIG_8723AU_BT_COEXIST) += hal/rtl8723a_bt-coexist.o -r8723au-$(CONFIG_8723AU_AP_MODE) += core/rtw_ap.o - -obj-$(CONFIG_R8723AU) := r8723au.o - -ccflags-y += $(call cc-option,-Wtype-limits,) -ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/include diff --git a/drivers/staging/rtl8723au/TODO b/drivers/staging/rtl8723au/TODO deleted file mode 100644 index 42b86e478df8..000000000000 --- a/drivers/staging/rtl8723au/TODO +++ /dev/null @@ -1,16 +0,0 @@ -TODO: -- find and remove code valid only for 5 HGz. Many of the obvious - ones have been removed, but things like channel > 14 still exist. -- find and remove any code for other chips that is left over -- convert any remaining unusual variable types -- find codes that can use %pM and %Nph formatting -- checkpatch.pl fixes - most of the remaining ones are lines too long. Many - of them will require refactoring -- merge Realtek's bugfixes and new features into the driver -- switch to use MAC80211 - -A mac80211 driver for this hardware already was integrated at -drivers/net/wireless/realtek/rtl8xxxu/ - -Please send any patches to Greg Kroah-Hartman , -Jes Sorensen , and Larry Finger . diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c deleted file mode 100644 index aad686da3cf0..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_ap.c +++ /dev/null @@ -1,1738 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_AP_C_ - -#include -#include -#include -#include -#include -#include -#include -#include - -void init_mlme_ap_info23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - spin_lock_init(&pmlmepriv->bcn_update_lock); - - /* for ACL */ - _rtw_init_queue23a(&pacl_list->acl_node_q); - - start_ap_mode23a(padapter); -} - -void free_mlme_ap_info23a(struct rtw_adapter *padapter) -{ - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmlmepriv->update_bcn = false; - pmlmeext->bstart_bss = false; - - rtw_sta_flush23a(padapter); - - pmlmeinfo->state = MSR_NOLINK; - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo23a(padapter); - - /* free bc/mc sta_info */ - psta = rtw_get_bcmc_stainfo23a(padapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); -} - -static void update_BCNTIM(struct rtw_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; - unsigned char *pie = pnetwork_mlmeext->IEs; - u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; - uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; - - p = rtw_get_ie23a(pie, WLAN_EID_TIM, &tim_ielen, - pnetwork_mlmeext->IELength); - if (p != NULL && tim_ielen > 0) { - tim_ielen += 2; - - premainder_ie = p+tim_ielen; - - tim_ie_offset = (int)(p - pie); - - remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; - - /* append TIM IE from dst_ie offset */ - dst_ie = p; - } else { - tim_ielen = 0; - - /* calculate head_len */ - offset = 0; - - /* get ssid_ie len */ - p = rtw_get_ie23a(pie, WLAN_EID_SSID, - &tmp_len, pnetwork_mlmeext->IELength); - if (p != NULL) - offset += tmp_len+2; - - /* get supported rates len */ - p = rtw_get_ie23a(pie, WLAN_EID_SUPP_RATES, - &tmp_len, pnetwork_mlmeext->IELength); - if (p != NULL) - offset += tmp_len+2; - - /* DS Parameter Set IE, len = 3 */ - offset += 3; - - premainder_ie = pie + offset; - - remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen; - - /* append TIM IE from offset */ - dst_ie = pie + offset; - } - - if (remainder_ielen > 0) { - pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC); - if (pbackup_remainder_ie && premainder_ie) - memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - - *dst_ie++ = WLAN_EID_TIM; - - if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc)) - tim_ielen = 5; - else - tim_ielen = 4; - - *dst_ie++ = tim_ielen; - - *dst_ie++ = 0; /* DTIM count */ - *dst_ie++ = 1; /* DTIM period */ - - if (pstapriv->tim_bitmap & BIT(0)) /* for bc/mc frames */ - *dst_ie++ = BIT(0); /* bitmap ctrl */ - else - *dst_ie++ = 0; - - if (tim_ielen == 4) { - *dst_ie++ = pstapriv->tim_bitmap & 0xff; - } else if (tim_ielen == 5) { - put_unaligned_le16(pstapriv->tim_bitmap, dst_ie); - dst_ie += 2; - } - - /* copy remainder IE */ - if (pbackup_remainder_ie) { - memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); - - kfree(pbackup_remainder_ie); - } - - offset = (uint)(dst_ie - pie); - pnetwork_mlmeext->IELength = offset + remainder_ielen; - - set_tx_beacon_cmd23a(padapter); -} - -static u8 chk_sta_is_alive(struct sta_info *psta) -{ - u8 ret = false; - - if ((psta->sta_stats.last_rx_data_pkts + - psta->sta_stats.last_rx_ctrl_pkts) != - (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts)) - ret = true; - - sta_update_last_rx_pkts(psta); - - return ret; -} - -void expire_timeout_chk23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - u8 updated = 0; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - spin_lock_bh(&pstapriv->auth_list_lock); - phead = &pstapriv->auth_list; - /* check auth_queue */ - list_for_each_entry_safe(psta, ptmp, phead, auth_list) { - if (psta->expire_to > 0) { - psta->expire_to--; - if (psta->expire_to == 0) { - list_del_init(&psta->auth_list); - pstapriv->auth_list_cnt--; - - DBG_8723A("auth expire %pM\n", psta->hwaddr); - - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - spin_lock_bh(&pstapriv->auth_list_lock); - } - } - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - /* check asoc_queue */ - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) { - if (chk_sta_is_alive(psta) || !psta->expire_to) { - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - } else { - psta->expire_to--; - } - - if (psta->expire_to <= 0) { - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (padapter->registrypriv.wifi_spec == 1) { - psta->expire_to = pstapriv->expire_to; - continue; - } - - if (psta->state & WIFI_SLEEP_STATE) { - if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - /* - * check if alive by another method - * if station is at ps mode. - */ - psta->expire_to = pstapriv->expire_to; - psta->state |= WIFI_STA_ALIVE_CHK_STATE; - /* - * update bcn with tim_bitmap - * for this station - */ - pstapriv->tim_bitmap |= CHKBIT(psta->aid); - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - if (!pmlmeext->active_keep_alive_check) - continue; - } - } - - if (pmlmeext->active_keep_alive_check) { - chk_alive_list[chk_alive_num++] = psta; - continue; - } - - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - DBG_8723A("asoc expire %pM, state = 0x%x\n", - psta->hwaddr, psta->state); - updated = ap_free_sta23a(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) - && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2) - ) { - DBG_8723A("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", - __func__, - psta->hwaddr, - psta->sleepq_len, - padapter->xmitpriv.free_xmitframe_cnt, - pstapriv->asoc_list_cnt); - wakeup_sta_to_xmit23a(padapter, psta); - } - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (chk_alive_num) { - - u8 backup_oper_channel = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - /* - * switch to correct channel of current - * network before issue keep-alive frames - */ - if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) { - backup_oper_channel = rtw_get_oper_ch23a(padapter); - SelectChannel23a(padapter, pmlmeext->cur_channel); - } - - /* issue null data to check sta alive */ - for (i = 0; i < chk_alive_num; i++) { - - int ret = _FAIL; - - psta = chk_alive_list[i]; - if (!(psta->state & _FW_LINKED)) - continue; - - if (psta->state & WIFI_SLEEP_STATE) - ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 1, 50); - else - ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 3, 50); - - psta->keep_alive_trycnt++; - if (ret == _SUCCESS) { - DBG_8723A("asoc check, sta(%pM) is alive\n", - psta->hwaddr); - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - continue; - } else if (psta->keep_alive_trycnt <= 3) { - DBG_8723A("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt); - psta->expire_to = 1; - continue; - } - - psta->keep_alive_trycnt = 0; - - DBG_8723A("asoc expire %pM, state = 0x%x\n", - psta->hwaddr, psta->state); - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - } - - if (backup_oper_channel > 0) /* back to original operation channel */ - SelectChannel23a(padapter, backup_oper_channel); -} - - associated_clients_update23a(padapter, updated); -} - -void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level) -{ - int i; - u8 rf_type; - u32 init_rate = 0; - unsigned char sta_band = 0, raid, shortGIrate = false; - unsigned char limit; - unsigned int tx_ra_bitmap = 0; - struct ht_priv *psta_ht = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_network = &pmlmepriv->cur_network.network; - - if (psta) - psta_ht = &psta->htpriv; - else - return; - - if (!(psta->state & _FW_LINKED)) - return; - - /* b/g mode ra_bitmap */ - for (i = 0; i < sizeof(psta->bssrateset); i++) { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f); - } - /* n mode ra_bitmap */ - if (psta_ht->ht_option) { - rf_type = rtl8723a_get_rf_type(padapter); - - if (rf_type == RF_2T2R) - limit = 16; /* 2R */ - else - limit = 8; /* 1R */ - - for (i = 0; i < limit; i++) { - if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8)) - tx_ra_bitmap |= BIT(i + 12); - } - - /* max short GI rate */ - shortGIrate = psta_ht->sgi; - } - - if (pcur_network->DSConfig > 14) { - /* 5G band */ - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_5N | WIRELESS_11A; - else - sta_band |= WIRELESS_11A; - } else { - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B; - else if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11G | WIRELESS_11B; - else - sta_band |= WIRELESS_11B; - } - - psta->wireless_mode = sta_band; - - raid = networktype_to_raid23a(sta_band); - init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f; - - if (psta->aid < NUM_STA) { - u8 arg; - - arg = psta->mac_id&0x1f; - - arg |= BIT(7); /* support entry 2~31 */ - - if (shortGIrate == true) - arg |= BIT(5); - - tx_ra_bitmap |= ((raid<<28)&0xf0000000); - - DBG_8723A("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = " - "0x%x\n", - __func__, psta->mac_id, raid, tx_ra_bitmap, arg); - - /* bitmap[0:27] = tx_rate_bitmap */ - /* bitmap[28:31]= Rate Adaptive id */ - /* arg[0:4] = macid */ - /* arg[5] = Short GI */ - rtl8723a_add_rateatid(padapter, tx_ra_bitmap, arg, rssi_level); - - if (shortGIrate == true) - init_rate |= BIT(6); - - /* set ra_id, init_rate */ - psta->raid = raid; - psta->init_rate = init_rate; - - } else - DBG_8723A("station aid %d exceed the max number\n", psta->aid); -} - -static void update_bmc_sta(struct rtw_adapter *padapter) -{ - u32 init_rate = 0; - unsigned char network_type, raid; - int i, supportRateNum = 0; - unsigned int tx_ra_bitmap = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_network = &pmlmepriv->cur_network.network; - struct sta_info *psta = rtw_get_bcmc_stainfo23a(padapter); - - if (psta) { - psta->aid = 0; /* default set to 0 */ - psta->mac_id = psta->aid + 1; - - psta->qos_option = 0; - psta->htpriv.ht_option = false; - - psta->ieee8021x_blocked = 0; - - memset((void *)&psta->sta_stats, 0, - sizeof(struct stainfo_stats)); - - /* prepare for add_RATid23a */ - supportRateNum = rtw_get_rateset_len23a((u8 *)&pcur_network->SupportedRates); - network_type = rtw_check_network_type23a((u8 *)&pcur_network->SupportedRates, supportRateNum, 1); - - memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum); - psta->bssratelen = supportRateNum; - - /* b/g mode ra_bitmap */ - for (i = 0; i < supportRateNum; i++) { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f); - } - - if (pcur_network->DSConfig > 14) { - /* force to A mode. 5G doesn't support CCK rates */ - network_type = WIRELESS_11A; - tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */ - } else { - /* force to b mode */ - network_type = WIRELESS_11B; - tx_ra_bitmap = 0xf; - } - - raid = networktype_to_raid23a(network_type); - init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f; - - /* ap mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - { - u8 arg; - - arg = psta->mac_id&0x1f; - - arg |= BIT(7); - - tx_ra_bitmap |= ((raid<<28)&0xf0000000); - - DBG_8723A("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg); - - /* bitmap[0:27] = tx_rate_bitmap */ - /* bitmap[28:31]= Rate Adaptive id */ - /* arg[0:4] = macid */ - /* arg[5] = Short GI */ - rtl8723a_add_rateatid(padapter, tx_ra_bitmap, arg, 0); - } - - /* set ra_id, init_rate */ - psta->raid = raid; - psta->init_rate = init_rate; - - spin_lock_bh(&psta->lock); - psta->state = _FW_LINKED; - spin_unlock_bh(&psta->lock); - - } else - DBG_8723A("add_RATid23a_bmc_sta error!\n"); -} - -/* - * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode - * MAC_ID = AID+1 for sta in ap/adhoc mode - * MAC_ID = 1 for bc/mc for sta/ap/adhoc - * MAC_ID = 0 for bssid for sta/ap/adhoc - * CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid + 1; - */ -void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - struct ht_priv *phtpriv_sta = &psta->htpriv; - /* set intf_tag to if1 */ - - psta->mac_id = psta->aid+1; - DBG_8723A("%s\n", __func__); - - /* ap mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->ieee8021x_blocked = true; - else - psta->ieee8021x_blocked = false; - - /* update sta's cap */ - - /* ERP */ - VCS_update23a(padapter, psta); - /* HT related cap */ - if (phtpriv_sta->ht_option) { - /* check if sta supports rx ampdu */ - phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; - - /* check if sta support s Short GI */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) - phtpriv_sta->sgi = true; - - /* bwmode */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40)) { - /* phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; */ - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; - - } - - psta->qos_option = true; - - } else { - phtpriv_sta->ampdu_enable = false; - - phtpriv_sta->sgi = false; - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - /* Rx AMPDU */ - send_delba23a(padapter, 0, psta->hwaddr); /* recipient */ - - /* TX AMPDU */ - send_delba23a(padapter, 1, psta->hwaddr); /* originator */ - phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */ - phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */ - - /* todo: init other variables */ - - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - - spin_lock_bh(&psta->lock); - psta->state |= _FW_LINKED; - spin_unlock_bh(&psta->lock); -} - -static void update_hw_ht_param(struct rtw_adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - /* - * handle A-MPDU parameter field - * AMPDU_para [1:0]:Max AMPDU Len => 0:8k, 1:16k, 2:32k, 3:64k - * AMPDU_para [4:2]:Min MPDU Start Spacing - */ - max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - min_MPDU_spacing = (pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; - - rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing); - rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len); - - /* Config SM Power Save setting */ - pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) & - IEEE80211_HT_CAP_SM_PS) >> 2; - if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); -} - -static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf) -{ - const u8 *p; - u8 val8, cur_channel, cur_bwmode, cur_ch_offset; - u16 bcn_interval; - u32 acparm; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct wlan_bssid_ex *pnetwork = &pmlmepriv->cur_network.network; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; - struct ieee80211_ht_operation *pht_info = NULL; - - bcn_interval = (u16)pnetwork->beacon_interval; - cur_channel = pnetwork->DSConfig; - cur_bwmode = HT_CHANNEL_WIDTH_20; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - /* - * 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 (!cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - pnetwork->IEs, - pnetwork->IELength)) - pmlmeext->bstart_bss = true; - - /* todo: update wmm, ht cap */ - /* pmlmeinfo->WMM_enable; */ - /* pmlmeinfo->HT_enable; */ - if (pmlmepriv->qos_option) - pmlmeinfo->WMM_enable = true; - if (pmlmepriv->htpriv.ht_option) { - pmlmeinfo->WMM_enable = true; - pmlmeinfo->HT_enable = true; - - update_hw_ht_param(padapter); - } - - if (pmlmepriv->cur_network.join_res != true) { - /* - * setting only at first time - * WEP Key will be set before this - * function, do not clear CAM. - */ - if (psecuritypriv->dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_WEP40 && - psecuritypriv->dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_WEP104) - flush_all_cam_entry23a(padapter); /* clear CAM */ - } - - /* set MSR to AP_Mode */ - rtl8723a_set_media_status(padapter, MSR_AP); - - /* Set BSSID REG */ - hw_var_set_bssid(padapter, pnetwork->MacAddress); - - /* Set EDCA param reg */ - acparm = 0x002F3217; /* VO */ - rtl8723a_set_ac_param_vo(padapter, acparm); - acparm = 0x005E4317; /* VI */ - rtl8723a_set_ac_param_vi(padapter, acparm); - acparm = 0x005ea42b; - rtl8723a_set_ac_param_be(padapter, acparm); - acparm = 0x0000A444; /* BK */ - rtl8723a_set_ac_param_bk(padapter, acparm); - - /* Set Security */ - val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? - 0xcc : 0xcf; - rtl8723a_set_sec_cfg(padapter, val8); - - /* Beacon Control related register */ - rtl8723a_set_beacon_interval(padapter, bcn_interval); - - UpdateBrateTbl23a(padapter, pnetwork->SupportedRates); - HalSetBrateCfg23a(padapter, pnetwork->SupportedRates); - - if (!pmlmepriv->cur_network.join_res) { - /* setting only at first time */ - - /* disable dynamic functions, such as high power, DIG */ - - /* turn on all dynamic functions */ - rtl8723a_odm_support_ability_set(padapter, - DYNAMIC_ALL_FUNC_ENABLE); - } - /* set channel, bwmode */ - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pnetwork->IEs, - pnetwork->IELength); - if (p && p[1]) { - pht_info = (struct ieee80211_ht_operation *)(p + 2); - - if (pregpriv->cbw40_enable && pht_info->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { - /* switch to the 40M Hz mode */ - cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pht_info->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - /* - * pmlmeext->cur_ch_offset = - * HAL_PRIME_CHNL_OFFSET_LOWER; - */ - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - } - /* - * TODO: need to judge the phy parameters - * on concurrent mode for single phy - */ - set_channel_bwmode23a(padapter, cur_channel, cur_ch_offset, cur_bwmode); - - DBG_8723A("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, - cur_ch_offset); - - pmlmeext->cur_channel = cur_channel; - pmlmeext->cur_bwmode = cur_bwmode; - pmlmeext->cur_ch_offset = cur_ch_offset; - pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type; - - /* update cur_wireless_mode */ - update_wireless_mode23a(padapter); - - /* update capability after cur_wireless_mode updated */ - update_capinfo23a(padapter, pnetwork->capability); - - /* let pnetwork_mlmeext == pnetwork_mlme. */ - memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length); - - if (pmlmeext->bstart_bss) { - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - /* issue beacon frame */ - if (send_beacon23a(padapter) == _FAIL) - DBG_8723A("issue_beacon23a, fail!\n"); - } - - /* update bc/mc sta_info */ - update_bmc_sta(padapter); -} - -int rtw_check_beacon_data23a(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, unsigned int len) -{ - int ret = _SUCCESS; - u8 *p; - u8 *pHT_caps_ie = NULL; - u8 *pHT_info_ie = NULL; - struct sta_info *psta = NULL; - u16 ht_cap = false; - uint ie_len = 0; - int group_cipher, pairwise_cipher; - u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX]; - int supportRateNum = 0; - u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network; - u8 *ie = pbss_network->IEs; - u8 *pbuf = mgmt->u.beacon.variable; - - len -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - /* SSID */ - /* Supported rates */ - /* DS Params */ - /* WLAN_EID_COUNTRY */ - /* ERP Information element */ - /* Extended supported rates */ - /* WPA/WPA2 */ - /* Wi-Fi Wireless Multimedia Extensions */ - /* ht_capab, ht_oper */ - /* WPS IE */ - - DBG_8723A("%s, len =%d\n", __func__, len); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return _FAIL; - - if (len > MAX_IE_SZ) - return _FAIL; - - pbss_network->IELength = len; - - memset(ie, 0, MAX_IE_SZ); - - memcpy(ie, pbuf, pbss_network->IELength); - - if (pbss_network->ifmode != NL80211_IFTYPE_AP && - pbss_network->ifmode != NL80211_IFTYPE_P2P_GO) - return _FAIL; - - pbss_network->Rssi = 0; - - memcpy(pbss_network->MacAddress, myid(&padapter->eeprompriv), ETH_ALEN); - - /* SSID */ - p = rtw_get_ie23a(ie, WLAN_EID_SSID, &ie_len, pbss_network->IELength); - if (p && ie_len > 0) { - memset(&pbss_network->Ssid, 0, sizeof(struct cfg80211_ssid)); - memcpy(pbss_network->Ssid.ssid, (p + 2), ie_len); - pbss_network->Ssid.ssid_len = ie_len; - } - - /* channel */ - channel = 0; - p = rtw_get_ie23a(ie, WLAN_EID_DS_PARAMS, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - channel = *(p + 2); - - pbss_network->DSConfig = channel; - - memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); - /* get supported rates */ - p = rtw_get_ie23a(ie, WLAN_EID_SUPP_RATES, &ie_len, - pbss_network->IELength); - if (p) { - memcpy(supportRate, p+2, ie_len); - supportRateNum = ie_len; - } - - /* get ext_supported rates */ - p = rtw_get_ie23a(ie, WLAN_EID_EXT_SUPP_RATES, - &ie_len, pbss_network->IELength); - if (p) { - memcpy(supportRate+supportRateNum, p+2, ie_len); - supportRateNum += ie_len; - } - - network_type = rtw_check_network_type23a(supportRate, - supportRateNum, channel); - - rtw_set_supported_rate23a(pbss_network->SupportedRates, network_type); - - /* parsing ERP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_ERP_INFO, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - ERP_IE_handler23a(padapter, p); - - /* update privacy/security */ - if (pbss_network->capability & BIT(4)) - pbss_network->Privacy = 1; - else - pbss_network->Privacy = 0; - - psecuritypriv->wpa_psk = 0; - - /* wpa2 */ - group_cipher = 0; pairwise_cipher = 0; - psecuritypriv->wpa2_group_cipher = 0; - psecuritypriv->wpa2_pairwise_cipher = 0; - p = rtw_get_ie23a(ie, WLAN_EID_RSN, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) { - if (rtw_parse_wpa2_ie23a(p, ie_len+2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - psecuritypriv->dot8021xalg = 1; /* psk, todo:802.1x */ - psecuritypriv->wpa_psk |= BIT(1); - - psecuritypriv->wpa2_group_cipher = group_cipher; - psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; - } - } - - /* wpa */ - ie_len = 0; - group_cipher = 0; - pairwise_cipher = 0; - psecuritypriv->wpa_group_cipher = 0; - psecuritypriv->wpa_pairwise_cipher = 0; - for (p = ie; ; p += (ie_len + 2)) { - p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, - pbss_network->IELength - (ie_len + 2)); - if ((p) && (!memcmp(p+2, RTW_WPA_OUI23A_TYPE, 4))) { - if (rtw_parse_wpa_ie23a(p, ie_len+2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - /* psk, todo:802.1x */ - psecuritypriv->dot8021xalg = 1; - - psecuritypriv->wpa_psk |= BIT(0); - - psecuritypriv->wpa_group_cipher = group_cipher; - psecuritypriv->wpa_pairwise_cipher = pairwise_cipher; - } - break; - } - - if (!p || !ie_len) - break; - } - - /* wmm */ - ie_len = 0; - pmlmepriv->qos_option = 0; - if (pregistrypriv->wmm_enable) { - for (p = ie; ; p += (ie_len + 2)) { - p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, - (pbss_network->IELength - - (ie_len + 2))); - if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) { - pmlmepriv->qos_option = 1; - - *(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 */ - *(p + 14) &= ~BIT(4); /* BK */ - *(p + 18) &= ~BIT(4); /* VI */ - *(p + 22) &= ~BIT(4); /* VO */ - break; - } - if ((p == NULL) || (ie_len == 0)) - break; - } - } - /* parsing HT_CAP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_HT_CAPABILITY, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) { - u8 rf_type; - - struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p+2); - - pHT_caps_ie = p; - - ht_cap = true; - network_type |= WIRELESS_11_24N; - - rf_type = rtl8723a_get_rf_type(padapter); - - if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || - (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07<<2)); - else - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY&0x00); - - /* set Max Rx AMPDU size to 64K */ - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_FACTOR & 0x03); - - if (rf_type == RF_1T1R) { - pht_cap->mcs.rx_mask[0] = 0xff; - pht_cap->mcs.rx_mask[1] = 0x0; - } - - memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); - } - - /* parsing HT_INFO_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_HT_OPERATION, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - pHT_info_ie = p; - - pmlmepriv->cur_network.network_type = network_type; - - pmlmepriv->htpriv.ht_option = false; - - /* ht_cap */ - if (pregistrypriv->ht_enable && ht_cap) { - pmlmepriv->htpriv.ht_option = true; - pmlmepriv->qos_option = 1; - - if (pregistrypriv->ampdu_enable == 1) - pmlmepriv->htpriv.ampdu_enable = true; - - HT_caps_handler23a(padapter, pHT_caps_ie); - - HT_info_handler23a(padapter, pHT_info_ie); - } - - pbss_network->Length = get_wlan_bssid_ex_sz(pbss_network); - - /* issue beacon to start bss network */ - start_bss_network(padapter, (u8 *)pbss_network); - - /* alloc sta_info for ap itself */ - psta = rtw_get_stainfo23a(&padapter->stapriv, pbss_network->MacAddress); - if (!psta) { - psta = rtw_alloc_stainfo23a(&padapter->stapriv, - pbss_network->MacAddress, - GFP_KERNEL); - if (!psta) - return _FAIL; - } - /* fix bug of flush_cam_entry at STOP AP mode */ - psta->state |= WIFI_AP_STATE; - rtw_indicate_connect23a(padapter); - - /* for check if already set beacon */ - pmlmepriv->cur_network.join_res = true; - - return ret; -} - -void rtw_set_macaddr_acl23a(struct rtw_adapter *padapter, int mode) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - DBG_8723A("%s, mode =%d\n", __func__, mode); - - pacl_list->mode = mode; -} - -static void update_bcn_erpinfo_ie(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - unsigned char *p, *ie = pnetwork->IEs; - u32 len = 0; - - DBG_8723A("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable); - - if (!pmlmeinfo->ERP_enable) - return; - - /* parsing ERP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_ERP_INFO, &len, pnetwork->IELength); - if (p && len > 0) { - if (pmlmepriv->num_sta_non_erp == 1) - p[2] |= WLAN_ERP_NON_ERP_PRESENT | - WLAN_ERP_USE_PROTECTION; - else - p[2] &= ~(WLAN_ERP_NON_ERP_PRESENT | - WLAN_ERP_USE_PROTECTION); - - if (pmlmepriv->num_sta_no_short_preamble > 0) - p[2] |= WLAN_ERP_BARKER_PREAMBLE; - else - p[2] &= ~(WLAN_ERP_BARKER_PREAMBLE); - - ERP_IE_handler23a(padapter, p); - } -} - -static void update_bcn_wpa_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_wmm_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_wps_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_p2p_ie(struct rtw_adapter *padapter) -{ -} - -static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8 *oui) -{ - DBG_8723A("%s\n", __func__); - - if (!memcmp(RTW_WPA_OUI23A_TYPE, oui, 4)) - update_bcn_wpa_ie(padapter); - else if (!memcmp(WMM_OUI23A, oui, 4)) - update_bcn_wmm_ie(padapter); - else if (!memcmp(WPS_OUI23A, oui, 4)) - update_bcn_wps_ie(padapter); - else if (!memcmp(P2P_OUI23A, oui, 4)) - update_bcn_p2p_ie(padapter); - else - DBG_8723A("unknown OUI type!\n"); -} - -void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx) -{ - struct mlme_priv *pmlmepriv; - struct mlme_ext_priv *pmlmeext; - /* struct mlme_ext_info *pmlmeinfo; */ - - /* DBG_8723A("%s\n", __func__); */ - - if (!padapter) - return; - - pmlmepriv = &padapter->mlmepriv; - pmlmeext = &padapter->mlmeextpriv; - /* pmlmeinfo = &pmlmeext->mlmext_info; */ - - if (false == pmlmeext->bstart_bss) - return; - - spin_lock_bh(&pmlmepriv->bcn_update_lock); - - switch (ie_id) { - case WLAN_EID_TIM: - update_BCNTIM(padapter); - break; - - case WLAN_EID_ERP_INFO: - update_bcn_erpinfo_ie(padapter); - break; - - case WLAN_EID_VENDOR_SPECIFIC: - update_bcn_vendor_spec_ie(padapter, oui); - break; - - default: - break; - } - - pmlmepriv->update_bcn = true; - - spin_unlock_bh(&pmlmepriv->bcn_update_lock); - - if (tx) - set_tx_beacon_cmd23a(padapter); -} - -/* - * op_mode - * 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 - * in both the primary and the secondary channel - * Set to 2 if only HT STAs are associated in BSS, - * however and at least one 20 MHz HT STA is associated - * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated - * (currently non-GF HT station is considered as non-HT STA also) -*/ -static int rtw_ht_operation_update(struct rtw_adapter *padapter) -{ - u16 cur_op_mode, new_op_mode; - int op_mode_changes = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - - if (pmlmepriv->htpriv.ht_option) - return 0; - - /* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */ - /* return 0; */ - - DBG_8723A("%s current operation mode = 0x%X\n", - __func__, pmlmepriv->ht_op_mode); - - if (!(pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) - && pmlmepriv->num_sta_ht_no_gf) { - pmlmepriv->ht_op_mode |= - IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) && - pmlmepriv->num_sta_ht_no_gf == 0) { - pmlmepriv->ht_op_mode &= - ~IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; - op_mode_changes++; - } - - if (!(pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) && - (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode |= IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) && - (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode &= - ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; - op_mode_changes++; - } - - /* - * Note: currently we switch to the MIXED op mode if HT non-greenfield - * station is associated. Probably it's a theoretical case, since - * it looks like all known HT STAs support greenfield. - */ - if (pmlmepriv->num_sta_no_ht || - (pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; - else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - pmlmepriv->num_sta_ht_20mhz) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; - else if (pmlmepriv->olbc_ht) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER; - else - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - - cur_op_mode = pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_PROTECTION; - if (cur_op_mode != new_op_mode) { - pmlmepriv->ht_op_mode &= ~IEEE80211_HT_OP_MODE_PROTECTION; - pmlmepriv->ht_op_mode |= new_op_mode; - op_mode_changes++; - } - - DBG_8723A("%s new operation mode = 0x%X changes =%d\n", - __func__, pmlmepriv->ht_op_mode, op_mode_changes); - - return op_mode_changes; -} - -void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated) -{ - /* update associated stations cap. */ - if (updated == true) { - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) - VCS_update23a(padapter, psta); - spin_unlock_bh(&pstapriv->asoc_list_lock); - } -} - -/* called > TSR LEVEL for USB or SDIO Interface */ -void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) { - if (!psta->no_short_preamble_set) { - psta->no_short_preamble_set = 1; - - pmlmepriv->num_sta_no_short_preamble++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 1)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } else { - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - - pmlmepriv->num_sta_no_short_preamble--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 0)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } - - if (psta->flags & WLAN_STA_NONERP) { - if (!psta->nonerp_set) { - psta->nonerp_set = 1; - - pmlmepriv->num_sta_non_erp++; - - if (pmlmepriv->num_sta_non_erp == 1) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, NULL, true); - } - } - - } else { - if (psta->nonerp_set) { - psta->nonerp_set = 0; - - pmlmepriv->num_sta_non_erp--; - - if (pmlmepriv->num_sta_non_erp == 0) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, NULL, true); - } - } - - } - - if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) { - if (!psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 1; - - pmlmepriv->num_sta_no_short_slot_time++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 1)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } else { - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - - pmlmepriv->num_sta_no_short_slot_time--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 0)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - } - - if (psta->flags & WLAN_STA_HT) { - u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); - - DBG_8723A("HT: STA %pM HT Capabilities Info: 0x%04x\n", - psta->hwaddr, ht_capab); - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) { - if (!psta->no_ht_gf_set) { - psta->no_ht_gf_set = 1; - pmlmepriv->num_sta_ht_no_gf++; - } - DBG_8723A("%s STA %pM - no greenfield, num of non-gf stations %d\n", - __func__, psta->hwaddr, - pmlmepriv->num_sta_ht_no_gf); - } - - if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) { - if (!psta->ht_20mhz_set) { - psta->ht_20mhz_set = 1; - pmlmepriv->num_sta_ht_20mhz++; - } - DBG_8723A("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n", - __func__, psta->hwaddr, - pmlmepriv->num_sta_ht_20mhz); - } - - } else { - if (!psta->no_ht_set) { - psta->no_ht_set = 1; - pmlmepriv->num_sta_no_ht++; - } - if (pmlmepriv->htpriv.ht_option) { - DBG_8723A("%s STA %pM - no HT, num of non-HT stations %d\n", - __func__, psta->hwaddr, - pmlmepriv->num_sta_no_ht); - } - } - - if (rtw_ht_operation_update(padapter) > 0) { - update_beacon23a(padapter, WLAN_EID_HT_CAPABILITY, NULL, false); - update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true); - } - - /* update associated stations cap. */ - associated_clients_update23a(padapter, beacon_updated); - - DBG_8723A("%s, updated =%d\n", __func__, beacon_updated); -} - -u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!psta) - return beacon_updated; - - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - pmlmepriv->num_sta_no_short_preamble--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B - && pmlmepriv->num_sta_no_short_preamble == 0) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - - if (psta->nonerp_set) { - psta->nonerp_set = 0; - pmlmepriv->num_sta_non_erp--; - if (pmlmepriv->num_sta_non_erp == 0) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, - NULL, true); - } - } - - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - pmlmepriv->num_sta_no_short_slot_time--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B - && pmlmepriv->num_sta_no_short_slot_time == 0) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - - if (psta->no_ht_gf_set) { - psta->no_ht_gf_set = 0; - pmlmepriv->num_sta_ht_no_gf--; - } - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if (psta->ht_20mhz_set) { - psta->ht_20mhz_set = 0; - pmlmepriv->num_sta_ht_20mhz--; - } - - if (rtw_ht_operation_update(padapter) > 0) { - update_beacon23a(padapter, WLAN_EID_HT_CAPABILITY, NULL, false); - update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true); - } - - /* update associated stations cap. */ - - DBG_8723A("%s, updated =%d\n", __func__, beacon_updated); - - return beacon_updated; -} - -u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool active, u16 reason) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - u8 beacon_updated = false; - - if (!psta) - return beacon_updated; - - if (active) { - /* tear down Rx AMPDU */ - send_delba23a(padapter, 0, psta->hwaddr); /* recipient */ - - /* tear down TX AMPDU */ - send_delba23a(padapter, 1, psta->hwaddr); /* originator */ - - issue_deauth23a(padapter, psta->hwaddr, reason); - } - - psta->htpriv.agg_enable_bitmap = 0x0; /* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0; /* reset */ - - /* report_del_sta_event23a(padapter, psta->hwaddr, reason); */ - - /* clear cam entry / key */ - /* clear_cam_entry23a(padapter, (psta->mac_id + 3)); */ - rtw_clearstakey_cmd23a(padapter, (u8 *)psta, (u8)(psta->mac_id + 3), - true); - - spin_lock_bh(&psta->lock); - psta->state &= ~_FW_LINKED; - spin_unlock_bh(&psta->lock); - - rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason); - - report_del_sta_event23a(padapter, psta->hwaddr, reason); - - beacon_updated = bss_cap_update_on_sta_leave23a(padapter, psta); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - return beacon_updated; -} - -int rtw_sta_flush23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if ((pmlmeinfo->state&0x03) != MSR_AP) - return 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) { - /* Remove sta from asoc_list */ - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - /* Keep sta for ap_free_sta23a() beyond this asoc_list loop */ - chk_alive_list[chk_alive_num++] = psta; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - /* For each sta in chk_alive_list, call ap_free_sta23a */ - for (i = 0; i < chk_alive_num; i++) - ap_free_sta23a(padapter, chk_alive_list[i], true, - WLAN_REASON_DEAUTH_LEAVING); - - issue_deauth23a(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING); - - associated_clients_update23a(padapter, true); - - return 0; -} - -/* called > TSR LEVEL for USB or SDIO Interface */ -void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - int flags = psta->flags; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - /* update wmm cap. */ - if (WLAN_STA_WME&flags) - psta->qos_option = 1; - else - psta->qos_option = 0; - - if (pmlmepriv->qos_option == 0) - psta->qos_option = 0; - - /* update 802.11n ht cap. */ - if (WLAN_STA_HT&flags) { - psta->htpriv.ht_option = true; - psta->qos_option = 1; - } else { - psta->htpriv.ht_option = false; - } - - if (!pmlmepriv->htpriv.ht_option) - psta->htpriv.ht_option = false; - - update_sta_info23a_apmode23a(padapter, psta); -} - -/* called >= TSR LEVEL for USB or SDIO Interface */ -void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - if (psta->state & _FW_LINKED) { - /* add ratid */ - add_RATid23a(padapter, psta, 0);/* DM_RATR_STA_INIT */ - } -} - -/* restore hw setting from sw data structures */ -void rtw_ap_restore_network(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta, *ptmp; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct list_head *phead; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - rtw_setopmode_cmd23a(padapter, NL80211_IFTYPE_AP); - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - start_bss_network(padapter, (u8 *)&mlmepriv->cur_network.network); - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_TKIP || - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - /* restore group key, WEP keys is restored in ips_leave23a() */ - rtw_set_key23a(padapter, psecuritypriv, - psecuritypriv->dot118021XGrpKeyid, 0); - } - - /* per sta pairwise key and settings */ - if (padapter->securitypriv.dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_TKIP && - padapter->securitypriv.dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_CCMP) { - return; - } - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) - chk_alive_list[chk_alive_num++] = psta; - spin_unlock_bh(&pstapriv->asoc_list_lock); - - for (i = 0; i < chk_alive_num; i++) { - psta = chk_alive_list[i]; - - if (psta->state & _FW_LINKED) { - Update_RA_Entry23a(padapter, psta); - /* pairwise key */ - rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true); - } - } -} - -void start_ap_mode23a(struct rtw_adapter *padapter) -{ - int i; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - pmlmepriv->update_bcn = false; - - /* init_mlme_ap_info23a(padapter); */ - pmlmeext->bstart_bss = false; - - pmlmepriv->num_sta_non_erp = 0; - - pmlmepriv->num_sta_no_short_slot_time = 0; - - pmlmepriv->num_sta_no_short_preamble = 0; - - pmlmepriv->num_sta_ht_no_gf = 0; - pmlmepriv->num_sta_no_ht = 0; - pmlmepriv->num_sta_ht_20mhz = 0; - - pmlmepriv->olbc = false; - - pmlmepriv->olbc_ht = false; - - pmlmepriv->ht_op_mode = 0; - - for (i = 0; i < NUM_STA; i++) - pstapriv->sta_aid[i] = NULL; - - /* for ACL */ - INIT_LIST_HEAD(&pacl_list->acl_node_q.queue); - pacl_list->num = 0; - pacl_list->mode = 0; - for (i = 0; i < NUM_ACL; i++) { - INIT_LIST_HEAD(&pacl_list->aclnode[i].list); - pacl_list->aclnode[i].valid = false; - } -} - -void stop_ap_mode23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct rtw_wlan_acl_node *paclnode, *ptmp; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q; - - pmlmepriv->update_bcn = false; - pmlmeext->bstart_bss = false; - - /* - * reset and init security priv , this can - * refine with rtw_reset_securitypriv23a - */ - memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; - - /* for ACL */ - spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - list_for_each_entry_safe(paclnode, ptmp, phead, list) { - if (paclnode->valid == true) { - paclnode->valid = false; - list_del_init(&paclnode->list); - pacl_list->num--; - } - } - spin_unlock_bh(&pacl_node_q->lock); - - DBG_8723A("%s, free acl_node_queue, num =%d\n", - __func__, pacl_list->num); - - rtw_sta_flush23a(padapter); - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo23a(padapter); - - psta = rtw_get_bcmc_stainfo23a(padapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - rtw_init_bcmc_stainfo23a(padapter); - - rtw23a_free_mlme_priv_ie_data(pmlmepriv); -} diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c deleted file mode 100644 index cd4e0f05d82f..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_cmd.c +++ /dev/null @@ -1,1470 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_CMD_C_ - -#include -#include -#include -#include -#include -#include - -static struct cmd_hdl wlancmds[] = { - GEN_DRV_CMD_HANDLER(0, NULL) /*0*/ - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*10*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), join_cmd_hdl23a) /*14*/ - GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), createbss_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl23a) /*18*/ - GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl23a) /*20*/ - GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL) /*30*/ - GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*40*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl23a) /* 46 */ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*50*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl23a) /*55*/ - - GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl23a) /*56*/ - GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl23a) /*57*/ - - GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl23a) /*58*/ - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl23a) /*59*/ - GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl23a) /*60*/ - - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl23a) /*61*/ - GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl23a) /*62*/ -}; - -struct _cmd_callback rtw_cmd_callback[] = { - {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ - {GEN_CMD_CODE(_Write_MACREG), NULL}, - {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback23a}, - {GEN_CMD_CODE(_Write_BBREG), NULL}, - {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback23a}, - {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ - {GEN_CMD_CODE(_Read_EEPROM), NULL}, - {GEN_CMD_CODE(_Write_EEPROM), NULL}, - {GEN_CMD_CODE(_Read_EFUSE), NULL}, - {GEN_CMD_CODE(_Write_EFUSE), NULL}, - - {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ - {GEN_CMD_CODE(_Write_CAM), NULL}, - {GEN_CMD_CODE(_setBCNITV), NULL}, - {GEN_CMD_CODE(_setMBIDCFG), NULL}, - {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd23a_callback}, /*14*/ - {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd23a_callback}, /*15*/ - {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd23a_callback}, - {GEN_CMD_CODE(_SetOpMode), NULL}, - {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback23a}, /*18*/ - {GEN_CMD_CODE(_SetAuth), NULL}, - - {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ - {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback23a}, - {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback23a}, - {GEN_CMD_CODE(_DelAssocSta), NULL}, - {GEN_CMD_CODE(_SetStaPwrState), NULL}, - {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ - {GEN_CMD_CODE(_GetBasicRate), NULL}, - {GEN_CMD_CODE(_SetDataRate), NULL}, - {GEN_CMD_CODE(_GetDataRate), NULL}, - {GEN_CMD_CODE(_SetPhyInfo), NULL}, - - {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ - {GEN_CMD_CODE(_SetPhy), NULL}, - {GEN_CMD_CODE(_GetPhy), NULL}, - {GEN_CMD_CODE(_readRssi), NULL}, - {GEN_CMD_CODE(_readGain), NULL}, - {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ - {GEN_CMD_CODE(_SetPwrMode), NULL}, - {GEN_CMD_CODE(_JoinbssRpt), NULL}, - {GEN_CMD_CODE(_SetRaTable), NULL}, - {GEN_CMD_CODE(_GetRaTable), NULL}, - - {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ - {GEN_CMD_CODE(_GetDTMReport), NULL}, - {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, - {GEN_CMD_CODE(_SetUsbSuspend), NULL}, - {GEN_CMD_CODE(_SetH2cLbk), NULL}, - {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ - {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ - {GEN_CMD_CODE(_SetTxPower), NULL}, - {GEN_CMD_CODE(_SwitchAntenna), NULL}, - {GEN_CMD_CODE(_SetCrystalCap), NULL}, - {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ - - {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/ - {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, - {GEN_CMD_CODE(_SetContinuousTx), NULL}, - {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ - {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/ - - {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/ - {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/ - {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/ - {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/ - {GEN_CMD_CODE(_LedBlink), NULL},/*60*/ - - {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/ - {GEN_CMD_CODE(_TDLS), NULL},/*62*/ -}; - -/* -Caller and the rtw_cmd_thread23a can protect cmd_q by spin_lock. -No irqsave is necessary. -*/ - -int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv) -{ - int res = _SUCCESS; - - pcmdpriv->cmd_issued_cnt = 0; - pcmdpriv->cmd_done_cnt = 0; - pcmdpriv->rsp_cnt = 0; - - pcmdpriv->wq = alloc_workqueue("rtl8723au_cmd", 0, 1); - if (!pcmdpriv->wq) - res = _FAIL; - - return res; -} - -/* forward definition */ - -static void rtw_irq_work(struct work_struct *work); - -u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv) -{ - pevtpriv->wq = alloc_workqueue("rtl8723au_evt", 0, 1); - - INIT_WORK(&pevtpriv->irq_wk, rtw_irq_work); - - return _SUCCESS; -} - -void rtw_free_evt_priv23a(struct evt_priv *pevtpriv) -{ - cancel_work_sync(&pevtpriv->irq_wk); -} - -static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) -{ - /* set to true to allow enqueuing cmd when hw_init_completed is false */ - u8 bAllow = false; - - if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) - bAllow = true; - - if (pcmdpriv->padapter->hw_init_completed == false && bAllow == false) - return _FAIL; - return _SUCCESS; -} - -static void rtw_cmd_work(struct work_struct *work); - -int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) -{ - int res = _FAIL; - - if (!cmd_obj) - goto exit; - - cmd_obj->padapter = pcmdpriv->padapter; - - res = rtw_cmd_filter(pcmdpriv, cmd_obj); - if (res == _FAIL) { - rtw_free_cmd_obj23a(cmd_obj); - goto exit; - } - - INIT_WORK(&cmd_obj->work, rtw_cmd_work); - - res = queue_work(pcmdpriv->wq, &cmd_obj->work); - - if (!res) { - netdev_err(pcmdpriv->padapter->pnetdev, - "%s: Call to queue_work() failed\n", __func__); - res = _FAIL; - } else - res = _SUCCESS; -exit: - - return res; -} - -void rtw_free_cmd_obj23a(struct cmd_obj *pcmd) -{ - - if (pcmd->cmdcode != _JoinBss_CMD_ && - pcmd->cmdcode != _CreateBss_CMD_) { - /* free parmbuf in cmd_obj */ - kfree(pcmd->parmbuf); - } - - if (pcmd->rsp) { - if (pcmd->rspsz != 0) { - /* free rsp in cmd_obj */ - kfree(pcmd->rsp); - } - } - - kfree(pcmd); -} - -static void rtw_cmd_work(struct work_struct *work) -{ - int (*cmd_hdl)(struct rtw_adapter *padapter, const u8 *pbuf); - void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd); - struct cmd_priv *pcmdpriv; - struct cmd_obj *pcmd = container_of(work, struct cmd_obj, work); - - pcmdpriv = &pcmd->padapter->cmdpriv; - - if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { - pcmd->res = H2C_DROPPED; - goto post_process; - } - - pcmdpriv->cmd_issued_cnt++; - - pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4); - - if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) { - cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; - - if (cmd_hdl) - pcmd->res = cmd_hdl(pcmd->padapter, pcmd->parmbuf); - else - pcmd->res = H2C_DROPPED; - } else - pcmd->res = H2C_PARAMETERS_ERROR; - -post_process: - /* call callback function for post-processed */ - if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { - pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; - if (!pcmd_callback) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", - pcmd_callback, pcmd->cmdcode); - rtw_free_cmd_obj23a(pcmd); - } else { - /* need consider that free cmd_obj in - rtw_cmd_callback */ - pcmd_callback(pcmd->padapter, pcmd); - } - } else { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "%s: cmdcode = 0x%x callback not defined!\n", - __func__, pcmd->cmdcode); - rtw_free_cmd_obj23a(pcmd); - } -} - - -int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter, - struct cfg80211_ssid *ssid, int ssid_num, - struct rtw_ieee80211_channel *ch, int ch_num) -{ - int res = _FAIL; - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1); - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) - return _FAIL; - - psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - return _FAIL; - } - - rtw_free_network_queue23a(padapter); - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "%s: flush network queue\n", __func__); - - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, - GEN_CMD_CODE(_SiteSurvey)); - - /* psurveyPara->bsslimit = 48; */ - psurveyPara->scan_mode = pmlmepriv->scan_mode; - - /* prepare ssid list */ - if (ssid) { - int i; - - for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { - if (ssid[i].ssid_len) { - memcpy(&psurveyPara->ssid[i], &ssid[i], - sizeof(struct cfg80211_ssid)); - psurveyPara->ssid_num++; - } - } - } - - /* prepare channel list */ - if (ch) { - int i; - - for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { - if (ch[i].hw_value && - !(ch[i].flags & IEEE80211_CHAN_DISABLED)) { - memcpy(&psurveyPara->ch[i], &ch[i], - sizeof(struct rtw_ieee80211_channel)); - psurveyPara->ch_num++; - } - } - } - - set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - - if (res == _SUCCESS) { - mod_timer(&pmlmepriv->scan_to_timer, jiffies + - msecs_to_jiffies(SCANNING_TIMEOUT)); - - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - } else - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - return res; -} - -void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - kfree(pcmd->parmbuf); - kfree(pcmd); -} - -int rtw_createbss_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pdev_network; - u8 res = _SUCCESS; - - pdev_network = &padapter->registrypriv.dev_network; - - if (pmlmepriv->assoc_ssid.ssid_len == 0) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "createbss for Any SSid:%s\n", - pmlmepriv->assoc_ssid.ssid); - } else { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "createbss for SSid:%s\n", - pmlmepriv->assoc_ssid.ssid); - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd) { - res = _FAIL; - goto exit; - } - - pcmd->cmdcode = _CreateBss_CMD_; - pcmd->parmbuf = (unsigned char *)pdev_network; - pcmd->cmdsz = get_wlan_bssid_ex_sz(pdev_network); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - pdev_network->Length = pcmd->cmdsz; - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -int rtw_joinbss_cmd23a(struct rtw_adapter *padapter, - struct wlan_network *pnetwork) -{ - int res = _SUCCESS; - struct wlan_bssid_ex *psecnetwork; - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - enum nl80211_iftype ifmode; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - ifmode = pnetwork->network.ifmode; - - if (pmlmepriv->assoc_ssid.ssid_len == 0) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "+Join cmd: Any SSid\n"); - } else { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, - "+Join cmd: SSid =[%s]\n", - pmlmepriv->assoc_ssid.ssid); - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd) { - res = _FAIL; - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "rtw_joinbss_cmd23a: memory allocate for cmd_obj fail!!!\n"); - goto exit; - } - - /* for hidden ap to set fw_state here */ - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) { - switch (ifmode) { - case NL80211_IFTYPE_ADHOC: - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - set_fwstate(pmlmepriv, WIFI_STATION_STATE); - break; - default: - break; - } - } - - psecnetwork = &psecuritypriv->sec_bss; - if (!psecnetwork) { - kfree(pcmd); - res = _FAIL; - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n"); - - goto exit; - } - - memset(psecnetwork, 0, sizeof(struct wlan_bssid_ex)); - - memcpy(psecnetwork, &pnetwork->network, - get_wlan_bssid_ex_sz(&pnetwork->network)); - - psecnetwork->IELength = 0; - /* Added by Albert 2009/02/18 */ - /* If the the driver wants to use the bssid to create the - * connection. If not, we have to copy the connecting AP's - * MAC address to it so that the driver just has the bssid - * information for PMKIDList searching. */ - - if (pmlmepriv->assoc_by_bssid == false) - ether_addr_copy(&pmlmepriv->assoc_bssid[0], - &pnetwork->network.MacAddress[0]); - - psecnetwork->IELength = - rtw_restruct_sec_ie23a(padapter, &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength); - - pmlmepriv->qos_option = 0; - - if (pregistrypriv->wmm_enable) { - u32 tmp_len; - - tmp_len = rtw_restruct_wmm_ie23a(padapter, - &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength, - psecnetwork->IELength); - - if (psecnetwork->IELength != tmp_len) { - psecnetwork->IELength = tmp_len; - /* There is WMM IE in this corresp. beacon */ - pmlmepriv->qos_option = 1; - } else { - /* There is no WMM IE in this corresp. beacon */ - pmlmepriv->qos_option = 0; - } - } - - phtpriv->ht_option = false; - if (pregistrypriv->ht_enable) { - u32 algo = padapter->securitypriv.dot11PrivacyAlgrthm; - /* Added by Albert 2010/06/23 */ - /* For the WEP mode, we will use the bg mode to do - the connection to avoid some IOT issue. */ - /* Especially for Realtek 8192u SoftAP. */ - if (algo != WLAN_CIPHER_SUITE_WEP40 && - algo != WLAN_CIPHER_SUITE_WEP104 && - algo != WLAN_CIPHER_SUITE_TKIP) { - /* rtw_restructure_ht_ie23a */ - rtw_restructure_ht_ie23a(padapter, - &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength, - &psecnetwork->IELength); - } - } - - pmlmeinfo->assoc_AP_vendor = - check_assoc_AP23a(pnetwork->network.IEs, - pnetwork->network.IELength); - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA) - padapter->pwrctrlpriv.smart_ps = 0; - else - padapter->pwrctrlpriv.smart_ps = - padapter->registrypriv.smart_ps; - - DBG_8723A("%s: smart_ps =%d\n", __func__, - padapter->pwrctrlpriv.smart_ps); - - /* get cmdsz before endian conversion */ - pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork); - - pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ - pcmd->parmbuf = (unsigned char *)psecnetwork; - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); -exit: - - return res; -} - -int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, - bool enqueue) -{ - struct cmd_obj *cmdobj = NULL; - struct disconnect_parm *param = NULL; - struct cmd_priv *cmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, - "+rtw_disassoc_cmd23a\n"); - - /* prepare cmd parameter */ - param = kzalloc(sizeof(*param), GFP_ATOMIC); - if (param == NULL) { - res = _FAIL; - goto exit; - } - param->deauth_timeout_ms = deauth_timeout_ms; - - if (enqueue) { - /* need enqueue, prepare cmd_obj and enqueue */ - cmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!cmdobj) { - res = _FAIL; - kfree(param); - goto exit; - } - init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); - res = rtw_enqueue_cmd23a(cmdpriv, cmdobj); - } else { - /* no need to enqueue, do the cmd hdl directly and - free cmd parameter */ - if (disconnect_hdl23a(padapter, (u8 *)param) != H2C_SUCCESS) - res = _FAIL; - kfree(param); - } - -exit: - return res; -} - -int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, - enum nl80211_iftype ifmode) -{ - struct cmd_obj *ph2c; - struct setopmode_parm *psetop; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = false; - goto exit; - } - psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL); - - if (!psetop) { - kfree(ph2c); - res = false; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); - psetop->mode = ifmode; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - return res; -} - -int rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sta_info *sta = (struct sta_info *)psta; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL); - if (!psetstakey_para) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - ph2c->rsp = (u8 *) psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - - ether_addr_copy(psetstakey_para->addr, sta->hwaddr); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - psetstakey_para->algorithm = - (unsigned char)psecuritypriv->dot11PrivacyAlgrthm; - } else { - GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, - false); - } - - if (unicast_key == true) { - memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); - } else { - int idx = psecuritypriv->dot118021XGrpKeyid; - - memcpy(&psetstakey_para->key, - &psecuritypriv->dot118021XGrpKey[idx].skey, 16); - } - - /* jeff: set this because at least sw key is ready */ - padapter->securitypriv.busetkipkey = 1; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - - return res; -} - -int rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry, - u8 enqueue) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - struct sta_info *sta = (struct sta_info *)psta; - int res = _SUCCESS; - - if (!enqueue) { - clear_cam_entry23a(padapter, entry); - } else { - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), - GFP_KERNEL); - if (!psetstakey_para) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), - GFP_KERNEL); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, - _SetStaKey_CMD_); - ph2c->rsp = (u8 *) psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - - ether_addr_copy(psetstakey_para->addr, sta->hwaddr); - - psetstakey_para->algorithm = 0; - - psetstakey_para->id = entry; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } -exit: - return res; -} - -int rtw_addbareq_cmd23a(struct rtw_adapter *padapter, u8 tid, u8 *addr) -{ - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct cmd_obj *ph2c; - struct addBaReq_parm *paddbareq_parm; - int res = _SUCCESS; - - if (tid >= MAXTID) { - res = _FAIL; - goto exit; - } - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC); - if (!paddbareq_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - paddbareq_parm->tid = tid; - ether_addr_copy(paddbareq_parm->addr, addr); - - init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, - GEN_CMD_CODE(_AddBAReq)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - return res; -} - -int rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; - pdrvextra_cmd_parm->type_size = 0; - pdrvextra_cmd_parm->pbuf = (u8 *)padapter; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - - return res; -} - -static void traffic_status_watchdog(struct rtw_adapter *padapter) -{ - u8 bEnterPS; - u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; - u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false; - u8 bHigherBusyTxTraffic = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int BusyThreshold = 100; - struct rt_link_detect *ldi = &pmlmepriv->LinkDetectInfo; - - /* */ - /* Determine if our traffic is busy now */ - /* */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (rtl8723a_BT_coexist(padapter)) - BusyThreshold = 50; - else if (ldi->bBusyTraffic) - BusyThreshold = 75; - /* if we raise bBusyTraffic in last watchdog, using - lower threshold. */ - if (ldi->NumRxOkInPeriod > BusyThreshold || - ldi->NumTxOkInPeriod > BusyThreshold) { - bBusyTraffic = true; - - if (ldi->NumRxOkInPeriod > ldi->NumTxOkInPeriod) - bRxBusyTraffic = true; - else - bTxBusyTraffic = true; - } - - /* Higher Tx/Rx data. */ - if (ldi->NumRxOkInPeriod > 4000 || - ldi->NumTxOkInPeriod > 4000) { - bHigherBusyTraffic = true; - - if (ldi->NumRxOkInPeriod > ldi->NumTxOkInPeriod) - bHigherBusyRxTraffic = true; - else - bHigherBusyTxTraffic = true; - } - - if (!rtl8723a_BT_coexist(padapter) || - !rtl8723a_BT_using_antenna_1(padapter)) { - /* check traffic for powersaving. */ - if (((ldi->NumRxUnicastOkInPeriod + - ldi->NumTxOkInPeriod) > 8) || - ldi->NumRxUnicastOkInPeriod > 2) - bEnterPS = false; - else - bEnterPS = true; - - /* LeisurePS only work in infra mode. */ - if (bEnterPS) - LPS_Enter23a(padapter); - else - LPS_Leave23a(padapter); - } - } else - LPS_Leave23a(padapter); - - ldi->NumRxOkInPeriod = 0; - ldi->NumTxOkInPeriod = 0; - ldi->NumRxUnicastOkInPeriod = 0; - ldi->bBusyTraffic = bBusyTraffic; - ldi->bTxBusyTraffic = bTxBusyTraffic; - ldi->bRxBusyTraffic = bRxBusyTraffic; - ldi->bHigherBusyTraffic = bHigherBusyTraffic; - ldi->bHigherBusyRxTraffic = bHigherBusyRxTraffic; - ldi->bHigherBusyTxTraffic = bHigherBusyTxTraffic; -} - -static void dynamic_chk_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz) -{ - struct mlme_priv *pmlmepriv; - - padapter = (struct rtw_adapter *)pbuf; - pmlmepriv = &padapter->mlmepriv; - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - expire_timeout_chk23a(padapter); -#endif - - rtl8723a_sreset_xmit_status_check(padapter); - - linked_status_chk23a(padapter); - traffic_status_watchdog(padapter); - - rtl8723a_HalDmWatchDog(padapter); - - /* */ - /* BT-Coexist */ - /* */ - rtl8723a_BT_do_coexist(padapter); -} - -static void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 mstatus; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - return; - - switch (lps_ctrl_type) { - case LPS_CTRL_SCAN: - rtl8723a_BT_wifiscan_notify(padapter, true); - if (!rtl8723a_BT_using_antenna_1(padapter)) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) - LPS_Leave23a(padapter); - } - break; - case LPS_CTRL_JOINBSS: - LPS_Leave23a(padapter); - break; - case LPS_CTRL_CONNECT: - mstatus = 1;/* connect */ - /* Reset LPS Setting */ - padapter->pwrctrlpriv.LpsIdleCount = 0; - rtl8723a_set_FwJoinBssReport_cmd(padapter, 1); - rtl8723a_BT_mediastatus_notify(padapter, mstatus); - break; - case LPS_CTRL_DISCONNECT: - mstatus = 0;/* disconnect */ - rtl8723a_BT_mediastatus_notify(padapter, mstatus); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - rtl8723a_set_FwJoinBssReport_cmd(padapter, 0); - break; - case LPS_CTRL_SPECIAL_PACKET: - pwrpriv->DelayLPSLastTimeStamp = jiffies; - rtl8723a_BT_specialpacket_notify(padapter); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - break; - case LPS_CTRL_LEAVE: - rtl8723a_BT_lps_leave(padapter); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - break; - - default: - break; - } -} - -int rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter, - u8 lps_ctrl_type, u8 enqueue) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - if (enqueue) { - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; - pdrvextra_cmd_parm->type_size = lps_ctrl_type; - pdrvextra_cmd_parm->pbuf = NULL; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } else - lps_ctrl_wk_hdl(padapter, lps_ctrl_type); -exit: - - return res; -} - -int rtw_ps_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ppscmd; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ppscmd) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ppscmd); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; - pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd); -exit: - - return res; -} - -#ifdef CONFIG_8723AU_AP_MODE - -static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter) -{ - int cnt = 0; - struct sta_info *psta_bmc; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return; - - if (psta_bmc->sleepq_len == 0) { - bool val; - - val = rtl8723a_chk_hi_queue_empty(padapter); - - while (!val) { - msleep(100); - - cnt++; - - if (cnt > 10) - break; - - val = rtl8723a_chk_hi_queue_empty(padapter); - } - - if (cnt <= 10) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - } else /* re check again */ - rtw_chk_hi_queue_cmd23a(padapter); - } -} - -int rtw_chk_hi_queue_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; - pdrvextra_cmd_parm->type_size = 0; - pdrvextra_cmd_parm->pbuf = NULL; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - - return res; -} -#endif - -int rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = C2H_WK_CID; - pdrvextra_cmd_parm->type_size = c2h_evt?16:0; - pdrvextra_cmd_parm->pbuf = c2h_evt; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - - return res; -} - -static int c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt) -{ - int ret = _FAIL; - u8 buf[16]; - - if (!c2h_evt) { - /* No c2h event in cmd_obj, read c2h event before handling*/ - if (c2h_evt_read23a(adapter, buf) == _SUCCESS) { - c2h_evt = (struct c2h_evt_hdr *)buf; - - ret = c2h_handler_8723a(adapter, c2h_evt); - } - } else - ret = c2h_handler_8723a(adapter, c2h_evt); - - return ret; -} - -static void rtw_irq_work(struct work_struct *work) -{ - struct evt_priv *evtpriv; - struct rtw_adapter *adapter; - - evtpriv = container_of(work, struct evt_priv, irq_wk); - adapter = container_of(evtpriv, struct rtw_adapter, evtpriv); - - c2h_evt_clear23a(adapter); -} - -void rtw_evt_work(struct work_struct *work) -{ - struct evt_work *ework; - struct rtw_adapter *adapter; - - ework = container_of(work, struct evt_work, work); - adapter = ework->adapter; - - c2h_evt_clear23a(adapter); - - if (!c2h_evt_exist(&ework->u.c2h_evt)) { - kfree(ework); - return; - } - - if (c2h_id_filter_ccx_8723a(ework->u.c2h_evt.id) == true) { - /* Handle CCX report here */ - c2h_handler_8723a(adapter, &ework->u.c2h_evt); - kfree(ework); - } else { - /* - * Enqueue into cmd_thread for others. - * ework will be turned into a c2h_evt and freed once it - * has been consumed. - */ - rtw_c2h_wk_cmd23a(adapter, (u8 *)&ework->u.c2h_evt); - } -} - -int rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct drvextra_cmd_parm *pdrvextra_cmd; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; - - switch (pdrvextra_cmd->ec_id) { - case DYNAMIC_CHK_WK_CID: - dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, - pdrvextra_cmd->type_size); - break; - case POWER_SAVING_CTRL_WK_CID: - rtw_ps_processor23a(padapter); - break; - case LPS_CTRL_WK_CID: - lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size); - break; -#ifdef CONFIG_8723AU_AP_MODE - case CHECK_HIQ_WK_CID: - rtw_chk_hi_queue_hdl(padapter); - break; -#endif /* CONFIG_8723AU_AP_MODE */ - case C2H_WK_CID: - c2h_evt_hdl(padapter, - (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf); - break; - - default: - break; - } - - if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) { - kfree(pdrvextra_cmd->pbuf); - /* - * No need to set pdrvextra_cmd->pbuf = NULL as we were - * operating on a copy of the original pcmd->parmbuf - * created in rtw_cmd_work(). - */ - } - - return H2C_SUCCESS; -} - -void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res == H2C_DROPPED) { - /* TODO: cancel timer and do timeout handler directly... */ - /* need to make timeout handlerOS independent */ - mod_timer(&pmlmepriv->scan_to_timer, - jiffies + msecs_to_jiffies(1)); - } else if (pcmd->res != H2C_SUCCESS) { - mod_timer(&pmlmepriv->scan_to_timer, - jiffies + msecs_to_jiffies(1)); - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "********Error: MgntActrtw_set_802_11_bssid23a_LIST_SCAN Fail ************\n"); - } - - /* free cmd */ - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) { - spin_lock_bh(&pmlmepriv->lock); - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_bh(&pmlmepriv->lock); - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "***Error: disconnect_cmd_callback Fail ***\n"); - return; - } - - /* free cmd */ - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res == H2C_DROPPED) { - /* TODO: cancel timer and do timeout handler directly... */ - /* need to make timeout handlerOS independent */ - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - } else if (pcmd->res != H2C_SUCCESS) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "********Error:rtw_select_and_join_from_scanned_queue Wait Sema Fail ************\n"); - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - } - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_info *psta; - struct wlan_network *pwlan; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue; - - if (pcmd->res != H2C_SUCCESS) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "********Error: rtw_createbss_cmd23a_callback Fail ************\n"); - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - } - - del_timer_sync(&pmlmepriv->assoc_timer); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - psta = rtw_get_stainfo23a(&padapter->stapriv, - pnetwork->MacAddress); - if (!psta) { - psta = rtw_alloc_stainfo23a(&padapter->stapriv, - pnetwork->MacAddress, - GFP_KERNEL); - if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Can't alloc sta_info when createbss_cmd_callback\n"); - goto createbss_cmd_fail; - } - } - - spin_lock_bh(&pmlmepriv->lock); - rtw_indicate_connect23a(padapter); - spin_unlock_bh(&pmlmepriv->lock); - } else { - pwlan = rtw_alloc_network(pmlmepriv, GFP_KERNEL); - spin_lock_bh(&scanned_queue->lock); - if (!pwlan) { - pwlan = rtw_get_oldest_wlan_network23a(scanned_queue); - if (!pwlan) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Error: can't get pwlan in rtw23a_joinbss_event_cb\n"); - spin_unlock_bh(&scanned_queue->lock); - goto createbss_cmd_fail; - } - pwlan->last_scanned = jiffies; - } else { - list_add_tail(&pwlan->list, - &scanned_queue->queue); - } - - pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); - memcpy(&pwlan->network, pnetwork, pnetwork->Length); - /* pwlan->fixed = true; */ - - /* list_add_tail(&pwlan->list, - &pmlmepriv->scanned_queue.queue); */ - - /* copy pdev_network information to - pmlmepriv->cur_network */ - memcpy(&tgt_network->network, pnetwork, - get_wlan_bssid_ex_sz(pnetwork)); - - /* reset DSConfig */ - - clr_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - /* we will set _FW_LINKED when there is one more sat to - join us (rtw_stassoc_event_callback23a) */ - spin_unlock_bh(&scanned_queue->lock); - } - -createbss_cmd_fail: - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv; - struct set_stakey_rsp *psetstakey_rsp; - struct sta_info *psta; - - pstapriv = &padapter->stapriv; - psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); - psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr); - - if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "ERROR: rtw_setstaKey_cmdrsp_callback23a => can't get sta_info\n"); - goto exit; - } - -exit: - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct set_assocsta_parm *passocsta_parm; - struct set_assocsta_rsp *passocsta_rsp; - struct sta_info *psta; - - passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); - passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); - psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr); - - if (psta == NULL) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "ERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n"); - goto exit; - } - - psta->aid = psta->mac_id = passocsta_rsp->cam_id; - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && - check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_bh(&pmlmepriv->lock); - -exit: - rtw_free_cmd_obj23a(pcmd); -} diff --git a/drivers/staging/rtl8723au/core/rtw_efuse.c b/drivers/staging/rtl8723au/core/rtw_efuse.c deleted file mode 100644 index 359ef4197e94..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_efuse.c +++ /dev/null @@ -1,538 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_EFUSE_C_ - -#include -#include - -#include -#include -#include - -#define REG_EFUSE_CTRL 0x0030 -#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control */ - -#define VOLTAGE_V25 0x03 -#define LDOE25_SHIFT 28 - -/* - * When we want to enable write operation, we should change to - * pwr on state. When we stop write, we should switch to 500k mode - * and disable LDO 2.5V. - */ -static void Efuse_PowerSwitch(struct rtw_adapter *padapter, - u8 bWrite, u8 PwrState) -{ - u8 tempval; - u16 tmpV16; - - if (PwrState == true) { - rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); - - /* - * 1.2V Power: From VDDON with Power - * Cut(0x0000h[15]), default valid - */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_ISO_CTRL); - if (!(tmpV16 & PWC_EV12V)) { - tmpV16 |= PWC_EV12V; - rtl8723au_write16(padapter, REG_SYS_ISO_CTRL, tmpV16); - } - /* Reset: 0x0000h[28], default valid */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN); - if (!(tmpV16 & FEN_ELDR)) { - tmpV16 |= FEN_ELDR; - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, tmpV16); - } - - /* - * Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) - * clock from ANA, default valid - */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_CLKR); - if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { - tmpV16 |= (LOADER_CLK_EN | ANA8M); - rtl8723au_write16(padapter, REG_SYS_CLKR, tmpV16); - } - - if (bWrite == true) { - /* Enable LDO 2.5V before read/write action */ - tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3); - tempval &= 0x0F; - tempval |= (VOLTAGE_V25 << 4); - rtl8723au_write8(padapter, EFUSE_TEST + 3, - tempval | 0x80); - } - } else { - rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); - - if (bWrite == true) { - /* Disable LDO 2.5V after read/write action */ - tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3); - rtl8723au_write8(padapter, EFUSE_TEST + 3, - tempval & 0x7F); - } - } -} - -u16 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType) -{ - u16 ret = 0; - - if (efuseType == EFUSE_WIFI) - ret = rtl8723a_EfuseGetCurrentSize_WiFi(pAdapter); - else - ret = rtl8723a_EfuseGetCurrentSize_BT(pAdapter); - - return ret; -} - -/* Get current efuse area enabled word */ -u8 Efuse_CalculateWordCnts23a(u8 word_en) -{ - return hweight8((~word_en) & 0xf); -} - -/* - * Description: Execute E-Fuse read byte operation. - * - * Assumptions: 1. Boot from E-Fuse and successfully auto-load. - * 2. PASSIVE_LEVEL (USB interface) - */ -void ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf) -{ - u32 value32; - u8 readbyte; - u16 retry; - - /* Write Address */ - rtl8723au_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff)); - readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+2); - rtl8723au_write8(Adapter, EFUSE_CTRL+2, - ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); - - /* Write bit 32 0 */ - readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - rtl8723au_write8(Adapter, EFUSE_CTRL+3, readbyte & 0x7f); - - /* Check bit 32 read-ready */ - retry = 0; - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - while (!((value32 >> 24) & 0x80) && retry < 10000) { - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - retry++; - } - - /* - * Added suggested delay. This fixes the problem that - * Efuse read error in high temperature condition. - * Designer says that there shall be some delay after - * ready bit is set, or the result will always stay - * on last data we read. - */ - udelay(50); - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - - *pbuf = (u8)(value32 & 0xff); -} - -void EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType, - u8 type, void *pOut) -{ - u8 *pu1Tmp; - u16 *pu2Tmp; - u8 *pMax_section; - - switch (type) { - case TYPE_EFUSE_MAX_SECTION: - pMax_section = pOut; - - if (efuseType == EFUSE_WIFI) - *pMax_section = EFUSE_MAX_SECTION_8723A; - else - *pMax_section = EFUSE_BT_MAX_SECTION; - break; - - case TYPE_EFUSE_REAL_CONTENT_LEN: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN; - break; - - case TYPE_AVAILABLE_EFUSE_BYTES_BANK: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A - - EFUSE_OOB_PROTECT_BYTES); - else - *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN - - EFUSE_PROTECT_BYTES_BANK); - break; - - case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A - - EFUSE_OOB_PROTECT_BYTES); - else - *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN - - (EFUSE_PROTECT_BYTES_BANK * 3)); - break; - - case TYPE_EFUSE_MAP_LEN: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_MAP_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_MAP_LEN; - break; - - case TYPE_EFUSE_PROTECT_BYTES_BANK: - pu1Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu1Tmp = EFUSE_OOB_PROTECT_BYTES; - else - *pu1Tmp = EFUSE_PROTECT_BYTES_BANK; - break; - - case TYPE_EFUSE_CONTENT_LEN_BANK: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN; - break; - - default: - pu1Tmp = pOut; - *pu1Tmp = 0; - break; - } -} - -/* Copy from WMAC for EFUSE read 1 byte. */ -u8 EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address) -{ - u8 data; - u8 Bytetemp = {0x00}; - u8 temp = {0x00}; - u32 k = 0; - u16 contentLen = 0; - - EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI, - TYPE_EFUSE_REAL_CONTENT_LEN, - (void *)&contentLen); - - if (Address < contentLen) { /* E-fuse 512Byte */ - /* Write E-fuse Register address bit0~7 */ - temp = Address & 0xFF; - rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp); - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2); - /* Write E-fuse Register address bit8~9 */ - temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC); - rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp); - - /* Write 0x30[31]= 0 */ - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - temp = Bytetemp & 0x7F; - rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp); - - /* Wait Write-ready (0x30[31]= 1) */ - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - while (!(Bytetemp & 0x80)) { - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - k++; - if (k == 1000) { - k = 0; - break; - } - } - data = rtl8723au_read8(Adapter, EFUSE_CTRL); - return data; - } - return 0xFF; -} - -/* Read one byte from real Efuse. */ -int efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data) -{ - u8 tmpidx = 0; - int bResult; - - /* -----------------e-fuse reg ctrl ---------------------------- */ - /* address */ - rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); - rtl8723au_write8(pAdapter, EFUSE_CTRL + 2, - ((u8)((addr >> 8) & 0x03)) | - (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC)); - - rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0x72); /* read cmd */ - - while (!(0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) - tmpidx++; - if (tmpidx < 100) { - *data = rtl8723au_read8(pAdapter, EFUSE_CTRL); - bResult = _SUCCESS; - } else { - *data = 0xff; - bResult = _FAIL; - } - return bResult; -} - -/* Write one byte to reald Efuse. */ -int efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data) -{ - u8 tmpidx = 0; - int bResult; - - /* return 0; */ - - /* -----------------e-fuse reg ctrl ------------------------- */ - /* address */ - rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); - rtl8723au_write8(pAdapter, EFUSE_CTRL + 2, - (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) | - (u8)((addr >> 8) & 0x03)); - rtl8723au_write8(pAdapter, EFUSE_CTRL, data); /* data */ - - rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */ - - while ((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) { - tmpidx++; - } - - if (tmpidx < 100) - bResult = _SUCCESS; - else - bResult = _FAIL; - - return bResult; -} - -/* Read allowed word in current efuse section data. */ -void efuse_WordEnableDataRead23a(u8 word_en, u8 *sourdata, u8 *targetdata) -{ - if (!(word_en&BIT(0))) { - targetdata[0] = sourdata[0]; - targetdata[1] = sourdata[1]; - } - if (!(word_en&BIT(1))) { - targetdata[2] = sourdata[2]; - targetdata[3] = sourdata[3]; - } - if (!(word_en&BIT(2))) { - targetdata[4] = sourdata[4]; - targetdata[5] = sourdata[5]; - } - if (!(word_en&BIT(3))) { - targetdata[6] = sourdata[6]; - targetdata[7] = sourdata[7]; - } -} - -static int efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value) -{ - return efuse_OneByteRead23a(padapter, address, value); -} - -static int efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value) -{ - return efuse_OneByteWrite23a(padapter, address, *value); -} - -/* read/write raw efuse data */ -int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr, - u16 cnts, u8 *data) -{ - int i = 0; - u16 real_content_len = 0, max_available_size = 0; - int res = _FAIL; - int (*rw8)(struct rtw_adapter *, u16, u8*); - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_EFUSE_REAL_CONTENT_LEN, - (void *)&real_content_len); - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, - (void *)&max_available_size); - - if (start_addr > real_content_len) - return _FAIL; - - if (true == bWrite) { - if ((start_addr + cnts) > max_available_size) - return _FAIL; - rw8 = &efuse_write8; - } else - rw8 = &efuse_read8; - - Efuse_PowerSwitch(padapter, bWrite, true); - - /* e-fuse one byte read/write */ - for (i = 0; i < cnts; i++) { - if (start_addr >= real_content_len) { - res = _FAIL; - break; - } - - res = rw8(padapter, start_addr++, data++); - if (res == _FAIL) - break; - } - - Efuse_PowerSwitch(padapter, bWrite, false); - - return res; -} - -u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter) -{ - u16 max_size; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, - (void *)&max_size); - return max_size; -} - -int rtw_efuse_map_read23a(struct rtw_adapter *padapter, - u16 addr, u16 cnts, u8 *data) -{ - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if ((addr + cnts) > mapLen) - return _FAIL; - - Efuse_PowerSwitch(padapter, false, true); - - rtl8723a_readefuse(padapter, EFUSE_WIFI, addr, cnts, data); - - Efuse_PowerSwitch(padapter, false, false); - - return _SUCCESS; -} - -int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, - u16 addr, u16 cnts, u8 *data) -{ - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if ((addr + cnts) > mapLen) - return _FAIL; - - Efuse_PowerSwitch(padapter, false, true); - - rtl8723a_readefuse(padapter, EFUSE_BT, addr, cnts, data); - - Efuse_PowerSwitch(padapter, false, false); - - return _SUCCESS; -} - -/* Read All Efuse content */ -static void Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, - u8 *Efuse) -{ - u16 mapLen = 0; - - Efuse_PowerSwitch(pAdapter, false, true); - - EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, - (void *)&mapLen); - - rtl8723a_readefuse(pAdapter, efuseType, 0, mapLen, Efuse); - - Efuse_PowerSwitch(pAdapter, false, false); -} - -/* - * Functions: efuse_ShadowRead1Byte - * efuse_ShadowRead2Byte - * efuse_ShadowRead4Byte - * - * Read from efuse init map by one/two/four bytes - */ -static void efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset, - u8 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; -} - -static void efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset, - u16 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; - *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8; -} - -static void efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset, - u32 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; - *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8; - *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16; - *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24; -} - -/* Transfer current EFUSE content to shadow init and modify map. */ -void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if (pEEPROM->bautoload_fail_flag == true) - memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen); - else - Efuse_ReadAllMap(pAdapter, efuseType, - pEEPROM->efuse_eeprom_data); -} - -/* Read from efuse init map */ -void EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, u8 Type, - u16 Offset, u32 *Value) -{ - if (Type == 1) - efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value); - else if (Type == 2) - efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value); - else if (Type == 4) - efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value); -} diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c deleted file mode 100644 index 07a6490a83d6..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c +++ /dev/null @@ -1,855 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _IEEE80211_C - -#include -#include -#include -#include -#include -#include - -u8 RTW_WPA_OUI23A_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; -u16 RTW_WPA_VERSION23A = 1; -u8 WPA_AUTH_KEY_MGMT_NONE23A[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_NONE23A[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x50, 0xf2, 3 }; -u8 WPA_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x50, 0xf2, 4 }; -u8 WPA_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x50, 0xf2, 5 }; - -u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_NONE23A[] = { 0x00, 0x0f, 0xac, 0 }; -u8 RSN_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x0f, 0xac, 3 }; -u8 RSN_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x0f, 0xac, 4 }; -u8 RSN_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x0f, 0xac, 5 }; -/* */ -/* for adhoc-master to generate ie and provide supported-rate to fw */ -/* */ - -static u8 WIFI_CCKRATES[] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 WIFI_OFDMRATES[] = { - IEEE80211_OFDM_RATE_6MB, - IEEE80211_OFDM_RATE_9MB, - IEEE80211_OFDM_RATE_12MB, - IEEE80211_OFDM_RATE_18MB, - IEEE80211_OFDM_RATE_24MB, - IEEE80211_OFDM_RATE_36MB, - IEEE80211_OFDM_RATE_48MB, - IEEE80211_OFDM_RATE_54MB -}; - -int rtw_get_bit_value_from_ieee_value23a(u8 val) -{ - unsigned char dot11_rate_table[]= - {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; - - int i = 0; - - while (dot11_rate_table[i] != 0) { - if (dot11_rate_table[i] == val) - return BIT(i); - i++; - } - return 0; -} - -static bool rtw_is_cckrates_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i]) { - if ((rate[i] & 0x7f) == 2 || (rate[i] & 0x7f) == 4 || - (rate[i] & 0x7f) == 11 || (rate[i] & 0x7f) == 22) - return true; - i++; - } - - return false; -} - -static bool rtw_is_cckratesonly_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i]) { - if ((rate[i] & 0x7f) != 2 && (rate[i] & 0x7f) != 4 && - (rate[i] & 0x7f) != 11 && (rate[i] & 0x7f) != 22) - return false; - - i++; - } - - return true; -} - -int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel) -{ - if (channel > 14) { - if (rtw_is_cckrates_included(rate)) - return WIRELESS_INVALID; - else - return WIRELESS_11A; - } else { /* could be pure B, pure G, or B/G */ - if (rtw_is_cckratesonly_included(rate)) - return WIRELESS_11B; - else if (rtw_is_cckrates_included(rate)) - return WIRELESS_11BG; - else - return WIRELESS_11G; - } -} - -/* rtw_set_ie23a will update frame length */ -u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen) -{ - - *pbuf = (u8)index; - - *(pbuf + 1) = (u8)len; - - if (len > 0) - memcpy((void *)(pbuf + 2), (void *)source, len); - - *frlen = *frlen + (len + 2); - - return pbuf + len + 2; -} - -inline u8 *rtw_set_ie23a_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode, - u8 new_ch, u8 ch_switch_cnt) -{ - u8 ie_data[3]; - - ie_data[0] = ch_switch_mode; - ie_data[1] = new_ch; - ie_data[2] = ch_switch_cnt; - return rtw_set_ie23a(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); -} - -inline u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset) -{ - if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - return IEEE80211_HT_PARAM_CHA_SEC_BELOW; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - return IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - - return IEEE80211_HT_PARAM_CHA_SEC_NONE; -} - -inline u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len, - u8 secondary_ch_offset) -{ - return rtw_set_ie23a(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, - 1, &secondary_ch_offset, buf_len); -} - -/*---------------------------------------------------------------------------- -index: the information element id index, limit is the limit for search ------------------------------------------------------------------------------*/ -u8 *rtw_get_ie23a(u8 *pbuf, int index, int *len, int limit) -{ - int tmp, i; - u8 *p; - - if (limit < 1) { - - return NULL; - } - - p = pbuf; - i = 0; - *len = 0; - while (1) { - if (*p == index) { - *len = *(p + 1); - return p; - } else { - tmp = *(p + 1); - p += (tmp + 2); - i += (tmp + 2); - } - if (i >= limit) - break; - } - - return NULL; -} - -/** - * rtw_get_ie23a_ex - Search specific IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * @ie: If not NULL and the specific IE is found, the IE will be copied - * to the buf starting from the specific IE - * @ielen: If not NULL and the specific IE is found, will set to the length - * of the entire IE - * - * Returns: The address of the specific IE found, or NULL - */ -u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, - u8 *ie, uint *ielen) -{ - uint cnt; - u8 *target_ie = NULL; - - if (ielen) - *ielen = 0; - - if (!in_ie || in_len <= 0) - return target_ie; - - cnt = 0; - - while (cnt < in_len) { - if (eid == in_ie[cnt] && - (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) { - target_ie = &in_ie[cnt]; - - if (ie) - memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2); - - if (ielen) - *ielen = in_ie[cnt+1]+2; - break; - } else { - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - } - - return target_ie; -} - -/** - * rtw_ies_remove_ie23a - Find matching IEs and remove - * @ies: Address of IEs to search - * @ies_len: Pointer of length of ies, will update to new length - * @offset: The offset to start search - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * - * Returns: _SUCCESS: ies is updated, _FAIL: not updated - */ -int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid, - u8 *oui, u8 oui_len) -{ - int ret = _FAIL; - u8 *target_ie; - u32 target_ielen; - u8 *start; - uint search_len; - - if (!ies || !ies_len || *ies_len <= offset) - goto exit; - - start = ies + offset; - search_len = *ies_len - offset; - - while (1) { - target_ie = rtw_get_ie23a_ex(start, search_len, eid, oui, oui_len, - NULL, &target_ielen); - if (target_ie && target_ielen) { - u8 buf[MAX_IE_SZ] = {0}; - u8 *remain_ies = target_ie + target_ielen; - uint remain_len = search_len - (remain_ies - start); - - memcpy(buf, remain_ies, remain_len); - memcpy(target_ie, buf, remain_len); - *ies_len = *ies_len - target_ielen; - ret = _SUCCESS; - - start = target_ie; - search_len = remain_len; - } else { - break; - } - } -exit: - return ret; -} - -void rtw_set_supported_rate23a(u8 *SupportedRates, uint mode) -{ - - - memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); - - switch (mode) { - case WIRELESS_11B: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - break; - - case WIRELESS_11G: - case WIRELESS_11A: - case WIRELESS_11_5N: - case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */ - memcpy(SupportedRates, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); - break; - - case WIRELESS_11BG: - case WIRELESS_11G_24N: - case WIRELESS_11_24N: - case WIRELESS_11BG_24N: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); - break; - } - -} - -uint rtw_get_rateset_len23a(u8 *rateset) -{ - uint i = 0; - - while(1) { - if (rateset[i] == 0) - break; - - if (i > 12) - break; - - i++; - } - - return i; -} - -int rtw_generate_ie23a(struct registry_priv *pregistrypriv) -{ - u8 wireless_mode; - int sz = 0, rateLen; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *ie = pdev_network->IEs; - u16 cap; - - pdev_network->tsf = 0; - - cap = WLAN_CAPABILITY_IBSS; - - if (pregistrypriv->preamble == PREAMBLE_SHORT) - cap |= WLAN_CAPABILITY_SHORT_PREAMBLE; - - if (pdev_network->Privacy) - cap |= WLAN_CAPABILITY_PRIVACY; - - pdev_network->capability = cap; - - /* SSID */ - ie = rtw_set_ie23a(ie, WLAN_EID_SSID, pdev_network->Ssid.ssid_len, - pdev_network->Ssid.ssid, &sz); - - /* supported rates */ - if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { - if (pdev_network->DSConfig > 14) - wireless_mode = WIRELESS_11A_5N; - else - wireless_mode = WIRELESS_11BG_24N; - } else { - wireless_mode = pregistrypriv->wireless_mode; - } - - rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode) ; - - rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates); - - if (rateLen > 8) { - ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, 8, - pdev_network->SupportedRates, &sz); - /* ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ - } else { - ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, rateLen, - pdev_network->SupportedRates, &sz); - } - - /* DS parameter set */ - ie = rtw_set_ie23a(ie, WLAN_EID_DS_PARAMS, 1, - (u8 *)&pdev_network->DSConfig, &sz); - - /* IBSS Parameter Set */ - - ie = rtw_set_ie23a(ie, WLAN_EID_IBSS_PARAMS, 2, - (u8 *)&pdev_network->ATIMWindow, &sz); - - if (rateLen > 8) { - ie = rtw_set_ie23a(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), - (pdev_network->SupportedRates + 8), &sz); - } - - - - /* return _SUCCESS; */ - - return sz; -} - -static int rtw_get_wpa_cipher_suite(const u8 *s) -{ - if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, WPA_CIPHER_SUITE_WEP4023A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, WPA_CIPHER_SUITE_TKIP23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, WPA_CIPHER_SUITE_CCMP23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, WPA_CIPHER_SUITE_WEP10423A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - - return 0; -} - -static int rtw_get_wpa2_cipher_suite(const u8 *s) -{ - if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, RSN_CIPHER_SUITE_WEP4023A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, RSN_CIPHER_SUITE_TKIP23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, RSN_CIPHER_SUITE_CCMP23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, RSN_CIPHER_SUITE_WEP10423A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - - return 0; -} - -int rtw_parse_wpa_ie23a(const u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher, int *is_8021x) -{ - int i, ret = _SUCCESS; - int left, count; - const u8 *pos; - - if (wpa_ie_len <= 0) { - /* No WPA IE - fail silently */ - return _FAIL; - } - - if (wpa_ie[1] != (u8)(wpa_ie_len - 2)) - return _FAIL; - - pos = wpa_ie; - - pos += 8; - left = wpa_ie_len - 8; - - /* group_cipher */ - if (left >= WPA_SELECTOR_LEN) { - - *group_cipher = rtw_get_wpa_cipher_suite(pos); - - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } else if (left > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie length mismatch, %u too much\n", - __func__, left); - - return _FAIL; - } - - /* pairwise_cipher */ - if (left >= 2) { - /* count = le16_to_cpu(*(u16*)pos); */ - count = get_unaligned_le16(pos); - pos += 2; - left -= 2; - - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie count botch (pairwise), count %u left %u\n", - __func__, count, left); - return _FAIL; - } - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); - - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie too short (for key mgmt)\n", __func__); - return _FAIL; - } - - if (is_8021x) { - if (left >= 6) { - pos += 2; - if (!memcmp(pos, RTW_WPA_OUI23A_TYPE, 4)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s : there has 802.1x auth\n", - __func__); - *is_8021x = 1; - } - } - } - - return ret; -} - -int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher, - int *pairwise_cipher, int *is_8021x) -{ - int i, ret = _SUCCESS; - int left, count; - const u8 *pos; - u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01}; - - if (rsn_ie_len <= 0) { - /* No RSN IE - fail silently */ - return _FAIL; - } - - if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie+1) != (u8)(rsn_ie_len - 2)) { - return _FAIL; - } - - pos = rsn_ie; - pos += 4; - left = rsn_ie_len - 4; - - /* group_cipher */ - if (left >= RSN_SELECTOR_LEN) { - *group_cipher = rtw_get_wpa2_cipher_suite(pos); - - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } else if (left > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie length mismatch, %u too much\n", - __func__, left); - return _FAIL; - } - - /* pairwise_cipher */ - if (left >= 2) { - /* count = le16_to_cpu(*(u16*)pos); */ - count = get_unaligned_le16(pos); - pos += 2; - left -= 2; - - if (count == 0 || left < count * RSN_SELECTOR_LEN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie count botch (pairwise), count %u left %u\n", - __func__, count, left); - return _FAIL; - } - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos); - - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - } else if (left == 1) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie too short (for key mgmt)\n", __func__); - - return _FAIL; - } - - if (is_8021x) { - if (left >= 6) { - pos += 2; - if (!memcmp(pos, SUITE_1X, 4)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s (): there has 802.1x auth\n", - __func__); - *is_8021x = 1; - } - } - } - - return ret; -} - -/** - * rtw_get_wps_attr23a - Search a specific WPS attribute from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute - * will be copied to the buf starting from buf_attr - * @len_attr: If not NULL and the WPS attribute is found, will set to the - * length of the entire WPS attribute - * - * Returns: the address of the specific WPS attribute found, or NULL - */ -const u8 *rtw_get_wps_attr23a(const u8 *wps_ie, uint wps_ielen, - u16 target_attr_id, u8 *buf_attr, u32 *len_attr) -{ - const u8 *attr_ptr = NULL; - const u8 *target_attr_ptr = NULL; - u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04}; - - if (len_attr) - *len_attr = 0; - - if (wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC || - memcmp(wps_ie + 2, wps_oui, 4)) { - return attr_ptr; - } - - /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */ - attr_ptr = wps_ie + 6; /* goto first attr */ - - while (attr_ptr - wps_ie < wps_ielen) { - /* 4 = 2(Attribute ID) + 2(Length) */ - u16 attr_id = get_unaligned_be16(attr_ptr); - u16 attr_data_len = get_unaligned_be16(attr_ptr + 2); - u16 attr_len = attr_data_len + 4; - - /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */ - if (attr_id == target_attr_id) { - target_attr_ptr = attr_ptr; - - if (buf_attr) - memcpy(buf_attr, attr_ptr, attr_len); - - if (len_attr) - *len_attr = attr_len; - - break; - } else { - attr_ptr += attr_len; /* goto next */ - } - } - - return target_attr_ptr; -} - -/** - * rtw_get_wps_attr_content23a - Search a specific WPS attribute content - * from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_content: If not NULL and the WPS attribute is found, WPS attribute - * content will be copied to the buf starting from buf_content - * @len_content: If not NULL and the WPS attribute is found, will set to the - * length of the WPS attribute content - * - * Returns: the address of the specific WPS attribute content found, or NULL - */ -const u8 *rtw_get_wps_attr_content23a(const u8 *wps_ie, uint wps_ielen, - u16 target_attr_id, u8 *buf_content) -{ - const u8 *attr_ptr; - u32 attr_len; - - attr_ptr = rtw_get_wps_attr23a(wps_ie, wps_ielen, target_attr_id, - NULL, &attr_len); - - if (attr_ptr && attr_len) { - if (buf_content) - memcpy(buf_content, attr_ptr + 4, attr_len - 4); - - return attr_ptr + 4; - } - - return NULL; -} - -static int rtw_get_cipher_info(struct wlan_network *pnetwork) -{ - const u8 *pbuf; - int group_cipher = 0, pairwise_cipher = 0, is8021x = 0; - int ret = _FAIL; - int r, plen; - char *pie; - - pie = pnetwork->network.IEs; - plen = pnetwork->network.IELength; - - pbuf = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, pie, plen); - - if (pbuf && pbuf[1] > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_get_cipher_info: wpa_ielen: %d\n", pbuf[1]); - r = rtw_parse_wpa_ie23a(pbuf, pbuf[1] + 2, &group_cipher, - &pairwise_cipher, &is8021x); - if (r == _SUCCESS) { - pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; - pnetwork->BcnInfo.group_cipher = group_cipher; - pnetwork->BcnInfo.is_8021x = is8021x; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: pnetwork->pairwise_cipher: %d, is_8021x is %d\n", - __func__, pnetwork->BcnInfo.pairwise_cipher, - pnetwork->BcnInfo.is_8021x); - ret = _SUCCESS; - } - } else { - pbuf = cfg80211_find_ie(WLAN_EID_RSN, pie, plen); - - if (pbuf && pbuf[1] > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "get RSN IE\n"); - r = rtw_parse_wpa2_ie23a(pbuf, pbuf[1] + 2, - &group_cipher, &pairwise_cipher, - &is8021x); - if (r == _SUCCESS) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "get RSN IE OK!!!\n"); - pnetwork->BcnInfo.pairwise_cipher = - pairwise_cipher; - pnetwork->BcnInfo.group_cipher = group_cipher; - pnetwork->BcnInfo.is_8021x = is8021x; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: pnetwork->pairwise_cipher: %d,pnetwork->group_cipher is %d, is_8021x is %d\n", - __func__, - pnetwork->BcnInfo.pairwise_cipher, - pnetwork->BcnInfo.group_cipher, - pnetwork->BcnInfo.is_8021x); - ret = _SUCCESS; - } - } - } - - return ret; -} - -void rtw_get_bcn_info23a(struct wlan_network *pnetwork) -{ - u8 bencrypt = 0; - int pie_len; - u8 *pie; - const u8 *p; - - if (pnetwork->network.capability & WLAN_CAPABILITY_PRIVACY) { - bencrypt = 1; - pnetwork->network.Privacy = 1; - } else - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: ssid =%s\n", __func__, pnetwork->network.Ssid.ssid); - - pie = pnetwork->network.IEs; - pie_len = pnetwork->network.IELength; - - p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len); - if (p && p[1]) { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2; - } else if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pie, pie_len)) { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA; - } else { - if (bencrypt) - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP; - } - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: pnetwork->encryp_protocol is %x\n", __func__, - pnetwork->BcnInfo.encryp_protocol); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: pnetwork->encryp_protocol is %x\n", __func__, - pnetwork->BcnInfo.encryp_protocol); - rtw_get_cipher_info(pnetwork); - - /* get bwmode and ch_offset */ -} - -/* show MCS rate, unit: 100Kbps */ -u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, - struct ieee80211_mcs_info *mcs) -{ - u16 max_rate = 0; - - if (rf_type == RF_1T1R) { - if (mcs->rx_mask[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350): - ((short_GI_20)?722:650); - else if (mcs->rx_mask[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215): - ((short_GI_20)?650:585); - else if (mcs->rx_mask[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080): - ((short_GI_20)?578:520); - else if (mcs->rx_mask[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810): - ((short_GI_20)?433:390); - else if (mcs->rx_mask[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540): - ((short_GI_20)?289:260); - else if (mcs->rx_mask[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?450:405): - ((short_GI_20)?217:195); - else if (mcs->rx_mask[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270): - ((short_GI_20)?144:130); - else if (mcs->rx_mask[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?150:135): - ((short_GI_20)?72:65); - } else { - if (mcs->rx_mask[1]) { - if (mcs->rx_mask[1] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300); - else if (mcs->rx_mask[1] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170); - else if (mcs->rx_mask[1] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040); - else if (mcs->rx_mask[1] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780); - else if (mcs->rx_mask[1] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520); - else if (mcs->rx_mask[1] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390); - else if (mcs->rx_mask[1] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260); - else if (mcs->rx_mask[1] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130); - } else { - if (mcs->rx_mask[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650); - else if (mcs->rx_mask[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585); - else if (mcs->rx_mask[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520); - else if (mcs->rx_mask[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390); - else if (mcs->rx_mask[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260); - else if (mcs->rx_mask[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195); - else if (mcs->rx_mask[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130); - else if (mcs->rx_mask[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65); - } - } - return max_rate; -} diff --git a/drivers/staging/rtl8723au/core/rtw_mlme.c b/drivers/staging/rtl8723au/core/rtw_mlme.c deleted file mode 100644 index a786fc4bdb53..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_mlme.c +++ /dev/null @@ -1,2314 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_MLME_C_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct wlan_network * -rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv); -static int rtw_do_join(struct rtw_adapter *padapter); - -static void rtw_init_mlme_timer(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler, - (unsigned long)padapter); - - setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler23a, - (unsigned long)padapter); - - setup_timer(&pmlmepriv->dynamic_chk_timer, - rtw_dynamic_check_timer_handler, (unsigned long)padapter); - - setup_timer(&pmlmepriv->set_scan_deny_timer, - rtw_set_scan_deny_timer_hdl, (unsigned long)padapter); -} - -int rtw_init_mlme_priv23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pmlmepriv->nic_hdl = padapter; - - pmlmepriv->fw_state = 0; - pmlmepriv->cur_network.network.ifmode = NL80211_IFTYPE_UNSPECIFIED; - /* 1: active, 0: pasive. Maybe someday we should rename this - varable to "active_mode" (Jeff) */ - pmlmepriv->scan_mode = SCAN_ACTIVE; - - spin_lock_init(&pmlmepriv->lock); - _rtw_init_queue23a(&pmlmepriv->scanned_queue); - - memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct cfg80211_ssid)); - - rtw_clear_scan_deny(padapter); - - rtw_init_mlme_timer(padapter); - return _SUCCESS; -} - -#ifdef CONFIG_8723AU_AP_MODE -static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen) -{ - if (*ppie) { - kfree(*ppie); - *plen = 0; - *ppie = NULL; - } -} -#endif - -void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) -{ -#ifdef CONFIG_8723AU_AP_MODE - kfree(pmlmepriv->assoc_req); - kfree(pmlmepriv->assoc_rsp); - rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, - &pmlmepriv->wps_probe_req_ie_len); -#endif -} - -void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv) -{ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_free_mlme_priv23a\n"); - - rtw23a_free_mlme_priv_ie_data(pmlmepriv); -} - -struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp) -{ - struct wlan_network *pnetwork; - - pnetwork = kzalloc(sizeof(struct wlan_network), gfp); - if (pnetwork) { - INIT_LIST_HEAD(&pnetwork->list); - pnetwork->network_type = 0; - pnetwork->fixed = false; - pnetwork->last_scanned = jiffies; - pnetwork->join_res = 0; - } - - return pnetwork; -} - -static void _rtw_free_network23a(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - if (!pnetwork) - return; - - if (pnetwork->fixed == true) - return; - - list_del_init(&pnetwork->list); - - kfree(pnetwork); -} - -/* - return the wlan_network with the matching addr - - Shall be called under atomic context... to avoid possible racing condition... -*/ -struct wlan_network * -rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr) -{ - struct list_head *phead, *plist; - struct wlan_network *pnetwork = NULL; - - if (is_zero_ether_addr(addr)) { - pnetwork = NULL; - goto exit; - } - - /* spin_lock_bh(&scanned_queue->lock); */ - - phead = get_list_head(scanned_queue); - plist = phead->next; - - while (plist != phead) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (ether_addr_equal(addr, pnetwork->network.MacAddress)) - break; - - plist = plist->next; - } - - if (plist == phead) - pnetwork = NULL; - - /* spin_unlock_bh(&scanned_queue->lock); */ - -exit: - - return pnetwork; -} - -void rtw_free_network_queue23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct wlan_network *pnetwork, *ptmp; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue; - - spin_lock_bh(&scanned_queue->lock); - phead = get_list_head(scanned_queue); - list_for_each_entry_safe(pnetwork, ptmp, phead, list) - _rtw_free_network23a(pmlmepriv, pnetwork); - spin_unlock_bh(&scanned_queue->lock); -} - -int rtw_if_up23a(struct rtw_adapter *padapter) -{ - int res; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved || - !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_if_up23a:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved); - res = false; - } else - res = true; - - return res; -} - -void rtw_generate_random_ibss23a(u8 *pibss) -{ - unsigned long curtime = jiffies; - - pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */ - pibss[1] = 0x11; - pibss[2] = 0x87; - pibss[3] = curtime & 0xff;/* p[0]; */ - pibss[4] = (curtime >> 8) & 0xff;/* p[1]; */ - pibss[5] = (curtime >> 16) & 0xff;/* p[2]; */ -} - -void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming) -{ - if (to_roaming == 0) - adapter->mlmepriv.to_join = false; - adapter->mlmepriv.to_roaming = to_roaming; -} - -static void _rtw_roaming(struct rtw_adapter *padapter, - struct wlan_network *tgt_network) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *pnetwork; - int do_join_r; - - if (tgt_network) - pnetwork = tgt_network; - else - pnetwork = &pmlmepriv->cur_network; - - if (padapter->mlmepriv.to_roaming > 0) { - DBG_8723A("roaming from %s(%pM), length:%d\n", - pnetwork->network.Ssid.ssid, - pnetwork->network.MacAddress, - pnetwork->network.Ssid.ssid_len); - memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid, - sizeof(struct cfg80211_ssid)); - - pmlmepriv->assoc_by_bssid = false; - - while (1) { - do_join_r = rtw_do_join(padapter); - if (do_join_r == _SUCCESS) - break; - else { - DBG_8723A("roaming do_join return %d\n", - do_join_r); - pmlmepriv->to_roaming--; - - if (padapter->mlmepriv.to_roaming > 0) - continue; - else { - DBG_8723A("%s(%d) -to roaming fail, " - "indicate_disconnect\n", - __func__, __LINE__); - rtw_indicate_disconnect23a(padapter); - break; - } - } - } - } -} - -void rtw23a_roaming(struct rtw_adapter *padapter, - struct wlan_network *tgt_network) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - spin_lock_bh(&pmlmepriv->lock); - _rtw_roaming(padapter, tgt_network); - spin_unlock_bh(&pmlmepriv->lock); -} - -static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - _rtw_free_network23a(pmlmepriv, pnetwork); -} - -bool rtw_is_same_ibss23a(struct rtw_adapter *adapter, - struct wlan_network *pnetwork) -{ - int ret; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - if (psecuritypriv->dot11PrivacyAlgrthm != 0 && - pnetwork->network.Privacy == 0) - ret = false; - else if (psecuritypriv->dot11PrivacyAlgrthm == 0 && - pnetwork->network.Privacy == 1) - ret = false; - else - ret = true; - - return ret; -} - -inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b); -inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b) -{ - return (a->Ssid.ssid_len == b->Ssid.ssid_len) && - !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len); -} - -int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst) -{ - u16 s_cap, d_cap; - - s_cap = src->capability; - d_cap = dst->capability; - - return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) && - /* (src->DSConfig == dst->DSConfig) && */ - ether_addr_equal(src->MacAddress, dst->MacAddress) && - !memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len) && - (s_cap & WLAN_CAPABILITY_IBSS) == - (d_cap & WLAN_CAPABILITY_IBSS) && - (s_cap & WLAN_CAPABILITY_ESS) == (d_cap & WLAN_CAPABILITY_ESS)); -} - -struct wlan_network * -rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue) -{ - struct list_head *phead; - struct wlan_network *pwlan; - struct wlan_network *oldest = NULL; - - phead = get_list_head(scanned_queue); - list_for_each_entry(pwlan, phead, list) { - if (pwlan->fixed != true) { - if (!oldest || time_after(oldest->last_scanned, - pwlan->last_scanned)) - oldest = pwlan; - } - } - - return oldest; -} - -void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, - struct rtw_adapter *padapter, bool update_ie) -{ - u8 ss_ori = dst->SignalStrength; - u8 sq_ori = dst->SignalQuality; - long rssi_ori = dst->Rssi; - - u8 ss_smp = src->SignalStrength; - u8 sq_smp = src->SignalQuality; - long rssi_smp = src->Rssi; - - u8 ss_final; - u8 sq_final; - long rssi_final; - - DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, " - "ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n", - __func__, src->Ssid.ssid, src->MacAddress, - src->DSConfig, ss_ori, sq_ori, rssi_ori, - ss_smp, sq_smp, rssi_smp - ); - - /* The rule below is 1/5 for sample value, 4/5 for history value */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && - is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) { - /* Take the recvpriv's value for the connected AP*/ - ss_final = padapter->recvpriv.signal_strength; - sq_final = padapter->recvpriv.signal_qual; - /* the rssi value here is undecorated, and will be - used for antenna diversity */ - if (sq_smp != 101) /* from the right channel */ - rssi_final = (src->Rssi+dst->Rssi*4)/5; - else - rssi_final = rssi_ori; - } else { - if (sq_smp != 101) { /* from the right channel */ - ss_final = ((u32)src->SignalStrength + - (u32)dst->SignalStrength * 4) / 5; - sq_final = ((u32)src->SignalQuality + - (u32)dst->SignalQuality * 4) / 5; - rssi_final = src->Rssi+dst->Rssi * 4 / 5; - } else { - /* bss info not receiving from the right channel, use - the original RX signal infos */ - ss_final = dst->SignalStrength; - sq_final = dst->SignalQuality; - rssi_final = dst->Rssi; - } - - } - - if (update_ie) - memcpy(dst, src, get_wlan_bssid_ex_sz(src)); - - dst->SignalStrength = ss_final; - dst->SignalQuality = sq_final; - dst->Rssi = rssi_final; - - DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, " - "RawRSSI:%ld\n", __func__, dst->Ssid.ssid, dst->MacAddress, - dst->SignalStrength, dst->SignalQuality, dst->Rssi); -} - -static void update_current_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)) { - update_network23a(&pmlmepriv->cur_network.network, - pnetwork, adapter, true); - - rtw_update_protection23a(adapter, - pmlmepriv->cur_network.network.IEs, - pmlmepriv->cur_network.network.IELength); - } -} - -/* - -Caller must hold pmlmepriv->lock first. - -*/ -static void rtw_update_scanned_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *target) -{ - struct list_head *plist, *phead; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *pnetwork = NULL; - struct wlan_network *oldest = NULL; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - u32 bssid_ex_sz; - int found = 0; - - spin_lock_bh(&queue->lock); - phead = get_list_head(queue); - list_for_each(plist, phead) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (is_same_network23a(&pnetwork->network, target)) { - found = 1; - break; - } - if (!oldest || time_after(oldest->last_scanned, - pnetwork->last_scanned)) - oldest = pnetwork; - } - - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ - if (!found) { - pnetwork = rtw_alloc_network(pmlmepriv, GFP_ATOMIC); - if (!pnetwork) { - if (!oldest) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "something wrong here\n"); - goto exit; - } - pnetwork = oldest; - } else - list_add_tail(&pnetwork->list, &queue->queue); - - bssid_ex_sz = get_wlan_bssid_ex_sz(target); - target->Length = bssid_ex_sz; - memcpy(&pnetwork->network, target, bssid_ex_sz); - - /* variable initialize */ - pnetwork->fixed = false; - pnetwork->last_scanned = jiffies; - - pnetwork->network_type = 0; - pnetwork->join_res = 0; - - /* bss info not receiving from the right channel */ - if (pnetwork->network.SignalQuality == 101) - pnetwork->network.SignalQuality = 0; - } else { - /* - * we have an entry and we are going to update it. But - * this entry may be already expired. In this case we - * do the same as we found a new net and call the - * new_net handler - */ - bool update_ie = true; - - pnetwork->last_scanned = jiffies; - - /* target.reserved == 1, means that scanned network is - * a bcn frame. */ - if (pnetwork->network.IELength > target->IELength && - target->reserved == 1) - update_ie = false; - - update_network23a(&pnetwork->network, target, adapter, - update_ie); - } - -exit: - spin_unlock_bh(&queue->lock); -} - -static void rtw_add_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - update_current_network(adapter, pnetwork); - rtw_update_scanned_network(adapter, pnetwork); -} - -/* select the desired network based on the capability of the (i)bss. */ -/* check items: (1) security */ -/* (2) network_type */ -/* (3) WMM */ -/* (4) HT */ -/* (5) others */ -static int rtw_is_desired_network(struct rtw_adapter *adapter, - struct wlan_network *pnetwork) -{ - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u32 desired_encmode; - u32 privacy; - int bselected = true; - - desired_encmode = psecuritypriv->ndisencryptstatus; - privacy = pnetwork->network.Privacy; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { - if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pnetwork->network.IEs, - pnetwork->network.IELength)) - return true; - else - return false; - } - if (adapter->registrypriv.wifi_spec == 1) { - /* for correct flow of 8021X to do.... */ - if (desired_encmode == Ndis802_11EncryptionDisabled && - privacy != 0) - bselected = false; - } - - if (desired_encmode != Ndis802_11EncryptionDisabled && privacy == 0) { - DBG_8723A("desired_encmode: %d, privacy: %d\n", - desired_encmode, privacy); - bselected = false; - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (pnetwork->network.ifmode != - pmlmepriv->cur_network.network.ifmode) - bselected = false; - } - - return bselected; -} - -void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - u32 len; - struct wlan_bssid_ex *pnetwork; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct survey_event *survey = (struct survey_event *)pbuf; - - pnetwork = survey->bss; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid); - - len = get_wlan_bssid_ex_sz(pnetwork); - if (len > (sizeof(struct wlan_bssid_ex))) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "****rtw_survey_event_cb23a: return a wrong bss ***\n"); - return; - } - - spin_lock_bh(&pmlmepriv->lock); - - /* update IBSS_network 's timestamp */ - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress, - pnetwork->MacAddress)) { - struct wlan_network *ibss_wlan; - - pmlmepriv->cur_network.network.beacon_interval = - pnetwork->beacon_interval; - pmlmepriv->cur_network.network.capability = - pnetwork->capability; - pmlmepriv->cur_network.network.tsf = pnetwork->tsf; - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - ibss_wlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, - pnetwork->MacAddress); - if (ibss_wlan) { - pmlmepriv->cur_network.network.beacon_interval = - ibss_wlan->network.beacon_interval; - pmlmepriv->cur_network.network.capability = - ibss_wlan->network.capability; - pmlmepriv->cur_network.network.tsf = - ibss_wlan->network.tsf; - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto exit; - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - } - } - - /* lock pmlmepriv->lock when you accessing network_q */ - if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - if (pnetwork->Ssid.ssid[0] == 0) - pnetwork->Ssid.ssid_len = 0; - - rtw_add_network(adapter, pnetwork); - } - -exit: - - spin_unlock_bh(&pmlmepriv->lock); - - kfree(survey->bss); - survey->bss = NULL; -} - -void -rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - int ret; - - spin_lock_bh(&pmlmepriv->lock); - - if (pmlmepriv->wps_probe_req_ie) { - pmlmepriv->wps_probe_req_ie_len = 0; - kfree(pmlmepriv->wps_probe_req_ie); - pmlmepriv->wps_probe_req_ie = NULL; - } - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_surveydone_event_callback23a: fw_state:%x\n", - get_fwstate(pmlmepriv)); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - del_timer_sync(&pmlmepriv->scan_to_timer); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "nic status =%x, survey done event comes too late!\n", - get_fwstate(pmlmepriv)); - } - - rtw_set_signal_stat_timer(&adapter->recvpriv); - - if (pmlmepriv->to_join == true) { - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - ret = rtw_select_and_join_from_scanned_queue23a( - pmlmepriv); - if (ret != _SUCCESS) - rtw_do_join_adhoc(adapter); - } else { - pmlmepriv->to_join = false; - ret = rtw_select_and_join_from_scanned_queue23a( - pmlmepriv); - if (ret != _SUCCESS) { - DBG_8723A("try_to_join, but select scanning " - "queue fail, to_roaming:%d\n", - adapter->mlmepriv.to_roaming); - if (adapter->mlmepriv.to_roaming) { - if (--pmlmepriv->to_roaming == 0 || - rtw_sitesurvey_cmd23a( - adapter, - &pmlmepriv->assoc_ssid, 1, - NULL, 0) != _SUCCESS) { - rtw_set_roaming(adapter, 0); - rtw_free_assoc_resources23a( - adapter, 1); - rtw_indicate_disconnect23a( - adapter); - } else - pmlmepriv->to_join = true; - } - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - } - } - - spin_unlock_bh(&pmlmepriv->lock); - - rtw_os_xmit_schedule23a(adapter); - - if (pmlmeext->sitesurvey_res.bss_cnt == 0) - rtw_sreset_reset(adapter); - - rtw_cfg80211_surveydone_event_callback(adapter); -} - -static void free_scanqueue(struct mlme_priv *pmlmepriv) -{ - struct wlan_network *pnetwork, *ptemp; - struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue; - struct list_head *phead; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, "+free_scanqueue\n"); - spin_lock_bh(&scan_queue->lock); - phead = get_list_head(scan_queue); - list_for_each_entry_safe(pnetwork, ptemp, phead, list) { - pnetwork->fixed = false; - _rtw_free_network23a(pmlmepriv, pnetwork); - } - spin_unlock_bh(&scan_queue->lock); -} - -/* - *rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock - */ -void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, - int lock_scanned_queue) -{ - struct wlan_network *pwlan; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct sta_info *psta; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "+rtw_free_assoc_resources23a\n"); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "tgt_network->network.MacAddress=%pM ssid=%s\n", - tgt_network->network.MacAddress, - tgt_network->network.Ssid.ssid); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) { - psta = rtw_get_stainfo23a(&adapter->stapriv, - tgt_network->network.MacAddress); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) { - rtw_free_all_stainfo23a(adapter); - - psta = rtw_get_bcmc_stainfo23a(adapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - rtw_init_bcmc_stainfo23a(adapter); - } - - if (lock_scanned_queue) - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) - pwlan->fixed = false; - else - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_free_assoc_resources23a : pwlan== NULL\n"); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && - adapter->stapriv.asoc_sta_count == 1) - rtw_free_network_nolock(pmlmepriv, pwlan); - - if (lock_scanned_queue) - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - pmlmepriv->key_mask = 0; -} - -/* -*rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock -*/ -void rtw_indicate_connect23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "+rtw_indicate_connect23a\n"); - - pmlmepriv->to_join = false; - - if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - set_fwstate(pmlmepriv, _FW_LINKED); - - rtw_cfg80211_indicate_connect(padapter); - - netif_carrier_on(padapter->pnetdev); - - if (padapter->pid[2] != 0) - kill_pid(find_vpid(padapter->pid[2]), SIGALRM, 1); - } - - rtw_set_roaming(padapter, 0); - - rtw_set_scan_deny(padapter, 3000); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "-rtw_indicate_connect23a: fw_state=0x%08x\n", - get_fwstate(pmlmepriv)); -} - -/* - *rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock - */ -void rtw_indicate_disconnect23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "+rtw_indicate_disconnect23a\n"); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS); - - /* DBG_8723A("clear wps when %s\n", __func__); */ - - if (padapter->mlmepriv.to_roaming > 0) - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) || - padapter->mlmepriv.to_roaming <= 0) { - rtw_os_indicate_disconnect23a(padapter); - - /* set ips_deny_time to avoid enter IPS before LPS leave */ - padapter->pwrctrlpriv.ips_deny_time = - jiffies + msecs_to_jiffies(3000); - - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - rtw_clear_scan_deny(padapter); - } - - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1); -} - -void rtw_scan_abort23a(struct rtw_adapter *adapter) -{ - unsigned long start; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - - start = jiffies; - pmlmeext->scan_abort = true; - while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) && - jiffies_to_msecs(jiffies - start) <= 200) { - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) - break; - - DBG_8723A("%s(%s): fw_state = _FW_UNDER_SURVEY!\n", - __func__, adapter->pnetdev->name); - msleep(20); - } - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved) - DBG_8723A("%s(%s): waiting for scan_abort time out!\n", - __func__, adapter->pnetdev->name); - rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), - true); - } - pmlmeext->scan_abort = false; -} - -static struct sta_info * -rtw_joinbss_update_stainfo(struct rtw_adapter *padapter, - struct wlan_network *pnetwork) -{ - int i; - struct sta_info *bmc_sta, *psta; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress); - if (!psta) - psta = rtw_alloc_stainfo23a(pstapriv, - pnetwork->network.MacAddress, - GFP_ATOMIC); - - if (psta) { /* update ptarget_sta */ - DBG_8723A("%s\n", __func__); - - psta->aid = pnetwork->join_res; - psta->mac_id = 0; - - /* sta mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - /* security related */ - if (padapter->securitypriv.dot11AuthAlgrthm == - dot11AuthAlgrthm_8021X) { - padapter->securitypriv.binstallGrpkey = 0; - padapter->securitypriv.busetkipkey = 0; - - psta->ieee8021x_blocked = true; - psta->dot118021XPrivacy = - padapter->securitypriv.dot11PrivacyAlgrthm; - - memset(&psta->dot118021x_UncstKey, 0, - sizeof (union Keytype)); - - memset(&psta->dot11tkiprxmickey, 0, - sizeof (union Keytype)); - memset(&psta->dot11tkiptxmickey, 0, - sizeof (union Keytype)); - - memset(&psta->dot11txpn, 0, sizeof (union pn48)); - memset(&psta->dot11rxpn, 0, sizeof (union pn48)); - } - - /* Commented by Albert 2012/07/21 */ - /* When doing the WPS, the wps_ie_len won't equal to 0 */ - /* And the Wi-Fi driver shouldn't allow the data packet - to be transmitted. */ - if (padapter->securitypriv.wps_ie_len != 0) { - psta->ieee8021x_blocked = true; - padapter->securitypriv.wps_ie_len = 0; - } - - /* for A-MPDU Rx reordering buffer control for bmc_sta & - * sta_info */ - /* if A-MPDU Rx is enabled, resetting - rx_ordering_ctrl wstart_b(indicate_seq) to default - value = 0xffff */ - /* todo: check if AP can send A-MPDU packets */ - for (i = 0; i < 16 ; i++) { - /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */ - preorder_ctrl = &psta->recvreorder_ctrl[i]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */ - preorder_ctrl->wsize_b = 64; - } - - bmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (bmc_sta) { - for (i = 0; i < 16 ; i++) { - preorder_ctrl = &bmc_sta->recvreorder_ctrl[i]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* max_ampdu_sz; ex. 32(kbytes) -> - wsize_b = 32 */ - preorder_ctrl->wsize_b = 64; - } - } - - /* misc. */ - update_sta_info23a(padapter, psta); - - } - - return psta; -} - -/* pnetwork : returns from rtw23a_joinbss_event_cb */ -/* ptarget_wlan: found from scanned_queue */ -static void -rtw_joinbss_update_network23a(struct rtw_adapter *padapter, - struct wlan_network *ptarget_wlan, - struct wlan_network *pnetwork) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - - DBG_8723A("%s\n", __func__); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "fw_state:%x, BSSID:%pM\n", - get_fwstate(pmlmepriv), - pnetwork->network.MacAddress); - - /* why not use ptarget_wlan?? */ - memcpy(&cur_network->network, &pnetwork->network, - pnetwork->network.Length); - /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */ - cur_network->network.IELength = ptarget_wlan->network.IELength; - memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], - MAX_IE_SZ); - - cur_network->network.capability = ptarget_wlan->network.capability; - cur_network->network.beacon_interval = - ptarget_wlan->network.beacon_interval; - cur_network->network.tsf = ptarget_wlan->network.tsf; - - rtw_set_signal_stat_timer(&padapter->recvpriv); - padapter->recvpriv.signal_strength = - ptarget_wlan->network.SignalStrength; - padapter->recvpriv.signal_qual = ptarget_wlan->network.SignalQuality; - /* - * the ptarget_wlan->network.Rssi is raw data, we use - * ptarget_wlan->network.SignalStrength instead (has scaled) - */ - DBG_8723A("%s signal_strength:%3u, signal_qual:%3u\n", - __func__, padapter->recvpriv.signal_strength, - padapter->recvpriv.signal_qual); - rtw_set_signal_stat_timer(&padapter->recvpriv); - - /* update fw_state will clr _FW_UNDER_LINKING here indirectly */ - switch (pnetwork->network.ifmode) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - if (pmlmepriv->fw_state & WIFI_UNDER_WPS) - pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS; - else - pmlmepriv->fw_state = WIFI_STATION_STATE; - break; - case NL80211_IFTYPE_ADHOC: - pmlmepriv->fw_state = WIFI_ADHOC_STATE; - break; - default: - pmlmepriv->fw_state = WIFI_NULL_STATE; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Invalid network_mode\n"); - break; - } - - rtw_update_protection23a(padapter, cur_network->network.IEs, - cur_network->network.IELength); - - rtw_update_ht_cap23a(padapter, cur_network->network.IEs, - cur_network->network.IELength); -} - -/* - * Notes: - * the function could be > passive_level (the same context as Rx tasklet) - * pnetwork : returns from rtw23a_joinbss_event_cb - * ptarget_wlan: found from scanned_queue - * if join_res > 0, for (fw_state==WIFI_STATION_STATE), - * we check if "ptarget_sta" & "ptarget_wlan" exist. - * if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), - * we only check if "ptarget_wlan" exist. - * if join_res > 0, update "cur_network->network" from "pnetwork->network" - * if (ptarget_wlan !=NULL). - */ - -void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf) -{ - struct sta_info *ptarget_sta, *pcur_sta; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *pnetwork = (struct wlan_network *)pbuf; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *pcur_wlan, *ptarget_wlan = NULL; - bool the_same_macaddr; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "joinbss event call back received with res=%d\n", - pnetwork->join_res); - - if (pmlmepriv->assoc_ssid.ssid_len == 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "@@@@@ joinbss event call back for Any SSid\n"); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n", - pmlmepriv->assoc_ssid.ssid); - } - - if (ether_addr_equal(pnetwork->network.MacAddress, - cur_network->network.MacAddress)) - the_same_macaddr = true; - else - the_same_macaddr = false; - - pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network); - if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "***joinbss_evt_callback return a wrong bss ***\n"); - return; - } - - spin_lock_bh(&pmlmepriv->lock); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw23a_joinbss_event_cb !! _enter_critical\n"); - - if (pnetwork->join_res > 0) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - /* s1. find ptarget_wlan */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (the_same_macaddr) { - ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - } else { - pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - if (pcur_wlan) - pcur_wlan->fixed = false; - - pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress); - if (pcur_sta) { - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, - pcur_sta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - } - - ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress); - if (check_fwstate(pmlmepriv, - WIFI_STATION_STATE)) { - if (ptarget_wlan) - ptarget_wlan->fixed = - true; - } - } - - } else { - ptarget_wlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, - pnetwork->network.MacAddress); - if (check_fwstate(pmlmepriv, - WIFI_STATION_STATE)) { - if (ptarget_wlan) - ptarget_wlan->fixed = true; - } - } - - /* s2. update cur_network */ - if (ptarget_wlan) - rtw_joinbss_update_network23a(adapter, - ptarget_wlan, - pnetwork); - else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Can't find ptarget_wlan when joinbss_event callback\n"); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - - /* s3. find ptarget_sta & update ptarget_sta after - update cur_network only for station mode */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ptarget_sta = rtw_joinbss_update_stainfo( - adapter, pnetwork); - if (!ptarget_sta) { - RT_TRACE(_module_rtl871x_mlme_c_, - _drv_err_, - "Can't update stainfo when joinbss_event callback\n"); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - } - - /* s4. indicate connect */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - rtw_indicate_connect23a(adapter); - else { - /* adhoc mode will rtw_indicate_connect23a - when rtw_stassoc_event_callback23a */ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "adhoc mode, fw_state:%x\n", - get_fwstate(pmlmepriv)); - } - - /* s5. Cancle assoc_timer */ - del_timer_sync(&pmlmepriv->assoc_timer); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "Cancle assoc_timer\n"); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw23a_joinbss_event_cb err: fw_state:%x\n", - get_fwstate(pmlmepriv)); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - } else if (pnetwork->join_res == -4) { - rtw_reset_securitypriv23a(adapter); - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - - /* rtw_free_assoc_resources23a(adapter, 1); */ - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n", - get_fwstate(pmlmepriv)); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - } else { - /* if join_res < 0 (join fails), then try again */ - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - -ignore_joinbss_callback: - - spin_unlock_bh(&pmlmepriv->lock); -} - -void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct wlan_network *pnetwork = (struct wlan_network *)pbuf; - - mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res); - - rtw_os_xmit_schedule23a(adapter); -} - -void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct sta_info *psta; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *ptarget_wlan; - - if (rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false) - return; - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr); - if (psta) { - /* bss_cap_update_on_sta_join23a(adapter, psta); */ - /* sta_info_update23a(adapter, psta); */ - ap_sta_info_defer_update23a(adapter, psta); - } - return; - } -#endif - /* for AD-HOC mode */ - psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr); - if (psta != NULL) { - /* the sta have been in sta_info_queue => do nothing */ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Error: rtw_stassoc_event_callback23a: sta has been in sta_hash_queue\n"); - /* between drv has received this event before and - fw have not yet to set key to CAM_ENTRY) */ - return; - } - - psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr, - GFP_KERNEL); - if (!psta) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Can't alloc sta_info when rtw_stassoc_event_callback23a\n"); - return; - } - - /* to do : init sta_info variable */ - psta->qos_option = 0; - psta->mac_id = (uint)pstassoc->cam_id; - /* psta->aid = (uint)pstassoc->cam_id; */ - DBG_8723A("%s\n", __func__); - /* for ad-hoc mode */ - rtl8723a_SetHalODMVar(adapter, HAL_ODM_STA_INFO, psta, true); - - if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->dot118021XPrivacy = - adapter->securitypriv.dot11PrivacyAlgrthm; - - psta->ieee8021x_blocked = false; - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (adapter->stapriv.asoc_sta_count == 2) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - ptarget_wlan = - rtw_find_network23a(&pmlmepriv->scanned_queue, - cur_network->network.MacAddress); - if (ptarget_wlan) - ptarget_wlan->fixed = true; - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - rtw_indicate_connect23a(adapter); - } - } - - spin_unlock_bh(&pmlmepriv->lock); - - mlmeext_sta_add_event_callback23a(adapter, psta); -} - -void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - int mac_id; - struct sta_info *psta; - struct wlan_network *pwlan; - struct wlan_bssid_ex *pdev_network; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stadel_event *pstadel = (struct stadel_event *)pbuf; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - - psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr); - if (psta) - mac_id = psta->mac_id; - else - mac_id = pstadel->mac_id; - - DBG_8723A("%s(mac_id=%d)=%pM\n", __func__, mac_id, pstadel->macaddr); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return; - - mlmeext_sta_del_event_callback23a(adapter); - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (adapter->mlmepriv.to_roaming > 0) { - /* this stadel_event is caused by roaming, - decrease to_roaming */ - pmlmepriv->to_roaming--; - } else if (adapter->mlmepriv.to_roaming == 0) - rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times); - if (*((u16 *)pstadel->rsvd) != WLAN_REASON_EXPIRATION_CHK) - rtw_set_roaming(adapter, 0); /* don't roam */ - - rtw_free_uc_swdec_pending_queue23a(adapter); - - rtw_free_assoc_resources23a(adapter, 1); - rtw_indicate_disconnect23a(adapter); - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - /* remove the network entry in scanned_queue */ - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - rtw_free_network_nolock(pmlmepriv, pwlan); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - _rtw_roaming(adapter, tgt_network); - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - if (adapter->stapriv.asoc_sta_count == 1) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - /* free old ibss network */ - /* pwlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, pstadel->macaddr); */ - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - rtw_free_network_nolock(pmlmepriv, pwlan); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* re-create ibss */ - pdev_network = &adapter->registrypriv.dev_network; - - memcpy(pdev_network, &tgt_network->network, - get_wlan_bssid_ex_sz(&tgt_network->network)); - - rtw_do_join_adhoc(adapter); - } - } - - spin_unlock_bh(&pmlmepriv->lock); -} - -/* -* rtw23a_join_to_handler - Timeout/failure handler for CMD JoinBss -* @adapter: pointer to _adapter structure -*/ -void rtw23a_join_to_handler (unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - int do_join_r; - - DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv)); - - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) - return; - - spin_lock_bh(&pmlmepriv->lock); - - if (adapter->mlmepriv.to_roaming > 0) { - /* join timeout caused by roaming */ - while (1) { - pmlmepriv->to_roaming--; - if (adapter->mlmepriv.to_roaming != 0) { - /* try another */ - DBG_8723A("%s try another roaming\n", __func__); - do_join_r = rtw_do_join(adapter); - if (do_join_r != _SUCCESS) { - DBG_8723A("%s roaming do_join return " - "%d\n", __func__ , do_join_r); - continue; - } - break; - } else { - DBG_8723A("%s We've try roaming but fail\n", - __func__); - rtw_indicate_disconnect23a(adapter); - break; - } - } - } else { - rtw_indicate_disconnect23a(adapter); - free_scanqueue(pmlmepriv);/* */ - - /* indicate disconnect for the case that join_timeout and - check_fwstate != FW_LINKED */ - rtw_cfg80211_indicate_disconnect(adapter); - } - - spin_unlock_bh(&pmlmepriv->lock); - -} - -/* -* rtw_scan_timeout_handler23a - Timeout/Failure handler for CMD SiteSurvey -* @data: pointer to _adapter structure -*/ -void rtw_scan_timeout_handler23a(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - DBG_8723A("%s(%s): fw_state =%x\n", __func__, adapter->pnetdev->name, - get_fwstate(pmlmepriv)); - - spin_lock_bh(&pmlmepriv->lock); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - spin_unlock_bh(&pmlmepriv->lock); - - rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true); -} - -void rtw_dynamic_check_timer_handler(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - - if (adapter->hw_init_completed == false) - goto out; - - if (adapter->bDriverStopped == true || - adapter->bSurpriseRemoved == true) - goto out; - - if (adapter->net_closed == true) - goto out; - - rtw_dynamic_chk_wk_cmd23a(adapter); - -out: - mod_timer(&adapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(2000)); -} - -inline bool rtw_is_scan_deny(struct rtw_adapter *adapter) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false; -} - -void rtw_clear_scan_deny(struct rtw_adapter *adapter) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - atomic_set(&mlmepriv->set_scan_deny, 0); -} - -void rtw_set_scan_deny_timer_hdl(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - - rtw_clear_scan_deny(adapter); -} - -void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - atomic_set(&mlmepriv->set_scan_deny, 1); - mod_timer(&mlmepriv->set_scan_deny_timer, - jiffies + msecs_to_jiffies(ms)); -} - -#if defined(IEEE80211_SCAN_RESULT_EXPIRE) -#define RTW_SCAN_RESULT_EXPIRE \ - ((IEEE80211_SCAN_RESULT_EXPIRE / (HZ*1000)) - 1000) /* 3000 -1000 */ -#else -#define RTW_SCAN_RESULT_EXPIRE 2000 -#endif - -/* -* Select a new join candidate from the original @param candidate and -* @param competitor -* @return true: candidate is updated -* @return false: candidate is not updated -*/ -static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv, - struct wlan_network **candidate, - struct wlan_network *competitor) -{ - int updated = false; - struct rtw_adapter *adapter; - - adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv); - - /* check bssid, if needed */ - if (pmlmepriv->assoc_by_bssid == true) { - if (!ether_addr_equal(competitor->network.MacAddress, - pmlmepriv->assoc_bssid)) - goto exit; - } - - /* check ssid, if needed */ - if (pmlmepriv->assoc_ssid.ssid_len) { - if (competitor->network.Ssid.ssid_len != - pmlmepriv->assoc_ssid.ssid_len || - memcmp(competitor->network.Ssid.ssid, - pmlmepriv->assoc_ssid.ssid, - pmlmepriv->assoc_ssid.ssid_len)) - goto exit; - } - - if (rtw_is_desired_network(adapter, competitor) == false) - goto exit; - - if (adapter->mlmepriv.to_roaming > 0) { - unsigned int passed; - - passed = jiffies_to_msecs(jiffies - competitor->last_scanned); - if (passed >= RTW_SCAN_RESULT_EXPIRE || - is_same_ess(&competitor->network, - &pmlmepriv->cur_network.network) == false) - goto exit; - } - - if (!*candidate || - (*candidate)->network.Rssinetwork.Rssi) { - *candidate = competitor; - updated = true; - } - - if (updated) { - DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] new candidate: %s(%pM) rssi:%d\n", - pmlmepriv->assoc_by_bssid, - pmlmepriv->assoc_ssid.ssid, - adapter->mlmepriv.to_roaming, - (*candidate)->network.Ssid.ssid, - (*candidate)->network.MacAddress, - (int)(*candidate)->network.Rssi); - } - -exit: - return updated; -} - -/* -Calling context: -The caller of the sub-routine will be in critical section... - -The caller must hold the following spinlock - -pmlmepriv->lock - -*/ - -static int rtw_do_join(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int ret; - - pmlmepriv->cur_network.join_res = -2; - - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - pmlmepriv->to_join = true; - - ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv); - if (ret == _SUCCESS) { - pmlmepriv->to_join = false; - } else { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - /* switch to ADHOC_MASTER */ - ret = rtw_do_join_adhoc(padapter); - if (ret != _SUCCESS) - goto exit; - } else { - /* can't associate ; reset under-linking */ - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - ret = _FAIL; - pmlmepriv->to_join = false; - } - } - -exit: - return ret; -} - -static struct wlan_network * -rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv) -{ - struct wlan_network *pnetwork, *ptmp, *candidate = NULL; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - struct list_head *phead; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - phead = get_list_head(queue); - list_for_each_entry_safe(pnetwork, ptmp, phead, list) - rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - return candidate; -} - - -int rtw_do_join_adhoc(struct rtw_adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_bssid_ex *pdev_network; - u8 *ibss; - int ret; - - pdev_network = &adapter->registrypriv.dev_network; - ibss = adapter->registrypriv.dev_network.MacAddress; - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "switching to adhoc master\n"); - - memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, - sizeof(struct cfg80211_ssid)); - - rtw_update_registrypriv_dev_network23a(adapter); - rtw_generate_random_ibss23a(ibss); - - pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; - - ret = rtw_createbss_cmd23a(adapter); - if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Error =>rtw_createbss_cmd23a status FAIL\n"); - } else { - pmlmepriv->to_join = false; - } - - return ret; -} - -int rtw_do_join_network(struct rtw_adapter *adapter, - struct wlan_network *candidate) -{ - int ret; - - /* check for situation of _FW_LINKED */ - if (check_fwstate(&adapter->mlmepriv, _FW_LINKED)) { - DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!\n", __func__); - - rtw_disassoc_cmd23a(adapter, 0, true); - rtw_indicate_disconnect23a(adapter); - rtw_free_assoc_resources23a(adapter, 0); - } - set_fwstate(&adapter->mlmepriv, _FW_UNDER_LINKING); - - ret = rtw_joinbss_cmd23a(adapter, candidate); - - if (ret == _SUCCESS) - mod_timer(&adapter->mlmepriv.assoc_timer, - jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT)); - - return ret; -} - -int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv) -{ - struct rtw_adapter *adapter; - struct wlan_network *candidate = NULL; - int ret; - - adapter = pmlmepriv->nic_hdl; - - candidate = rtw_select_candidate_from_queue(pmlmepriv); - if (!candidate) { - DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__); - ret = _FAIL; - goto exit; - } else { - DBG_8723A("%s: candidate: %s(%pM, ch:%u)\n", - __func__, - candidate->network.Ssid.ssid, - candidate->network.MacAddress, - candidate->network.DSConfig); - } - - ret = rtw_do_join_network(adapter, candidate); - -exit: - return ret; -} - -int rtw_set_auth23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv) -{ - struct cmd_obj *pcmd; - struct setauth_parm *psetauthparm; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - int res = _SUCCESS; - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; /* try again */ - goto exit; - } - - psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL); - if (!psetauthparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm; - - pcmd->cmdcode = _SetAuth_CMD_; - pcmd->parmbuf = (unsigned char *)psetauthparm; - pcmd->cmdsz = (sizeof(struct setauth_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "after enqueue set_auth_cmd, auth_mode=%x\n", - psecuritypriv->dot11AuthAlgrthm); - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -int rtw_set_key23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv, int keyid, u8 set_tx) -{ - u8 keylen; - struct cmd_obj *pcmd; - struct setkey_parm *psetkeyparm; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - int res = _SUCCESS; - - if (keyid >= 4) { - res = _FAIL; - goto exit; - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; /* try again */ - goto exit; - } - psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL); - if (!psetkeyparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { - psetkeyparm->algorithm = (unsigned char) - psecuritypriv->dot118021XGrpPrivacy; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy =%d\n", - psetkeyparm->algorithm); - } else { - psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm =%d\n", - psetkeyparm->algorithm); - } - psetkeyparm->keyid = keyid;/* 0~3 */ - psetkeyparm->set_tx = set_tx; - if (is_wep_enc(psetkeyparm->algorithm)) - pmlmepriv->key_mask |= BIT(psetkeyparm->keyid); - - DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n", - psetkeyparm->algorithm, psetkeyparm->keyid, - pmlmepriv->key_mask); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->keyid = (u8)keyid =%d\n", - psetkeyparm->algorithm, keyid); - - switch (psetkeyparm->algorithm) { - case WLAN_CIPHER_SUITE_WEP40: - keylen = 5; - memcpy(&psetkeyparm->key[0], - &psecuritypriv->wep_key[keyid].key, keylen); - break; - case WLAN_CIPHER_SUITE_WEP104: - keylen = 13; - memcpy(&psetkeyparm->key[0], - &psecuritypriv->wep_key[keyid].key, keylen); - break; - case WLAN_CIPHER_SUITE_TKIP: - keylen = 16; - memcpy(&psetkeyparm->key, - &psecuritypriv->dot118021XGrpKey[keyid], keylen); - psetkeyparm->grpkey = 1; - break; - case WLAN_CIPHER_SUITE_CCMP: - keylen = 16; - memcpy(&psetkeyparm->key, - &psecuritypriv->dot118021XGrpKey[keyid], keylen); - psetkeyparm->grpkey = 1; - break; - default: - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n", - psecuritypriv->dot11PrivacyAlgrthm); - res = _FAIL; - kfree(pcmd); - kfree(psetkeyparm); - goto exit; - } - - pcmd->cmdcode = _SetKey_CMD_; - pcmd->parmbuf = (u8 *)psetkeyparm; - pcmd->cmdsz = (sizeof(struct setkey_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - /* sema_init(&pcmd->cmd_sem, 0); */ - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -/* adjust IEs for rtw_joinbss_cmd23a in WMM */ -int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint initial_out_len) -{ - int ielength; - const u8 *p; - - ielength = initial_out_len; - - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - in_ie, in_len); - - if (p && p[1]) { - memcpy(out_ie + initial_out_len, p, 9); - - out_ie[initial_out_len + 1] = 7; - out_ie[initial_out_len + 6] = 0; - out_ie[initial_out_len + 8] = 0; - - ielength += 9; - } - - return ielength; -} - -/* */ -/* Ported from 8185: IsInPreAuthKeyList(). - (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */ -/* Added by Annie, 2006-05-07. */ -/* */ -/* Search by BSSID, */ -/* Return Value: */ -/* -1 :if there is no pre-auth key in the table */ -/* >= 0 :if there is pre-auth key, and return the entry id */ -/* */ -/* */ - -static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid) -{ - struct security_priv *psecuritypriv = &Adapter->securitypriv; - int i = 0; - - do { - if (psecuritypriv->PMKIDList[i].bUsed && - ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) { - break; - } else { - i++; - /* continue; */ - } - } while (i < NUM_PMKID_CACHE); - - if (i == NUM_PMKID_CACHE) - i = -1;/* Could not find. */ - else { - /* There is one Pre-Authentication Key for - the specific BSSID. */ - } - - return i; -} - -/* */ -/* Check the RSN IE length */ -/* If the RSN IE length <= 20, the RSN IE didn't include - the PMKID information */ -/* 0-11th element in the array are the fixed IE */ -/* 12th element in the array is the IE */ -/* 13th element in the array is the IE length */ -/* */ - -static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry, - u8 *ie, uint ie_len) -{ - struct security_priv *psecuritypriv = &Adapter->securitypriv; - - if (ie[1] <= 20) { - /* The RSN IE didn't include the PMK ID, - append the PMK information */ - ie[ie_len] = 1; - ie_len++; - ie[ie_len] = 0; /* PMKID count = 0x0100 */ - ie_len++; - memcpy(&ie[ie_len], - &psecuritypriv->PMKIDList[iEntry].PMKID, 16); - - ie_len += 16; - ie[1] += 18;/* PMKID length = 2+16 */ - } - return ie_len; -} - -int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len) -{ - u8 authmode; - uint ielength; - int iEntry; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct security_priv *psecuritypriv = &adapter->securitypriv; - uint ndisauthmode = psecuritypriv->ndisauthtype; - uint ndissecuritytype = psecuritypriv->ndisencryptstatus; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "+rtw_restruct_sec_ie23a: ndisauthmode=%d ndissecuritytype=%d\n", - ndisauthmode, ndissecuritytype); - - ielength = 0; - if (ndisauthmode == Ndis802_11AuthModeWPA || - ndisauthmode == Ndis802_11AuthModeWPAPSK) - authmode = WLAN_EID_VENDOR_SPECIFIC; - if (ndisauthmode == Ndis802_11AuthModeWPA2 || - ndisauthmode == Ndis802_11AuthModeWPA2PSK) - authmode = WLAN_EID_RSN; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { - memcpy(out_ie + ielength, psecuritypriv->wps_ie, - psecuritypriv->wps_ie_len); - - ielength += psecuritypriv->wps_ie_len; - } else if (authmode == WLAN_EID_VENDOR_SPECIFIC || - authmode == WLAN_EID_RSN) { - /* copy RSN or SSN */ - memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], - psecuritypriv->supplicant_ie[1] + 2); - ielength += psecuritypriv->supplicant_ie[1] + 2; - } - - iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid); - if (iEntry < 0) - return ielength; - else { - if (authmode == WLAN_EID_RSN) - ielength = rtw_append_pmkid(adapter, iEntry, - out_ie, ielength); - } - - return ielength; -} - -void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter) -{ - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct eeprom_priv *peepriv = &adapter->eeprompriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *myhwaddr = myid(peepriv); - - ether_addr_copy(pdev_network->MacAddress, myhwaddr); - - memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, - sizeof(struct cfg80211_ssid)); - - pdev_network->beacon_interval = 100; -} - -void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter) -{ - int sz = 0; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct wlan_network *cur_network = &adapter->mlmepriv.cur_network; - /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */ - - pdev_network->Privacy = - (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0); - - pdev_network->Rssi = 0; - - pdev_network->DSConfig = pregistrypriv->channel; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n", - pregistrypriv->channel, pdev_network->DSConfig); - - if (cur_network->network.ifmode == NL80211_IFTYPE_ADHOC) - pdev_network->ATIMWindow = 0; - - pdev_network->ifmode = cur_network->network.ifmode; - - /* 1. Supported rates */ - /* 2. IE */ - - sz = rtw_generate_ie23a(pregistrypriv); - - pdev_network->IELength = sz; - - pdev_network->Length = - get_wlan_bssid_ex_sz(pdev_network); - - /* notes: translate IELength & Length after assign the - Length to cmdsz in createbss_cmd(); */ - /* pdev_network->IELength = cpu_to_le32(sz); */ -} - -/* the function is at passive_level */ -void rtw_joinbss_reset23a(struct rtw_adapter *padapter) -{ - u8 threshold; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - /* todo: if you want to do something io/reg/hw setting - before join_bss, please add code here */ - - pmlmepriv->num_FortyMHzIntolerant = 0; - - pmlmepriv->num_sta_no_ht = 0; - - phtpriv->ampdu_enable = false;/* reset to disabled */ - - /* TH = 1 => means that invalidate usb rx aggregation */ - /* TH = 0 => means that validate usb rx aggregation, use init value. */ - if (phtpriv->ht_option) { - if (padapter->registrypriv.wifi_spec == 1) - threshold = 1; - else - threshold = 0; - } else - threshold = 1; - - rtl8723a_set_rxdma_agg_pg_th(padapter, threshold); -} - -/* the function is >= passive_level */ -bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint *pout_len) -{ - u32 out_len; - int max_rx_ampdu_factor; - unsigned char *pframe; - const u8 *p; - struct ieee80211_ht_cap ht_capie; - u8 WMM_IE[7] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - phtpriv->ht_option = false; - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie, in_len); - - if (p && p[1] > 0) { - u32 rx_packet_offset, max_recvbuf_sz; - - if (pmlmepriv->qos_option == 0) { - out_len = *pout_len; - pframe = rtw_set_ie23a(out_ie + out_len, - WLAN_EID_VENDOR_SPECIFIC, - sizeof(WMM_IE), WMM_IE, - pout_len); - - pmlmepriv->qos_option = 1; - } - - out_len = *pout_len; - - memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap)); - - ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40); - - GetHalDefVar8192CUsb(padapter, HAL_DEF_RX_PACKET_OFFSET, - &rx_packet_offset); - GetHalDefVar8192CUsb(padapter, HAL_DEF_MAX_RECVBUF_SZ, - &max_recvbuf_sz); - - GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, - &max_rx_ampdu_factor); - ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03; - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) - ht_capie.ampdu_params_info |= - (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2)); - else - ht_capie.ampdu_params_info |= - (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00); - - pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY, - sizeof(struct ieee80211_ht_cap), - (unsigned char *)&ht_capie, pout_len); - - phtpriv->ht_option = true; - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie, in_len); - if (p && (p[1] == sizeof(struct ieee80211_ht_operation))) { - out_len = *pout_len; - pframe = rtw_set_ie23a(out_ie + out_len, - WLAN_EID_HT_OPERATION, - p[1], p + 2 , pout_len); - } - } - - return phtpriv->ht_option; -} - -/* the function is > passive_level (in critical_section) */ -void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len) -{ - u8 max_ampdu_sz; - const u8 *p; - struct ieee80211_ht_cap *pht_capie; - struct ieee80211_ht_operation *pht_addtinfo; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (!phtpriv->ht_option) - return; - - if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable)) - return; - - DBG_8723A("+rtw_update_ht_cap23a()\n"); - - /* maybe needs check if ap supports rx ampdu. */ - if (!phtpriv->ampdu_enable && pregistrypriv->ampdu_enable == 1) { - if (pregistrypriv->wifi_spec == 1) - phtpriv->ampdu_enable = false; - else - phtpriv->ampdu_enable = true; - } else if (pregistrypriv->ampdu_enable == 2) - phtpriv->ampdu_enable = true; - - /* check Max Rx A-MPDU Size */ - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, ie_len); - - if (p && p[1] > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - max_ampdu_sz = pht_capie->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - /* max_ampdu_sz (kbytes); */ - max_ampdu_sz = 1 << (max_ampdu_sz + 3); - - phtpriv->rx_ampdu_maxlen = max_ampdu_sz; - } - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len); - if (p && p[1] > 0) { - pht_addtinfo = (struct ieee80211_ht_operation *)(p + 2); - /* todo: */ - } - - /* update cur_bwmode & cur_ch_offset */ - if (pregistrypriv->cbw40_enable && - pmlmeinfo->ht_cap.cap_info & - cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - pmlmeinfo->HT_info.ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { - int i; - u8 rf_type; - - rf_type = rtl8723a_get_rf_type(padapter); - - /* update the MCS rates */ - for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { - if (rf_type == RF_1T1R || rf_type == RF_1T2R) - pmlmeinfo->ht_cap.mcs.rx_mask[i] &= - MCS_rate_1R23A[i]; - else - pmlmeinfo->ht_cap.mcs.rx_mask[i] &= - MCS_rate_2R23A[i]; - } - /* switch to the 40M Hz mode according to the AP */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pmlmeinfo->HT_info.ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - - default: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - - /* */ - /* Config SM Power Save setting */ - /* */ - pmlmeinfo->SM_PS = - (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) & - IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT; - if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); - - /* */ - /* Config current HT Protection mode. */ - /* */ - pmlmeinfo->HT_protection = - le16_to_cpu(pmlmeinfo->HT_info.operation_mode) & - IEEE80211_HT_OP_MODE_PROTECTION; -} - -void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - u8 issued; - int priority; - struct sta_info *psta; - struct ht_priv *phtpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - s32 bmcst = is_multicast_ether_addr(pattrib->ra); - - if (bmcst || padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100) - return; - - priority = pattrib->priority; - - if (pattrib->psta) - psta = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - - if (!psta) { - DBG_8723A("%s, psta == NUL\n", __func__); - return; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, psta->state); - return; - } - - phtpriv = &psta->htpriv; - - if (phtpriv->ht_option && phtpriv->ampdu_enable) { - issued = (phtpriv->agg_enable_bitmap>>priority)&0x1; - issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1; - - if (issued == 0) { - DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n", - priority); - psta->htpriv.candidate_tid_bitmap |= BIT(priority); - rtw_addbareq_cmd23a(padapter, (u8) priority, - pattrib->ra); - } - } -} - -int rtw_linked_check(struct rtw_adapter *padapter) -{ - if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) || - check_fwstate(&padapter->mlmepriv, - WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) { - if (padapter->stapriv.asoc_sta_count > 2) - return true; - } else { /* Station mode */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) - return true; - } - return false; -} diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c deleted file mode 100644 index 7dd1540ebedd..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c +++ /dev/null @@ -1,6187 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_MLME_EXT_C_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); - -static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame); - -static void issue_assocreq(struct rtw_adapter *padapter); -static void issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da); -static int issue_probereq_ex(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, - u8 *da, int try_cnt, int wait_ms); -static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da); -static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta, - unsigned short status); -static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da, - unsigned short reason, int try_cnt, int wait_ms); -static void start_clnt_assoc(struct rtw_adapter *padapter); -static void start_clnt_auth(struct rtw_adapter *padapter); -static void start_clnt_join(struct rtw_adapter *padapter); -static void start_create_ibss(struct rtw_adapter *padapter); -static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); - -#ifdef CONFIG_8723AU_AP_MODE -static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status, - struct sta_info *pstat, u16 pkt_type); -#endif - -static struct mlme_handler mlme_sta_tbl[]={ - {"OnAssocReq23a", &OnAssocReq23a}, - {"OnAssocRsp23a", &OnAssocRsp23a}, - {"OnReAssocReq", &OnAssocReq23a}, - {"OnReAssocRsp", &OnAssocRsp23a}, - {"OnProbeReq23a", &OnProbeReq23a}, - {"OnProbeRsp23a", &OnProbeRsp23a}, - - /*---------------------------------------------------------- - below 2 are reserved - -----------------------------------------------------------*/ - {"DoReserved23a", &DoReserved23a}, - {"DoReserved23a", &DoReserved23a}, - {"OnBeacon23a", &OnBeacon23a}, - {"OnATIM", &OnAtim23a}, - {"OnDisassoc23a", &OnDisassoc23a}, - {"OnAuth23a", &OnAuth23aClient23a}, - {"OnDeAuth23a", &OnDeAuth23a}, - {"OnAction23a", &OnAction23a}, -}; - -static struct action_handler OnAction23a_tbl[]={ - {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a}, - {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos}, - {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls}, - {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a}, - {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a}, - {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht}, - {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a}, - {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm}, - {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p}, -}; - -static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0}; - -/************************************************** -OUI definitions for the vendor specific IE -***************************************************/ -unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02}; -unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04}; -unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09}; -unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A}; - -unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; -unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - -static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20}; - -/******************************************************** -MCS rate definitions -*********************************************************/ -unsigned char MCS_rate_2R23A[16] = { - 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; -unsigned char MCS_rate_1R23A[16] = { - 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - -/******************************************************** -ChannelPlan definitions -*********************************************************/ - -static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { - /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, - /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, - /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, - /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, - /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */ - {{10, 11, 12, 13}, 4}, - /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */ - {{}, 0}, -}; - -static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = { - /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */ - {{}, 0}, - /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140}, 19}, - /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, - /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22}, - /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, - /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */ - {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, - /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, - /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, - /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */ - {{149, 153, 157, 161, 165}, 5}, - /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, - /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 136, 140, 149, 153, 157, 161, 165}, 20}, - /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 149, 153, 157, 161, 165}, 20}, - /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140}, 19}, - /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, - /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */ - {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, - /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */ - {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, - 153, 157, 161, 165}, 15}, - /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */ - {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, - - /* Driver self defined for old channel plan Compatible, - Remember to modify if have new channel plan definition ===== */ - /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21}, - /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */ - {{36, 40, 44, 48}, 4}, - /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */ - {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, -}; - -static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { - /* 0x00 ~ 0x1F , Old Define ===== */ - {0x02, 0x11}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ - {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ - {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ - {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ - {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ - {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ - {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ - {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ - {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ - {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ - {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ - {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ - {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ - {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ - {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ - {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ - {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ - {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ - {0x01, 0x12}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ - {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ - {0x00, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ - {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ - {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x05, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ - {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ - {0x00, 0x00}, /* 0x1A, */ - {0x00, 0x00}, /* 0x1B, */ - {0x00, 0x00}, /* 0x1C, */ - {0x00, 0x00}, /* 0x1D, */ - {0x00, 0x00}, /* 0x1E, */ - {0x05, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ - /* 0x20 ~ 0x7F , New Define ===== */ - {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ - {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ - {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ - {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ - {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ - {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ - {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ - {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ - {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ - {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ - {0x00, 0x00}, /* 0x2A, */ - {0x00, 0x00}, /* 0x2B, */ - {0x00, 0x00}, /* 0x2C, */ - {0x00, 0x00}, /* 0x2D, */ - {0x00, 0x00}, /* 0x2E, */ - {0x00, 0x00}, /* 0x2F, */ - {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ - {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ - {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ - {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ - {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ - {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ - {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ - {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ - {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ - {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ - {0x00, 0x00}, /* 0x3A, */ - {0x00, 0x00}, /* 0x3B, */ - {0x00, 0x00}, /* 0x3C, */ - {0x00, 0x00}, /* 0x3D, */ - {0x00, 0x00}, /* 0x3E, */ - {0x00, 0x00}, /* 0x3F, */ - {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ - {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */ -}; - -static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = -{0x03, 0x02}; /* use the conbination for max channel numbers */ - -static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf) -{ -} - -static struct fwevent wlanevents[] = -{ - {0, &dummy_event_callback}, /*0*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &rtw_survey_event_cb23a}, /*8*/ - {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a}, - {0, &rtw23a_joinbss_event_cb}, /*10*/ - {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a}, - {sizeof(struct stadel_event), &rtw_stadel_event_callback23a}, - {0, &dummy_event_callback}, - {0, &dummy_event_callback}, - {0, NULL}, /*15*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &dummy_event_callback}, - {0, NULL}, /*20*/ - {0, NULL}, - {0, NULL}, - {0, &dummy_event_callback}, - {0, NULL}, -}; - - -static void rtw_correct_TSF(struct rtw_adapter *padapter) -{ - hw_var_set_correct_tsf(padapter); -} - -static void -rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt) -{ - pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp); -} - -/* - * Search the @param channel_num in given @param channel_set - * @ch_set: the given channel set - * @ch: the given channel number - * - * return the index of channel_num in channel_set, -1 if not found - */ -int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch) -{ - int i; - - for (i = 0; ch_set[i]. ChannelNum != 0; i++) { - if (ch == ch_set[i].ChannelNum) - break; - } - - if (i >= ch_set[i].ChannelNum) - return -1; - return i; -} - -/**************************************************************************** - -Following are the initialization functions for WiFi MLME - -*****************************************************************************/ - -int init_hw_mlme_ext23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - return _SUCCESS; -} - -static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char mixed_datarate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, - _48M_RATE_, _54M_RATE_, 0xff}; - unsigned char mixed_basicrate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _12M_RATE_, _24M_RATE_, 0xff,}; - - atomic_set(&pmlmeext->event_seq, 0); - /* reset to zero when disconnect at client mode */ - pmlmeext->mgnt_seq = 0; - - pmlmeext->cur_channel = padapter->registrypriv.channel; - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - pmlmeext->retry = 0; - - pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; - - memcpy(pmlmeext->datarate, mixed_datarate, NumRates); - memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); - - if (pmlmeext->cur_channel > 14) - pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB; - else - 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; - pmlmeext->scan_abort = false; - - pmlmeinfo->state = MSR_NOLINK; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeinfo->auth_seq = 0; - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - pmlmeinfo->key_index = 0; - pmlmeinfo->iv = 0; - - pmlmeinfo->enc_algo = 0; - pmlmeinfo->authModeToggle = 0; - - memset(pmlmeinfo->chg_txt, 0, 128); - - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - pmlmeinfo->preamble_mode = PREAMBLE_AUTO; - - pmlmeinfo->dialogToken = 0; - - pmlmeext->action_public_rxseq = 0xffff; - pmlmeext->action_public_dialog_token = 0xff; -} - -static int has_channel(struct rt_channel_info *channel_set, - u8 chanset_size, u8 chan) { - int i; - - for (i = 0; i < chanset_size; i++) { - if (channel_set[i].ChannelNum == chan) - return 1; - } - - return 0; -} - -static void init_channel_list(struct rtw_adapter *padapter, - struct rt_channel_info *channel_set, - u8 chanset_size, - struct p2p_channels *channel_list) -{ - struct p2p_oper_class_map op_class[] = { - { IEEE80211G, 81, 1, 13, 1, BW20 }, - { IEEE80211G, 82, 14, 14, 1, BW20 }, - { IEEE80211A, 115, 36, 48, 4, BW20 }, - { IEEE80211A, 116, 36, 44, 8, BW40PLUS }, - { IEEE80211A, 117, 40, 48, 8, BW40MINUS }, - { IEEE80211A, 124, 149, 161, 4, BW20 }, - { IEEE80211A, 125, 149, 169, 4, BW20 }, - { IEEE80211A, 126, 149, 157, 8, BW40PLUS }, - { IEEE80211A, 127, 153, 161, 8, BW40MINUS }, - { -1, 0, 0, 0, 0, BW20 } - }; - - int cla, op; - - cla = 0; - - for (op = 0; op_class[op].op_class; op++) { - u8 ch; - struct p2p_oper_class_map *o = &op_class[op]; - struct p2p_reg_class *reg = NULL; - - for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { - if (!has_channel(channel_set, chanset_size, ch)) - continue; - - if ((0 == padapter->registrypriv.ht_enable) && - (o->inc == 8)) - continue; - - if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) && - ((BW40MINUS == o->bw) || (BW40PLUS == o->bw))) - continue; - - if (reg == NULL) { - reg = &channel_list->reg_class[cla]; - cla++; - reg->reg_class = o->op_class; - reg->channels = 0; - } - reg->channel[reg->channels] = ch; - reg->channels++; - } - } - channel_list->reg_classes = cla; -} - -static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan, - struct rt_channel_info *c_set) -{ - u8 i, ch_size = 0; - u8 b5GBand = false, b2_4GBand = false; - u8 Index2G = 0, Index5G = 0; - - memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM); - - if (cplan >= RT_CHANNEL_DOMAIN_MAX && - cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) { - DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan); - return ch_size; - } - - if (padapter->registrypriv.wireless_mode & WIRELESS_11G) { - b2_4GBand = true; - if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan) - Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; - else - Index2G = RTW_ChannelPlanMap[cplan].Index2G; - } - - if (padapter->registrypriv.wireless_mode & WIRELESS_11A) { - b5GBand = true; - if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan) - Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G; - else - Index5G = RTW_ChannelPlanMap[cplan].Index5G; - } - - if (b2_4GBand) { - for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) { - c_set[ch_size].ChannelNum = - RTW_ChannelPlan2G[Index2G].Channel[i]; - - if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) || - /* Channel 1~11 is active, and 12~14 is passive */ - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) { - if (c_set[ch_size].ChannelNum >= 1 && - c_set[ch_size].ChannelNum <= 11) - c_set[ch_size].ScanType = SCAN_ACTIVE; - else if (c_set[ch_size].ChannelNum >= 12 && - c_set[ch_size].ChannelNum <= 14) - c_set[ch_size].ScanType = SCAN_PASSIVE; - } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan || - RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan || - RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { - /* channel 12~13, passive scan */ - if (c_set[ch_size].ChannelNum <= 11) - c_set[ch_size].ScanType = SCAN_ACTIVE; - else - c_set[ch_size].ScanType = SCAN_PASSIVE; - } else - c_set[ch_size].ScanType = SCAN_ACTIVE; - - ch_size++; - } - } - - if (b5GBand) { - for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) { - if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 || - RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) { - c_set[ch_size].ChannelNum = - RTW_ChannelPlan5G[Index5G].Channel[i]; - if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) { - /* passive scan for all 5G channels */ - c_set[ch_size].ScanType = - SCAN_PASSIVE; - } else - c_set[ch_size].ScanType = - SCAN_ACTIVE; - DBG_8723A("%s(): channel_set[%d].ChannelNum = " - "%d\n", __func__, ch_size, - c_set[ch_size].ChannelNum); - ch_size++; - } - } - } - - return ch_size; -} - -int init_mlme_ext_priv23a(struct rtw_adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmlmeext->padapter = padapter; - - init_mlme_ext_priv23a_value(padapter); - pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; - - init_mlme_ext_timer23a(padapter); - -#ifdef CONFIG_8723AU_AP_MODE - init_mlme_ap_info23a(padapter); -#endif - - pmlmeext->max_chan_nums = init_channel_set(padapter, - pmlmepriv->ChannelPlan, - pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, - pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->mlmeext_init = true; - - pmlmeext->active_keep_alive_check = true; - return _SUCCESS; -} - -void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext) -{ - struct rtw_adapter *padapter = pmlmeext->padapter; - - if (!padapter) - return; - - if (padapter->bDriverStopped == true) { - del_timer_sync(&pmlmeext->survey_timer); - del_timer_sync(&pmlmeext->link_timer); - /* del_timer_sync(&pmlmeext->ADDBA_timer); */ - } -} - -static void -_mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - if (ptable->func) { - /* receive the frames that ra(a1) is my address - or ra(a1) is bc address. */ - if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&& - !is_broadcast_ether_addr(hdr->addr1)) - return; - - ptable->func(padapter, precv_frame); - } -} - -void mgt_dispatcher23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct mlme_handler *ptable; -#ifdef CONFIG_8723AU_AP_MODE - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; -#endif /* CONFIG_8723AU_AP_MODE */ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct sta_info *psta; - u16 stype; - int index; - - if (!ieee80211_is_mgmt(mgmt->frame_control)) - return; - - /* receive the frames that ra(a1) is my address or ra(a1) is - bc address. */ - if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) && - !is_broadcast_ether_addr(mgmt->da)) - return; - - ptable = mlme_sta_tbl; - - stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; - index = stype >> 4; - - if (index > 13) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Currently we do not support reserved sub-fr-type =%d\n", - index); - return; - } - ptable += index; - - psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa); - - if (psta) { - if (ieee80211_has_retry(mgmt->frame_control)) { - if (precv_frame->attrib.seq_num == - psta->RxMgmtFrameSeqNum) { - /* drop the duplicate management frame */ - DBG_8723A("Drop duplicate management frame " - "with seq_num = %d.\n", - precv_frame->attrib.seq_num); - return; - } - } - psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num; - } - -#ifdef CONFIG_8723AU_AP_MODE - switch (stype) { - case IEEE80211_STYPE_AUTH: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - ptable->func = &OnAuth23a; - else - ptable->func = &OnAuth23aClient23a; - /* pass through */ - case IEEE80211_STYPE_ASSOC_REQ: - case IEEE80211_STYPE_REASSOC_REQ: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_PROBE_REQ: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - _mgt_dispatcher23a(padapter, ptable, precv_frame); - else - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_BEACON: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_ACTION: - /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */ - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - default: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - } -#else - _mgt_dispatcher23a(padapter, ptable, precv_frame); -#endif -} - -/**************************************************************************** - -Following are the callback functions for each subtype of the management frames - -*****************************************************************************/ - -static int -OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - const u8 *ie; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur = &pmlmeinfo->network; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - int len = skb->len; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - return _SUCCESS; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) && - !check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) - return _SUCCESS; - - if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) { - printk(KERN_WARNING "%s: Received non probe request frame\n", - __func__); - return _FAIL; - } - - len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable); - - ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len); - - /* check (wildcard) SSID */ - if (!ie) - goto out; - - if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) || - (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) { - return _SUCCESS; - } - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - pmlmepriv->cur_network.join_res) - issue_probersp(padapter, mgmt->sa); - -out: - return _SUCCESS; -} - -static int -OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event23a(padapter, precv_frame); - return _SUCCESS; - } - - return _SUCCESS; -} - -static int -OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - int cam_idx; - struct sta_info *psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - int pkt_len = skb->len; - struct wlan_bssid_ex *pbss; - int ret = _SUCCESS; - u8 *p, *pie; - int pie_len; - u32 ielen = 0; - - pie = mgmt->u.beacon.variable; - pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len); - if (p && ielen > 0) { - if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) { - /* Invalid value 0x2D is detected in Extended Supported - * Rates (ESR) IE. Try to fix the IE length to avoid - * failed Beacon parsing. - */ - DBG_8723A("[WIFIDBG] Error in ESR IE is detected in " - "Beacon of BSSID: %pM. Fix the length of " - "ESR IE to avoid failed Beacon parsing.\n", - mgmt->bssid); - p[1] = ielen - 1; - } - } - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event23a(padapter, precv_frame); - return _SUCCESS; - } - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - goto out; - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - /* we should update current network before auth, - or some IE is wrong */ - pbss = collect_bss_info(padapter, precv_frame); - if (pbss) { - update_network23a(&pmlmepriv->cur_network.network, pbss, - padapter, true); - rtw_get_bcn_info23a(&pmlmepriv->cur_network); - kfree(pbss); - } - - /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = - check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len - - offsetof(struct ieee80211_mgmt, u)); - - /* update TSF Value */ - rtw_update_TSF(pmlmeext, mgmt); - - /* start auth */ - start_clnt_auth(padapter); - - return _SUCCESS; - } - - if (((pmlmeinfo->state & 0x03) == MSR_AP) && - (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len); - if (ret != _SUCCESS) { - DBG_8723A_LEVEL(_drv_always_, "ap has changed, " - "disconnect now\n"); - receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535); - return _SUCCESS; - } - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of - the number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) { - /* DBG_8723A("update_bcn_info\n"); */ - update_beacon23a_info(padapter, mgmt, - pkt_len, psta); - } - } - } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) { - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of the - number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) { - /* DBG_8723A("update_bcn_info\n"); */ - update_beacon23a_info(padapter, mgmt, - pkt_len, psta); - } - } else { - /* allocate a new CAM entry for IBSS station */ - cam_idx = allocate_fw_sta_entry23a(padapter); - if (cam_idx == NUM_STA) - goto out; - - /* get supported rate */ - if (update_sta_support_rate23a(padapter, pie, pie_len, - cam_idx) == _FAIL) { - pmlmeinfo->FW_sta_info[cam_idx].status = 0; - goto out; - } - - /* update TSF Value */ - rtw_update_TSF(pmlmeext, mgmt); - - /* report sta add event */ - report_add_sta_event23a(padapter, mgmt->sa, - cam_idx); - } - } - -out: - - return _SUCCESS; -} - -#ifdef CONFIG_8723AU_AP_MODE -static int -OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - static struct sta_info stat; - struct sta_info *pstat = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - u8 *pframe; - const u8 *p; - unsigned char *sa; - u16 auth_mode, seq, algorithm; - int status, len = skb->len; - - if ((pmlmeinfo->state & 0x03) != MSR_AP) - return _FAIL; - - DBG_8723A("+OnAuth23a\n"); - - sa = mgmt->sa; - - auth_mode = psecuritypriv->dot11AuthAlgrthm; - - pframe = mgmt->u.auth.variable; - len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable); - - seq = le16_to_cpu(mgmt->u.auth.auth_transaction); - algorithm = le16_to_cpu(mgmt->u.auth.auth_alg); - - DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq); - - if (auth_mode == 2 && - psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 && - psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104) - auth_mode = 0; - - /* rx a shared-key auth but shared not enabled, or */ - /* rx a open-system auth but shared-key is enabled */ - if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) || - (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) { - DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib " - "=%d] %02X%02X%02X%02X%02X%02X\n", - algorithm, auth_mode, - sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - - status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; - - goto auth_fail; - } - - if (rtw_access_ctrl23a(padapter, sa) == false) { - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto auth_fail; - } - - pstat = rtw_get_stainfo23a(pstapriv, sa); - if (!pstat) { - /* allocate a new one */ - DBG_8723A("going to alloc stainfo for sa =%pM\n", sa); - pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC); - if (!pstat) { - DBG_8723A(" Exceed the upper limit of supported " - "clients...\n"); - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto auth_fail; - } - - pstat->state = WIFI_FW_AUTH_NULL; - pstat->auth_seq = 0; - - /* pstat->flags = 0; */ - /* pstat->capability = 0; */ - } else { - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&pstat->asoc_list)) { - list_del_init(&pstat->asoc_list); - pstapriv->asoc_list_cnt--; - if (pstat->expire_to > 0) { - /* TODO: STA re_auth within expire_to */ - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (seq == 1) { - /* TODO: STA re_auth and auth timeout */ - } - } - - spin_lock_bh(&pstapriv->auth_list_lock); - if (list_empty(&pstat->auth_list)) { - list_add_tail(&pstat->auth_list, &pstapriv->auth_list); - pstapriv->auth_list_cnt++; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - if (pstat->auth_seq == 0) - pstat->expire_to = pstapriv->auth_to; - - if ((pstat->auth_seq + 1) != seq) { - DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, " - "exp_seq =%d]!\n", seq, pstat->auth_seq+1); - status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto auth_fail; - } - - if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) { - if (seq == 1) { - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - pstat->expire_to = pstapriv->assoc_to; - pstat->authalg = algorithm; - } else { - DBG_8723A("(2)auth rejected because out of seq " - "[rx_seq =%d, exp_seq =%d]!\n", - seq, pstat->auth_seq+1); - status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto auth_fail; - } - } else { /* shared system or auto authentication */ - if (seq == 1) { - /* prepare for the challenging txt... */ - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_STATE; - pstat->authalg = algorithm; - pstat->auth_seq = 2; - } else if (seq == 3) { - /* checking for challenging txt... */ - DBG_8723A("checking for challenging txt...\n"); - - p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len); - if (!p || p[1] <= 0) { - DBG_8723A("auth rejected because challenge " - "failure!(1)\n"); - status = WLAN_STATUS_CHALLENGE_FAIL; - goto auth_fail; - } - - if (!memcmp(p + 2, pstat->chg_txt, 128)) { - pstat->state &= ~WIFI_FW_AUTH_STATE; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - /* challenging txt is correct... */ - pstat->expire_to = pstapriv->assoc_to; - } else { - DBG_8723A("auth rejected because challenge " - "failure!\n"); - status = WLAN_STATUS_CHALLENGE_FAIL; - goto auth_fail; - } - } else { - DBG_8723A("(3)auth rejected because out of seq " - "[rx_seq =%d, exp_seq =%d]!\n", - seq, pstat->auth_seq+1); - status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto auth_fail; - } - } - - /* Now, we are going to issue_auth... */ - pstat->auth_seq = seq + 1; - - issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS); - - if (pstat->state & WIFI_FW_AUTH_SUCCESS) - pstat->auth_seq = 0; - - return _SUCCESS; - -auth_fail: - - if (pstat) - rtw_free_stainfo23a(padapter, pstat); - - pstat = &stat; - memset((char *)pstat, '\0', sizeof(stat)); - pstat->auth_seq = 2; - ether_addr_copy(pstat->hwaddr, sa); - - issue_auth(padapter, pstat, (unsigned short)status); - - return _FAIL; -} -#endif - -static int -OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int seq, status, algthm; - unsigned int go2asoc = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - const u8 *p; - u8 *pie; - int plen = skb->len; - - DBG_8723A("%s\n", __func__); - - /* check A1 matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da)) - return _SUCCESS; - - if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) - return _SUCCESS; - - pie = mgmt->u.auth.variable; - plen -= offsetof(struct ieee80211_mgmt, u.auth.variable); - - algthm = le16_to_cpu(mgmt->u.auth.auth_alg); - seq = le16_to_cpu(mgmt->u.auth.auth_transaction); - status = le16_to_cpu(mgmt->u.auth.status_code); - - if (status) { - DBG_8723A("clnt auth fail, status: %d\n", status); - /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ - if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - else - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; - /* pmlmeinfo->reauth_count = 0; */ - } - - set_link_timer(pmlmeext, 1); - goto authclnt_fail; - } - - if (seq == 2) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - /* legendary shared system */ - p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen); - - if (!p) { - /* DBG_8723A("marc: no challenge text?\n"); */ - goto authclnt_fail; - } - - memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]); - pmlmeinfo->auth_seq = 3; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - - return _SUCCESS; - } else { - /* open system */ - go2asoc = 1; - } - } else if (seq == 4) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - go2asoc = 1; - else - goto authclnt_fail; - } else { - /* this is also illegal */ - /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n", - seq); */ - goto authclnt_fail; - } - - if (go2asoc) { - DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n"); - start_clnt_assoc(padapter); - return _SUCCESS; - } - -authclnt_fail: - - /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */ - - return _FAIL; -} - -#ifdef CONFIG_8723AU_AP_MODE -static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen) -{ - unsigned int oui; - - /* first 3 bytes in vendor specific information element are the IEEE - * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ - if (elen < 4) { - DBG_8723A("short vendor specific information element " - "ignored (len =%i)\n", elen); - return -EINVAL; - } - - oui = RTW_GET_BE24(pos); - switch (oui) { - case WLAN_OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ - switch (pos[3]) { - case WLAN_OUI_TYPE_MICROSOFT_WPA: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ - break; - case WLAN_OUI_TYPE_MICROSOFT_WMM: - if (elen < 5) { - DBG_8723A("short WME information element " - "ignored (len =%i)\n", elen); - return -EINVAL; - } - switch (pos[4]) { - case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: - break; - case WME_OUI_SUBTYPE_TSPEC_ELEMENT: - break; - default: - DBG_8723A("unknown WME information element " - "ignored (subtype =%d len =%i)\n", - pos[4], elen); - return -EINVAL; - } - break; - case WLAN_OUI_TYPE_MICROSOFT_WPS: - /* Wi-Fi Protected Setup (WPS) IE */ - break; - default: - DBG_8723A("Unknown Microsoft information element " - "ignored (type =%d len =%i)\n", - pos[3], elen); - return -EINVAL; - } - break; - - case OUI_BROADCOM: - switch (pos[3]) { - case VENDOR_HT_CAPAB_OUI_TYPE: - break; - default: - DBG_8723A("Unknown Broadcom information element " - "ignored (type =%d len =%i)\n", pos[3], elen); - return -EINVAL; - } - break; - - default: - DBG_8723A("unknown vendor specific information element " - "ignored (vendor OUI %02x:%02x:%02x len =%i)\n", - pos[0], pos[1], pos[2], elen); - return -EINVAL; - } - - return 0; -} - -static int rtw_validate_frame_ies(const u8 *start, uint len) -{ - const u8 *pos = start; - int left = len; - int unknown = 0; - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { - DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d " - "left =%i)\n", __func__, id, elen, left); - return -EINVAL; - } - - switch (id) { - case WLAN_EID_SSID: - case WLAN_EID_SUPP_RATES: - case WLAN_EID_FH_PARAMS: - case WLAN_EID_DS_PARAMS: - case WLAN_EID_CF_PARAMS: - case WLAN_EID_TIM: - case WLAN_EID_IBSS_PARAMS: - case WLAN_EID_CHALLENGE: - case WLAN_EID_ERP_INFO: - case WLAN_EID_EXT_SUPP_RATES: - break; - case WLAN_EID_VENDOR_SPECIFIC: - if (rtw_validate_vendor_specific_ies(pos, elen)) - unknown++; - break; - case WLAN_EID_RSN: - case WLAN_EID_PWR_CAPABILITY: - case WLAN_EID_SUPPORTED_CHANNELS: - case WLAN_EID_MOBILITY_DOMAIN: - case WLAN_EID_FAST_BSS_TRANSITION: - case WLAN_EID_TIMEOUT_INTERVAL: - case WLAN_EID_HT_CAPABILITY: - case WLAN_EID_HT_OPERATION: - default: - unknown++; - DBG_8723A("%s IEEE 802.11 ignored unknown element " - "(id =%d elen =%d)\n", __func__, id, elen); - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return -EINVAL; - - return 0; -} -#endif - -static int -OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - u16 capab_info, listen_interval; - struct sta_info *pstat; - unsigned char reassoc; - int i, wpa_ie_len, left; - unsigned char supportRate[16]; - int supportRateNum; - unsigned short status = WLAN_STATUS_SUCCESS; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - const u8 *pos, *p, *wpa_ie, *wps_ie; - u8 *pframe = skb->data; - uint pkt_len = skb->len; - int r; - - if ((pmlmeinfo->state & 0x03) != MSR_AP) - return _FAIL; - - left = pkt_len - sizeof(struct ieee80211_hdr_3addr); - if (ieee80211_is_assoc_req(mgmt->frame_control)) { - reassoc = 0; - pos = mgmt->u.assoc_req.variable; - left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable); - } else { /* WIFI_REASSOCREQ */ - reassoc = 1; - pos = mgmt->u.reassoc_req.variable; - left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable); - } - - if (left < 0) { - DBG_8723A("handle_assoc(reassoc =%d) - too short payload " - "(len =%lu)\n", reassoc, (unsigned long)pkt_len); - return _FAIL; - } - - pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (!pstat) { - status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; - goto asoc_class2_error; - } - - /* These two are located at the same offsets whether it's an - * assoc_req or a reassoc_req */ - capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info); - listen_interval = - get_unaligned_le16(&mgmt->u.assoc_req.listen_interval); - - DBG_8723A("%s\n", __func__); - - /* check if this stat has been successfully authenticated/assocated */ - if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) { - if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) { - status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; - goto asoc_class2_error; - } else { - pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - } else { - pstat->state &= (~WIFI_FW_AUTH_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - - pstat->capability = capab_info; - - /* now parse all ieee802_11 ie to point to elems */ - - if (rtw_validate_frame_ies(pos, left)) { - DBG_8723A("STA %pM sent invalid association request\n", - pstat->hwaddr); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } - - /* now we should check all the fields... */ - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, pos, left); - if (!p || p[1] == 0) { - /* broadcast ssid, however it is not allowed in assocreq */ - DBG_8723A("STA %pM sent invalid association request lacking an SSID\n", - pstat->hwaddr); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } else { - /* check if ssid match */ - if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - - if (p[1] != cur->Ssid.ssid_len) - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - /* check if the supported rate is ok */ - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left); - if (!p) { - DBG_8723A("Rx a sta assoc-req which supported rate is " - "empty!\n"); - /* use our own rate set as statoin used */ - /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ - /* supportRateNum = AP_BSSRATE_LEN; */ - - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } else { - memcpy(supportRate, p + 2, p[1]); - supportRateNum = p[1]; - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left); - if (p) { - if (supportRateNum <= sizeof(supportRate)) { - memcpy(supportRate+supportRateNum, p + 2, p[1]); - supportRateNum += p[1]; - } - } - } - - /* todo: mask supportRate between AP & STA -> move to update raid */ - /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ - - /* update station supportRate */ - pstat->bssratelen = supportRateNum; - memcpy(pstat->bssrateset, supportRate, supportRateNum); - Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen); - - /* check RSN/WPA/WPS */ - pstat->dot8021xalg = 0; - pstat->wpa_psk = 0; - pstat->wpa_group_cipher = 0; - pstat->wpa2_group_cipher = 0; - pstat->wpa_pairwise_cipher = 0; - pstat->wpa2_pairwise_cipher = 0; - memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); - - wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left); - if (!wpa_ie) - wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pos, left); - if (wpa_ie) { - int group_cipher = 0, pairwise_cipher = 0; - - wpa_ie_len = wpa_ie[1]; - if (psecuritypriv->wpa_psk & BIT(1)) { - r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2, - &group_cipher, - &pairwise_cipher, NULL); - if (r == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(1); - - pstat->wpa2_group_cipher = group_cipher & - psecuritypriv->wpa2_group_cipher; - pstat->wpa2_pairwise_cipher = pairwise_cipher & - psecuritypriv->wpa2_pairwise_cipher; - } else - status = WLAN_STATUS_INVALID_IE; - } else if (psecuritypriv->wpa_psk & BIT(0)) { - r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2, - &group_cipher, &pairwise_cipher, - NULL); - if (r == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(0); - - pstat->wpa_group_cipher = group_cipher & - psecuritypriv->wpa_group_cipher; - pstat->wpa_pairwise_cipher = pairwise_cipher & - psecuritypriv->wpa_pairwise_cipher; - } else - status = WLAN_STATUS_INVALID_IE; - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - if (wpa_ie && status == WLAN_STATUS_SUCCESS) { - if (!pstat->wpa_group_cipher) - status = WLAN_STATUS_INVALID_GROUP_CIPHER; - - if (!pstat->wpa_pairwise_cipher) - status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; - } - } - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - pos, left); - - if (!wpa_ie) { - if (wps_ie) { - DBG_8723A("STA included WPS IE in (Re)Association " - "Request - assume WPS is used\n"); - pstat->flags |= WLAN_STA_WPS; - } else { - DBG_8723A("STA did not include WPA/RSN IE in (Re)" - "Association Request - possible WPS use\n"); - pstat->flags |= WLAN_STA_MAYBE_WPS; - } - } else { - int copy_len; - - if (psecuritypriv->wpa_psk == 0) { - DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n", - pstat->hwaddr); - - status = WLAN_STATUS_INVALID_IE; - - goto OnAssocReq23aFail; - } - - if (wps_ie) { - DBG_8723A("STA included WPS IE in (Re)Association " - "Request - WPS is used\n"); - pstat->flags |= WLAN_STA_WPS; - copy_len = 0; - } else { - copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ? - sizeof(pstat->wpa_ie) : (wpa_ie_len + 2); - } - - if (copy_len > 0) - memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len); - } - - /* check if there is WMM IE & support WWM-PS */ - pstat->flags &= ~WLAN_STA_WME; - pstat->qos_option = 0; - pstat->qos_info = 0; - pstat->has_legacy_ac = true; - pstat->uapsd_vo = 0; - pstat->uapsd_vi = 0; - pstat->uapsd_be = 0; - pstat->uapsd_bk = 0; - if (pmlmepriv->qos_option) { - const u8 *end = pos + left; - - p = pos; - - for (;;) { - left = end - p; - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - p, left); - if (p) { - pstat->flags |= WLAN_STA_WME; - - pstat->qos_option = 1; - pstat->qos_info = *(p + 8); - - pstat->max_sp_len = - (pstat->qos_info >> 5) & 0x3; - - if ((pstat->qos_info & 0xf) != 0xf) - pstat->has_legacy_ac = true; - else - pstat->has_legacy_ac = false; - - if (pstat->qos_info & 0xf) { - if (pstat->qos_info & BIT(0)) - pstat->uapsd_vo = BIT(0)|BIT(1); - else - pstat->uapsd_vo = 0; - - if (pstat->qos_info & BIT(1)) - pstat->uapsd_vi = BIT(0)|BIT(1); - else - pstat->uapsd_vi = 0; - - if (pstat->qos_info & BIT(2)) - pstat->uapsd_bk = BIT(0)|BIT(1); - else - pstat->uapsd_bk = 0; - - if (pstat->qos_info & BIT(3)) - pstat->uapsd_be = BIT(0)|BIT(1); - else - pstat->uapsd_be = 0; - - break; - } - } else { - break; - } - p = p + p[1] + 2; - } - } - - /* save HT capabilities in the sta object */ - memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left); - - if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) { - pstat->flags |= WLAN_STA_HT; - - pstat->flags |= WLAN_STA_WME; - - memcpy(&pstat->htpriv.ht_cap, p + 2, - sizeof(struct ieee80211_ht_cap)); - } else - pstat->flags &= ~WLAN_STA_HT; - - if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){ - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } - - if (pstat->flags & WLAN_STA_HT && - (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP || - pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { - DBG_8723A("HT: %pM tried to use TKIP with HT association\n", - pstat->hwaddr); - - /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */ - /* goto OnAssocReq23aFail; */ - } - - pstat->flags |= WLAN_STA_NONERP; - for (i = 0; i < pstat->bssratelen; i++) { - if ((pstat->bssrateset[i] & 0x7f) > 22) { - pstat->flags &= ~WLAN_STA_NONERP; - break; - } - } - - if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - pstat->flags |= WLAN_STA_SHORT_PREAMBLE; - else - pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - /* TODO: identify_proprietary_vendor_ie(); */ - /* Realtek proprietary IE */ - /* identify if this is Broadcom sta */ - /* identify if this is ralink sta */ - /* Customer proprietary IE */ - - /* get a unique AID */ - if (pstat->aid > 0) { - DBG_8723A(" old AID %d\n", pstat->aid); - } else { - for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) - if (pstapriv->sta_aid[pstat->aid - 1] == NULL) - break; - - if (pstat->aid > NUM_STA) - pstat->aid = NUM_STA; - if (pstat->aid > pstapriv->max_num_sta) { - - pstat->aid = 0; - - DBG_8723A(" no room for more AIDs\n"); - - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - - goto OnAssocReq23aFail; - } else { - pstapriv->sta_aid[pstat->aid - 1] = pstat; - DBG_8723A("allocate new AID = (%d)\n", pstat->aid); - } - } - - pstat->state &= ~WIFI_FW_ASSOC_STATE; - pstat->state |= WIFI_FW_ASSOC_SUCCESS; - - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&pstat->auth_list)) { - list_del_init(&pstat->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (list_empty(&pstat->asoc_list)) { - pstat->expire_to = pstapriv->expire_to; - list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); - pstapriv->asoc_list_cnt++; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - /* now the station is qualified to join our BSS... */ - if (pstat->state & WIFI_FW_ASSOC_SUCCESS && - status == WLAN_STATUS_SUCCESS) { - /* 1 bss_cap_update & sta_info_update23a */ - bss_cap_update_on_sta_join23a(padapter, pstat); - sta_info_update23a(padapter, pstat); - - /* issue assoc rsp before notify station join event. */ - if (ieee80211_is_assoc_req(mgmt->frame_control)) - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_ASSOC_RESP); - else - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_REASSOC_RESP); - - /* 2 - report to upper layer */ - DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n"); - rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len); - - /* 3-(1) report sta add event */ - report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid); - } - - return _SUCCESS; - -asoc_class2_error: - - issue_deauth23a(padapter, mgmt->sa, status); - return _FAIL; - -OnAssocReq23aFail: - - pstat->aid = 0; - if (ieee80211_is_assoc_req(mgmt->frame_control)) - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_ASSOC_RESP); - else - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_REASSOC_RESP); - -#endif /* CONFIG_8723AU_AP_MODE */ - - return _FAIL; -} - -static int -OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data; - int res; - unsigned short status; - const u8 *p, *pie; - u8 *pframe = skb->data; - int pkt_len = skb->len; - int pielen; - - DBG_8723A("%s\n", __func__); - - /* check A1 matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da)) - return _SUCCESS; - - if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) - return _SUCCESS; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - return _SUCCESS; - - del_timer_sync(&pmlmeext->link_timer); - - /* status */ - status = le16_to_cpu(pmgmt->u.assoc_resp.status_code); - if (status > 0) { - DBG_8723A("assoc reject, status code: %d\n", status); - pmlmeinfo->state = MSR_NOLINK; - res = -4; - goto report_assoc_result; - } - - /* get capabilities */ - pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info); - - /* set slot time */ - pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20; - - /* AID */ - res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff; - - pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - pielen = pkt_len - - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - HT_caps_handler23a(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - HT_info_handler23a(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - ERP_IE_handler23a(padapter, p); - - pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - while (true) { - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - pie, pframe + pkt_len - pie); - if (!p) - break; - - pie = p + p[1] + 2; - /* if this IE is too short, try the next */ - if (p[1] <= 4) - continue; - /* if this IE is WMM params, we found what we wanted */ - if (p[6] == 1) - break; - } - - if (p && p[1]) - WMM_param_handler23a(padapter, p); - - pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE; - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - - /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ - UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates); - -report_assoc_result: - pmlmepriv->assoc_rsp_len = 0; - if (res > 0) { - kfree(pmlmepriv->assoc_rsp); - pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC); - if (pmlmepriv->assoc_rsp) { - memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len); - pmlmepriv->assoc_rsp_len = pkt_len; - } - } else - kfree(pmlmepriv->assoc_rsp); - - report_join_res23a(padapter, res); - - return _SUCCESS; -} - -static int -OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - reason = le16_to_cpu(mgmt->u.deauth.reason_code); - - DBG_8723A("%s Reason code(%d)\n", __func__, reason); - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) " - "sta:%pM\n", reason, mgmt->sa); - - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - u8 updated = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, - false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update23a(padapter, updated); - } - - return _SUCCESS; - } else -#endif - { - DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) " - "sta:%pM\n", reason, mgmt->bssid); - - receive_disconnect23a(padapter, mgmt->bssid, reason); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - - return _SUCCESS; -} - -static int -OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - reason = le16_to_cpu(mgmt->u.disassoc.reason_code); - - DBG_8723A("%s Reason code(%d)\n", __func__, reason); - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)" - " sta:%pM\n", reason, mgmt->sa); - - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - u8 updated = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, - false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update23a(padapter, updated); - } - - return _SUCCESS; - } else -#endif - { - DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason " - "code(%d) sta:%pM\n", reason, mgmt->bssid); - - receive_disconnect23a(padapter, mgmt->bssid, reason); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - return _SUCCESS; -} - -static int -OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - DBG_8723A("%s\n", __func__); - return _SUCCESS; -} - -static int -on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _FAIL; -} - -static int -OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int OnAction23a_back23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - u8 *addr; - struct sta_info *psta = NULL; - struct recv_reorder_ctrl *preorder_ctrl; - unsigned char category, action; - unsigned short tid, status, capab, params, reason_code = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* check RA matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da)) - return _SUCCESS; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state&0x03) != MSR_AP) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - addr = mgmt->sa; - psta = rtw_get_stainfo23a(pstapriv, addr); - - if (!psta) - return _SUCCESS; - - category = mgmt->u.action.category; - if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */ - if (!pmlmeinfo->HT_enable) - return _SUCCESS; - /* action_code is located in the same place for all - action events, so pick any */ - action = mgmt->u.action.u.wme_action.action_code; - DBG_8723A("%s, action =%d\n", __func__, action); - switch (action) { - case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ - memcpy(&pmlmeinfo->ADDBA_req, - &mgmt->u.action.u.addba_req.dialog_token, - sizeof(struct ADDBA_request)); - process_addba_req23a(padapter, - (u8 *)&pmlmeinfo->ADDBA_req, addr); - if (pmlmeinfo->bAcceptAddbaReq == true) - issue_action_BA23a(padapter, addr, - WLAN_ACTION_ADDBA_RESP, 0); - else { - /* reject ADDBA Req */ - issue_action_BA23a(padapter, addr, - WLAN_ACTION_ADDBA_RESP, 37); - } - break; - case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ - status = get_unaligned_le16( - &mgmt->u.action.u.addba_resp.status); - capab = get_unaligned_le16( - &mgmt->u.action.u.addba_resp.capab); - tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - if (status == 0) { /* successful */ - DBG_8723A("agg_enable for TID =%d\n", tid); - psta->htpriv.agg_enable_bitmap |= BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } else - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - break; - - case WLAN_ACTION_DELBA: /* DELBA */ - params = get_unaligned_le16( - &mgmt->u.action.u.delba.params); - tid = params >> 12; - - if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) { - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - } else { - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } - reason_code = get_unaligned_le16( - &mgmt->u.action.u.delba.reason_code); - /* todo: how to notify the host while receiving - DELETE BA */ - break; - default: - break; - } - } - return _SUCCESS; -} - -static int on_action_public23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u8 *pframe = skb->data; - int freq, channel; - - /* check RA matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1)) - return _FAIL; - - channel = rtw_get_oper_ch23a(padapter); - - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe, - skb->len, 0)) - return _SUCCESS; - - return _FAIL; -} - -static int -OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - int i; - u8 category; - struct action_handler *ptable; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - category = mgmt->u.action.category; - - for (i = 0; i < ARRAY_SIZE(OnAction23a_tbl); i++) { - ptable = &OnAction23a_tbl[i]; - - if (category == ptable->num) - ptable->func(padapter, precv_frame); - } - - return _SUCCESS; -} - -static int DoReserved23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pmgntframe; - struct xmit_buf *pxmitbuf; - - pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv); - - if (!pmgntframe) { - DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__, - pxmitpriv->adapter->pnetdev->name); - goto exit; - } - - pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv); - if (!pxmitbuf) { - DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__, - pxmitpriv->adapter->pnetdev->name); - rtw_free_xmitframe23a(pxmitpriv, pmgntframe); - pmgntframe = NULL; - goto exit; - } - - pmgntframe->frame_tag = MGNT_FRAMETAG; - pmgntframe->pxmitbuf = pxmitbuf; - pmgntframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pmgntframe; - -exit: - return pmgntframe; -} - -/**************************************************************************** - -Following are some TX functions for WiFi MLME - -*****************************************************************************/ - -void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - pmlmeext->tx_rate = rate; - DBG_8723A("%s(): rate = %x\n", __func__, rate); -} - -void update_mgntframe_attrib23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib)); - - pattrib->hdrlen = 24; - pattrib->nr_frags = 1; - pattrib->priority = 7; - pattrib->mac_id = 0; - pattrib->qsel = 0x12; - - pattrib->pktlen = 0; - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - pattrib->raid = 6;/* b mode */ - else - pattrib->raid = 5;/* a/g mode */ - - pattrib->encrypt = 0; - pattrib->bswenc = false; - - pattrib->qos_en = false; - pattrib->ht_en = false; - pattrib->bwmode = HT_CHANNEL_WIDTH_20; - pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pattrib->sgi = false; - - pattrib->seqnum = pmlmeext->mgnt_seq; - - pattrib->retry_ctrl = true; -} - -void dump_mgntframe23a(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return; - - rtl8723au_mgnt_xmit(padapter, pmgntframe); -} - -int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe, int timeout_ms) -{ - int ret = _FAIL; - unsigned long irqL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; - struct submit_ctx sctx; - - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return ret; - - rtw_sctx_init23a(&sctx, timeout_ms); - pxmitbuf->sctx = &sctx; - - ret = rtl8723au_mgnt_xmit(padapter, pmgntframe); - - if (ret == _SUCCESS) - ret = rtw_sctx_wait23a(&sctx); - - spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); - pxmitbuf->sctx = NULL; - spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); - - return ret; -} - -int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - int ret = _FAIL; - u32 timeout_ms = 500;/* 500ms */ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return _FAIL; - - mutex_lock(&pxmitpriv->ack_tx_mutex); - pxmitpriv->ack_tx = true; - - pmgntframe->ack_report = 1; - if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) - ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms); - - pxmitpriv->ack_tx = false; - mutex_unlock(&pxmitpriv->ack_tx_mutex); - - return ret; -} - -static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) -{ - u8 *ssid_ie; - int ssid_len_ori; - int len_diff = 0; - u8 *next_ie; - u32 remain_len; - - ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); - - /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", - __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */ - - if (ssid_ie && ssid_len_ori > 0) { - switch (hidden_ssid_mode) { - case 1: - next_ie = ssid_ie + 2 + ssid_len_ori; - remain_len = ies_len -(next_ie-ies); - - ssid_ie[1] = 0; - memcpy(ssid_ie+2, next_ie, remain_len); - len_diff -= ssid_len_ori; - - break; - case 2: - memset(&ssid_ie[2], 0, ssid_len_ori); - break; - default: - break; - } - } - - return len_diff; -} - -void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned int rate_len; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const u8 *wps_ie; - u8 sr = 0; - int len_diff; - - /* DBG_8723A("%s\n", __func__); */ - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) { - DBG_8723A("%s, alloc mgnt frame fail\n", __func__); - return; - } -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pmlmepriv->bcn_update_lock); -#endif - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->qsel = 0x10; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - mgmt->seq_ctrl = 0; - - ether_addr_copy(mgmt->da, bc_addr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network)); - - /* timestamp will be inserted by hardware */ - - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.beacon.beacon_int); - - put_unaligned_le16(cur_network->capability, - &mgmt->u.beacon.capab_info); - - pframe = mgmt->u.beacon.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable); - - if ((pmlmeinfo->state & 0x03) == MSR_AP) { - u8 *iebuf; - int buflen; - /* DBG_8723A("ie len =%d\n", cur_network->IELength); */ - memcpy(pframe, cur_network->IEs, cur_network->IELength); - len_diff = update_hidden_ssid(pframe, cur_network->IELength, - pmlmeinfo->hidden_ssid_mode); - pframe += (cur_network->IELength+len_diff); - pattrib->pktlen += (cur_network->IELength+len_diff); - - iebuf = mgmt->u.beacon.variable; - buflen = pattrib->pktlen - - offsetof(struct ieee80211_mgmt, u.beacon.variable); - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - iebuf, buflen); - - if (wps_ie && wps_ie[1] > 0) { - rtw_get_wps_attr_content23a(wps_ie, wps_ie[1], - WPS_ATTR_SELECTED_REGISTRAR, - (u8 *)&sr); - } - if (sr != 0) - set_fwstate(pmlmepriv, WIFI_UNDER_WPS); - else - _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); - - goto _issue_bcn; - } - - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - cur_network->Ssid.ssid_len, - cur_network->Ssid.ssid, &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates); - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - ((rate_len > 8)? 8: rate_len), - cur_network->SupportedRates, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *) - &cur_network->DSConfig, &pattrib->pktlen); - - /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */ - { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2, - (unsigned char *)&ATIMWindow, - &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1, - &erpinfo, &pattrib->pktlen); - } - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - rate_len - 8, - cur_network->SupportedRates + 8, - &pattrib->pktlen); - - /* todo:HT for adhoc */ - -_issue_bcn: - -#ifdef CONFIG_8723AU_AP_MODE - pmlmepriv->update_bcn = false; - - spin_unlock_bh(&pmlmepriv->bcn_update_lock); -#endif - - if ((pattrib->pktlen + TXDESC_SIZE) > 512) { - DBG_8723A("beacon frame too large\n"); - return; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */ - if (timeout_ms > 0) - dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms); - else - dump_mgntframe23a(padapter, pmgntframe); -} - -static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned char *mac, *bssid; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; -#ifdef CONFIG_8723AU_AP_MODE - const u8 *pwps_ie; - u8 *ssid_ie; - int ssid_ielen; - int ssid_ielen_diff; - u8 buf[MAX_IE_SZ]; -#endif - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - unsigned int rate_len; - - /* DBG_8723A("%s\n", __func__); */ - - if (cur_network->IELength > MAX_IE_SZ) - return; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) { - DBG_8723A("%s, alloc mgnt frame fail\n", __func__); - return; - } - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mac = myid(&padapter->eeprompriv); - bssid = cur_network->MacAddress; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); - - ether_addr_copy(mgmt->da, da); - ether_addr_copy(mgmt->sa, mac); - ether_addr_copy(mgmt->bssid, bssid); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - - /* timestamp will be inserted by hardware */ - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.probe_resp.beacon_int); - - put_unaligned_le16(cur_network->capability, - &mgmt->u.probe_resp.capab_info); - - pframe = mgmt->u.probe_resp.variable; - pattrib->pktlen = - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - - /* below for ad-hoc mode */ - -#ifdef CONFIG_8723AU_AP_MODE - if ((pmlmeinfo->state & 0x03) == MSR_AP) { - pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - cur_network->IEs, - cur_network->IELength); - - memcpy(pframe, cur_network->IEs, cur_network->IELength); - pframe += cur_network->IELength; - pattrib->pktlen += cur_network->IELength; - - /* retrieve SSID IE from cur_network->Ssid */ - - ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable, - WLAN_EID_SSID, &ssid_ielen, - pframe - mgmt->u.probe_resp.variable); - - ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen; - - if (ssid_ie && cur_network->Ssid.ssid_len) { - uint remainder_ielen; - u8 *remainder_ie; - - remainder_ie = ssid_ie + 2; - - remainder_ielen = pframe - remainder_ie; - - DBG_8723A_LEVEL(_drv_warning_, "%s(%s): " - "remainder_ielen > MAX_IE_SZ\n", - __func__, padapter->pnetdev->name); - if (remainder_ielen > MAX_IE_SZ) - remainder_ielen = MAX_IE_SZ; - - memcpy(buf, remainder_ie, remainder_ielen); - memcpy(remainder_ie + ssid_ielen_diff, buf, - remainder_ielen); - *(ssid_ie + 1) = cur_network->Ssid.ssid_len; - memcpy(ssid_ie + 2, cur_network->Ssid.ssid, - cur_network->Ssid.ssid_len); - - pframe += ssid_ielen_diff; - pattrib->pktlen += ssid_ielen_diff; - } - } else -#endif - { - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - cur_network->Ssid.ssid_len, - cur_network->Ssid.ssid, - &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates); - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - ((rate_len > 8)? 8: rate_len), - cur_network->SupportedRates, - &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, - (unsigned char *)&cur_network->DSConfig, - &pattrib->pktlen); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2, - (unsigned char *)&ATIMWindow, - &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1, - &erpinfo, &pattrib->pktlen); - } - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - rate_len - 8, - cur_network->SupportedRates + 8, - &pattrib->pktlen); - - /* todo:HT for adhoc */ - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -static int _issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - unsigned char *mac; - unsigned char bssrate[NumRates]; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - int bssrate_len = 0; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "+%s\n", __func__); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - mac = myid(&padapter->eeprompriv); - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_REQ); - - if (da) { - /* unicast probe request frame */ - ether_addr_copy(pwlanhdr->addr1, da); - ether_addr_copy(pwlanhdr->addr3, da); - } else { - /* broadcast probe request frame */ - ether_addr_copy(pwlanhdr->addr1, bc_addr); - ether_addr_copy(pwlanhdr->addr3, bc_addr); - } - - ether_addr_copy(pwlanhdr->addr2, mac); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - - pmlmeext->mgnt_seq++; - - pframe += sizeof (struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr); - - if (pssid) - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len, - pssid->ssid, &pattrib->pktlen); - else - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL, - &pattrib->pktlen); - - get_rate_set23a(padapter, bssrate, &bssrate_len); - - if (bssrate_len > 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - bssrate, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - (bssrate_len - 8), (bssrate + 8), - &pattrib->pktlen); - } else { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - bssrate_len, bssrate, &pattrib->pktlen); - } - - /* add wps_ie for wps2.0 */ - if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) { - memcpy(pframe, pmlmepriv->wps_probe_req_ie, - pmlmepriv->wps_probe_req_ie_len); - pframe += pmlmepriv->wps_probe_req_ie_len; - pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz); - - if (wait_ack) { - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - } else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -static inline void issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da) -{ - _issue_probereq(padapter, pssid, da, false); -} - -static int issue_probereq_ex(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da, - int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - - do { - ret = _issue_probereq(padapter, pssid, da, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -/* if psta == NULL, indiate we are station(client) now... */ -static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta, - unsigned short status) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned int val32; - u16 auth_algo; - int use_shared_key = 0; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable); - - if (psta) { /* for AP mode */ -#ifdef CONFIG_8723AU_AP_MODE - unsigned short val16; - - ether_addr_copy(mgmt->da, psta->hwaddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv)); - - /* setting auth algo number */ - val16 = (u16)psta->authalg; - - if (status != WLAN_STATUS_SUCCESS) - val16 = 0; - - if (val16) - use_shared_key = 1; - - mgmt->u.auth.auth_alg = cpu_to_le16(val16); - - /* setting auth seq number */ - mgmt->u.auth.auth_transaction = - cpu_to_le16((u16)psta->auth_seq); - - /* setting status code... */ - mgmt->u.auth.status_code = cpu_to_le16(status); - - pframe = mgmt->u.auth.variable; - /* added challenging text... */ - if ((psta->auth_seq == 2) && - (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) - pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128, - psta->chg_txt, &pattrib->pktlen); -#endif - } else { - struct ieee80211_mgmt *iv_mgmt; - - ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network)); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network)); - - /* setting auth algo number */ - /* 0:OPEN System, 1:Shared key */ - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - use_shared_key = 1; - auth_algo = WLAN_AUTH_SHARED_KEY; - } else - auth_algo = WLAN_AUTH_OPEN; - - /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__, - (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED", - pmlmeinfo->auth_seq); */ - - /* setting IV for auth seq #3 */ - if ((pmlmeinfo->auth_seq == 3) && - (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && - (use_shared_key == 1)) { - u32 *piv = (u32 *)&mgmt->u.auth; - - iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4); - /* DBG_8723A("==> iv(%d), key_index(%d)\n", - pmlmeinfo->iv, pmlmeinfo->key_index); */ - val32 = (pmlmeinfo->iv & 0x3fffffff) | - (pmlmeinfo->key_index << 30); - pmlmeinfo->iv++; - put_unaligned_le32(val32, piv); - - pattrib->pktlen += 4; - - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - } else - iv_mgmt = mgmt; - - iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo); - - /* setting auth seq number */ - iv_mgmt->u.auth.auth_transaction = - cpu_to_le16(pmlmeinfo->auth_seq); - - /* setting status code... */ - iv_mgmt->u.auth.status_code = cpu_to_le16(status); - - pframe = iv_mgmt->u.auth.variable; - - /* then checking to see if sending challenging text... */ - if ((pmlmeinfo->auth_seq == 3) && - (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && - (use_shared_key == 1)) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128, - pmlmeinfo->chg_txt, - &pattrib->pktlen); - - mgmt->frame_control |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - - pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40; - - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - - pattrib->pktlen += pattrib->icv_len; - } - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - rtw_wep_encrypt23a(padapter, pmgntframe); - DBG_8723A("%s\n", __func__); - dump_mgntframe23a(padapter, pmgntframe); -} - -#ifdef CONFIG_8723AU_AP_MODE -static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status, - struct sta_info *pstat, u16 pkt_type) -{ - struct xmit_frame *pmgntframe; - struct ieee80211_mgmt *mgmt; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const u8 *p; - u8 *ie = pnetwork->IEs; - - DBG_8723A("%s\n", __func__); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type); - - ether_addr_copy(mgmt->da, pstat->hwaddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - - pmlmeext->mgnt_seq++; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - - mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability); - mgmt->u.assoc_resp.status_code = cpu_to_le16(status); - mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15)); - - pframe = mgmt->u.assoc_resp.variable; - - if (pstat->bssratelen <= 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - pstat->bssratelen, pstat->bssrateset, - &pattrib->pktlen); - } else { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - pstat->bssrateset, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - pstat->bssratelen - 8, - pstat->bssrateset + 8, &pattrib->pktlen); - } - - if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) { - /* FILL HT CAP INFO IE */ - /* p = hostapd_eid_ht_capabilities_info(hapd, p); */ - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie, - pnetwork->IELength); - if (p && p[1]) { - memcpy(pframe, p, p[1] + 2); - pframe += (p[1] + 2); - pattrib->pktlen += (p[1] + 2); - } - - /* FILL HT ADD INFO IE */ - /* p = hostapd_eid_ht_operation(hapd, p); */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, - pnetwork->IELength); - if (p && p[1] > 0) { - memcpy(pframe, p, p[1] + 2); - pframe += (p[1] + 2); - pattrib->pktlen += (p[1] + 2); - } - } - - /* FILL WMM IE */ - if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) { - unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, - 0x01, 0x01}; - int ie_len = 0; - - for (p = ie; ; p += (ie_len + 2)) { - p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p, - pnetwork->IELength - (ie_len + 2)); - if (p) - ie_len = p[1]; - else - ie_len = 0; - if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) { - memcpy(pframe, p, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - - break; - } - - if (!p || ie_len == 0) - break; - } - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, - REALTEK_96B_IE, &pattrib->pktlen); - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} -#endif - -static void issue_assocreq(struct rtw_adapter *padapter) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - const u8 *p; - struct ieee80211_mgmt *mgmt; - unsigned int i, j, index = 0; - unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates]; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int bssrate_len = 0, sta_bssrate_len = 0, pie_len; - u8 *pie; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); - - ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network)); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - /* caps */ - put_unaligned_le16(pmlmeinfo->network.capability, - &mgmt->u.assoc_req.capab_info); - /* todo: listen interval for power saving */ - put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval); - - pframe = mgmt->u.assoc_req.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable); - - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - pmlmeinfo->network.Ssid.ssid_len, - pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen); - - /* supported rate & extended supported rate */ - - get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len); - /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */ - - /* for JAPAN, channel 14 can only uses B Mode(CCK) */ - if (pmlmeext->cur_channel == 14) - sta_bssrate_len = 4; - - /* for (i = 0; i < sta_bssrate_len; i++) { */ - /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */ - /* */ - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - DBG_8723A("network.SupportedRates[%d]=%02X\n", i, - pmlmeinfo->network.SupportedRates[i]); - } - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - - /* Check if the AP's supported rates are also - supported by STA. */ - for (j = 0; j < sta_bssrate_len; j++) { - /* Avoid the proprietary data rate (22Mbps) of - Handlink WSG-4000 AP */ - if ((pmlmeinfo->network.SupportedRates[i] | - IEEE80211_BASIC_RATE_MASK) == - (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) { - /* DBG_8723A("match i = %d, j =%d\n", i, j); */ - break; - } - } - - if (j == sta_bssrate_len) { - /* the rate is not supported by STA */ - DBG_8723A("%s(): the rate[%d]=%02X is not supported by " - "STA!\n", __func__, i, - pmlmeinfo->network.SupportedRates[i]); - } else { - /* the rate is supported by STA */ - bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; - } - } - - bssrate_len = index; - DBG_8723A("bssrate_len = %d\n", bssrate_len); - - if (bssrate_len == 0) { - rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pmgntframe); - goto exit; /* don't connect to AP if no joint supported rate */ - } - - if (bssrate_len > 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - bssrate, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - (bssrate_len - 8), (bssrate + 8), - &pattrib->pktlen); - } else - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - bssrate_len, bssrate, &pattrib->pktlen); - - /* RSN */ - - pie = pmlmeinfo->network.IEs; - pie_len = pmlmeinfo->network.IELength; - - p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len); - if (p) - pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2, - &pattrib->pktlen); - - /* HT caps */ - if (padapter->mlmepriv.htpriv.ht_option) { - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len); - - if (p && !is_ap_in_tkip23a(padapter)) { - struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap; - - memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap)); - - /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */ - if (pregpriv->cbw40_enable == 0) { - cap->cap_info &= ~cpu_to_le16( - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_SUP_WIDTH_20_40); - } else { - cap->cap_info |= cpu_to_le16( - IEEE80211_HT_CAP_SUP_WIDTH_20_40); - } - - /* todo: disable SM power save mode */ - cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS); - - rf_type = rtl8723a_get_rf_type(padapter); - /* switch (pregpriv->rf_config) */ - switch (rf_type) { - case RF_1T1R: - /* RX STBC One spatial stream */ - if (pregpriv->rx_stbc) - cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - - memcpy(&cap->mcs, MCS_rate_1R23A, 16); - break; - - case RF_2T2R: - case RF_1T2R: - default: - /* enable for 2.4/5 GHz */ - if (pregpriv->rx_stbc == 0x3 || - (pmlmeext->cur_wireless_mode & - WIRELESS_11_24N && - /* enable for 2.4GHz */ - pregpriv->rx_stbc == 0x1) || - (pmlmeext->cur_wireless_mode & - WIRELESS_11_5N && - pregpriv->rx_stbc == 0x2) || - /* enable for 5GHz */ - pregpriv->wifi_spec == 1) { - DBG_8723A("declare supporting RX " - "STBC\n"); - /* RX STBC two spatial stream */ - cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - } - memcpy(&cap->mcs, MCS_rate_2R23A, 16); - break; - } - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter)) { - /* set to 8K */ - cap->ampdu_params_info &= - ~IEEE80211_HT_AMPDU_PARM_FACTOR; -/* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */ - } - - pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY, - p[1], (u8 *)&pmlmeinfo->ht_cap, - &pattrib->pktlen); - } - } - - /* vendor specific IE, such as WPA, WMM, WPS */ - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) || - !memcmp(p + 2, WMM_OUI23A, 4) || - !memcmp(p + 2, WPS_OUI23A, 4)) { - u8 plen = p[1]; - - if (!padapter->registrypriv.wifi_spec) { - /* Commented by Kurt 20110629 */ - /* In some older APs, WPS handshake */ - /* would be fail if we append vender - extensions informations to AP */ - if (!memcmp(p + 2, WPS_OUI23A, 4)) - plen = 14; - } - pframe = rtw_set_ie23a(pframe, - WLAN_EID_VENDOR_SPECIFIC, - plen, p + 2, - &pattrib->pktlen); - } - break; - - default: - break; - } - - i += p[1] + 2; - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, - REALTEK_96B_IE, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe23a(padapter, pmgntframe); - - ret = _SUCCESS; - -exit: - pmlmepriv->assoc_req_len = 0; - if (ret == _SUCCESS) { - kfree(pmlmepriv->assoc_req); - pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC); - if (pmlmepriv->assoc_req) { - memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen); - pmlmepriv->assoc_req_len = pattrib->pktlen; - } - } else - kfree(pmlmepriv->assoc_req); -} - -/* when wait_ack is true, this function should be called at process context */ -static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned int power_mode, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - - /* DBG_8723A("%s:%d\n", __func__, power_mode); */ - - if (!padapter) - goto exit; - - pxmitpriv = &padapter->xmitpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC); - - if ((pmlmeinfo->state&0x03) == MSR_AP) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS); - else if ((pmlmeinfo->state&0x03) == MSR_INFRA) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS); - - if (power_mode) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - ether_addr_copy(pwlanhdr->addr1, da); - ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); - ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network)); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* when wait_ms >0 , this function should be called at process context */ -/* da == NULL for station mode */ -int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned int power_mode, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* da == NULL, assume it's null data for sta to ap*/ - if (da == NULL) - da = get_my_bssid23a(&pmlmeinfo->network); - - do { - ret = _issue_nulldata23a(padapter, da, power_mode, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -/* when wait_ack is true, this function should be called at process context */ -static int _issue_qos_nulldata23a(struct rtw_adapter *padapter, - unsigned char *da, u16 tid, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_qos_hdr *pwlanhdr; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - pattrib->hdrlen += 2; - pattrib->qos_en = true; - pattrib->eosp = 1; - pattrib->ack_policy = 0; - pattrib->mdata = 0; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_qos_hdr *)pframe; - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_QOS_NULLFUNC); - - if ((pmlmeinfo->state&0x03) == MSR_AP) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS); - else if ((pmlmeinfo->state&0x03) == MSR_INFRA) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS); - - if (pattrib->mdata) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - - pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK); - pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) & - IEEE80211_QOS_CTL_ACK_POLICY_MASK); - if (pattrib->eosp) - pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - - ether_addr_copy(pwlanhdr->addr1, da); - ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); - ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network)); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pframe += sizeof(struct ieee80211_qos_hdr); - pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* when wait_ms >0 , this function should be called at process context */ -/* da == NULL for station mode */ -int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - u16 tid, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* da == NULL, assume it's null data for sta to ap*/ - if (da == NULL) - da = get_my_bssid23a(&pmlmeinfo->network); - - do { - ret = _issue_qos_nulldata23a(padapter, da, tid, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da, - unsigned short reason, u8 wait_ack) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int ret = _FAIL; - - /* DBG_8723A("%s to %pM\n", __func__, da); */ - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - - ether_addr_copy(mgmt->da, da); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2; - - mgmt->u.deauth.reason_code = cpu_to_le16(reason); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned short reason) -{ - DBG_8723A("%s to %pM\n", __func__, da); - return _issue_deauth(padapter, da, reason, false); -} - -static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da, - unsigned short reason, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - - do { - ret = _issue_deauth(padapter, da, reason, - wait_ms >0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter, - u8 *ra, u8 new_ch, u8 ch_offset) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n", - __func__, padapter->pnetdev->name, ra, new_ch, ch_offset); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); - - ether_addr_copy(mgmt->da, ra); /* RA */ - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */ - ether_addr_copy(mgmt->bssid, ra); /* DA = RA */ - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; - mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH; - - pframe = mgmt->u.action.u.chan_switch.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, - u.action.u.chan_switch.variable); - - pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0, - new_ch, 0); - pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen, - hal_ch_offset_to_secondary_ch_offset23a(ch_offset)); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -void issue_action_BA23a(struct rtw_adapter *padapter, - const unsigned char *raddr, - unsigned char action, unsigned short status) -{ - u16 start_seq; - u16 BA_para_set; - u16 BA_starting_seqctrl; - u16 BA_para; - int max_rx_ampdu_factor; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - u8 tendaAPMac[] = {0xC8, 0x3A, 0x35}; - - DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); - - ether_addr_copy(mgmt->da, raddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - mgmt->u.action.category = WLAN_CATEGORY_BACK; - - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1; - - switch (action) { - case WLAN_ACTION_ADDBA_REQ: - pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req); - - mgmt->u.action.u.addba_req.action_code = action; - - do { - pmlmeinfo->dialogToken++; - } while (pmlmeinfo->dialogToken == 0); - - mgmt->u.action.u.addba_req.dialog_token = - pmlmeinfo->dialogToken; - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter) && - (pmlmeinfo->assoc_AP_vendor != broadcomAP || - memcmp(raddr, tendaAPMac, 3))) { - /* A-MSDU NOT Supported */ - BA_para_set = 0; - /* immediate Block Ack */ - BA_para_set |= (1 << 1) & - IEEE80211_ADDBA_PARAM_POLICY_MASK; - /* TID */ - BA_para_set |= (status << 2) & - IEEE80211_ADDBA_PARAM_TID_MASK; - /* max buffer size is 8 MSDU */ - BA_para_set |= (8 << 6) & - IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - } else { - /* immediate ack & 64 buffer size */ - BA_para_set = 0x1002 | ((status & 0xf) << 2); - } - - put_unaligned_le16(BA_para_set, - &mgmt->u.action.u.addba_req.capab); - - /* 5ms */ - put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout); - - psta = rtw_get_stainfo23a(pstapriv, raddr); - if (psta) { - int idx; - - idx = status & 0x07; - start_seq = - (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1; - - DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n", - start_seq, idx); - - psta->BA_starting_seqctrl[idx] = start_seq; - - BA_starting_seqctrl = start_seq << 4; - } else - BA_starting_seqctrl = 0; - - put_unaligned_le16(BA_starting_seqctrl, - &mgmt->u.action.u.addba_req.start_seq_num); - - break; - - case WLAN_ACTION_ADDBA_RESP: - pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp); - - mgmt->u.action.u.addba_resp.action_code = action; - mgmt->u.action.u.addba_resp.dialog_token = - pmlmeinfo->ADDBA_req.dialog_token; - put_unaligned_le16(status, - &mgmt->u.action.u.addba_resp.status); - - GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, - &max_rx_ampdu_factor); - - BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f; - if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K) - BA_para_set = BA_para | 0x1000; /* 64 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K) - BA_para_set = BA_para | 0x0800; /* 32 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K) - BA_para_set = BA_para | 0x0400; /* 16 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K) - BA_para_set = BA_para | 0x0200; /* 8 buffer size */ - else - BA_para_set = BA_para | 0x1000; /* 64 buffer size */ - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter) && - (pmlmeinfo->assoc_AP_vendor != broadcomAP || - memcmp(raddr, tendaAPMac, 3))) { - /* max buffer size is 8 MSDU */ - BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - BA_para_set |= (8 << 6) & - IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - } - - if (pregpriv->ampdu_amsdu == 0)/* disabled */ - BA_para_set &= ~BIT(0); - else if (pregpriv->ampdu_amsdu == 1)/* enabled */ - BA_para_set |= BIT(0); - - put_unaligned_le16(BA_para_set, - &mgmt->u.action.u.addba_resp.capab); - - mgmt->u.action.u.addba_resp.timeout - = pmlmeinfo->ADDBA_req.BA_timeout_value; - - pattrib->pktlen += 8; - break; - case WLAN_ACTION_DELBA: - pattrib->pktlen += sizeof(mgmt->u.action.u.delba); - - mgmt->u.action.u.delba.action_code = action; - BA_para_set = (status & 0x1F) << 3; - mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set); - mgmt->u.action.u.delba.reason_code = - cpu_to_le16(WLAN_REASON_QSTA_NOT_USE); - - pattrib->pktlen += 5; - break; - default: - break; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta = NULL; - /* struct recv_reorder_ctrl *preorder_ctrl; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u16 tid; - - if ((pmlmeinfo->state&0x03) != MSR_AP) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - psta = rtw_get_stainfo23a(pstapriv, addr); - if (psta == NULL) - return _SUCCESS; - - if (initiator == 0) { /* recipient */ - for (tid = 0; tid < MAXTID; tid++) { - if (psta->recvreorder_ctrl[tid].enable == true) { - DBG_8723A("rx agg disable tid(%d)\n", tid); - issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F)); - psta->recvreorder_ctrl[tid].enable = false; - psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; - } - } - } else if (initiator == 1) { /* originator */ - for (tid = 0; tid < MAXTID; tid++) { - if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { - DBG_8723A("tx agg disable tid(%d)\n", tid); - issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F)); - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - - } - } - } - return _SUCCESS; -} - -int send_beacon23a(struct rtw_adapter *padapter) -{ - bool bxmitok; - int issue = 0; - int poll = 0; - unsigned long start = jiffies; - unsigned int passing_time; - - rtl8723a_bcn_valid(padapter); - do { - issue_beacon23a(padapter, 100); - issue++; - do { - yield(); - bxmitok = rtl8723a_get_bcn_valid(padapter); - poll++; - } while ((poll % 10) != 0 && !bxmitok && - !padapter->bSurpriseRemoved && - !padapter->bDriverStopped); - - } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved && - !padapter->bDriverStopped); - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped) - return _FAIL; - - passing_time = jiffies_to_msecs(jiffies - start); - - if (!bxmitok) { - DBG_8723A("%s fail! %u ms\n", __func__, passing_time); - return _FAIL; - } else { - - if (passing_time > 100 || issue > 3) - DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n", - __func__, issue, poll, passing_time); - return _SUCCESS; - } -} - -/**************************************************************************** - -Following are some utitity functions for WiFi MLME - -*****************************************************************************/ - -bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel) -{ - - int i = 0; - u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, - 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, - 161, 163, 165}; - for (i = 0; i < sizeof(Channel_5G); i++) - if (channel == Channel_5G[i]) - return true; - return false; -} - -static void rtw_site_survey(struct rtw_adapter *padapter) -{ - unsigned char survey_channel = 0; - enum rt_scan_type ScanType = SCAN_PASSIVE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct rtw_ieee80211_channel *ch; - - if (pmlmeext->sitesurvey_res.channel_idx < - pmlmeext->sitesurvey_res.ch_num) { - ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx]; - survey_channel = ch->hw_value; - ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ? - SCAN_PASSIVE : SCAN_ACTIVE; - } - - if (survey_channel != 0) { - /* PAUSE 4-AC Queue when site_survey */ - if (pmlmeext->sitesurvey_res.channel_idx == 0) - set_channel_bwmode23a(padapter, survey_channel, - HAL_PRIME_CHNL_OFFSET_DONT_CARE, - HT_CHANNEL_WIDTH_20); - else - SelectChannel23a(padapter, survey_channel); - - if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */ - { - int i; - - for (i = 0;isitesurvey_res.ssid[i].ssid_len) { - /* todo: to issue two probe req??? */ - issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL); - /* msleep(SURVEY_TO>>1); */ - issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL); - } - } - - if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { - /* todo: to issue two probe req??? */ - issue_probereq(padapter, NULL, NULL); - /* msleep(SURVEY_TO>>1); */ - issue_probereq(padapter, NULL, NULL); - } - } - - set_survey_timer(pmlmeext, pmlmeext->chan_scan_time); - } else { - /* channel number is 0 or this channel is not valid. */ - pmlmeext->sitesurvey_res.state = SCAN_COMPLETE; - - /* switch back to the original channel */ - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, - pmlmeext->cur_bwmode); - - /* flush 4-AC Queue after rtw_site_survey */ - /* val8 = 0; */ - - /* config MSR */ - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - /* restore RX GAIN */ - rtl8723a_set_initial_gain(padapter, 0xff); - /* turn on dynamic functions */ - rtl8723a_odm_support_ability_restore(padapter); - - if (is_client_associated_to_ap23a(padapter) == true) - issue_nulldata23a(padapter, NULL, 0, 3, 500); - - rtl8723a_mlme_sitesurvey(padapter, 0); - - report_surveydone_event23a(padapter); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - } -} - -/* collect bss info from Beacon and Probe request/response frames. */ -static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *bssid; - const u8 *p; - u8 *pie; - unsigned int length; - int i; - - length = skb->len; - - bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); - if (!bssid) - return NULL; - - if (ieee80211_is_beacon(mgmt->frame_control)) { - length -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - pie = mgmt->u.beacon.variable; - bssid->reserved = 1; - bssid->capability = - get_unaligned_le16(&mgmt->u.beacon.capab_info); - bssid->beacon_interval = - get_unaligned_le16(&mgmt->u.beacon.beacon_int); - bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp); - } else if (ieee80211_is_probe_req(mgmt->frame_control)) { - length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable); - pie = mgmt->u.probe_req.variable; - bssid->reserved = 2; - bssid->capability = 0; - bssid->beacon_interval = - padapter->registrypriv.dev_network.beacon_interval; - bssid->tsf = 0; - } else if (ieee80211_is_probe_resp(mgmt->frame_control)) { - length -= - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - pie = mgmt->u.probe_resp.variable; - bssid->reserved = 3; - bssid->capability = - get_unaligned_le16(&mgmt->u.probe_resp.capab_info); - bssid->beacon_interval = - get_unaligned_le16(&mgmt->u.probe_resp.beacon_int); - bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp); - } else { - length -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - pie = mgmt->u.beacon.variable; - bssid->reserved = 0; - bssid->capability = - get_unaligned_le16(&mgmt->u.beacon.capab_info); - bssid->beacon_interval = - padapter->registrypriv.dev_network.beacon_interval; - bssid->tsf = 0; - } - - if (length > MAX_IE_SZ) { - /* DBG_8723A("IE too long for survey event\n"); */ - kfree(bssid); - return NULL; - } - - bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length; - - /* below is to copy the information element */ - bssid->IELength = length; - memcpy(bssid->IEs, pie, bssid->IELength); - - /* get the signal strength */ - /* in dBM.raw data */ - bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower; - bssid->SignalQuality = - precv_frame->attrib.phy_info.SignalQuality;/* in percentage */ - bssid->SignalStrength = - precv_frame->attrib.phy_info.SignalStrength;/* in percentage */ - - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength); - - if (!p) { - DBG_8723A("marc: cannot find SSID for survey event\n"); - goto fail; - } - - if (p[1] > IEEE80211_MAX_SSID_LEN) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->Ssid.ssid, p + 2, p[1]); - bssid->Ssid.ssid_len = p[1]; - - /* checking rate info... */ - i = 0; - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength); - if (p) { - if (p[1] > NDIS_802_11_LENGTH_RATES_EX) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->SupportedRates, p + 2, p[1]); - i = p[1]; - } - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs, - bssid->IELength); - if (p) { - if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->SupportedRates + i, p + 2, p[1]); - } - - /* Checking for DSConfig */ - p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength); - - bssid->DSConfig = 0; - - if (p) { - bssid->DSConfig = p[2]; - } else {/* In 5G, some ap do not have DSSET IE */ - /* checking HT info for channel */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs, - bssid->IELength); - if (p) { - struct ieee80211_ht_operation *HT_info = - (struct ieee80211_ht_operation *)(p + 2); - bssid->DSConfig = HT_info->primary_chan; - } else /* use current channel */ - bssid->DSConfig = rtw_get_oper_ch23a(padapter); - } - - if (ieee80211_is_probe_req(mgmt->frame_control)) { - /* FIXME */ - bssid->ifmode = NL80211_IFTYPE_STATION; - ether_addr_copy(bssid->MacAddress, mgmt->sa); - bssid->Privacy = 1; - return bssid; - } - - if (bssid->capability & WLAN_CAPABILITY_ESS) { - bssid->ifmode = NL80211_IFTYPE_STATION; - ether_addr_copy(bssid->MacAddress, mgmt->sa); - } else { - bssid->ifmode = NL80211_IFTYPE_ADHOC; - ether_addr_copy(bssid->MacAddress, mgmt->bssid); - } - - if (bssid->capability & WLAN_CAPABILITY_PRIVACY) - bssid->Privacy = 1; - else - bssid->Privacy = 0; - - bssid->ATIMWindow = 0; - - /* 20/40 BSS Coexistence check */ - if (pregistrypriv->wifi_spec == 1 && - pmlmeinfo->bwmode_updated == false) { - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs, - bssid->IELength); - if (p && p[1] > 0) { - struct ieee80211_ht_cap *pHT_caps; - - pHT_caps = (struct ieee80211_ht_cap *)(p + 2); - - if (pHT_caps->cap_info & - cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT)) - pmlmepriv->num_FortyMHzIntolerant++; - } else - pmlmepriv->num_sta_no_ht++; - } - - - /* mark bss info receiving from nearby channel as SignalQuality 101 */ - if (bssid->DSConfig != rtw_get_oper_ch23a(padapter)) - bssid->SignalQuality = 101; - - return bssid; -fail: - kfree (bssid); - return NULL; -} - -static void start_create_ibss(struct rtw_adapter *padapter) -{ - unsigned short caps; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - - pmlmeext->cur_channel = (u8)pnetwork->DSConfig; - pmlmeinfo->bcn_interval = pnetwork->beacon_interval; - - /* update wireless mode */ - update_wireless_mode23a(padapter); - - /* update capability */ - caps = pnetwork->capability; - update_capinfo23a(padapter, caps); - if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */ - rtl8723a_set_sec_cfg(padapter, 0xcf); - - /* switch channel */ - /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - - rtl8723a_SetBeaconRelatedRegisters(padapter); - - /* set msr to MSR_ADHOC */ - pmlmeinfo->state = MSR_ADHOC; - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - /* issue beacon */ - if (send_beacon23a(padapter) == _FAIL) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "issuing beacon frame fail....\n"); - - report_join_res23a(padapter, -1); - pmlmeinfo->state = MSR_NOLINK; - } else { - hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - report_join_res23a(padapter, 1); - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - } - } else { - DBG_8723A("%s: invalid cap:%x\n", __func__, caps); - return; - } -} - -static void start_clnt_join(struct rtw_adapter *padapter) -{ - unsigned short caps; - u8 val8; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - int beacon_timeout; - - pmlmeext->cur_channel = (u8)pnetwork->DSConfig; - pmlmeinfo->bcn_interval = pnetwork->beacon_interval; - - /* update wireless mode */ - update_wireless_mode23a(padapter); - - /* update capability */ - caps = pnetwork->capability; - update_capinfo23a(padapter, caps); - if (caps & WLAN_CAPABILITY_ESS) { - /* switch channel */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - rtl8723a_set_media_status(padapter, MSR_INFRA); - - val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? - 0xcc: 0xcf; - - rtl8723a_set_sec_cfg(padapter, val8); - - /* switch channel */ - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - - /* here wait for receiving the beacon to start auth */ - /* and enable a timer */ - beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval); - set_link_timer(pmlmeext, beacon_timeout); - mod_timer(&padapter->mlmepriv.assoc_timer, jiffies + - msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout)); - pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA; - } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */ - rtl8723a_set_media_status(padapter, MSR_ADHOC); - - rtl8723a_set_sec_cfg(padapter, 0xcf); - - /* switch channel */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - rtl8723a_SetBeaconRelatedRegisters(padapter); - - pmlmeinfo->state = MSR_ADHOC; - - report_join_res23a(padapter, 1); - } else { - /* DBG_8723A("marc: invalid cap:%x\n", caps); */ - return; - } -} - -static void start_clnt_auth(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - del_timer_sync(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); - pmlmeinfo->state |= WIFI_FW_AUTH_STATE; - - pmlmeinfo->auth_seq = 1; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeext->retry = 0; - - /* Because of AP's not receiving deauth before */ - /* AP may: 1)not response auth or 2)deauth us after link is complete */ - /* issue deauth before issuing auth to deal with the situation */ - /* Commented by Albert 2012/07/21 */ - /* For the Win8 P2P connection, it will be hard to have a - successful connection if this Wi-Fi doesn't connect to it. */ - issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress, - WLAN_REASON_DEAUTH_LEAVING); - - DBG_8723A_LEVEL(_drv_always_, "start auth\n"); - issue_auth(padapter, NULL, 0); - - set_link_timer(pmlmeext, REAUTH_TO); -} - -static void start_clnt_assoc(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - del_timer_sync(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); - pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); - - issue_assocreq(padapter); - - set_link_timer(pmlmeext, REASSOC_TO); -} - -int receive_disconnect23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, unsigned short reason) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* check A3 */ - if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state&0x03) == MSR_INFRA) { - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - pmlmeinfo->state = MSR_NOLINK; - report_del_sta_event23a(padapter, MacAddr, reason); - - } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -2); - } - } - - return _SUCCESS; -} - -static void process_80211d(struct rtw_adapter *padapter, - struct wlan_bssid_ex *bssid) -{ - struct registry_priv *pregistrypriv; - struct mlme_ext_priv *pmlmeext; - struct rt_channel_info *chplan_new; - u8 channel; - u8 i; - - pregistrypriv = &padapter->registrypriv; - pmlmeext = &padapter->mlmeextpriv; - - /* Adjust channel plan by AP Country IE */ - if (pregistrypriv->enable80211d && - !pmlmeext->update_channel_plan_by_ap_done) { - const u8 *ie, *p; - struct rt_channel_plan chplan_ap; - struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM]; - u8 country[4]; - u8 fcn; /* first channel number */ - u8 noc; /* number of channel */ - u8 j, k; - - ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs, - bssid->IELength); - if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN) - return; - - p = ie + 2; - ie += ie[1]; - ie += 2; - - memcpy(country, p, 3); - country[3] = '\0'; - - p += 3; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "%s: 802.11d country =%s\n", __func__, country); - - i = 0; - while ((ie - p) >= 3) { - fcn = *(p++); - noc = *(p++); - p++; - - for (j = 0; j < noc; j++) { - if (fcn <= 14) - channel = fcn + j; /* 2.4 GHz */ - else - channel = fcn + j * 4; /* 5 GHz */ - - chplan_ap.Channel[i++] = channel; - } - } - chplan_ap.Len = i; - - memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta)); - memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set)); - chplan_new = pmlmeext->channel_set; - - i = j = k = 0; - if (pregistrypriv->wireless_mode & WIRELESS_11G) { - do { - if (i == MAX_CHANNEL_NUM || - chplan_sta[i].ChannelNum == 0 || - chplan_sta[i].ChannelNum > 14) - break; - - if (j == chplan_ap.Len || - chplan_ap.Channel[j] > 14) - break; - - if (chplan_sta[i].ChannelNum == - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - i++; - j++; - k++; - } else if (chplan_sta[i].ChannelNum < - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = - SCAN_PASSIVE; - i++; - k++; - } else if (chplan_sta[i].ChannelNum > - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_ap.Channel[j]; - chplan_new[k].ScanType = - SCAN_ACTIVE; - j++; - k++; - } - } while (1); - - /* change AP not support channel to Passive scan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0 && - chplan_sta[i].ChannelNum <= 14) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } - - /* add channel AP supported */ - while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){ - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 2.4G channel plan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0 && - chplan_sta[i].ChannelNum <= 14) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - - /* skip AP 2.4G channel plan */ - while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14) - j++; - } - - if (pregistrypriv->wireless_mode & WIRELESS_11A) { - do { - if (i == MAX_CHANNEL_NUM || - chplan_sta[i].ChannelNum == 0) - break; - - if (j == chplan_ap.Len || - chplan_ap.Channel[j] == 0) - break; - - if (chplan_sta[i].ChannelNum == - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - i++; - j++; - k++; - } else if (chplan_sta[i].ChannelNum < - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } else if (chplan_sta[i].ChannelNum > - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } while (1); - - /* change AP not support channel to Passive scan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } - - /* add channel AP supported */ - while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 5G channel plan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - } - pmlmeext->update_channel_plan_by_ap_done = 1; - } - - /* If channel is used by AP, set channel scan type to active */ - channel = bssid->DSConfig; - chplan_new = pmlmeext->channel_set; - i = 0; - while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) { - if (chplan_new[i].ChannelNum == channel) { - if (chplan_new[i].ScanType == SCAN_PASSIVE) { - /* 5G Bnad 2, 3 (DFS) doesn't change - to active scan */ - if (channel >= 52 && channel <= 144) - break; - - chplan_new[i].ScanType = SCAN_ACTIVE; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "%s: change channel %d scan type from passive to active\n", - __func__, channel); - } - break; - } - i++; - } -} - -/**************************************************************************** - -Following are the functions to report events - -*****************************************************************************/ - -void report_survey_event23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct survey_event *psurvey_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext; - struct cmd_priv *pcmdpriv; - - if (!padapter) - return; - - pmlmeext = &padapter->mlmeextpriv; - pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct survey_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - - psurvey_evt->bss = collect_bss_info(padapter, precv_frame); - if (!psurvey_evt->bss) { - kfree(pcmd_obj); - kfree(pevtcmd); - return; - } - - process_80211d(padapter, psurvey_evt->bss); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); - - pmlmeext->sitesurvey_res.bss_cnt++; -} - -void report_surveydone_event23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct surveydone_event *psurveydone_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct surveydone_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; - - DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_join_res23a(struct rtw_adapter *padapter, int res) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct joinbss_event *pjoinbss_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct joinbss_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)&pjoinbss_evt->network.network, - &pmlmeinfo->network, sizeof(struct wlan_bssid_ex)); - pjoinbss_evt->network.join_res = res; - - DBG_8723A("report_join_res23a(%d)\n", res); - - rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_del_sta_event23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, unsigned short reason) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct sta_info *psta; - int mac_id; - struct stadel_event *pdel_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stadel_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr); - memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason, - 2); - - psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr); - if (psta) - mac_id = (int)psta->mac_id; - else - mac_id = -1; - - pdel_sta_evt->mac_id = mac_id; - - DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_add_sta_event23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, int cam_idx) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct stassoc_event *padd_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stassoc_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr); - padd_sta_evt->cam_id = cam_idx; - - DBG_8723A("report_add_sta_event23a: add STA\n"); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -/**************************************************************************** - -Following are the event callback functions - -*****************************************************************************/ - -/* for sta/adhoc mode */ -void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* ERP */ - VCS_update23a(padapter, psta); - - /* HT */ - if (pmlmepriv->htpriv.ht_option) { - psta->htpriv.ht_option = true; - - psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; - - if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap)) - psta->htpriv.sgi = true; - - psta->qos_option = true; - - } else { - psta->htpriv.ht_option = false; - - psta->htpriv.ampdu_enable = false; - - psta->htpriv.sgi = false; - psta->qos_option = false; - - } - psta->htpriv.bwmode = pmlmeext->cur_bwmode; - psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; - - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ - - /* QoS */ - if (pmlmepriv->qos_option) - psta->qos_option = true; - - psta->state = _FW_LINKED; -} - -void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, - int join_res) -{ - struct sta_info *psta, *psta_bmc; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (join_res < 0) { - hw_var_set_mlme_join(padapter, 1); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, - padapter->registrypriv.wireless_mode); - - goto exit_mlmeext_joinbss_event_callback23a; - } - - if ((pmlmeinfo->state&0x03) == MSR_ADHOC) { - /* for bc/mc */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (psta_bmc) { - pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc; - update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id); - Update_RA_Entry23a(padapter, psta_bmc); - } - } - - /* turn on dynamic functions */ - rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE); - - /* update IOT-releated issue */ - update_IOT_info23a(padapter); - - HalSetBrateCfg23a(padapter, cur_network->SupportedRates); - - /* BCN interval */ - rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval); - - /* update capability */ - update_capinfo23a(padapter, pmlmeinfo->capability); - - /* WMM, Update EDCA param */ - WMMOnAssocRsp23a(padapter); - - /* HT */ - HTOnAssocRsp23a(padapter); - - /* Set cur_channel&cur_bwmode&cur_ch_offset */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - if (psta) { /* only for infra. mode */ - pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; - - /* DBG_8723A("set_sta_rate23a\n"); */ - - psta->wireless_mode = pmlmeext->cur_wireless_mode; - - /* set per sta rate after updating HT cap. */ - set_sta_rate23a(padapter, psta); - } - - hw_var_set_mlme_join(padapter, 2); - - if ((pmlmeinfo->state&0x03) == MSR_INFRA) { - /* correcting TSF */ - rtw_correct_TSF(padapter); - - /* set_link_timer(pmlmeext, DISCONNECT_TO); */ - } - - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0); - -exit_mlmeext_joinbss_event_callback23a: - DBG_8723A("=>%s\n", __func__); -} - -void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) { - /* adhoc master or sta_count>1 */ - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - /* nothing to do */ - } else { /* adhoc client */ - /* correcting TSF */ - rtw_correct_TSF(padapter); - - /* start beacon */ - if (send_beacon23a(padapter) != _SUCCESS) { - pmlmeinfo->FW_sta_info[psta->mac_id].status = 0; - - pmlmeinfo->state ^= MSR_ADHOC; - - return; - } - - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - } - hw_var_set_mlme_join(padapter, 2); - } - - pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; - - /* rate radaptive */ - Update_RA_Entry23a(padapter, psta); - - /* update adhoc sta_info */ - update_sta_info23a(padapter, psta); -} - -void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (is_client_associated_to_ap23a(padapter) || - is_IBSS_empty23a(padapter)) { - /* set_opmode_cmd(padapter, infra_client_with_mlme); */ - - hw_var_set_mlme_disconnect(padapter); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, - padapter->registrypriv.wireless_mode); - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, - pmlmeext->cur_bwmode); - - flush_all_cam_entry23a(padapter); - - pmlmeinfo->state = MSR_NOLINK; - - /* set MSR to no link state -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - del_timer_sync(&pmlmeext->link_timer); - } -} - -static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 ret = false; - - if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) && - sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) && - sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)) - ret = false; - else - ret = true; - - sta_update_last_rx_pkts(psta); - return ret; -} - -void linked_status_chk23a(struct rtw_adapter *padapter) -{ - u32 i; - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (is_client_associated_to_ap23a(padapter)) { - /* linked infrastructure client mode */ - - int tx_chk = _SUCCESS, rx_chk = _SUCCESS; - int rx_chk_limit; - - rx_chk_limit = 4; - - psta = rtw_get_stainfo23a(pstapriv, - pmlmeinfo->network.MacAddress); - if (psta) { - bool is_p2p_enable = false; - - if (chk_ap_is_alive(padapter, psta) == false) - rx_chk = _FAIL; - - if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts) - tx_chk = _FAIL; - - if (pmlmeext->active_keep_alive_check && - (rx_chk == _FAIL || tx_chk == _FAIL)) { - u8 backup_oper_channel = 0; - - /* switch to correct channel of current - network before issue keep-alive frames */ - if (rtw_get_oper_ch23a(padapter) != - pmlmeext->cur_channel) { - backup_oper_channel = - rtw_get_oper_ch23a(padapter); - SelectChannel23a(padapter, - pmlmeext->cur_channel); - } - - if (rx_chk != _SUCCESS) - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1); - - if ((tx_chk != _SUCCESS && - pmlmeinfo->link_count++ == 0xf) || - rx_chk != _SUCCESS) { - tx_chk = issue_nulldata23a(padapter, - psta->hwaddr, - 0, 3, 1); - /* if tx acked and p2p disabled, - set rx_chk _SUCCESS to reset retry - count */ - if (tx_chk == _SUCCESS && - !is_p2p_enable) - rx_chk = _SUCCESS; - } - - /* back to the original operation channel */ - if (backup_oper_channel>0) - SelectChannel23a(padapter, - backup_oper_channel); - } else { - if (rx_chk != _SUCCESS) { - if (pmlmeext->retry == 0) { - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - } - } - - if (tx_chk != _SUCCESS && - pmlmeinfo->link_count++ == 0xf) - tx_chk = issue_nulldata23a(padapter, - NULL, 0, 1, - 0); - } - - if (rx_chk == _FAIL) { - pmlmeext->retry++; - if (pmlmeext->retry > rx_chk_limit) { - DBG_8723A_LEVEL(_drv_always_, - "%s(%s): disconnect or " - "roaming\n", __func__, - padapter->pnetdev->name); - receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, - WLAN_REASON_EXPIRATION_CHK); - return; - } - } else - pmlmeext->retry = 0; - - if (tx_chk == _FAIL) - pmlmeinfo->link_count &= 0xf; - else { - pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts; - pmlmeinfo->link_count = 0; - } - - } - } else if (is_client_associated_to_ibss23a(padapter)) { - /* linked IBSS mode */ - /* for each assoc list entry to check the rx pkt counter */ - for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { - if (pmlmeinfo->FW_sta_info[i].status == 1) { - psta = pmlmeinfo->FW_sta_info[i].psta; - - if (!psta) - continue; - - if (pmlmeinfo->FW_sta_info[i].rx_pkt == - sta_rx_pkts(psta)) { - - if (pmlmeinfo->FW_sta_info[i].retry<3) { - pmlmeinfo->FW_sta_info[i].retry++; - } else { - pmlmeinfo->FW_sta_info[i].retry = 0; - pmlmeinfo->FW_sta_info[i].status = 0; - report_del_sta_event23a(padapter, psta->hwaddr, - 65535/* indicate disconnect caused by no rx */ - ); - } - } else { - pmlmeinfo->FW_sta_info[i].retry = 0; - pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta); - } - } - } - /* set_link_timer(pmlmeext, DISCONNECT_TO); */ - } -} - -static void survey_timer_hdl(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - /* issue rtw_sitesurvey_cmd23a */ - if (pmlmeext->sitesurvey_res.state > SCAN_START) { - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) - pmlmeext->sitesurvey_res.channel_idx++; - - if (pmlmeext->scan_abort == true) { - pmlmeext->sitesurvey_res.channel_idx = - pmlmeext->sitesurvey_res.ch_num; - DBG_8723A("%s idx:%d\n", __func__, - pmlmeext->sitesurvey_res.channel_idx); - - pmlmeext->scan_abort = false;/* reset */ - } - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) - goto exit_survey_timer_hdl; - - psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), - GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - goto exit_survey_timer_hdl; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, - GEN_CMD_CODE(_SiteSurvey)); - rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } - -exit_survey_timer_hdl: - return; -} - -static void link_timer_hdl(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - /* static unsigned int rx_pkt = 0; */ - /* static u64 tx_cnt = 0; */ - /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - /* struct sta_priv *pstapriv = &padapter->stapriv; */ - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - DBG_8723A("link_timer_hdl:no beacon while connecting\n"); - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -3); - } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { - /* re-auth timer */ - if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { - /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */ - /* */ - pmlmeinfo->state = 0; - report_join_res23a(padapter, -1); - return; - /* */ - /* else */ - /* */ - /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */ - /* pmlmeinfo->reauth_count = 0; */ - /* */ - } - - DBG_8723A("link_timer_hdl: auth timeout and try again\n"); - pmlmeinfo->auth_seq = 1; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { - /* re-assoc timer */ - if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -2); - return; - } - - DBG_8723A("link_timer_hdl: assoc timeout and try again\n"); - issue_assocreq(padapter); - set_link_timer(pmlmeext, REASSOC_TO); - } -} - -static void addba_timer_hdl(unsigned long data) -{ - struct sta_info *psta = (struct sta_info *)data; - struct ht_priv *phtpriv; - - if (!psta) - return; - - phtpriv = &psta->htpriv; - - if (phtpriv->ht_option && phtpriv->ampdu_enable) { - if (phtpriv->candidate_tid_bitmap) - phtpriv->candidate_tid_bitmap = 0x0; - } -} - -void init_addba_retry_timer23a(struct sta_info *psta) -{ - setup_timer(&psta->addba_retry_timer, addba_timer_hdl, - (unsigned long)psta); -} - -void init_mlme_ext_timer23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - setup_timer(&pmlmeext->survey_timer, survey_timer_hdl, - (unsigned long)padapter); - - setup_timer(&pmlmeext->link_timer, link_timer_hdl, - (unsigned long)padapter); -} - -int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_SUCCESS; -} - -int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - enum nl80211_iftype type; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; - - switch (psetop->mode) { - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - pmlmeinfo->state = MSR_AP; - type = MSR_AP; - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - /* clear state */ - pmlmeinfo->state &= ~(BIT(0)|BIT(1)); - /* set to STATION_STATE */ - pmlmeinfo->state |= MSR_INFRA; - type = MSR_INFRA; - break; - case NL80211_IFTYPE_ADHOC: - type = MSR_ADHOC; - break; - default: - type = MSR_NOLINK; - break; - } - - hw_var_set_opmode(padapter, type); - /* Set_NETYPE0_MSR(padapter, type); */ - - return H2C_SUCCESS; -} - -int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf; - /* u32 initialgain; */ - - if (pparm->ifmode == NL80211_IFTYPE_AP || - pparm->ifmode == NL80211_IFTYPE_P2P_GO) { -#ifdef CONFIG_8723AU_AP_MODE - if (pmlmeinfo->state == MSR_AP) { - /* todo: */ - return H2C_SUCCESS; - } -#endif - } - - /* below is for ad-hoc master */ - if (pparm->ifmode == NL80211_IFTYPE_ADHOC) { - rtw_joinbss_reset23a(padapter); - - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - - /* disable dynamic functions, such as high power, DIG */ - rtl8723a_odm_support_ability_backup(padapter); - - rtl8723a_odm_support_ability_clr(padapter, - DYNAMIC_FUNC_DISABLE); - - /* cancel link timer */ - del_timer_sync(&pmlmeext->link_timer); - - /* clear CAM */ - flush_all_cam_entry23a(padapter); - - if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex)); - - start_create_ibss(padapter); - } - - return H2C_SUCCESS; -} - -int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf; - struct ieee80211_ht_operation *pht_info; - u32 i; - u8 *p; - /* u32 initialgain; */ - /* u32 acparm; */ - - /* check already connecting to AP or not */ - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - if (pmlmeinfo->state & MSR_INFRA) - issue_deauth_ex(padapter, pnetwork->MacAddress, - WLAN_REASON_DEAUTH_LEAVING, 5, 100); - - pmlmeinfo->state = MSR_NOLINK; - - /* clear CAM */ - flush_all_cam_entry23a(padapter); - - del_timer_sync(&pmlmeext->link_timer); - - /* set MSR to nolink -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - hw_var_set_mlme_disconnect(padapter); - } - - rtw_joinbss_reset23a(padapter); - - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - pmlmeinfo->bwmode_updated = false; - /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ - - if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex)); - - /* Check AP vendor to move rtw_joinbss_cmd23a() */ - /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs, - pnetwork->IELength); */ - - for (i = 0; i < pnetwork->IELength;) { - p = pnetwork->IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */ - if (!memcmp(p + 2, WMM_OUI23A, 4)) - pmlmeinfo->WMM_enable = 1; - break; - - case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */ - pmlmeinfo->HT_caps_enable = 1; - break; - - case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */ - pmlmeinfo->HT_info_enable = 1; - - /* spec case only for cisco's ap because cisco's ap - * issue assoc rsp using mcs rate @40MHz or @20MHz */ - pht_info = (struct ieee80211_ht_operation *)(p + 2); - - if (pregpriv->cbw40_enable && - (pht_info->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { - /* switch to the 40M Hz mode according to AP */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pht_info->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_LOWER; - break; - - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_UPPER; - break; - - default: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - - DBG_8723A("set ch/bw before connected\n"); - } - break; - - default: - break; - } - - i += (p[1] + 2); - } - - hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - /* cancel link timer */ - del_timer_sync(&pmlmeext->link_timer); - - start_clnt_join(padapter); - - return H2C_SUCCESS; -} - -int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct disconnect_parm *param = (struct disconnect_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - - if (is_client_associated_to_ap23a(padapter)) { - issue_deauth_ex(padapter, pnetwork->MacAddress, - WLAN_REASON_DEAUTH_LEAVING, - param->deauth_timeout_ms/100, 100); - } - - /* set_opmode_cmd(padapter, infra_client_with_mlme); */ - - /* pmlmeinfo->state = MSR_NOLINK; */ - - hw_var_set_mlme_disconnect(padapter); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC || - (pmlmeinfo->state & 0x03) == MSR_AP) - rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */ - - /* set MSR to no link state -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - pmlmeinfo->state = MSR_NOLINK; - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - flush_all_cam_entry23a(padapter); - - del_timer_sync(&pmlmeext->link_timer); - - rtw_free_uc_swdec_pending_queue23a(padapter); - - return H2C_SUCCESS; -} - -static int -rtw_scan_ch_decision(struct rtw_adapter *padapter, - struct rtw_ieee80211_channel *out, u32 out_num, - const struct rtw_ieee80211_channel *in, u32 in_num) -{ - int i, j; - int scan_ch_num = 0; - int set_idx; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - /* clear out first */ - memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num); - - /* acquire channels from in */ - j = 0; - for (i = 0;ichannel_set, - in[i].hw_value)) >= 0) { - memcpy(&out[j], &in[i], - sizeof(struct rtw_ieee80211_channel)); - - if (pmlmeext->channel_set[set_idx].ScanType == - SCAN_PASSIVE) - out[j].flags &= IEEE80211_CHAN_NO_IR; - - j++; - } - if (j>= out_num) - break; - } - - /* if out is empty, use channel_set as default */ - if (j == 0) { - for (i = 0;imax_chan_nums;i++) { - out[i].hw_value = pmlmeext->channel_set[i].ChannelNum; - - if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) - out[i].flags &= IEEE80211_CHAN_NO_IR; - - j++; - } - } - - if (padapter->setband == GHZ_24) { /* 2.4G */ - for (i = 0; i < j ; i++) { - if (out[i].hw_value > 35) - memset(&out[i], 0, - sizeof(struct rtw_ieee80211_channel)); - else - scan_ch_num++; - } - j = scan_ch_num; - } else if (padapter->setband == GHZ_50) { /* 5G */ - for (i = 0; i < j ; i++) { - if (out[i].hw_value > 35) { - memcpy(&out[scan_ch_num++], &out[i], - sizeof(struct rtw_ieee80211_channel)); - } - } - j = scan_ch_num; - } else - {} - - return j; -} - -int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; - u8 bdelayscan = false; - u32 initialgain; - u32 i; - - if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { - pmlmeext->sitesurvey_res.state = SCAN_START; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->sitesurvey_res.channel_idx = 0; - - for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (pparm->ssid[i].ssid_len) { - memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, - pparm->ssid[i].ssid, - IEEE80211_MAX_SSID_LEN); - pmlmeext->sitesurvey_res.ssid[i].ssid_len = - pparm->ssid[i].ssid_len; - } else { - pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0; - } - } - - pmlmeext->sitesurvey_res.ch_num = - rtw_scan_ch_decision(padapter, - pmlmeext->sitesurvey_res.ch, - RTW_CHANNEL_SCAN_AMOUNT, - pparm->ch, pparm->ch_num); - - pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode; - - /* issue null data if associating to the AP */ - if (is_client_associated_to_ap23a(padapter)) { - pmlmeext->sitesurvey_res.state = SCAN_TXNULL; - - /* switch to correct channel of current network - before issue keep-alive frames */ - if (rtw_get_oper_ch23a(padapter) != - pmlmeext->cur_channel) - SelectChannel23a(padapter, - pmlmeext->cur_channel); - - issue_nulldata23a(padapter, NULL, 1, 3, 500); - - bdelayscan = true; - } - - if (bdelayscan) { - /* delay 50ms to protect nulldata(1). */ - set_survey_timer(pmlmeext, 50); - return H2C_SUCCESS; - } - } - - if (pmlmeext->sitesurvey_res.state == SCAN_START || - pmlmeext->sitesurvey_res.state == SCAN_TXNULL) { - /* disable dynamic functions, such as high power, DIG */ - rtl8723a_odm_support_ability_backup(padapter); - rtl8723a_odm_support_ability_clr(padapter, - DYNAMIC_FUNC_DISABLE); - - /* config the initial gain under scanning, need to - write the BB registers */ - if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true) - initialgain = 0x30; - else - initialgain = 0x1E; - - rtl8723a_set_initial_gain(padapter, initialgain); - - /* set MSR to no link state */ - rtl8723a_set_media_status(padapter, MSR_NOLINK); - - rtl8723a_mlme_sitesurvey(padapter, 1); - - pmlmeext->sitesurvey_res.state = SCAN_PROCESS; - } - - rtw_site_survey(padapter); - - return H2C_SUCCESS; -} - -int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct setauth_parm *pparm = (struct setauth_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pparm->mode < 4) - pmlmeinfo->auth_algo = pparm->mode; - - return H2C_SUCCESS; -} - -int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - unsigned short ctrl; - const struct setkey_parm *pparm = (struct setkey_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - /* main tx key for wep. */ - if (pparm->set_tx) - pmlmeinfo->key_index = pparm->keyid; - - /* write cam */ - ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid; - - DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 " - "WEP104-5 TKIP-2 AES-4) keyid:%d\n", - pparm->algorithm, pparm->keyid); - rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key); - - /* allow multicast packets to driver */ - rtl8723a_on_rcr_am(padapter); - - return H2C_SUCCESS; -} - -int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - u16 ctrl = 0; - u8 cam_id;/* cam_entry */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; - - /* cam_entry: */ - /* 0~3 for default key */ - - /* for concurrent mode (ap+sta): */ - /* default key is disable, using sw encrypt/decrypt */ - /* cam_entry = 4 for sta mode (macid = 0) */ - /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */ - - /* for concurrent mode (sta+sta): */ - /* default key is disable, using sw encrypt/decrypt */ - /* cam_entry = 4 mapping to macid = 0 */ - /* cam_entry = 5 mapping to macid = 2 */ - - cam_id = 4; - - DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 " - "WEP104-5 TKIP-2 AES-4) camid:%d\n", - pparm->algorithm, cam_id); - if ((pmlmeinfo->state & 0x03) == MSR_AP) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (pparm->algorithm == 0) { /* clear cam entry */ - clear_cam_entry23a(padapter, pparm->id); - return H2C_SUCCESS_RSP; - } - - psta = rtw_get_stainfo23a(pstapriv, pparm->addr); - if (psta) { - ctrl = BIT(15) | (pparm->algorithm << 2); - - DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm " - "=%d\n", pparm->algorithm); - - if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) { - DBG_8723A("r871x_set_stakey_hdl23a():set_stakey" - " failed, mac_id(aid) =%d\n", - psta->mac_id); - return H2C_REJECTED; - } - - /* 0~3 for default key, cmd_id = macid + 3, - macid = aid+1; */ - cam_id = psta->mac_id + 3; - - DBG_8723A("Write CAM, mac_addr =%pM, " - "cam_entry =%d\n", pparm->addr, cam_id); - - rtl8723a_cam_write(padapter, cam_id, ctrl, - pparm->addr, pparm->key); - - return H2C_SUCCESS_RSP; - } else { - DBG_8723A("r871x_set_stakey_hdl23a(): sta has been " - "free\n"); - return H2C_REJECTED; - } - } - - /* below for sta mode */ - - if (pparm->algorithm == 0) { /* clear cam entry */ - clear_cam_entry23a(padapter, pparm->id); - return H2C_SUCCESS; - } - - ctrl = BIT(15) | (pparm->algorithm << 2); - - rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key); - - pmlmeinfo->enc_algo = pparm->algorithm; - - return H2C_SUCCESS; -} - -int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr); - - if (!psta) - return H2C_SUCCESS; - - if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && - pmlmeinfo->HT_enable) || - (pmlmeinfo->state & 0x03) == MSR_AP) { - issue_action_BA23a(padapter, pparm->addr, - WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); - mod_timer(&psta->addba_retry_timer, - jiffies + msecs_to_jiffies(ADDBA_TO)); - } else - psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); - - return H2C_SUCCESS; -} - -int set_tx_beacon_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct Tx_Beacon_param *ptxBeacon_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 res = _SUCCESS; - int len_diff = 0; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC); - if (!ptxBeacon_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network, - sizeof(struct wlan_bssid_ex)); - - len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs, - ptxBeacon_parm->network.IELength, - pmlmeinfo->hidden_ssid_mode); - ptxBeacon_parm->network.IELength += len_diff; - - init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, - GEN_CMD_CODE(_TX_Beacon)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - return res; -} - -int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - u8 evt_code, evt_seq; - u16 evt_sz; - const struct C2HEvent_Header *c2h; - void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf); - - c2h = (struct C2HEvent_Header *)pbuf; - evt_sz = c2h->len; - evt_seq = c2h->seq; - evt_code = c2h->ID; - - /* checking if event code is valid */ - if (evt_code >= MAX_C2HEVT) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Event Code(%d) mismatch!\n", evt_code); - goto _abort_event_; - } - - /* checking if event size match the event parm size */ - if (wlanevents[evt_code].parmsize != 0 && - wlanevents[evt_code].parmsize != evt_sz) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Event(%d) Parm Size mismatch (%d vs %d)!\n", - evt_code, wlanevents[evt_code].parmsize, evt_sz); - goto _abort_event_; - } - - event_callback = wlanevents[evt_code].event_callback; - event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header)); - -_abort_event_: - - return H2C_SUCCESS; -} - -int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - return H2C_SUCCESS; -} - -int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - if (send_beacon23a(padapter) == _FAIL) { - DBG_8723A("issue_beacon23a, fail!\n"); - return H2C_PARAMETERS_ERROR; - } -#ifdef CONFIG_8723AU_AP_MODE - else { /* tx bc/mc frames after update TIM */ - struct sta_info *psta_bmc; - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return H2C_SUCCESS; - - if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) { - msleep(10);/* 10ms, ATIM(HIQ) Windows */ - /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ - spin_lock_bh(&pxmitpriv->lock); - - phead = get_list_head(&psta_bmc->sleep_q); - - list_for_each_entry_safe(pxmitframe, ptmp, - phead, list) { - - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len>0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - pxmitframe->attrib.qsel = 0x11;/* HIQ */ - - rtl8723au_hal_xmitframe_enqueue(padapter, - pxmitframe); - } - /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - } - } -#endif - - return H2C_SUCCESS; -} - -int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct set_ch_parm *set_ch_parm; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - set_ch_parm = (struct set_ch_parm *)pbuf; - - DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__, - padapter->pnetdev->name, set_ch_parm->ch, - set_ch_parm->bw, set_ch_parm->ch_offset); - - pmlmeext->cur_channel = set_ch_parm->ch; - pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; - pmlmeext->cur_bwmode = set_ch_parm->bw; - - set_channel_bwmode23a(padapter, set_ch_parm->ch, - set_ch_parm->ch_offset, set_ch_parm->bw); - - return H2C_SUCCESS; -} - -int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct SetChannelPlan_param *setChannelPlan_param; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; - - pmlmeext->max_chan_nums = - init_channel_set(padapter, setChannelPlan_param->channel_plan, - pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, - pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - return H2C_SUCCESS; -} - -int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct LedBlink_param *ledBlink_param; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - ledBlink_param = (struct LedBlink_param *)pbuf; - - return H2C_SUCCESS; -} - -int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_REJECTED; -} - -/* TDLS_WRCR : write RCR DATA BIT */ -/* TDLS_SD_PTI : issue peer traffic indication */ -/* TDLS_CS_OFF : go back to the channel linked with AP, - terminating channel switch procedure */ -/* TDLS_INIT_CH_SEN : init channel sensing, receive all data and - mgnt frame */ -/* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */ -/* TDLS_OFF_CH : first time set channel to off channel */ -/* TDLS_BASE_CH : go back tp the channel linked with AP when set - base channel as target channel */ -/* TDLS_P_OFF_CH : periodically go to off channel */ -/* TDLS_P_BASE_CH : periodically go back to base channel */ -/* TDLS_RS_RCR : restore RCR */ -/* TDLS_CKALV_PH1 : check alive timer phase1 */ -/* TDLS_CKALV_PH2 : check alive timer phase2 */ -/* TDLS_FREE_STA : free tdls sta */ -int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_REJECTED; -} diff --git a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c deleted file mode 100644 index 7488a104935b..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c +++ /dev/null @@ -1,606 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_PWRCTRL_C_ - -#include -#include -#include -#include -#include - -#include -#include - -void ips_enter23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - down(&pwrpriv->lock); - - pwrpriv->bips_processing = true; - - /* syn ips_mode with request */ - pwrpriv->ips_mode = pwrpriv->ips_mode_req; - - pwrpriv->ips_enter23a_cnts++; - DBG_8723A("==>ips_enter23a cnts:%d\n", pwrpriv->ips_enter23a_cnts); - rtl8723a_BT_disable_coexist(padapter); - - if (pwrpriv->change_rfpwrstate == rf_off) { - pwrpriv->bpower_saving = true; - DBG_8723A_LEVEL(_drv_always_, "nolinked power save enter\n"); - - if (pwrpriv->ips_mode == IPS_LEVEL_2) - pwrpriv->bkeepfwalive = true; - - rtw_ips_pwr_down23a(padapter); - pwrpriv->rf_pwrstate = rf_off; - } - pwrpriv->bips_processing = false; - - up(&pwrpriv->lock); -} - -int ips_leave23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int result = _SUCCESS; - int keyid; - - down(&pwrpriv->lock); - - if (pwrpriv->rf_pwrstate == rf_off && !pwrpriv->bips_processing) { - pwrpriv->bips_processing = true; - pwrpriv->change_rfpwrstate = rf_on; - pwrpriv->ips_leave23a_cnts++; - DBG_8723A("==>ips_leave23a cnts:%d\n", - pwrpriv->ips_leave23a_cnts); - - result = rtw_ips_pwr_up23a(padapter); - if (result == _SUCCESS) - pwrpriv->rf_pwrstate = rf_on; - - DBG_8723A_LEVEL(_drv_always_, "nolinked power save leave\n"); - - if (psecuritypriv->dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_WEP40 || - psecuritypriv->dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_WEP104) { - DBG_8723A("==>%s, channel(%d), processing(%x)\n", - __func__, padapter->mlmeextpriv.cur_channel, - pwrpriv->bips_processing); - set_channel_bwmode23a(padapter, - padapter->mlmeextpriv.cur_channel, - HAL_PRIME_CHNL_OFFSET_DONT_CARE, - HT_CHANNEL_WIDTH_20); - for (keyid = 0; keyid < 4; keyid++) { - if (pmlmepriv->key_mask & BIT(keyid)) { - if (keyid == - psecuritypriv->dot11PrivacyKeyIndex) - result = rtw_set_key23a(padapter, psecuritypriv, keyid, 1); - else - result = rtw_set_key23a(padapter, psecuritypriv, keyid, 0); - } - } - } - - DBG_8723A("==> ips_leave23a.....LED(0x%08x)...\n", - rtl8723au_read32(padapter, 0x4c)); - pwrpriv->bips_processing = false; - - pwrpriv->bkeepfwalive = false; - pwrpriv->bpower_saving = false; - } - - up(&pwrpriv->lock); - - return result; -} - - -static bool rtw_pwr_unassociated_idle(struct rtw_adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct xmit_priv *pxmit_priv = &adapter->xmitpriv; - - bool ret = false; - - if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies)) - goto exit; - - if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) || - check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) || - check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)){ - goto exit; - } - - if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF || - pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) { - DBG_8723A_LEVEL(_drv_always_, - "There are some pkts to transmit\n"); - DBG_8723A_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, " - "free_xmit_extbuf_cnt: %d\n", - pxmit_priv->free_xmitbuf_cnt, - pxmit_priv->free_xmit_extbuf_cnt); - goto exit; - } - - ret = true; - -exit: - return ret; -} - -void rtw_ps_processor23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pwrpriv->ps_processing = true; - - if (pwrpriv->bips_processing == true) - goto exit; - - if (pwrpriv->ips_mode_req == IPS_NONE) - goto exit; - - if (!rtw_pwr_unassociated_idle(padapter)) - goto exit; - - if (pwrpriv->rf_pwrstate == rf_on && - (pwrpriv->pwr_state_check_cnts % 4) == 0) { - DBG_8723A("==>%s .fw_state(%x)\n", __func__, - get_fwstate(pmlmepriv)); - pwrpriv->change_rfpwrstate = rf_off; - ips_enter23a(padapter); - } -exit: - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - pwrpriv->ps_processing = false; -} - -static void pwr_state_check_handler(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - - rtw_ps_cmd23a(padapter); -} - -/* - * - * Parameters - * padapter - * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 - * - */ -void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv) -{ - u8 rpwm; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - pslv = PS_STATE(pslv); - - if (pwrpriv->btcoex_rfon) { - if (pslv < PS_STATE_S4) - pslv = PS_STATE_S3; - } - - if (pwrpriv->rpwm == pslv) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "%s: Already set rpwm[0x%02X], new = 0x%02X!\n", - __func__, pwrpriv->rpwm, pslv); - return; - } - - if (padapter->bSurpriseRemoved == true || - padapter->hw_init_completed == false) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", - __func__, padapter->bSurpriseRemoved, - padapter->hw_init_completed); - - pwrpriv->cpwm = PS_STATE_S4; - - return; - } - - if (padapter->bDriverStopped == true) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "%s: change power state(0x%02X) when DriverStopped\n", - __func__, pslv); - - if (pslv < PS_STATE_S2) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", - __func__, pslv); - return; - } - } - - rpwm = pslv | pwrpriv->tog; - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, - "rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n", - rpwm, pwrpriv->cpwm); - - pwrpriv->rpwm = pslv; - - rtl8723a_set_rpwm(padapter, rpwm); - - pwrpriv->tog += 0x80; - pwrpriv->cpwm = pslv; -} - -static bool PS_RDY_CHECK(struct rtw_adapter *padapter) -{ - unsigned long delta_time; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - delta_time = jiffies - pwrpriv->DelayLPSLastTimeStamp; - - if (delta_time < LPS_DELAY_TIME) - return false; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) || - check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - return false; - if (pwrpriv->bInSuspend) - return false; - if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && - !padapter->securitypriv.binstallGrpkey) { - DBG_8723A("Group handshake still in progress !!!\n"); - return false; - } - if (!rtw_cfg80211_pwr_mgmt(padapter)) - return false; - - return true; -} - -void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, - u8 smart_ps, u8 bcn_ant_mode) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, - "%s: PowerMode =%d Smart_PS =%d\n", - __func__, ps_mode, smart_ps); - - if (ps_mode > PM_Card_Disable) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "ps_mode:%d error\n", ps_mode); - return; - } - - if (pwrpriv->pwr_mode == ps_mode) { - if (PS_MODE_ACTIVE == ps_mode) - return; - - if (pwrpriv->smart_ps == smart_ps && - pwrpriv->bcn_ant_mode == bcn_ant_mode) - return; - } - - if (ps_mode == PS_MODE_ACTIVE) { - DBG_8723A("rtw_set_ps_mode23a: Leave 802.11 power save\n"); - - pwrpriv->pwr_mode = ps_mode; - rtw_set_rpwm23a(padapter, PS_STATE_S4); - rtl8723a_set_FwPwrMode_cmd(padapter, ps_mode); - pwrpriv->bFwCurrentInPSMode = false; - } else { - if (PS_RDY_CHECK(padapter) || - rtl8723a_BT_using_antenna_1(padapter)) { - DBG_8723A("%s: Enter 802.11 power save\n", __func__); - - pwrpriv->bFwCurrentInPSMode = true; - pwrpriv->pwr_mode = ps_mode; - pwrpriv->smart_ps = smart_ps; - pwrpriv->bcn_ant_mode = bcn_ant_mode; - rtl8723a_set_FwPwrMode_cmd(padapter, ps_mode); - - rtw_set_rpwm23a(padapter, PS_STATE_S2); - } - } -} - -/* - * Return: - * 0: Leave OK - * -1: Timeout - * -2: Other error - */ -s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms) -{ - unsigned long start_time, end_time; - u8 bAwake = false; - s32 err = 0; - - start_time = jiffies; - end_time = start_time + msecs_to_jiffies(delay_ms); - - while (1) { - bAwake = rtl8723a_get_fwlps_rf_on(padapter); - if (bAwake == true) - break; - - if (padapter->bSurpriseRemoved == true) { - err = -2; - DBG_8723A("%s: device surprise removed!!\n", __func__); - break; - } - - if (time_after(jiffies, end_time)) { - err = -1; - DBG_8723A("%s: Wait for FW LPS leave more than %u " - "ms!\n", __func__, delay_ms); - break; - } - udelay(100); - } - - return err; -} - -/* Description: */ -/* Enter the leisure power save mode. */ -void LPS_Enter23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (!PS_RDY_CHECK(padapter)) - return; - - if (pwrpriv->bLeisurePs) { - /* Idle for a while if we connect to AP a while ago. */ - if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */ - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { - pwrpriv->bpower_saving = true; - DBG_8723A("%s smart_ps:%d\n", __func__, - pwrpriv->smart_ps); - /* For Tenda W311R IOT issue */ - rtw_set_ps_mode23a(padapter, - pwrpriv->power_mgnt, - pwrpriv->smart_ps, 0); - } - } else - pwrpriv->LpsIdleCount++; - } -} - -/* Description: */ -/* Leave the leisure power save mode. */ -void LPS_Leave23a(struct rtw_adapter *padapter) -{ -#define LPS_LEAVE_TIMEOUT_MS 100 - - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (pwrpriv->bLeisurePs) { - if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) { - rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0); - - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - LPS_RF_ON_check23a(padapter, - LPS_LEAVE_TIMEOUT_MS); - } - } - - pwrpriv->bpower_saving = false; -} - -/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */ -/* Move code to function by tynli. 2010.03.26. */ -void LeaveAllPowerSaveMode23a(struct rtw_adapter *Adapter) -{ - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - u8 enqueue = 0; - - /* DBG_8723A("%s.....\n", __func__); */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_lps_ctrl_wk_cmd23a(Adapter, LPS_CTRL_LEAVE, enqueue); -} - -void rtw_init_pwrctrl_priv23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - sema_init(&pwrctrlpriv->lock, 1); - pwrctrlpriv->rf_pwrstate = rf_on; - pwrctrlpriv->ips_enter23a_cnts = 0; - pwrctrlpriv->ips_leave23a_cnts = 0; - pwrctrlpriv->bips_processing = false; - - pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode; - pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode; - - pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL; - pwrctrlpriv->pwr_state_check_cnts = 0; - pwrctrlpriv->bInSuspend = false; - pwrctrlpriv->bkeepfwalive = false; - - pwrctrlpriv->LpsIdleCount = 0; - - /* PS_MODE_MIN; */ - pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt; - pwrctrlpriv->bLeisurePs = - (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false; - - pwrctrlpriv->bFwCurrentInPSMode = false; - - pwrctrlpriv->rpwm = 0; - pwrctrlpriv->cpwm = PS_STATE_S4; - - pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE; - pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps; - pwrctrlpriv->bcn_ant_mode = 0; - - pwrctrlpriv->tog = 0x80; - - pwrctrlpriv->btcoex_rfon = false; - - setup_timer(&pwrctrlpriv->pwr_state_check_timer, - pwr_state_check_handler, (unsigned long)padapter); -} - -void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter) -{ -} - -inline void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms); -} - -/* -* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend -* @adapter: pointer to _adapter structure -* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup -* Return _SUCCESS or _FAIL -*/ - -int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms, const char *caller) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int ret = _SUCCESS; - unsigned long start = jiffies; - unsigned long new_deny_time; - - new_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms); - - if (time_before(pwrpriv->ips_deny_time, new_deny_time)) - pwrpriv->ips_deny_time = new_deny_time; - - if (pwrpriv->ps_processing) { - DBG_8723A("%s wait ps_processing...\n", __func__); - while (pwrpriv->ps_processing && - jiffies_to_msecs(jiffies - start) <= 3000) - msleep(10); - if (pwrpriv->ps_processing) - DBG_8723A("%s wait ps_processing timeout\n", __func__); - else - DBG_8723A("%s wait ps_processing done\n", __func__); - } - - if (rtw_sreset_inprogress(padapter)) { - DBG_8723A("%s wait sreset_inprogress...\n", __func__); - while (rtw_sreset_inprogress(padapter) && - jiffies_to_msecs(jiffies - start) <= 4000) - msleep(10); - if (rtw_sreset_inprogress(padapter)) - DBG_8723A("%s wait sreset_inprogress timeout\n", - __func__); - else - DBG_8723A("%s wait sreset_inprogress done\n", __func__); - } - - if (pwrpriv->bInSuspend) { - DBG_8723A("%s wait bInSuspend...\n", __func__); - while (pwrpriv->bInSuspend && - (jiffies_to_msecs(jiffies - start) <= 3000)) { - msleep(10); - } - if (pwrpriv->bInSuspend) - DBG_8723A("%s wait bInSuspend timeout\n", __func__); - else - DBG_8723A("%s wait bInSuspend done\n", __func__); - } - - /* System suspend is not allowed to wakeup */ - if (pwrpriv->bInSuspend) { - ret = _FAIL; - goto exit; - } - - /* I think this should be check in IPS, LPS, autosuspend functions... */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - ret = _SUCCESS; - goto exit; - } - - if (rf_off == pwrpriv->rf_pwrstate) { - DBG_8723A("%s call ips_leave23a....\n", __func__); - if (ips_leave23a(padapter)== _FAIL) { - DBG_8723A("======> ips_leave23a fail.............\n"); - ret = _FAIL; - goto exit; - } - } - - /* TODO: the following checking need to be merged... */ - if (padapter->bDriverStopped || !padapter->bup || - !padapter->hw_init_completed) { - DBG_8723A("%s: bDriverStopped =%d, bup =%d, hw_init_completed " - "=%u\n", caller, padapter->bDriverStopped, - padapter->bup, padapter->hw_init_completed); - ret = _FAIL; - goto exit; - } - -exit: - new_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms); - if (time_before(pwrpriv->ips_deny_time, new_deny_time)) - pwrpriv->ips_deny_time = new_deny_time; - return ret; -} - -int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode) -{ - int ret = 0; - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - if (mode < PS_MODE_NUM) { - if (pwrctrlpriv->power_mgnt != mode) { - if (PS_MODE_ACTIVE == mode) - LeaveAllPowerSaveMode23a(padapter); - else - pwrctrlpriv->LpsIdleCount = 2; - pwrctrlpriv->power_mgnt = mode; - pwrctrlpriv->bLeisurePs = - (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? - true:false; - } - } else - ret = -EINVAL; - - return ret; -} - -int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - if (mode != IPS_NORMAL && mode != IPS_LEVEL_2 && mode != IPS_NONE) - return -EINVAL; - - pwrctrlpriv->ips_mode_req = mode; - if (mode == IPS_NONE) { - DBG_8723A("%s %s\n", __func__, "IPS_NONE"); - if (padapter->bSurpriseRemoved == 0 && - rtw_pwr_wakeup(padapter) == _FAIL) - return -EFAULT; - } - - return 0; -} diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c deleted file mode 100644 index 150dabc2a58d..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_recv.c +++ /dev/null @@ -1,2204 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_RECV_C_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void rtw_signal_stat_timer_hdl23a(unsigned long data); - -void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv) -{ - - - - spin_lock_init(&psta_recvpriv->lock); - - /* for (i = 0; iblk_strms[i]); */ - - _rtw_init_queue23a(&psta_recvpriv->defrag_q); - - -} - -int _rtw_init_recv_priv23a(struct recv_priv *precvpriv, - struct rtw_adapter *padapter) -{ - struct recv_frame *precvframe; - int i; - int res = _SUCCESS; - - spin_lock_init(&precvpriv->lock); - - _rtw_init_queue23a(&precvpriv->free_recv_queue); - _rtw_init_queue23a(&precvpriv->recv_pending_queue); - _rtw_init_queue23a(&precvpriv->uc_swdec_pending_queue); - - precvpriv->adapter = padapter; - - for (i = 0; i < NR_RECVFRAME ; i++) { - precvframe = kzalloc(sizeof(struct recv_frame), GFP_KERNEL); - if (!precvframe) - break; - INIT_LIST_HEAD(&precvframe->list); - - list_add_tail(&precvframe->list, - &precvpriv->free_recv_queue.queue); - - precvframe->adapter = padapter; - precvframe++; - } - - precvpriv->free_recvframe_cnt = i; - precvpriv->rx_pending_cnt = 1; - - res = rtl8723au_init_recv_priv(padapter); - - setup_timer(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl23a, - (unsigned long)padapter); - - precvpriv->signal_stat_sampling_interval = 1000; /* ms */ - - rtw_set_signal_stat_timer(precvpriv); - - return res; -} - -void _rtw_free_recv_priv23a(struct recv_priv *precvpriv) -{ - struct rtw_adapter *padapter = precvpriv->adapter; - struct recv_frame *precvframe, *ptmp; - - rtw_free_uc_swdec_pending_queue23a(padapter); - - list_for_each_entry_safe(precvframe, ptmp, - &precvpriv->free_recv_queue.queue, list) { - list_del_init(&precvframe->list); - kfree(precvframe); - } - - rtl8723au_free_recv_priv(padapter); -} - -struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue) -{ - struct recv_frame *pframe; - struct rtw_adapter *padapter; - struct recv_priv *precvpriv; - - spin_lock_bh(&pfree_recv_queue->lock); - - pframe = list_first_entry_or_null(&pfree_recv_queue->queue, - struct recv_frame, list); - if (pframe) { - list_del_init(&pframe->list); - padapter = pframe->adapter; - if (padapter) { - precvpriv = &padapter->recvpriv; - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt--; - } - } - - spin_unlock_bh(&pfree_recv_queue->lock); - - return pframe; -} - -int rtw_free_recvframe23a(struct recv_frame *precvframe) -{ - struct rtw_adapter *padapter = precvframe->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct rtw_queue *pfree_recv_queue; - - if (precvframe->pkt) { - dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */ - precvframe->pkt = NULL; - } - - pfree_recv_queue = &precvpriv->free_recv_queue; - spin_lock_bh(&pfree_recv_queue->lock); - - list_del_init(&precvframe->list); - - list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue)); - - if (padapter) { - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - - spin_unlock_bh(&pfree_recv_queue->lock); - - - - return _SUCCESS; -} - -int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue) -{ - struct rtw_adapter *padapter = precvframe->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - - spin_lock_bh(&queue->lock); - - list_del_init(&precvframe->list); - - list_add_tail(&precvframe->list, get_list_head(queue)); - - if (padapter) { - if (queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - - spin_unlock_bh(&queue->lock); - - return _SUCCESS; -} - -/* -caller : defrag ; recvframe_chk_defrag23a in recv_thread (passive) -pframequeue: defrag_queue : will be accessed in recv_thread (passive) - -using spinlock to protect - -*/ - -static void rtw_free_recvframe23a_queue(struct rtw_queue *pframequeue) -{ - struct recv_frame *hdr, *ptmp; - struct list_head *phead; - - spin_lock(&pframequeue->lock); - phead = get_list_head(pframequeue); - list_for_each_entry_safe(hdr, ptmp, phead, list) - rtw_free_recvframe23a(hdr); - spin_unlock(&pframequeue->lock); -} - -u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter) -{ - u32 cnt = 0; - struct recv_frame *pending_frame; - - while ((pending_frame = rtw_alloc_recvframe23a(&adapter->recvpriv.uc_swdec_pending_queue))) { - rtw_free_recvframe23a(pending_frame); - DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__); - cnt++; - } - - return cnt; -} - -struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue) -{ - unsigned long irqL; - struct recv_buf *precvbuf; - - spin_lock_irqsave(&queue->lock, irqL); - - precvbuf = list_first_entry_or_null(&queue->queue, - struct recv_buf, list); - if (precvbuf) - list_del_init(&precvbuf->list); - - spin_unlock_irqrestore(&queue->lock, irqL); - - return precvbuf; -} - -int recvframe_chkmic(struct rtw_adapter *adapter, - struct recv_frame *precvframe); -int recvframe_chkmic(struct rtw_adapter *adapter, - struct recv_frame *precvframe) { - - int i, res = _SUCCESS; - u32 datalen; - u8 miccode[8]; - u8 bmic_err = false, brpt_micerror = true; - u8 *pframe, *payload, *pframemic; - u8 *mickey; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - - stainfo = rtw_get_stainfo23a(&adapter->stapriv, &prxattrib->ta[0]); - - if (prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic:prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP\n"); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic:da = %pM\n", prxattrib->ra); - - /* calculate mic code */ - if (stainfo != NULL) { - if (is_multicast_ether_addr(prxattrib->ra)) { - mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0]; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic: bcmc key\n"); - - if (!psecuritypriv->binstallGrpkey) { - res = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "recvframe_chkmic:didn't install group key!\n"); - DBG_8723A("\n recvframe_chkmic:didn't " - "install group key!!!!!!\n"); - goto exit; - } - } else { - mickey = &stainfo->dot11tkiprxmickey.skey[0]; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chkmic: unicast key\n"); - } - - /* icv_len included the mic code */ - datalen = precvframe->pkt->len-prxattrib-> - hdrlen-prxattrib->iv_len-prxattrib->icv_len - 8; - pframe = precvframe->pkt->data; - payload = pframe + prxattrib->hdrlen + - prxattrib->iv_len; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "prxattrib->iv_len =%d prxattrib->icv_len =%d\n", - prxattrib->iv_len, prxattrib->icv_len); - - /* care the length of the data */ - rtw_seccalctkipmic23a(mickey, pframe, payload, - datalen, &miccode[0], - (unsigned char)prxattrib->priority); - - pframemic = payload + datalen; - - bmic_err = false; - - for (i = 0; i < 8; i++) { - if (miccode[i] != *(pframemic + i)) { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "recvframe_chkmic:miccode[%d](%02x) != *(pframemic+%d)(%02x)\n", - i, miccode[i], - i, *(pframemic + i)); - bmic_err = true; - } - } - - if (bmic_err == true) { - int i; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "*(pframemic-8)-*(pframemic-1) =%*phC\n", - 8, pframemic - 8); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "*(pframemic-16)-*(pframemic-9) =%*phC\n", - 8, pframemic - 16); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "====== demp packet (len =%d) ======\n", - precvframe->pkt->len); - for (i = 0; i < precvframe->pkt->len; i = i + 8) { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, "%*phC\n", - 8, precvframe->pkt->data + i); - } - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "====== demp packet end [len =%d]======\n", - precvframe->pkt->len); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "hrdlen =%d\n", prxattrib->hdrlen); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "ra = %pM psecuritypriv->binstallGrpkey =%d\n", - prxattrib->ra, - psecuritypriv->binstallGrpkey); - - /* double check key_index for some timing - issue, cannot compare with - psecuritypriv->dot118021XGrpKeyid also - cause timing issue */ - if ((is_multicast_ether_addr(prxattrib->ra)) && - (prxattrib->key_index != - pmlmeinfo->key_index)) - brpt_micerror = false; - - if ((prxattrib->bdecrypted == true) && - (brpt_micerror == true)) { - rtw_handle_tkip_mic_err23a(adapter, (u8)is_multicast_ether_addr(prxattrib->ra)); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "mic error :prxattrib->bdecrypted =%d\n", - prxattrib->bdecrypted); - DBG_8723A(" mic error :prxattrib->" - "bdecrypted =%d\n", - prxattrib->bdecrypted); - } else { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "mic error :prxattrib->bdecrypted =%d\n", - prxattrib->bdecrypted); - DBG_8723A(" mic error :prxattrib->" - "bdecrypted =%d\n", - prxattrib->bdecrypted); - } - - res = _FAIL; - } else { - /* mic checked ok */ - if (!psecuritypriv->bcheck_grpkey && - is_multicast_ether_addr(prxattrib->ra)) { - psecuritypriv->bcheck_grpkey = 1; - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "psecuritypriv->bcheck_grpkey = true\n"); - } - } - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chkmic: rtw_get_stainfo23a ==NULL!!!\n"); - } - - skb_trim(precvframe->pkt, precvframe->pkt->len - 8); - } - -exit: - - - - return res; -} - -/* decrypt and set the ivlen, icvlen of the recv_frame */ -struct recv_frame *decryptor(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -struct recv_frame *decryptor(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct rx_pkt_attrib *prxattrib = &precv_frame->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct recv_frame *return_packet = precv_frame; - int res = _SUCCESS; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n", - prxattrib->bdecrypted, prxattrib->encrypt); - - if (prxattrib->encrypt > 0) { - u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen; - - prxattrib->key_index = (((iv[3]) >> 6) & 0x3); - - if (prxattrib->key_index > WEP_KEYS) { - DBG_8723A("prxattrib->key_index(%d) > WEP_KEYS\n", - prxattrib->key_index); - - switch (prxattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - prxattrib->key_index = - psecuritypriv->dot11PrivacyKeyIndex; - break; - case WLAN_CIPHER_SUITE_TKIP: - case WLAN_CIPHER_SUITE_CCMP: - default: - prxattrib->key_index = - psecuritypriv->dot118021XGrpKeyid; - break; - } - } - } - - if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0))) { - psecuritypriv->hw_decrypted = 0; - switch (prxattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - rtw_wep_decrypt23a(padapter, precv_frame); - break; - case WLAN_CIPHER_SUITE_TKIP: - res = rtw_tkip_decrypt23a(padapter, precv_frame); - break; - case WLAN_CIPHER_SUITE_CCMP: - res = rtw_aes_decrypt23a(padapter, precv_frame); - break; - default: - break; - } - } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 && - (psecuritypriv->busetkipkey == 1 || - prxattrib->encrypt != WLAN_CIPHER_SUITE_TKIP)) { - psecuritypriv->hw_decrypted = 1; - } - - if (res == _FAIL) { - rtw_free_recvframe23a(return_packet); - return_packet = NULL; - } - - - - return return_packet; -} - -/* set the security information in the recv_frame */ -static struct recv_frame *portctrl(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - u8 *psta_addr, *ptr; - uint auth_alg; - struct recv_frame *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv ; - struct recv_frame *prtnframe; - u16 ether_type; - u16 eapol_type = ETH_P_PAE;/* for Funia BD's WPA issue */ - struct rx_pkt_attrib *pattrib; - - pstapriv = &adapter->stapriv; - - auth_alg = adapter->securitypriv.dot11AuthAlgrthm; - - pfhdr = precv_frame; - pattrib = &pfhdr->attrib; - psta_addr = pattrib->ta; - psta = rtw_get_stainfo23a(pstapriv, psta_addr); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "########portctrl:adapter->securitypriv.dot11AuthAlgrthm =%d\n", - adapter->securitypriv.dot11AuthAlgrthm); - - prtnframe = precv_frame; - - if (auth_alg == dot11AuthAlgrthm_8021X) { - /* get ether_type */ - ptr = pfhdr->pkt->data + pfhdr->attrib.hdrlen; - - ether_type = (ptr[6] << 8) | ptr[7]; - - if (psta && psta->ieee8021x_blocked) { - /* blocked */ - /* only accept EAPOL frame */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "########portctrl:psta->ieee8021x_blocked ==1\n"); - - if (ether_type != eapol_type) { - /* free this frame */ - rtw_free_recvframe23a(precv_frame); - prtnframe = NULL; - } - } - } - - return prtnframe; -} - -int recv_decache(struct recv_frame *precv_frame, u8 bretry, - struct stainfo_rxcache *prxcache); -int recv_decache(struct recv_frame *precv_frame, u8 bretry, - struct stainfo_rxcache *prxcache) -{ - int tid = precv_frame->attrib.priority; - - u16 seq_ctrl = ((precv_frame->attrib.seq_num & 0xffff) << 4) | - (precv_frame->attrib.frag_num & 0xf); - - - - if (tid > 15) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n", - seq_ctrl, tid); - - return _FAIL; - } - - if (1) { /* if (bretry) */ - if (seq_ctrl == prxcache->tid_rxseq[tid]) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_decache, seq_ctrl = 0x%x, tid = 0x%x, tid_rxseq = 0x%x\n", - seq_ctrl, tid, prxcache->tid_rxseq[tid]); - - return _FAIL; - } - } - - prxcache->tid_rxseq[tid] = seq_ctrl; - - - - return _SUCCESS; -} - -void process23a_pwrbit_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -void process23a_pwrbit_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - unsigned char pwrbit; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - - if (psta) { - pwrbit = ieee80211_has_pm(hdr->frame_control); - - if (pwrbit) { - if (!(psta->state & WIFI_SLEEP_STATE)) - stop_sta_xmit23a(padapter, psta); - } else { - if (psta->state & WIFI_SLEEP_STATE) - wakeup_sta_to_xmit23a(padapter, psta); - } - } - -#endif -} - -void process_wmmps_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -void process_wmmps_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - - if (!psta) - return; - - - if (!psta->qos_option) - return; - - if (!(psta->qos_info & 0xf)) - return; - - if (psta->state & WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (wmmps_ac) { - if (psta->sleepq_ac_len > 0) { - /* process received triggered frame */ - xmit_delivery_enabled_frames23a(padapter, psta); - } else { - /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */ - issue_qos_nulldata23a(padapter, psta->hwaddr, - (u16)pattrib->priority, - 0, 0); - } - } - } - -#endif -} - -static void count_rx_stats(struct rtw_adapter *padapter, - struct recv_frame *prframe, struct sta_info *sta) -{ - int sz; - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct rx_pkt_attrib *pattrib = & prframe->attrib; - struct recv_priv *precvpriv = &padapter->recvpriv; - - sz = prframe->pkt->len; - precvpriv->rx_bytes += sz; - - padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++; - - if ((!is_broadcast_ether_addr(pattrib->dst)) && - (!is_multicast_ether_addr(pattrib->dst))) - padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++; - - if (sta) - psta = sta; - else - psta = prframe->psta; - - if (psta) { - pstats = &psta->sta_stats; - - pstats->rx_data_pkts++; - pstats->rx_bytes += sz; - } -} - -static int sta2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info**psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - int ret = _SUCCESS; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - u8 *sta_addr = NULL; - int bmcast = is_multicast_ether_addr(pattrib->dst); - - - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - - /* filter packets that SA is myself or multicast or broadcast */ - if (ether_addr_equal(myhwaddr, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "SA == myself\n"); - ret = _FAIL; - goto exit; - } - - if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - ret = _FAIL; - goto exit; - } - - if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") || - ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") || - !ether_addr_equal(pattrib->bssid, mybssid)) { - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->src; - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* For Station mode, sa and bssid should always be BSSID, - and DA is my mac-address */ - if (!ether_addr_equal(pattrib->bssid, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "bssid != TA under STATION_MODE; drop pkt\n"); - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->bssid; - - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - if (bmcast) { - /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */ - if (!is_multicast_ether_addr(pattrib->bssid)) { - ret = _FAIL; - goto exit; - } - } else { /* not mc-frame */ - /* For AP mode, if DA is non-MCAST, then it must - be BSSID, and bssid == BSSID */ - if (!ether_addr_equal(pattrib->bssid, pattrib->dst)) { - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->src; - } - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - ether_addr_copy(pattrib->dst, hdr->addr1); - ether_addr_copy(pattrib->src, hdr->addr2); - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - - sta_addr = mybssid; - } else { - ret = _FAIL; - } - - if (bmcast) - *psta = rtw_get_bcmc_stainfo23a(adapter); - else - *psta = rtw_get_stainfo23a(pstapriv, sta_addr); /* get ap_info */ - - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under sta2sta_data_frame ; drop pkt\n"); - ret = _FAIL; - goto exit; - } - -exit: - - return ret; -} - -int ap2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta); -int ap2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - int ret = _SUCCESS; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - int bmcast = is_multicast_ether_addr(pattrib->dst); - - - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - (check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) { - - /* filter packets that SA is myself or multicast or broadcast */ - if (ether_addr_equal(myhwaddr, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "SA == myself\n"); - ret = _FAIL; - goto exit; - } - - /* da should be for me */ - if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "ap2sta_data_frame: compare DA failed; DA=%pM\n", - pattrib->dst); - ret = _FAIL; - goto exit; - } - - /* check BSSID */ - if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") || - ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") || - !ether_addr_equal(pattrib->bssid, mybssid)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "ap2sta_data_frame: compare BSSID failed; BSSID=%pM\n", - pattrib->bssid); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "mybssid=%pM\n", mybssid); - - if (!bmcast) { - DBG_8723A("issue_deauth23a to the nonassociated ap=%pM for the reason(7)\n", - pattrib->bssid); - issue_deauth23a(adapter, pattrib->bssid, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - - ret = _FAIL; - goto exit; - } - - if (bmcast) - *psta = rtw_get_bcmc_stainfo23a(adapter); - else - /* get ap_info */ - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "ap2sta: can't get psta under STATION_MODE; drop pkt\n"); - ret = _FAIL; - goto exit; - } - - if (ieee80211_is_nullfunc(hdr->frame_control)) { - /* No data, will not indicate to upper layer, - temporily count it here */ - count_rx_stats(adapter, precv_frame, *psta); - ret = RTW_RX_HANDLED; - goto exit; - } - - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - ether_addr_copy(pattrib->dst, hdr->addr1); - ether_addr_copy(pattrib->src, hdr->addr2); - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - - /* */ - ether_addr_copy(pattrib->bssid, mybssid); - - /* get sta_info */ - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under MP_MODE ; drop pkt\n"); - ret = _FAIL; - goto exit; - } - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* Special case */ - ret = RTW_RX_HANDLED; - goto exit; - } else { - if (ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - if (*psta == NULL) { - DBG_8723A("issue_deauth23a to the ap=%pM for the reason(7)\n", - pattrib->bssid); - - issue_deauth23a(adapter, pattrib->bssid, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - } - - ret = _FAIL; - } - -exit: - - - - return ret; -} - -int sta2ap_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta); -int sta2ap_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - unsigned char *mybssid = get_bssid(pmlmepriv); - int ret = _SUCCESS; - - - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */ - if (!ether_addr_equal(pattrib->bssid, mybssid)) { - ret = _FAIL; - goto exit; - } - - *psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under AP_MODE; drop pkt\n"); - DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n", - pattrib->src); - - issue_deauth23a(adapter, pattrib->src, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - - ret = RTW_RX_HANDLED; - goto exit; - } - - process23a_pwrbit_data(adapter, precv_frame); - - /* We only get here if it's a data frame, so no need to - * confirm data frame type first */ - if (ieee80211_is_data_qos(hdr->frame_control)) - process_wmmps_data(adapter, precv_frame); - - if (ieee80211_is_nullfunc(hdr->frame_control)) { - /* No data, will not indicate to upper layer, - temporily count it here */ - count_rx_stats(adapter, precv_frame, *psta); - ret = RTW_RX_HANDLED; - goto exit; - } - } else { - u8 *myhwaddr = myid(&adapter->eeprompriv); - - if (!ether_addr_equal(pattrib->ra, myhwaddr)) { - ret = RTW_RX_HANDLED; - goto exit; - } - DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n", - pattrib->src); - issue_deauth23a(adapter, pattrib->src, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - ret = RTW_RX_HANDLED; - goto exit; - } - -exit: - - - - return ret; -} - -static int validate_recv_ctrl_frame(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - if (!ieee80211_is_ctl(hdr->frame_control)) - return _FAIL; - - /* receive the frames that ra(a1) is my address */ - if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))) - return _FAIL; - - /* only handle ps-poll */ - if (ieee80211_is_pspoll(hdr->frame_control)) { - struct ieee80211_pspoll *psp = (struct ieee80211_pspoll *)hdr; - u16 aid; - u8 wmmps_ac = 0; - struct sta_info *psta = NULL; - - aid = le16_to_cpu(psp->aid) & 0x3fff; - psta = rtw_get_stainfo23a(pstapriv, hdr->addr2); - - if (!psta || psta->aid != aid) - return _FAIL; - - /* for rx pkt statistics */ - psta->sta_stats.rx_ctrl_pkts++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - return _FAIL; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - DBG_8723A("%s alive check-rx ps-poll\n", __func__); - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - if ((psta->state & WIFI_SLEEP_STATE) && - (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid))) { - struct list_head *xmitframe_phead; - struct xmit_frame *pxmitframe; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - pxmitframe = list_first_entry_or_null(xmitframe_phead, - struct xmit_frame, - list); - if (pxmitframe) { - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - - if (psta->sleepq_len>0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - rtl8723au_hal_xmitframe_enqueue(padapter, - pxmitframe); - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - - spin_unlock_bh(&pxmitpriv->lock); - - } else { - spin_unlock_bh(&pxmitpriv->lock); - - if (pstapriv->tim_bitmap & CHKBIT(psta->aid)) { - if (psta->sleepq_len == 0) { - DBG_8723A("no buffered packets " - "to xmit\n"); - - /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */ - issue_nulldata23a(padapter, - psta->hwaddr, - 0, 0, 0); - } else { - DBG_8723A("error!psta->sleepq" - "_len =%d\n", - psta->sleepq_len); - psta->sleepq_len = 0; - } - - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - } - } - } - -#endif - return _FAIL; -} - -struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -static int validate_recv_mgnt_frame(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sta_info *psta; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "+validate_recv_mgnt_frame\n"); - - precv_frame = recvframe_chk_defrag23a(padapter, precv_frame); - if (precv_frame == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "%s: fragment packet\n", __func__); - return _SUCCESS; - } - - skb = precv_frame->pkt; - hdr = (struct ieee80211_hdr *) skb->data; - - /* for rx pkt statistics */ - psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2); - if (psta) { - psta->sta_stats.rx_mgnt_pkts++; - - if (ieee80211_is_beacon(hdr->frame_control)) - psta->sta_stats.rx_beacon_pkts++; - else if (ieee80211_is_probe_req(hdr->frame_control)) - psta->sta_stats.rx_probereq_pkts++; - else if (ieee80211_is_probe_resp(hdr->frame_control)) { - if (ether_addr_equal(padapter->eeprompriv.mac_addr, - hdr->addr1)) - psta->sta_stats.rx_probersp_pkts++; - else if (is_broadcast_ether_addr(hdr->addr1) || - is_multicast_ether_addr(hdr->addr1)) - psta->sta_stats.rx_probersp_bm_pkts++; - else - psta->sta_stats.rx_probersp_uo_pkts++; - } - } - - mgt_dispatcher23a(padapter, precv_frame); - - return _SUCCESS; -} - -static int validate_recv_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - u8 bretry; - u8 *psa, *pda; - struct sta_info *psta = NULL; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - int ret = _SUCCESS; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - - - bretry = ieee80211_has_retry(hdr->frame_control); - pda = ieee80211_get_DA(hdr); - psa = ieee80211_get_SA(hdr); - - ether_addr_copy(pattrib->dst, pda); - ether_addr_copy(pattrib->src, psa); - - switch (hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { - case cpu_to_le16(0): - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pda); - ether_addr_copy(pattrib->ta, psa); - ret = sta2sta_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_FROMDS): - ether_addr_copy(pattrib->bssid, hdr->addr2); - ether_addr_copy(pattrib->ra, pda); - ether_addr_copy(pattrib->ta, hdr->addr2); - ret = ap2sta_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_TODS): - ether_addr_copy(pattrib->bssid, hdr->addr1); - ether_addr_copy(pattrib->ra, hdr->addr1); - ether_addr_copy(pattrib->ta, psa); - ret = sta2ap_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): - /* - * There is no BSSID in this case, but the driver has been - * using addr1 so far, so keep it for now. - */ - ether_addr_copy(pattrib->bssid, hdr->addr1); - ether_addr_copy(pattrib->ra, hdr->addr1); - ether_addr_copy(pattrib->ta, hdr->addr2); - ret = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, "case 3\n"); - break; - } - - if ((ret == _FAIL) || (ret == RTW_RX_HANDLED)) - goto exit; - - if (!psta) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "after to_fr_ds_chk; psta == NULL\n"); - ret = _FAIL; - goto exit; - } - - precv_frame->psta = psta; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - if (ieee80211_has_a4(hdr->frame_control)) - pattrib->hdrlen += ETH_ALEN; - - /* parsing QC field */ - if (pattrib->qos == 1) { - __le16 *qptr = (__le16 *)ieee80211_get_qos_ctl(hdr); - u16 qos_ctrl = le16_to_cpu(*qptr); - - pattrib->priority = qos_ctrl & IEEE80211_QOS_CTL_TID_MASK; - pattrib->ack_policy = (qos_ctrl >> 5) & 3; - pattrib->amsdu = - (qos_ctrl & IEEE80211_QOS_CTL_A_MSDU_PRESENT) >> 7; - pattrib->hdrlen += IEEE80211_QOS_CTL_LEN; - - if (pattrib->priority != 0 && pattrib->priority != 3) { - adapter->recvpriv.bIsAnyNonBEPkts = true; - } - } else { - pattrib->priority = 0; - pattrib->ack_policy = 0; - pattrib->amsdu = 0; - } - - if (pattrib->order) { /* HT-CTRL 11n */ - pattrib->hdrlen += 4; - } - - precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority]; - - /* decache, drop duplicate recv packets */ - if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == - _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "decache : drop pkt\n"); - ret = _FAIL; - goto exit; - } - - if (pattrib->privacy) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "validate_recv_data_frame:pattrib->privacy =%x\n", - pattrib->privacy); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "^^^^^^^^^^^is_multicast_ether_addr(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n", - pattrib->ra[0], - is_multicast_ether_addr(pattrib->ra)); - - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, - is_multicast_ether_addr(pattrib->ra)); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "pattrib->encrypt =%d\n", pattrib->encrypt); - - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - break; - case WLAN_CIPHER_SUITE_TKIP: - pattrib->iv_len = IEEE80211_TKIP_IV_LEN; - pattrib->icv_len = IEEE80211_TKIP_ICV_LEN; - break; - case WLAN_CIPHER_SUITE_CCMP: - pattrib->iv_len = IEEE80211_CCMP_HDR_LEN; - pattrib->icv_len = IEEE80211_CCMP_MIC_LEN; - break; - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - } else { - pattrib->encrypt = 0; - pattrib->iv_len = 0; - pattrib->icv_len = 0; - } - -exit: - - - - return ret; -} - -static void dump_rx_pkt(struct sk_buff *skb, u16 type, int level) -{ - int i; - u8 *ptr; - - if ((level == 1) || - ((level == 2) && (type == IEEE80211_FTYPE_MGMT)) || - ((level == 3) && (type == IEEE80211_FTYPE_DATA))) { - - ptr = skb->data; - - DBG_8723A("#############################\n"); - - for (i = 0; i < 64; i = i + 8) - DBG_8723A("%*phC:\n", 8, ptr + i); - DBG_8723A("#############################\n"); - } -} - -static int validate_recv_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - /* shall check frame subtype, to / from ds, da, bssid */ - - /* then call check if rx seq/frag. duplicated. */ - u8 type; - u8 subtype; - int retval = _SUCCESS; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u8 ver; - u8 bDumpRxPkt; - u16 seq_ctrl, fctl; - - fctl = le16_to_cpu(hdr->frame_control); - ver = fctl & IEEE80211_FCTL_VERS; - type = fctl & IEEE80211_FCTL_FTYPE; - subtype = fctl & IEEE80211_FCTL_STYPE; - - /* add version chk */ - if (ver != 0) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_data_frame fail! (ver!= 0)\n"); - retval = _FAIL; - goto exit; - } - - seq_ctrl = le16_to_cpu(hdr->seq_ctrl); - pattrib->frag_num = seq_ctrl & IEEE80211_SCTL_FRAG; - pattrib->seq_num = seq_ctrl >> 4; - - pattrib->pw_save = ieee80211_has_pm(hdr->frame_control); - pattrib->mfrag = ieee80211_has_morefrags(hdr->frame_control); - pattrib->mdata = ieee80211_has_moredata(hdr->frame_control); - pattrib->privacy = ieee80211_has_protected(hdr->frame_control); - pattrib->order = ieee80211_has_order(hdr->frame_control); - - GetHalDefVar8192CUsb(adapter, HAL_DEF_DBG_DUMP_RXPKT, &bDumpRxPkt); - - if (unlikely(bDumpRxPkt == 1)) - dump_rx_pkt(skb, type, bDumpRxPkt); - - switch (type) { - case IEEE80211_FTYPE_MGMT: - retval = validate_recv_mgnt_frame(adapter, precv_frame); - if (retval == _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_mgnt_frame fail\n"); - } - retval = _FAIL; /* only data frame return _SUCCESS */ - break; - case IEEE80211_FTYPE_CTL: - retval = validate_recv_ctrl_frame(adapter, precv_frame); - if (retval == _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_ctrl_frame fail\n"); - } - retval = _FAIL; /* only data frame return _SUCCESS */ - break; - case IEEE80211_FTYPE_DATA: - pattrib->qos = (subtype & IEEE80211_STYPE_QOS_DATA) ? 1 : 0; - retval = validate_recv_data_frame(adapter, precv_frame); - if (retval == _FAIL) { - struct recv_priv *precvpriv = &adapter->recvpriv; - - precvpriv->rx_drop++; - } - break; - default: - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_data_frame fail! type = 0x%x\n", type); - retval = _FAIL; - break; - } - -exit: - return retval; -} - -/* remove the wlanhdr and add the eth_hdr */ - -static int wlanhdr_to_ethhdr (struct recv_frame *precvframe) -{ - u16 eth_type, len, hdrlen; - u8 bsnaphdr; - u8 *psnap; - struct rtw_adapter *adapter = precvframe->adapter; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - struct sk_buff *skb = precvframe->pkt; - u8 *ptr; - struct rx_pkt_attrib *pattrib = &precvframe->attrib; - - - - ptr = skb->data; - hdrlen = pattrib->hdrlen; - psnap = ptr + hdrlen; - eth_type = (psnap[6] << 8) | psnap[7]; - /* convert hdr + possible LLC headers into Ethernet header */ - if ((ether_addr_equal(psnap, rfc1042_header) && - eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || - ether_addr_equal(psnap, bridge_tunnel_header)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation - and replace EtherType */ - bsnaphdr = true; - hdrlen += SNAP_SIZE; - } else { - /* Leave Ethernet header part of hdr and full payload */ - bsnaphdr = false; - eth_type = (psnap[0] << 8) | psnap[1]; - } - - len = skb->len - hdrlen; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "=== pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n", - pattrib->hdrlen, pattrib->iv_len); - - pattrib->eth_type = eth_type; - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - ptr += hdrlen; - *ptr = 0x87; - *(ptr + 1) = 0x12; - - eth_type = 0x8712; - /* append rx status for mp test packets */ - - ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + 2) - 24); - memcpy(ptr, skb->head, 24); - ptr += 24; - } else { - ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + - (bsnaphdr ? 2:0))); - } - - ether_addr_copy(ptr, pattrib->dst); - ether_addr_copy(ptr + ETH_ALEN, pattrib->src); - - if (!bsnaphdr) { - put_unaligned_be16(len, ptr + 12); - } - - - return _SUCCESS; -} - -/* perform defrag */ -struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter, - struct rtw_queue *defrag_q); -struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter, - struct rtw_queue *defrag_q) -{ - struct list_head *phead; - u8 wlanhdr_offset; - u8 curfragnum; - struct recv_frame *pnfhdr, *ptmp; - struct recv_frame *prframe, *pnextrframe; - struct rtw_queue *pfree_recv_queue; - struct sk_buff *skb; - - curfragnum = 0; - pfree_recv_queue = &adapter->recvpriv.free_recv_queue; - - phead = get_list_head(defrag_q); - prframe = list_first_entry(phead, struct recv_frame, list); - list_del_init(&prframe->list); - skb = prframe->pkt; - - if (curfragnum != prframe->attrib.frag_num) { - /* the first fragment number must be 0 */ - /* free the whole queue */ - rtw_free_recvframe23a(prframe); - rtw_free_recvframe23a_queue(defrag_q); - - return NULL; - } - - curfragnum++; - - list_for_each_entry_safe(pnfhdr, ptmp, phead, list) { - pnextrframe = (struct recv_frame *)pnfhdr; - /* check the fragment sequence (2nd ~n fragment frame) */ - - if (curfragnum != pnfhdr->attrib.frag_num) { - /* the fragment number must be increasing - (after decache) */ - /* release the defrag_q & prframe */ - rtw_free_recvframe23a(prframe); - rtw_free_recvframe23a_queue(defrag_q); - return NULL; - } - - curfragnum++; - - /* copy the 2nd~n fragment frame's payload to the - first fragment */ - /* get the 2nd~last fragment frame's payload */ - - wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; - - skb_pull(pnfhdr->pkt, wlanhdr_offset); - - /* append to first fragment frame's tail - (if privacy frame, pull the ICV) */ - - skb_trim(skb, skb->len - prframe->attrib.icv_len); - - memcpy(skb_tail_pointer(skb), pnfhdr->pkt->data, - pnfhdr->pkt->len); - - skb_put(skb, pnfhdr->pkt->len); - - prframe->attrib.icv_len = pnfhdr->attrib.icv_len; - } - - /* free the defrag_q queue and return the prframe */ - rtw_free_recvframe23a_queue(defrag_q); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "Performance defrag!!!!!\n"); - - return prframe; -} - -/* check if need to defrag, if needed queue the frame to defrag_q */ -struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - u8 ismfrag; - u8 fragnum; - u8 *psta_addr; - struct recv_frame *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv; - struct list_head *phead; - struct recv_frame *prtnframe = NULL; - struct rtw_queue *pfree_recv_queue, *pdefrag_q; - - - - pstapriv = &padapter->stapriv; - - pfhdr = precv_frame; - - pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - - /* need to define struct of wlan header frame ctrl */ - ismfrag = pfhdr->attrib.mfrag; - fragnum = pfhdr->attrib.frag_num; - - psta_addr = pfhdr->attrib.ta; - psta = rtw_get_stainfo23a(pstapriv, psta_addr); - if (!psta) { - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) pfhdr->pkt->data; - if (!ieee80211_is_data(hdr->frame_control)) { - psta = rtw_get_bcmc_stainfo23a(padapter); - pdefrag_q = &psta->sta_recvpriv.defrag_q; - } else - pdefrag_q = NULL; - } else - pdefrag_q = &psta->sta_recvpriv.defrag_q; - - if ((ismfrag == 0) && (fragnum == 0)) { - prtnframe = precv_frame;/* isn't a fragment frame */ - } - - if (ismfrag == 1) { - /* 0~(n-1) fragment frame */ - /* enqueue to defraf_g */ - if (pdefrag_q != NULL) { - if (fragnum == 0) { - /* the first fragment */ - if (!list_empty(&pdefrag_q->queue)) { - /* free current defrag_q */ - rtw_free_recvframe23a_queue(pdefrag_q); - } - } - - /* Then enqueue the 0~(n-1) fragment into the - defrag_q */ - - /* spin_lock(&pdefrag_q->lock); */ - phead = get_list_head(pdefrag_q); - list_add_tail(&pfhdr->list, phead); - /* spin_unlock(&pdefrag_q->lock); */ - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "Enqueuq: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - - prtnframe = NULL; - - } else { - /* can't find this ta's defrag_queue, - so free this recv_frame */ - rtw_free_recvframe23a(precv_frame); - prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - } - } - - if ((ismfrag == 0) && (fragnum != 0)) { - /* the last fragment frame */ - /* enqueue the last fragment */ - if (pdefrag_q != NULL) { - /* spin_lock(&pdefrag_q->lock); */ - phead = get_list_head(pdefrag_q); - list_add_tail(&pfhdr->list, phead); - /* spin_unlock(&pdefrag_q->lock); */ - - /* call recvframe_defrag to defrag */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "defrag: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - precv_frame = recvframe_defrag(padapter, pdefrag_q); - prtnframe = precv_frame; - } else { - /* can't find this ta's defrag_queue, - so free this recv_frame */ - rtw_free_recvframe23a(precv_frame); - prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - } - - } - - if ((prtnframe != NULL) && (prtnframe->attrib.privacy)) { - /* after defrag we must check tkip mic code */ - if (recvframe_chkmic(padapter, prtnframe) == _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chkmic(padapter, prtnframe) ==_FAIL\n"); - rtw_free_recvframe23a(prtnframe); - prtnframe = NULL; - } - } - - - - return prtnframe; -} - -int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe); -int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib; - struct sk_buff *skb, *sub_skb; - struct sk_buff_head skb_list; - - pattrib = &prframe->attrib; - - skb = prframe->pkt; - skb_pull(skb, prframe->attrib.hdrlen); - __skb_queue_head_init(&skb_list); - - ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false); - - while (!skb_queue_empty(&skb_list)) { - sub_skb = __skb_dequeue(&skb_list); - - sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev); - sub_skb->dev = padapter->pnetdev; - - sub_skb->ip_summed = CHECKSUM_NONE; - - netif_rx(sub_skb); - } - - prframe->pkt = NULL; - rtw_free_recvframe23a(prframe); - return _SUCCESS; -} - -int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num); -int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num) -{ - u8 wsize = preorder_ctrl->wsize_b; - u16 wend = (preorder_ctrl->indicate_seq + wsize -1) & 0xFFF; - - /* Rx Reorder initialize condition. */ - if (preorder_ctrl->indicate_seq == 0xFFFF) - preorder_ctrl->indicate_seq = seq_num; - - /* Drop out the packet which SeqNum is smaller than WinStart */ - if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) - return false; - - /* */ - /* Sliding window manipulation. Conditions includes: */ - /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */ - /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */ - /* */ - if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) { - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) & 0xFFF; - } else if (SN_LESS(wend, seq_num)) { - /* boundary situation, when seq_num cross 0xFFF */ - if (seq_num >= (wsize - 1)) - preorder_ctrl->indicate_seq = seq_num + 1 -wsize; - else - preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1; - } - return true; -} - -static int enqueue_reorder_recvframe23a(struct recv_reorder_ctrl *preorder_ctrl, - struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct rtw_queue *ppending_recvframe_queue; - struct list_head *phead, *plist, *ptmp; - struct recv_frame *hdr; - struct rx_pkt_attrib *pnextattrib; - - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - phead = get_list_head(ppending_recvframe_queue); - - list_for_each_safe(plist, ptmp, phead) { - hdr = container_of(plist, struct recv_frame, list); - pnextattrib = &hdr->attrib; - - if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) { - continue; - } else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) { - /* Duplicate entry is found!! Do not insert current entry. */ - return false; - } else { - break; - } - - } - - list_del_init(&prframe->list); - - list_add_tail(&prframe->list, plist); - - return true; -} - -int recv_indicatepkts_in_order(struct rtw_adapter *padapter, - struct recv_reorder_ctrl *preorder_ctrl, - int bforced); -int recv_indicatepkts_in_order(struct rtw_adapter *padapter, - struct recv_reorder_ctrl *preorder_ctrl, - int bforced) -{ - struct list_head *phead, *plist; - struct recv_frame *prframe; - struct rx_pkt_attrib *pattrib; - int bPktInBuf = false; - struct recv_priv *precvpriv; - struct rtw_queue *ppending_recvframe_queue; - - precvpriv = &padapter->recvpriv; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - /* Handling some condition for forced indicate case. */ - if (bforced) { - if (list_empty(phead)) { - return true; - } - - prframe = container_of(plist, struct recv_frame, list); - pattrib = &prframe->attrib; - preorder_ctrl->indicate_seq = pattrib->seq_num; - } - - /* Prepare indication list and indication. */ - /* Check if there is any packet need indicate. */ - while (!list_empty(phead)) { - - prframe = container_of(plist, struct recv_frame, list); - pattrib = &prframe->attrib; - - if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_indicatepkts_in_order: indicate =%d seq =%d amsdu =%d\n", - preorder_ctrl->indicate_seq, - pattrib->seq_num, pattrib->amsdu); - - plist = plist->next; - list_del_init(&prframe->list); - - if (SN_EQUAL(preorder_ctrl->indicate_seq, - pattrib->seq_num)) { - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1)&0xFFF; - } - - if (!pattrib->amsdu) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - rtw_recv_indicatepkt23a(padapter, prframe); - } - } else { - if (amsdu_to_msdu(padapter, prframe) != - _SUCCESS) - rtw_free_recvframe23a(prframe); - } - - /* Update local variables. */ - bPktInBuf = false; - - } else { - bPktInBuf = true; - break; - } - - } - - return bPktInBuf; -} - -int recv_indicatepkt_reorder(struct rtw_adapter *padapter, - struct recv_frame *prframe); -int recv_indicatepkt_reorder(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int retval = _SUCCESS; - struct rx_pkt_attrib *pattrib; - struct recv_reorder_ctrl *preorder_ctrl; - struct rtw_queue *ppending_recvframe_queue; - - pattrib = &prframe->attrib; - preorder_ctrl = prframe->preorder_ctrl; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - if (!pattrib->amsdu) { - /* s1. */ - wlanhdr_to_ethhdr(prframe); - - if ((pattrib->qos!= 1) || (pattrib->eth_type == ETH_P_ARP) || - (pattrib->ack_policy != 0)) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ recv_indicatepkt_reorder -recv_func recv_indicatepkt\n"); - - rtw_recv_indicatepkt23a(padapter, prframe); - return _SUCCESS; - } - - return _FAIL; - } - - if (preorder_ctrl->enable == false) { - /* indicate this recv_frame */ - preorder_ctrl->indicate_seq = pattrib->seq_num; - rtw_recv_indicatepkt23a(padapter, prframe); - - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) % 4096; - return _SUCCESS; - } - } else { - /* temp filter -> means didn't support A-MSDUs in a A-MPDU */ - if (preorder_ctrl->enable == false) { - preorder_ctrl->indicate_seq = pattrib->seq_num; - retval = amsdu_to_msdu(padapter, prframe); - - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) % 4096; - return retval; - } - } - - spin_lock_bh(&ppending_recvframe_queue->lock); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_indicatepkt_reorder: indicate =%d seq =%d\n", - preorder_ctrl->indicate_seq, pattrib->seq_num); - - /* s2. check if winstart_b(indicate_seq) needs to been updated */ - if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) { - goto _err_exit; - } - - /* s3. Insert all packet into Reorder Queue to maintain its ordering. */ - if (!enqueue_reorder_recvframe23a(preorder_ctrl, prframe)) { - goto _err_exit; - } - - /* s4. */ - /* Indication process. */ - /* After Packet dropping and Sliding Window shifting as above, - we can now just indicate the packets */ - /* with the SeqNum smaller than latest WinStart and buffer - other packets. */ - /* */ - /* For Rx Reorder condition: */ - /* 1. All packets with SeqNum smaller than WinStart => Indicate */ - /* 2. All packets with SeqNum larger than or equal to WinStart => - Buffer it. */ - /* */ - - if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == true) { - mod_timer(&preorder_ctrl->reordering_ctrl_timer, - jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); - spin_unlock_bh(&ppending_recvframe_queue->lock); - } else { - spin_unlock_bh(&ppending_recvframe_queue->lock); - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - } - return _SUCCESS; - -_err_exit: - - spin_unlock_bh(&ppending_recvframe_queue->lock); - return _FAIL; -} - -void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext) -{ - struct recv_reorder_ctrl *preorder_ctrl; - struct rtw_adapter *padapter; - struct rtw_queue *ppending_recvframe_queue; - - preorder_ctrl = (struct recv_reorder_ctrl *)pcontext; - padapter = preorder_ctrl->padapter; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { - return; - } - - spin_lock_bh(&ppending_recvframe_queue->lock); - - if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true) { - mod_timer(&preorder_ctrl->reordering_ctrl_timer, - jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); - } - - spin_unlock_bh(&ppending_recvframe_queue->lock); -} - -int process_recv_indicatepkts(struct rtw_adapter *padapter, - struct recv_frame *prframe); -int process_recv_indicatepkts(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int retval = _SUCCESS; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (phtpriv->ht_option == true) { /* B/G/N Mode */ - /* including perform A-MPDU Rx Ordering Buffer Control */ - if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - retval = _FAIL; - return retval; - } - } - } else { /* B/G mode */ - retval = wlanhdr_to_ethhdr(prframe); - if (retval != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "wlanhdr_to_ethhdr: drop pkt\n"); - return retval; - } - - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - /* indicate this recv_frame */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ process_recv_indicatepkts- recv_func recv_indicatepkt\n"); - rtw_recv_indicatepkt23a(padapter, prframe); - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ process_recv_indicatepkts- recv_func free_indicatepkt\n"); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, - padapter->bSurpriseRemoved); - retval = _FAIL; - return retval; - } - - } - - return retval; -} - -static int recv_func_prehandle(struct rtw_adapter *padapter, - struct recv_frame *rframe) -{ - int ret; - - /* check the frame crtl field and decache */ - ret = validate_recv_frame(padapter, rframe); - if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recv_func: validate_recv_frame fail! drop pkt\n"); - rtw_free_recvframe23a(rframe); - goto exit; - } - -exit: - return ret; -} - -static int recv_func_posthandle(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int ret = _SUCCESS; - struct recv_frame *orig_prframe = prframe; - struct recv_priv *precvpriv = &padapter->recvpriv; - - /* DATA FRAME */ - prframe = decryptor(padapter, prframe); - if (prframe == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "decryptor: drop pkt\n"); - ret = _FAIL; - goto _recv_data_drop; - } - - prframe = recvframe_chk_defrag23a(padapter, prframe); - if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chk_defrag23a: drop pkt\n"); - goto _recv_data_drop; - } - - /* - * Pull off crypto headers - */ - if (prframe->attrib.iv_len > 0) { - skb_pull(prframe->pkt, prframe->attrib.iv_len); - } - - if (prframe->attrib.icv_len > 0) { - skb_trim(prframe->pkt, - prframe->pkt->len - prframe->attrib.icv_len); - } - - prframe = portctrl(padapter, prframe); - if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "portctrl: drop pkt\n"); - ret = _FAIL; - goto _recv_data_drop; - } - - count_rx_stats(padapter, prframe, NULL); - - ret = process_recv_indicatepkts(padapter, prframe); - if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recv_func: process_recv_indicatepkts fail!\n"); - rtw_free_recvframe23a(orig_prframe);/* free this recv_frame */ - goto _recv_data_drop; - } - return ret; - -_recv_data_drop: - precvpriv->rx_drop++; - return ret; -} - -int rtw_recv_entry23a(struct recv_frame *rframe) -{ - int ret, r; - struct rtw_adapter *padapter = rframe->adapter; - struct rx_pkt_attrib *prxattrib = &rframe->attrib; - struct recv_priv *recvpriv = &padapter->recvpriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - - /* check if need to handle uc_swdec_pending_queue*/ - if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && - psecuritypriv->busetkipkey) { - struct recv_frame *pending_frame; - - while ((pending_frame = rtw_alloc_recvframe23a(&padapter->recvpriv.uc_swdec_pending_queue))) { - r = recv_func_posthandle(padapter, pending_frame); - if (r == _SUCCESS) - DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__); - } - } - - ret = recv_func_prehandle(padapter, rframe); - - if (ret == _SUCCESS) { - /* check if need to enqueue into uc_swdec_pending_queue*/ - if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && - !is_multicast_ether_addr(prxattrib->ra) && - prxattrib->encrypt > 0 && - (prxattrib->bdecrypted == 0) && - !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) && - !psecuritypriv->busetkipkey) { - rtw_enqueue_recvframe23a(rframe, &padapter->recvpriv.uc_swdec_pending_queue); - DBG_8723A("%s: no key, enqueue uc_swdec_pending_queue\n", __func__); - goto exit; - } - - ret = recv_func_posthandle(padapter, rframe); - - recvpriv->rx_pkts++; - } - -exit: - return ret; -} - -void rtw_signal_stat_timer_hdl23a(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct recv_priv *recvpriv = &adapter->recvpriv; - - u32 tmp_s, tmp_q; - u8 avg_signal_strength = 0; - u8 avg_signal_qual = 0; - u32 num_signal_strength = 0; - u32 num_signal_qual = 0; - u8 _alpha = 3; /* this value is based on converging_constant = 5000 */ - /* and sampling_interval = 1000 */ - - if (recvpriv->signal_strength_data.update_req == 0) { - /* update_req is clear, means we got rx */ - avg_signal_strength = recvpriv->signal_strength_data.avg_val; - num_signal_strength = recvpriv->signal_strength_data.total_num; - /* after avg_vals are acquired, we can re-stat */ - /* the signal values */ - recvpriv->signal_strength_data.update_req = 1; - } - - if (recvpriv->signal_qual_data.update_req == 0) { - /* update_req is clear, means we got rx */ - avg_signal_qual = recvpriv->signal_qual_data.avg_val; - num_signal_qual = recvpriv->signal_qual_data.total_num; - /* after avg_vals are acquired, we can re-stat */ - /*the signal values */ - recvpriv->signal_qual_data.update_req = 1; - } - - /* update value of signal_strength, rssi, signal_qual */ - if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) { - tmp_s = avg_signal_strength + (_alpha - 1) * - recvpriv->signal_strength; - if (tmp_s %_alpha) - tmp_s = tmp_s / _alpha + 1; - else - tmp_s = tmp_s / _alpha; - if (tmp_s > 100) - tmp_s = 100; - - tmp_q = avg_signal_qual + (_alpha - 1) * recvpriv->signal_qual; - if (tmp_q %_alpha) - tmp_q = tmp_q / _alpha + 1; - else - tmp_q = tmp_q / _alpha; - if (tmp_q > 100) - tmp_q = 100; - - recvpriv->signal_strength = tmp_s; - recvpriv->signal_qual = tmp_q; - - DBG_8723A("%s signal_strength:%3u, signal_qual:%3u, " - "num_signal_strength:%u, num_signal_qual:%u\n", - __func__, recvpriv->signal_strength, - recvpriv->signal_qual, num_signal_strength, - num_signal_qual); - } - - rtw_set_signal_stat_timer(recvpriv); -} diff --git a/drivers/staging/rtl8723au/core/rtw_security.c b/drivers/staging/rtl8723au/core/rtw_security.c deleted file mode 100644 index 5a4cfdf1ebd4..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_security.c +++ /dev/null @@ -1,1630 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_SECURITY_C_ - -#include -#include -#include -#include - -/* WEP related ===== */ - -#define CRC32_POLY 0x04c11db7 - -struct arc4context { - u32 x; - u32 y; - u8 state[256]; -}; - -static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len) -{ - u32 t, u; - u32 keyindex; - u32 stateindex; - u8 *state; - u32 counter; - - state = parc4ctx->state; - parc4ctx->x = 0; - parc4ctx->y = 0; - for (counter = 0; counter < 256; counter++) - state[counter] = (u8)counter; - keyindex = 0; - stateindex = 0; - for (counter = 0; counter < 256; counter++) { - t = state[counter]; - stateindex = (stateindex + key[keyindex] + t) & 0xff; - u = state[stateindex]; - state[stateindex] = (u8)t; - state[counter] = (u8)u; - if (++keyindex >= key_len) - keyindex = 0; - } - -} - -static u32 arcfour_byte(struct arc4context *parc4ctx) -{ - u32 x; - u32 y; - u32 sx, sy; - u8 *state; - - state = parc4ctx->state; - x = (parc4ctx->x + 1) & 0xff; - sx = state[x]; - y = (sx + parc4ctx->y) & 0xff; - sy = state[y]; - parc4ctx->x = x; - parc4ctx->y = y; - state[y] = (u8)sx; - state[x] = (u8)sy; - - return state[(sx + sy) & 0xff]; -} - -static void arcfour_encrypt(struct arc4context *parc4ctx, u8 *dest, - u8 *src, u32 len) -{ - u32 i; - - for (i = 0; i < len; i++) - dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx); -} - -static int bcrc32initialized; -static u32 crc32_table[256]; - -static u8 crc32_reverseBit(u8 data) -{ - u8 retval = ((data << 7) & 0x80) | ((data << 5) & 0x40) | - ((data << 3) & 0x20) | ((data << 1) & 0x10) | - ((data >> 1) & 0x08) | ((data >> 3) & 0x04) | - ((data >> 5) & 0x02) | ((data >> 7) & 0x01); - return retval; -} - -static void crc32_init(void) -{ - int i, j; - u32 c; - u8 *p, *p1; - u8 k; - - if (bcrc32initialized == 1) - return; - - p = (u8 *) &c; - 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 u32 getcrc32(u8 *buf, int len) -{ - u8 *p; - u32 crc; - - if (bcrc32initialized == 0) - crc32_init(); - - crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ - - for (p = buf; len > 0; ++p, --len) - crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8); - - return ~crc; /* transmit complement, per CRC-32 spec */ -} - -/* Need to consider the fragment situation */ -void rtw_wep_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - /* exclude ICV */ - __le32 crc; - struct arc4context mycontext; - int curfragnum, length, index; - u32 keylength; - u8 *pframe, *payload, *iv; /* wepkey */ - u8 wepkey[16]; - u8 hw_hdr_offset = 0; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (!pxmitframe->buf_addr) - return; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* start to encrypt each fragment */ - if (pattrib->encrypt != WLAN_CIPHER_SUITE_WEP40 && - pattrib->encrypt != WLAN_CIPHER_SUITE_WEP104) - return; - - index = psecuritypriv->dot11PrivacyKeyIndex; - keylength = psecuritypriv->wep_key[index].keylen; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags ; curfragnum++) { - iv = pframe + pattrib->hdrlen; - memcpy(&wepkey[0], iv, 3); - memcpy(&wepkey[3], &psecuritypriv->wep_key[index].key, - keylength); - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - - if ((curfragnum + 1) == pattrib->nr_frags) { - /* the last fragment */ - length = pattrib->last_txcmdsz - pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - - crc = cpu_to_le32(getcrc32(payload, length)); - - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - } else { - length = pxmitpriv->frag_len - pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - crc = cpu_to_le32(getcrc32(payload, length)); - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - -} - -void rtw_wep_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ - /* exclude ICV */ - u32 actual_crc, expected_crc; - struct arc4context mycontext; - int length; - u32 keylength; - u8 *pframe, *payload, *iv, wepkey[16]; - u8 keyindex; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - - pframe = skb->data; - - /* start to decrypt recvframe */ - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_WEP40 && - prxattrib->encrypt != WLAN_CIPHER_SUITE_WEP104) - return; - - iv = pframe + prxattrib->hdrlen; - /* keyindex = (iv[3]&0x3); */ - keyindex = prxattrib->key_index; - keylength = psecuritypriv->wep_key[keyindex].keylen; - memcpy(&wepkey[0], iv, 3); - /* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */ - memcpy(&wepkey[3], &psecuritypriv->wep_key[keyindex].key, keylength); - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - - /* decrypt payload include icv */ - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - - /* calculate icv and compare the icv */ - actual_crc = getcrc32(payload, length - 4); - expected_crc = get_unaligned_le32(&payload[length - 4]); - - if (actual_crc != expected_crc) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:icv CRC mismatch: " - "actual: %08x, expected: %08x\n", - __func__, actual_crc, expected_crc); - } -} - -/* 3 ===== TKIP related ===== */ - -static u32 secmicgetuint32(u8 *p) -/* Convert from Byte[] to u32 in a portable way */ -{ - s32 i; - u32 res = 0; - - for (i = 0; i < 4; i++) - res |= ((u32)(*p++)) << (8 * i); - - return res; -} - -static void secmicputuint32(u8 *p, u32 val) -/* Convert from long to Byte[] in a portable way */ -{ - long i; - - for (i = 0; i < 4; i++) { - *p++ = (u8) (val & 0xff); - val >>= 8; - } - -} - -static void secmicclear(struct mic_data *pmicdata) -{ -/* Reset the state to the empty message. */ - - pmicdata->L = pmicdata->K0; - pmicdata->R = pmicdata->K1; - pmicdata->nBytesInM = 0; - pmicdata->M = 0; - -} - -void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 *key) -{ - /* Set the key */ - - pmicdata->K0 = secmicgetuint32(key); - pmicdata->K1 = secmicgetuint32(key + 4); - /* and reset the message */ - secmicclear(pmicdata); - -} - -void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b) -{ - - /* Append the byte to our word-sized buffer */ - pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM); - pmicdata->nBytesInM++; - /* Process the word if it is full. */ - if (pmicdata->nBytesInM >= 4) { - pmicdata->L ^= pmicdata->M; - pmicdata->R ^= ROL32(pmicdata->L, 17); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROL32(pmicdata->L, 3); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROR32(pmicdata->L, 2); - pmicdata->L += pmicdata->R; - /* Clear the buffer */ - pmicdata->M = 0; - pmicdata->nBytesInM = 0; - } - -} - -void rtw_secmicappend23a(struct mic_data *pmicdata, u8 *src, u32 nbytes) -{ - - /* This is simple */ - while (nbytes > 0) { - rtw_secmicappend23abyte23a(pmicdata, *src++); - nbytes--; - } - -} - -void rtw_secgetmic23a(struct mic_data *pmicdata, u8 *dst) -{ - - /* Append the minimum padding */ - rtw_secmicappend23abyte23a(pmicdata, 0x5a); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - /* and then zeroes until the length is a multiple of 4 */ - while (pmicdata->nBytesInM != 0) - rtw_secmicappend23abyte23a(pmicdata, 0); - /* The appendByte function has already computed the result. */ - secmicputuint32(dst, pmicdata->L); - secmicputuint32(dst + 4, pmicdata->R); - /* Reset to the empty message. */ - secmicclear(pmicdata); - -} - -void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len, - u8 *mic_code, u8 pri) -{ - - struct mic_data micdata; - u8 priority[4] = {0x0, 0x0, 0x0, 0x0}; - - rtw_secmicsetkey23a(&micdata, key); - priority[0] = pri; - - /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ - if (header[1]&1) { /* ToDS == 1 */ - rtw_secmicappend23a(&micdata, &header[16], 6); /* DA */ - if (header[1]&2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, &header[24], 6); - else - rtw_secmicappend23a(&micdata, &header[10], 6); - } else { /* ToDS == 0 */ - rtw_secmicappend23a(&micdata, &header[4], 6); /* DA */ - if (header[1]&2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, &header[16], 6); - else - rtw_secmicappend23a(&micdata, &header[10], 6); - - } - rtw_secmicappend23a(&micdata, &priority[0], 4); - - rtw_secmicappend23a(&micdata, data, data_len); - - rtw_secgetmic23a(&micdata, mic_code); - -} - -/* macros for extraction/creation of unsigned char/unsigned short values */ -#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15)) -#define Lo8(v16) ((u8)((v16) & 0x00FF)) -#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF)) -#define Lo16(v32) ((u16)((v32) & 0xFFFF)) -#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF)) -#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8)) - -/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */ -#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)]) - -/* S-box lookup: 16 bits --> 16 bits */ -#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)]) - -/* fixed algorithm "parameters" */ -#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */ -#define TA_SIZE 6 /* 48-bit transmitter address */ -#define TK_SIZE 16 /* 128-bit temporal key */ -#define P1K_SIZE 10 /* 80-bit Phase1 key */ -#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */ - -/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */ -static const unsigned short Sbox1[2][256] = { - /* Sbox for hash (can be in ROM) */ - { - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, - }, - { /* second half of table is unsigned char-reversed version of first! */ - 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, - 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, - 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, - 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, - 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, - 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, - 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, - 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, - 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, - 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, - 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, - 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, - 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, - 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, - 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, - 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, - 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, - 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, - 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, - 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, - 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, - 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, - 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, - 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, - 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, - 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, - 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, - 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, - 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, - 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, - 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, - 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C, - } -}; - - /* -********************************************************************** -* Routine: Phase 1 -- generate P1K, given TA, TK, IV32 -* -* Inputs: -* tk[] = temporal key [128 bits] -* ta[] = transmitter's MAC address [ 48 bits] -* iv32 = upper 32 bits of IV [ 32 bits] -* Output: -* p1k[] = Phase 1 key [ 80 bits] -* -* Note: -* This function only needs to be called every 2**16 packets, -* although in theory it could be called every packet. -* -********************************************************************** -*/ -static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) -{ - int i; - - /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */ - p1k[0] = Lo16(iv32); - p1k[1] = Hi16(iv32); - p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */ - p1k[3] = Mk16(ta[3], ta[2]); - p1k[4] = Mk16(ta[5], ta[4]); - - /* Now compute an unbalanced Feistel cipher with 80-bit block */ - /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ - for (i = 0; i < PHASE1_LOOP_CNT; i++) { - /* Each add operation here is mod 2**16 */ - p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0)); - p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2)); - p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4)); - p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6)); - p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0)); - p1k[4] += (unsigned short) i; /* avoid "slide attacks" */ - } - -} - -/* -********************************************************************** -* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 -* -* Inputs: -* tk[] = Temporal key [128 bits] -* p1k[] = Phase 1 output key [ 80 bits] -* iv16 = low 16 bits of IV counter [ 16 bits] -* Output: -* rc4key[] = the key used to encrypt the packet [128 bits] -* -* Note: -* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique -* across all packets using the same key TK value. Then, for a -* given value of TK[], this TKIP48 construction guarantees that -* the final RC4KEY value is unique across all packets. -* -* Suggested implementation optimization: if PPK[] is "overlaid" -* appropriately on RC4KEY[], there is no need for the final -* for loop below that copies the PPK[] result into RC4KEY[]. -* -********************************************************************** -*/ -static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) -{ - int i; - u16 PPK[6]; /* temporary key for mixing */ - - /* Note: all adds in the PPK[] equations below are mod 2**16 */ - for (i = 0; i < 5; i++) - PPK[i] = p1k[i]; /* first, copy P1K to PPK */ - - PPK[5] = p1k[4] + iv16; /* next, add in IV16 */ - - /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ - PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ - PPK[1] += _S_(PPK[0] ^ TK16(1)); - PPK[2] += _S_(PPK[1] ^ TK16(2)); - PPK[3] += _S_(PPK[2] ^ TK16(3)); - PPK[4] += _S_(PPK[3] ^ TK16(4)); - PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */ - - /* Final sweep: bijective, "linear". Rotates kill LSB correlations */ - PPK[0] += RotR1(PPK[5] ^ TK16(6)); - PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */ - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - /* Note: At this point, for a given key TK[0..15], the 96-bit output */ - /* value PPK[0..5] is guaranteed to be unique, as a function */ - /* of the 96-bit "input" value {TA, IV32, IV16}. That is, */ - /* P1K is now a keyed permutation of {TA, IV32, IV16}. */ - - /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */ - rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */ - rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */ - rc4key[2] = Lo8(iv16); - rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1); - - /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ - for (i = 0; i < 6; i++) { - rc4key[4 + 2 * i] = Lo8(PPK[i]); - rc4key[5 + 2 * i] = Hi8(PPK[i]); - } - -} - -/* The hlen isn't include the IV */ -int rtw_tkip_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - __le32 crc; - u8 hw_hdr_offset = 0; - struct arc4context mycontext; - int curfragnum, length; - u8 *pframe, *payload, *iv, *prwskey; - union pn48 dot11txpn; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int res = _SUCCESS; - - if (pattrib->encrypt != WLAN_CIPHER_SUITE_TKIP) - return _FAIL; - - if (!pxmitframe->buf_addr) - return _FAIL; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - if (pattrib->psta) - stainfo = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, - &pattrib->ra[0]); - } - - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - - if (!(stainfo->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state); - return _FAIL; - } - - if (is_multicast_ether_addr(pattrib->ra)) - prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; - else - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - - /* 4 start to encrypt each fragment */ - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - iv = pframe + pattrib->hdrlen; - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - - GET_TKIP_PN(iv, dot11txpn); - - pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); - - phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh); - - phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl); - - if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ - length = (pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len); - - RT_TRACE(_module_rtl871x_security_c_, _drv_info_, - "pattrib->iv_len =%x, pattrib->icv_len =%x\n", - pattrib->iv_len, - pattrib->icv_len); - crc = cpu_to_le32(getcrc32(payload, length)); - - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - } else { - length = (pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len); - - crc = cpu_to_le32(getcrc32(payload, length)); - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - - return res; -} - -/* The hlen isn't include the IV */ -int rtw_tkip_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - u32 actual_crc, expected_crc; - struct arc4context mycontext; - int length; - u8 *pframe, *payload, *iv, *prwskey; - union pn48 dot11txpn; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - int res = _SUCCESS; - - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_TKIP) - return _FAIL; - - pframe = skb->data; - - stainfo = rtw_get_stainfo23a(&padapter->stapriv, - &prxattrib->ta[0]); - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - return _FAIL; - } - - /* 4 start to decrypt recvframe */ - if (is_multicast_ether_addr(prxattrib->ra)) { - if (psecuritypriv->binstallGrpkey == 0) { - res = _FAIL; - DBG_8723A("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__); - goto exit; - } - prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; - } else { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - } - - iv = pframe + prxattrib->hdrlen; - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - GET_TKIP_PN(iv, dot11txpn); - - pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); - - phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh); - phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl); - - /* 4 decrypt payload include icv */ - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - - actual_crc = getcrc32(payload, length - 4); - expected_crc = get_unaligned_le32(&payload[length - 4]); - - if (actual_crc != expected_crc) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:icv CRC mismatch: " - "actual: %08x, expected: %08x\n", - __func__, actual_crc, expected_crc); - res = _FAIL; - } - -exit: - return res; -} - -/* 3 ===== AES related ===== */ - -#define MAX_MSG_SIZE 2048 -/*****************************/ -/******** SBOX Table *********/ -/*****************************/ - -static u8 sbox_table[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -/*****************************/ -/**** Function Prototypes ****/ -/*****************************/ - -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, - int qc_exists); - -static void xor_128(u8 *a, u8 *b, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = a[i] ^ b[i]; -} - -static void xor_32(u8 *a, u8 *b, u8 *out) -{ - int i; - - for (i = 0; i < 4; i++) - out[i] = a[i] ^ b[i]; -} - -static u8 sbox(u8 a) -{ - return sbox_table[(int)a]; -} - -static void next_key(u8 *key, int round) -{ - u8 rcon; - u8 sbox_key[4]; - u8 rcon_table[12] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - 0x1b, 0x36, 0x36, 0x36 - }; - - sbox_key[0] = sbox(key[13]); - sbox_key[1] = sbox(key[14]); - sbox_key[2] = sbox(key[15]); - sbox_key[3] = sbox(key[12]); - - rcon = rcon_table[round]; - - xor_32(&key[0], sbox_key, &key[0]); - key[0] = key[0] ^ rcon; - - xor_32(&key[4], &key[0], &key[4]); - xor_32(&key[8], &key[4], &key[8]); - xor_32(&key[12], &key[8], &key[12]); - -} - -static void byte_sub(u8 *in, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = sbox(in[i]); -} - -static void shift_row(u8 *in, u8 *out) -{ - - out[0] = in[0]; - out[1] = in[5]; - out[2] = in[10]; - out[3] = in[15]; - out[4] = in[4]; - out[5] = in[9]; - out[6] = in[14]; - out[7] = in[3]; - out[8] = in[8]; - out[9] = in[13]; - out[10] = in[2]; - out[11] = in[7]; - out[12] = in[12]; - out[13] = in[1]; - out[14] = in[6]; - out[15] = in[11]; - -} - -static void mix_column(u8 *in, u8 *out) -{ - int i; - u8 add1b[4]; - u8 add1bf7[4]; - u8 rotl[4]; - u8 swap_halfs[4]; - u8 andf7[4]; - u8 rotr[4]; - u8 temp[4]; - u8 tempb[4]; - - for (i = 0; i < 4; i++) { - if ((in[i] & 0x80) == 0x80) - add1b[i] = 0x1b; - else - add1b[i] = 0x00; - } - - swap_halfs[0] = in[2]; /* Swap halfs */ - swap_halfs[1] = in[3]; - swap_halfs[2] = in[0]; - swap_halfs[3] = in[1]; - - rotl[0] = in[3]; /* Rotate left 8 bits */ - rotl[1] = in[0]; - rotl[2] = in[1]; - rotl[3] = in[2]; - - andf7[0] = in[0] & 0x7f; - andf7[1] = in[1] & 0x7f; - andf7[2] = in[2] & 0x7f; - andf7[3] = in[3] & 0x7f; - - for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ - andf7[i] = andf7[i] << 1; - if ((andf7[i - 1] & 0x80) == 0x80) - andf7[i] = (andf7[i] | 0x01); - } - andf7[0] = andf7[0] << 1; - andf7[0] = andf7[0] & 0xfe; - - xor_32(add1b, andf7, add1bf7); - - xor_32(in, add1bf7, rotr); - - temp[0] = rotr[0]; /* Rotate right 8 bits */ - rotr[0] = rotr[1]; - rotr[1] = rotr[2]; - rotr[2] = rotr[3]; - rotr[3] = temp[0]; - - xor_32(add1bf7, rotr, temp); - xor_32(swap_halfs, rotl, tempb); - xor_32(temp, tempb, out); - -} - -static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext) -{ - int round; - int i; - u8 intermediatea[16]; - u8 intermediateb[16]; - u8 round_key[16]; - - for (i = 0; i < 16; i++) - round_key[i] = key[i]; - - for (round = 0; round < 11; round++) { - if (round == 0) { - xor_128(round_key, data, ciphertext); - next_key(round_key, round); - } else if (round == 10) { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - xor_128(intermediateb, round_key, ciphertext); - } else { /* 1 - 9 */ - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - mix_column(&intermediateb[0], &intermediatea[0]); - mix_column(&intermediateb[4], &intermediatea[4]); - mix_column(&intermediateb[8], &intermediatea[8]); - mix_column(&intermediateb[12], &intermediatea[12]); - xor_128(intermediatea, round_key, ciphertext); - next_key(round_key, round); - } - } - -} - -/************************************************/ -/* construct_mic_iv() */ -/* Builds the MIC IV from header fields and PN */ -/************************************************/ -static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu, - uint payload_length, u8 *pn_vector) -{ - int i; - - mic_iv[0] = 0x59; - if (qc_exists && a4_exists) - mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ - if (qc_exists && !a4_exists) - mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ - if (!qc_exists) - mic_iv[1] = 0x00; - for (i = 2; i < 8; i++) - mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ - mic_iv[14] = (unsigned char)(payload_length / 256); - mic_iv[15] = (unsigned char)(payload_length % 256); -} - -/************************************************/ -/* construct_mic_header1() */ -/* Builds the first MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu) -{ - mic_header1[0] = (u8)((header_length - 2) / 256); - mic_header1[1] = (u8)((header_length - 2) % 256); - mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ - mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ - mic_header1[4] = mpdu[4]; /* A1 */ - mic_header1[5] = mpdu[5]; - mic_header1[6] = mpdu[6]; - mic_header1[7] = mpdu[7]; - mic_header1[8] = mpdu[8]; - mic_header1[9] = mpdu[9]; - mic_header1[10] = mpdu[10]; /* A2 */ - mic_header1[11] = mpdu[11]; - mic_header1[12] = mpdu[12]; - mic_header1[13] = mpdu[13]; - mic_header1[14] = mpdu[14]; - mic_header1[15] = mpdu[15]; - -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, - int qc_exists) -{ - int i; - - for (i = 0; i < 16; i++) - mic_header2[i] = 0x00; - - mic_header2[0] = mpdu[16]; /* A3 */ - mic_header2[1] = mpdu[17]; - mic_header2[2] = mpdu[18]; - mic_header2[3] = mpdu[19]; - mic_header2[4] = mpdu[20]; - mic_header2[5] = mpdu[21]; - - mic_header2[6] = 0x00; - mic_header2[7] = 0x00; /* mpdu[23]; */ - - if (!qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ - } - - if (qc_exists && !a4_exists) { - mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ - mic_header2[9] = mpdu[25] & 0x00; - } - - if (qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ - - mic_header2[14] = mpdu[30] & 0x0f; - mic_header2[15] = mpdu[31] & 0x00; - } - -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, - u8 *mpdu, u8 *pn_vector, int c) -{ - int i = 0; - - for (i = 0; i < 16; i++) - ctr_preload[i] = 0x00; - - i = 0; - - ctr_preload[0] = 0x01; /* flag */ - if (qc_exists && a4_exists) - ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ - if (qc_exists && !a4_exists) - ctr_preload[1] = mpdu[24] & 0x0f; - - for (i = 2; i < 8; i++) - ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ - ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */ - ctr_preload[15] = (unsigned char) (c % 256); - -} - -/************************************/ -/* bitwise_xor() */ -/* A 128 bit, bitwise exclusive or */ -/************************************/ -static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = ina[i] ^ inb[i]; -} - -static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) -{ - uint qc_exists, a4_exists, i, j, payload_remainder, - num_blocks, payload_index; - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe; - u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE; - - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) || - (hdrlen == sizeof(struct ieee80211_qos_hdr)))) - a4_exists = 0; - else - a4_exists = 1; - - if (ieee80211_is_data(hdr->frame_control)) { - if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) { - qc_exists = 1; - if (hdrlen != sizeof(struct ieee80211_qos_hdr)) - hdrlen += 2; - } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) { - if (hdrlen != sizeof(struct ieee80211_qos_hdr)) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - } else { - qc_exists = 0; - } - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector); - - construct_mic_header1(mic_header1, hdrlen, pframe); - construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists); - - payload_remainder = plen % 16; - num_blocks = plen / 16; - - /* Find start of payload */ - payload_index = hdrlen + 8; - - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - - for (j = 0; j < 8; j++) - mic[j] = aes_out[j]; - - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - pframe[payload_index + j] = mic[j]; - - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, 0); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = pframe[j + hdrlen + 8 + plen]; - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - pframe[payload_index++] = chain_buffer[j]; - - return _SUCCESS; -} - -int rtw_aes_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ /* exclude ICV */ - /* Intermediate Buffers */ - int curfragnum, length; - u8 *pframe, *prwskey; - u8 hw_hdr_offset = 0; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int res = _SUCCESS; - - if (!pxmitframe->buf_addr) - return _FAIL; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* 4 start to encrypt each fragment */ - if (pattrib->encrypt != WLAN_CIPHER_SUITE_CCMP) - return _FAIL; - - if (pattrib->psta) { - stainfo = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - DBG_8723A("%s, psta == NUL\n", __func__); - res = _FAIL; - goto out; - } - if (!(stainfo->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, stainfo->state); - return _FAIL; - } - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - - if (is_multicast_ether_addr(pattrib->ra)) - prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; - else - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - /* 4 the last fragment */ - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen-pattrib->iv_len - - pattrib->icv_len; - - aes_cipher(prwskey, pattrib->hdrlen, pframe, length); - } else { - length = pxmitpriv->frag_len-pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - - aes_cipher(prwskey, pattrib->hdrlen, pframe, length); - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } -out: - return res; -} - -static int 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, - num_blocks, payload_index; - int res = _SUCCESS; - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe; - u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE; - - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - /* start to decrypt the payload */ - - num_blocks = (plen - 8) / 16; /* plen including llc, payload_length and mic) */ - - payload_remainder = (plen - 8) % 16; - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) || - (hdrlen == sizeof(struct ieee80211_qos_hdr)))) - a4_exists = 0; - else - a4_exists = 1; - - if (ieee80211_is_data(hdr->frame_control)) { - if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) { - qc_exists = 1; - if (hdrlen != sizeof(struct ieee80211_hdr_3addr)) - hdrlen += 2; - } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) { - if (hdrlen != sizeof(struct ieee80211_hdr_3addr)) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - } else { - qc_exists = 0; - } - - /* now, decrypt pframe with hdrlen offset and plen long */ - - payload_index = hdrlen + 8; /* 8 is for extiv */ - - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, i + 1); - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - /* start to calculate the mic */ - if ((hdrlen + plen + 8) <= MAX_MSG_SIZE) - memcpy(message, pframe, (hdrlen + plen + 8)); /* 8 is for ext iv len */ - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - construct_mic_iv(mic_iv, qc_exists, a4_exists, message, - plen - 8, pn_vector); - - construct_mic_header1(mic_header1, hdrlen, message); - construct_mic_header2(mic_header2, message, a4_exists, qc_exists); - - payload_remainder = (plen - 8) % 16; - num_blocks = (plen - 8) / 16; - - /* Find start of payload */ - payload_index = hdrlen + 8; - - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - - for (j = 0 ; j < 8; j++) - mic[j] = aes_out[j]; - - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - message[payload_index + j] = mic[j]; - - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - message, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - message[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - message, pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - message[payload_index++] = chain_buffer[j]; - } - - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, - pn_vector, 0); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = message[j + hdrlen + 8 + plen - 8]; - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - message[payload_index++] = chain_buffer[j]; - - /* compare the mic */ - for (i = 0; i < 8; i++) { - if (pframe[hdrlen + 8 + plen - 8 + i] != message[hdrlen + 8 + plen - 8 + i]) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:mic check error mic[%d]: pframe(%x) != message(%x)\n", - __func__, i, - pframe[hdrlen + 8 + plen - 8 + i], - message[hdrlen + 8 + plen - 8 + i]); - DBG_8723A("%s:mic check error mic[%d]: pframe(%x) != message(%x)\n", - __func__, i, - pframe[hdrlen + 8 + plen - 8 + i], - message[hdrlen + 8 + plen - 8 + i]); - res = _FAIL; - } - } - return res; -} - -int rtw_aes_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ /* exclude ICV */ - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - int length; - u8 *pframe, *prwskey; - int res = _SUCCESS; - - pframe = skb->data; - /* 4 start to encrypt each fragment */ - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_CCMP) - return _FAIL; - - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &prxattrib->ta[0]); - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - res = _FAIL; - goto exit; - } - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - - if (is_multicast_ether_addr(prxattrib->ra)) { - /* in concurrent we should use sw decrypt in - * group key, so we remove this message - */ - if (!psecuritypriv->binstallGrpkey) { - res = _FAIL; - DBG_8723A("%s:rx bc/mc packets, but didn't install " - "group key!!!!!!!!!!\n", __func__); - goto exit; - } - prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; - if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) { - DBG_8723A("not match packet_index =%d, install_index =" - "%d\n", prxattrib->key_index, - psecuritypriv->dot118021XGrpKeyid); - res = _FAIL; - goto exit; - } - } else { - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - } - - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); -exit: - return res; -} - -void rtw_use_tkipkey_handler23a(void *function_context) -{ - struct rtw_adapter *padapter = function_context; - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "^^^%s ^^^\n", __func__); - padapter->securitypriv.busetkipkey = 1; - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "^^^%s padapter->securitypriv.busetkipkey =%d^^^\n", - __func__, padapter->securitypriv.busetkipkey); -} diff --git a/drivers/staging/rtl8723au/core/rtw_sreset.c b/drivers/staging/rtl8723au/core/rtw_sreset.c deleted file mode 100644 index 29a29d92a6ac..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_sreset.c +++ /dev/null @@ -1,214 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#include -#include - -void rtw_sreset_init(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - mutex_init(&psrtpriv->silentreset_mutex); - psrtpriv->silent_reset_inprogress = false; - psrtpriv->last_tx_time = 0; - psrtpriv->last_tx_complete_time = 0; -} - -void rtw_sreset_reset_value(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - psrtpriv->silent_reset_inprogress = false; - psrtpriv->last_tx_time = 0; - psrtpriv->last_tx_complete_time = 0; -} - -bool rtw_sreset_inprogress(struct rtw_adapter *padapter) -{ - struct rtw_adapter *primary_adapter = GET_PRIMARY_ADAPTER(padapter); - struct hal_data_8723a *pHalData = GET_HAL_DATA(primary_adapter); - - return pHalData->srestpriv.silent_reset_inprogress; -} - -static void sreset_restore_security_station(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info; - u8 val8; - - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) - val8 = 0xcc; - else - val8 = 0xcf; - - rtl8723a_set_sec_cfg(padapter, val8); - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_TKIP || - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv)); - if (psta == NULL) { - /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */ - } else { - /* pairwise key */ - rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true); - /* group key */ - rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0); - } - } -} - -static void sreset_restore_network_station(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 threshold; - - rtw_setopmode_cmd23a(padapter, NL80211_IFTYPE_STATION); - - /* TH = 1 => means that invalidate usb rx aggregation */ - /* TH = 0 => means that validate usb rx aggregation, use init value. */ - if (mlmepriv->htpriv.ht_option) { - if (padapter->registrypriv.wifi_spec == 1) - threshold = 1; - else - threshold = 0; - } else - threshold = 1; - - rtl8723a_set_rxdma_agg_pg_th(padapter, threshold); - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - mlmeext_joinbss_event_callback23a(padapter, 1); - /* restore Sequence No. */ - rtl8723au_write8(padapter, REG_NQOS_SEQ, padapter->xmitpriv.nqos_ssn); - - sreset_restore_security_station(padapter); -} - -static void sreset_restore_network_status(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - - if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_STATION_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - sreset_restore_network_station(padapter); -#ifdef CONFIG_8723AU_AP_MODE - } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_AP_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - rtw_ap_restore_network(padapter); -#endif - } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_ADHOC_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - } else { - DBG_8723A("%s(%s): fwstate:0x%08x - ???\n", __func__, - padapter->pnetdev->name, get_fwstate(mlmepriv)); - } -} - -static void sreset_stop_adapter(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter == NULL) - return; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if (!rtw_netif_queue_stopped(padapter->pnetdev)) - netif_tx_stop_all_queues(padapter->pnetdev); - - rtw_cancel_all_timer23a(padapter); - - /* TODO: OS and HCI independent */ - tasklet_kill(&pxmitpriv->xmit_tasklet); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - rtw_scan_abort23a(padapter); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - rtw23a_join_to_handler((unsigned long)padapter); -} - -static void sreset_start_adapter(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter == NULL) - return; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - sreset_restore_network_status(padapter); - - /* TODO: OS and HCI independent */ - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - - mod_timer(&padapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(2000)); - - if (rtw_netif_queue_stopped(padapter->pnetdev)) - netif_tx_wake_all_queues(padapter->pnetdev); -} - -void rtw_sreset_reset(struct rtw_adapter *active_adapter) -{ - struct rtw_adapter *padapter = GET_PRIMARY_ADAPTER(active_adapter); - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - unsigned long start = jiffies; - - DBG_8723A("%s\n", __func__); - - mutex_lock(&psrtpriv->silentreset_mutex); - psrtpriv->silent_reset_inprogress = true; - pwrpriv->change_rfpwrstate = rf_off; - - sreset_stop_adapter(padapter); - - ips_enter23a(padapter); - ips_leave23a(padapter); - - sreset_start_adapter(padapter); - psrtpriv->silent_reset_inprogress = false; - mutex_unlock(&psrtpriv->silentreset_mutex); - - DBG_8723A("%s done in %d ms\n", __func__, - jiffies_to_msecs(jiffies - start)); -} diff --git a/drivers/staging/rtl8723au/core/rtw_sta_mgt.c b/drivers/staging/rtl8723au/core/rtw_sta_mgt.c deleted file mode 100644 index a9b778c45d44..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_sta_mgt.c +++ /dev/null @@ -1,439 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_STA_MGT_C_ - -#include -#include -#include -#include -#include -#include -#include - -static const u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -static void _rtw_init_stainfo(struct sta_info *psta) -{ - memset((u8 *)psta, 0, sizeof(struct sta_info)); - spin_lock_init(&psta->lock); - INIT_LIST_HEAD(&psta->list); - INIT_LIST_HEAD(&psta->hash_list); - _rtw_init_queue23a(&psta->sleep_q); - psta->sleepq_len = 0; - _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); - _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); -#ifdef CONFIG_8723AU_AP_MODE - INIT_LIST_HEAD(&psta->asoc_list); - INIT_LIST_HEAD(&psta->auth_list); - psta->expire_to = 0; - psta->flags = 0; - psta->capability = 0; - psta->bpairwise_key_installed = false; - psta->nonerp_set = 0; - psta->no_short_slot_time_set = 0; - psta->no_short_preamble_set = 0; - psta->no_ht_gf_set = 0; - psta->no_ht_set = 0; - psta->ht_20mhz_set = 0; - psta->keep_alive_trycnt = 0; -#endif /* CONFIG_8723AU_AP_MODE */ -} - -int _rtw_init_sta_priv23a(struct sta_priv *pstapriv) -{ - int i; - - spin_lock_init(&pstapriv->sta_hash_lock); - pstapriv->asoc_sta_count = 0; - for (i = 0; i < NUM_STA; i++) - INIT_LIST_HEAD(&pstapriv->sta_hash[i]); - -#ifdef CONFIG_8723AU_AP_MODE - pstapriv->sta_dz_bitmap = 0; - pstapriv->tim_bitmap = 0; - INIT_LIST_HEAD(&pstapriv->asoc_list); - INIT_LIST_HEAD(&pstapriv->auth_list); - spin_lock_init(&pstapriv->asoc_list_lock); - spin_lock_init(&pstapriv->auth_list_lock); - pstapriv->asoc_list_cnt = 0; - pstapriv->auth_list_cnt = 0; - pstapriv->auth_to = 3; /* 3*2 = 6 sec */ - pstapriv->assoc_to = 3; - /* pstapriv->expire_to = 900; 900*2 = 1800 sec = 30 min, - expire after no any traffic. */ - /* pstapriv->expire_to = 30; 30*2 = 60 sec = 1 min, - expire after no any traffic. */ - pstapriv->expire_to = 3; /* 3*2 = 6 sec */ - pstapriv->max_num_sta = NUM_STA; -#endif - return _SUCCESS; -} - -int _rtw_free_sta_priv23a(struct sta_priv *pstapriv) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct recv_reorder_ctrl *preorder_ctrl; - int index; - - if (pstapriv) { - /* delete all reordering_ctrl_timer */ - spin_lock_bh(&pstapriv->sta_hash_lock); - for (index = 0; index < NUM_STA; index++) { - phead = &pstapriv->sta_hash[index]; - list_for_each_entry_safe(psta, ptmp, phead, hash_list) { - int i; - - for (i = 0; i < 16 ; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - } - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - /*===============================*/ - } - return _SUCCESS; -} - -struct sta_info * -rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp) -{ - struct list_head *phash_list; - struct sta_info *psta; - struct recv_reorder_ctrl *preorder_ctrl; - s32 index; - int i = 0; - u16 wRxSeqInitialValue = 0xffff; - - psta = kmalloc(sizeof(struct sta_info), gfp); - if (!psta) - return NULL; - - spin_lock_bh(&pstapriv->sta_hash_lock); - - _rtw_init_stainfo(psta); - - psta->padapter = pstapriv->padapter; - - ether_addr_copy(psta->hwaddr, hwaddr); - - index = wifi_mac_hash(hwaddr); - - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, - "rtw_alloc_stainfo23a: index = %x\n", index); - if (index >= NUM_STA) { - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "ERROR => rtw_alloc_stainfo23a: index >= NUM_STA\n"); - psta = NULL; - goto exit; - } - phash_list = &pstapriv->sta_hash[index]; - - list_add_tail(&psta->hash_list, phash_list); - - pstapriv->asoc_sta_count++; - -/* For the SMC router, the sequence number of first packet of WPS - handshake will be 0. */ -/* In this case, this packet will be dropped by recv_decache function - if we use the 0x00 as the default value for tid_rxseq variable. */ -/* So, we initialize the tid_rxseq variable as the 0xffff. */ - - for (i = 0; i < 16; i++) - memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], - &wRxSeqInitialValue, 2); - - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, - "alloc number_%d stainfo with hwaddr = %pM\n", - pstapriv->asoc_sta_count, hwaddr); - - init_addba_retry_timer23a(psta); - - /* for A-MPDU Rx reordering buffer control */ - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - - preorder_ctrl->padapter = pstapriv->padapter; - - preorder_ctrl->enable = false; - - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */ - preorder_ctrl->wsize_b = 64;/* 64; */ - - _rtw_init_queue23a(&preorder_ctrl->pending_recvframe_queue); - - rtw_init_recv_timer23a(preorder_ctrl); - } - /* init for DM */ - psta->rssi_stat.UndecoratedSmoothedPWDB = (-1); - psta->rssi_stat.UndecoratedSmoothedCCK = (-1); - - /* init for the sequence number of received management frame */ - psta->RxMgmtFrameSeqNum = 0xffff; -exit: - spin_unlock_bh(&pstapriv->sta_hash_lock); - return psta; -} - -/* using pstapriv->sta_hash_lock to protect */ -int rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_xmit_priv *pstaxmitpriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct hw_xmit *phwxmit; - int i; - - if (!psta) - goto exit; - - spin_lock_bh(&psta->lock); - psta->state &= ~_FW_LINKED; - spin_unlock_bh(&psta->lock); - - pstaxmitpriv = &psta->sta_xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - rtw_free_xmitframe_queue23a(pxmitpriv, &psta->sleep_q); - psta->sleepq_len = 0; - - /* vo */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - phwxmit = pxmitpriv->hwxmits; - phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; - pstaxmitpriv->vo_q.qcnt = 0; - - /* vi */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+1; - phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; - pstaxmitpriv->vi_q.qcnt = 0; - - /* be */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+2; - phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; - pstaxmitpriv->be_q.qcnt = 0; - - /* bk */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+3; - phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; - pstaxmitpriv->bk_q.qcnt = 0; - - spin_unlock_bh(&pxmitpriv->lock); - - list_del_init(&psta->hash_list); - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "free number_%d stainfo with hwaddr = %pM\n", - pstapriv->asoc_sta_count, psta->hwaddr); - pstapriv->asoc_sta_count--; - - /* re-init sta_info; 20061114 will be init in alloc_stainfo */ - /* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */ - /* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */ - - del_timer_sync(&psta->addba_retry_timer); - - /* for A-MPDU Rx reordering buffer control, - cancel reordering_ctrl_timer */ - for (i = 0; i < 16; i++) { - struct list_head *phead, *plist; - struct recv_frame *prframe; - struct rtw_queue *ppending_recvframe_queue; - - preorder_ctrl = &psta->recvreorder_ctrl[i]; - - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - - ppending_recvframe_queue = - &preorder_ctrl->pending_recvframe_queue; - - spin_lock_bh(&ppending_recvframe_queue->lock); - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - while (!list_empty(phead)) { - prframe = container_of(plist, struct recv_frame, list); - plist = plist->next; - list_del_init(&prframe->list); - rtw_free_recvframe23a(prframe); - } - spin_unlock_bh(&ppending_recvframe_queue->lock); - } - if (!(psta->state & WIFI_AP_STATE)) - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, false); -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&psta->auth_list)) { - list_del_init(&psta->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - psta->expire_to = 0; - - psta->sleepq_ac_len = 0; - psta->qos_info = 0; - - psta->max_sp_len = 0; - psta->uapsd_bk = 0; - psta->uapsd_be = 0; - psta->uapsd_vi = 0; - psta->uapsd_vo = 0; - - psta->has_legacy_ac = 0; - - pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid); - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) { - pstapriv->sta_aid[psta->aid - 1] = NULL; - psta->aid = 0; - } -#endif /* CONFIG_8723AU_AP_MODE */ - - kfree(psta); -exit: - return _SUCCESS; -} - -/* free all stainfo which in sta_hash[all] */ -void rtw_free_all_stainfo23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter); - s32 index; - - if (pstapriv->asoc_sta_count == 1) - return; - - spin_lock_bh(&pstapriv->sta_hash_lock); - for (index = 0; index < NUM_STA; index++) { - phead = &pstapriv->sta_hash[index]; - list_for_each_entry_safe(psta, ptmp, phead, hash_list) { - if (pbcmc_stainfo != psta) - rtw_free_stainfo23a(padapter, psta); - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); -} - -/* any station allocated can be searched by hash list */ -struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr) -{ - struct list_head *phead; - struct sta_info *pos, *psta = NULL; - u32 index; - const u8 *addr; - - if (!hwaddr) - return NULL; - - if (is_multicast_ether_addr(hwaddr)) - addr = bc_addr; - else - addr = hwaddr; - - index = wifi_mac_hash(addr); - - spin_lock_bh(&pstapriv->sta_hash_lock); - phead = &pstapriv->sta_hash[index]; - list_for_each_entry(pos, phead, hash_list) { - psta = pos; - - /* if found the matched address */ - if (ether_addr_equal(psta->hwaddr, addr)) - break; - - psta = NULL; - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - return psta; -} - -int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - struct tx_servq *ptxservq; - int res = _SUCCESS; - - psta = rtw_alloc_stainfo23a(pstapriv, bc_addr, GFP_KERNEL); - if (!psta) { - res = _FAIL; - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "rtw_alloc_stainfo23a fail\n"); - return res; - } - /* default broadcast & multicast use macid 1 */ - psta->mac_id = 1; - - ptxservq = &psta->sta_xmitpriv.be_q; - return _SUCCESS; -} - -struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter) -{ - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo23a(pstapriv, bc_addr); - return psta; -} - -bool rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr) -{ - bool res = true; -#ifdef CONFIG_8723AU_AP_MODE - struct list_head *phead; - struct rtw_wlan_acl_node *paclnode; - bool match = false; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q; - - spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - list_for_each_entry(paclnode, phead, list) { - if (ether_addr_equal(paclnode->addr, mac_addr)) { - if (paclnode->valid) { - match = true; - break; - } - } - } - spin_unlock_bh(&pacl_node_q->lock); - - if (pacl_list->mode == 1)/* accept unless in deny list */ - res = (match) ? false : true; - else if (pacl_list->mode == 2)/* deny unless in accept list */ - res = (match) ? true : false; - else - res = true; -#endif - return res; -} diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c deleted file mode 100644 index 694cf17f82cf..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c +++ /dev/null @@ -1,1537 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_WLAN_UTIL_C_ - -#include -#include -#include -#include -#include - -static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f}; -static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74}; - -static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18}; -static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7}; - -static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96}; -static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43}; -static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43}; -static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c}; -static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5}; -static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c}; - -static unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02}; -static unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02}; - -#define R2T_PHY_DELAY 0 - -/* define WAIT_FOR_BCN_TO_MIN 3000 */ -#define WAIT_FOR_BCN_TO_MIN 6000 -#define WAIT_FOR_BCN_TO_MAX 20000 - -static u8 rtw_basic_rate_cck[4] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 rtw_basic_rate_ofdm[3] = { - IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 rtw_basic_rate_mix[7] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK -}; - -int cckrates_included23a(unsigned char *rate, int ratelen) -{ - int i; - - for (i = 0; i < ratelen; i++) { - if (((rate[i]) & 0x7f) == 2 || ((rate[i]) & 0x7f) == 4 || - ((rate[i]) & 0x7f) == 11 || ((rate[i]) & 0x7f) == 22) - return true; - } - - return false; -} - -int cckratesonly_included23a(unsigned char *rate, int ratelen) -{ - int i; - - for (i = 0; i < ratelen; i++) { - if (((rate[i]) & 0x7f) != 2 && ((rate[i]) & 0x7f) != 4 && - ((rate[i]) & 0x7f) != 11 && ((rate[i]) & 0x7f) != 22) - return false; - } - - return true; -} - -unsigned char networktype_to_raid23a(unsigned char network_type) -{ - unsigned char raid; - - switch (network_type) { - case WIRELESS_11B: - raid = RATR_INX_WIRELESS_B; - break; - case WIRELESS_11A: - case WIRELESS_11G: - raid = RATR_INX_WIRELESS_G; - break; - case WIRELESS_11BG: - raid = RATR_INX_WIRELESS_GB; - break; - case WIRELESS_11_24N: - case WIRELESS_11_5N: - raid = RATR_INX_WIRELESS_N; - break; - case WIRELESS_11A_5N: - case WIRELESS_11G_24N: - raid = RATR_INX_WIRELESS_NG; - break; - case WIRELESS_11BG_24N: - raid = RATR_INX_WIRELESS_NGB; - break; - default: - raid = RATR_INX_WIRELESS_GB; - break; - } - return raid; -} - -u8 judge_network_type23a(struct rtw_adapter *padapter, - unsigned char *rate, int ratelen) -{ - u8 network_type = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeext->cur_channel > 14) { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_5N; - network_type |= WIRELESS_11A; - } else { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_24N; - - if ((cckratesonly_included23a(rate, ratelen)) == true) - network_type |= WIRELESS_11B; - else if ((cckrates_included23a(rate, ratelen)) == true) - network_type |= WIRELESS_11BG; - else - network_type |= WIRELESS_11G; - } - return network_type; -} - -static unsigned char ratetbl_val_2wifirate(unsigned char rate) -{ - unsigned char val = 0; - - switch (rate & 0x7f) { - case 0: - val = IEEE80211_CCK_RATE_1MB; - break; - case 1: - val = IEEE80211_CCK_RATE_2MB; - break; - case 2: - val = IEEE80211_CCK_RATE_5MB; - break; - case 3: - val = IEEE80211_CCK_RATE_11MB; - break; - case 4: - val = IEEE80211_OFDM_RATE_6MB; - break; - case 5: - val = IEEE80211_OFDM_RATE_9MB; - break; - case 6: - val = IEEE80211_OFDM_RATE_12MB; - break; - case 7: - val = IEEE80211_OFDM_RATE_18MB; - break; - case 8: - val = IEEE80211_OFDM_RATE_24MB; - break; - case 9: - val = IEEE80211_OFDM_RATE_36MB; - break; - case 10: - val = IEEE80211_OFDM_RATE_48MB; - break; - case 11: - val = IEEE80211_OFDM_RATE_54MB; - break; - } - return val; -} - -static int is_basicrate(struct rtw_adapter *padapter, unsigned char rate) -{ - int i; - unsigned char val; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - for (i = 0; i < NumRates; i++) { - val = pmlmeext->basicrate[i]; - - if (val != 0xff && val != 0xfe) { - if (rate == ratetbl_val_2wifirate(val)) - return true; - } - } - - return false; -} - -static unsigned int ratetbl2rateset(struct rtw_adapter *padapter, - unsigned char *rateset) -{ - int i; - unsigned char rate; - unsigned int len = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - for (i = 0; i < NumRates; i++) { - rate = pmlmeext->datarate[i]; - - switch (rate) { - case 0xff: - return len; - case 0xfe: - continue; - default: - rate = ratetbl_val_2wifirate(rate); - - if (is_basicrate(padapter, rate) == true) - rate |= IEEE80211_BASIC_RATE_MASK; - - rateset[len] = rate; - len++; - break; - } - } - return len; -} - -void get_rate_set23a(struct rtw_adapter *padapter, - unsigned char *pbssrate, int *bssrate_len) -{ - unsigned char supportedrates[NumRates]; - - memset(supportedrates, 0, NumRates); - *bssrate_len = ratetbl2rateset(padapter, supportedrates); - memcpy(pbssrate, supportedrates, *bssrate_len); -} - -void UpdateBrateTbl23a(struct rtw_adapter *Adapter, u8 *mBratesOS) -{ - u8 i; - u8 rate; - - /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */ - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - rate = mBratesOS[i] & 0x7f; - switch (rate) { - case IEEE80211_CCK_RATE_1MB: - case IEEE80211_CCK_RATE_2MB: - case IEEE80211_CCK_RATE_5MB: - case IEEE80211_CCK_RATE_11MB: - case IEEE80211_OFDM_RATE_6MB: - case IEEE80211_OFDM_RATE_12MB: - case IEEE80211_OFDM_RATE_24MB: - mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK; - break; - default: - break; - } - } -} - -void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen) -{ - u8 i; - u8 rate; - - for (i = 0; i < bssratelen; i++) { - rate = bssrateset[i] & 0x7f; - switch (rate) { - case IEEE80211_CCK_RATE_1MB: - case IEEE80211_CCK_RATE_2MB: - case IEEE80211_CCK_RATE_5MB: - case IEEE80211_CCK_RATE_11MB: - bssrateset[i] |= IEEE80211_BASIC_RATE_MASK; - break; - } - } -} - -inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter) -{ - return adapter_to_dvobj(adapter)->oper_channel; -} - -inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch) -{ - adapter_to_dvobj(adapter)->oper_channel = ch; -} - -inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw) -{ - adapter_to_dvobj(adapter)->oper_bwmode = bw; -} - -inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset) -{ - adapter_to_dvobj(adapter)->oper_ch_offset = offset; -} - -void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel) -{ - mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex); - - /* saved channel info */ - rtw_set_oper_ch23a(padapter, channel); - - PHY_SwChnl8723A(padapter, channel); - - mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex); -} - -static void set_bwmode(struct rtw_adapter *padapter, unsigned short bwmode, - unsigned char channel_offset) -{ - mutex_lock(&adapter_to_dvobj(padapter)->setbw_mutex); - - /* saved bw info */ - rtw_set_oper_bw23a(padapter, bwmode); - rtw_set_oper_ch23aoffset23a(padapter, channel_offset); - - PHY_SetBWMode23a8723A(padapter, (enum ht_channel_width)bwmode, - channel_offset); - - mutex_unlock(&adapter_to_dvobj(padapter)->setbw_mutex); -} - -void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel, - unsigned char channel_offset, unsigned short bwmode) -{ - u8 center_ch; - - if (bwmode == HT_CHANNEL_WIDTH_20 || - channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) { - /* SelectChannel23a(padapter, channel); */ - center_ch = channel; - } else { - /* switch to the proper channel */ - if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) { - /* SelectChannel23a(padapter, channel + 2); */ - center_ch = channel + 2; - } else { - /* SelectChannel23a(padapter, channel - 2); */ - center_ch = channel - 2; - } - } - - /* set Channel */ - mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex); - - /* saved channel/bw info */ - rtw_set_oper_ch23a(padapter, channel); - rtw_set_oper_bw23a(padapter, bwmode); - rtw_set_oper_ch23aoffset23a(padapter, channel_offset); - - PHY_SwChnl8723A(padapter, center_ch); /* set center channel */ - - mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex); - - set_bwmode(padapter, bwmode, channel_offset); -} - -inline u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork) -{ - return pnetwork->MacAddress; -} - -bool is_client_associated_to_ap23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - - if (!padapter) - return false; - - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS && - (pmlmeinfo->state & 0x03) == MSR_INFRA) - return true; - else - return false; -} - -bool is_client_associated_to_ibss23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS && - (pmlmeinfo->state & 0x03) == MSR_ADHOC) - return true; - else - return false; -} - -bool is_IBSS_empty23a(struct rtw_adapter *padapter) -{ - unsigned int i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { - if (pmlmeinfo->FW_sta_info[i].status == 1) - return false; - } - - return true; -} - -unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval) -{ - if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN) - return WAIT_FOR_BCN_TO_MIN; - else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX) - return WAIT_FOR_BCN_TO_MAX; - else - return bcn_interval << 2; -} - -void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry) -{ - unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - - rtl8723a_cam_write(padapter, entry, 0, null_sta, null_key); -} - -int allocate_fw_sta_entry23a(struct rtw_adapter *padapter) -{ - unsigned int mac_id; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) { - if (pmlmeinfo->FW_sta_info[mac_id].status == 0) { - pmlmeinfo->FW_sta_info[mac_id].status = 1; - pmlmeinfo->FW_sta_info[mac_id].retry = 0; - break; - } - } - - return mac_id; -} - -void flush_all_cam_entry23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - rtl8723a_cam_invalidate_all(padapter); - - memset(pmlmeinfo->FW_sta_info, 0, sizeof(pmlmeinfo->FW_sta_info)); -} - -int WMM_param_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - /* struct registry_priv *pregpriv = &padapter->registrypriv; */ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmepriv->qos_option == 0) { - pmlmeinfo->WMM_enable = 0; - return _FAIL; - } - - pmlmeinfo->WMM_enable = 1; - memcpy(&pmlmeinfo->WMM_param, p + 2 + 6, - sizeof(struct WMM_para_element)); - return true; -} - -void WMMOnAssocRsp23a(struct rtw_adapter *padapter) -{ - u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime; - u8 acm_mask; - u16 TXOP; - u32 acParm, i; - u32 edca[4], inx[4]; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pmlmeinfo->WMM_enable == 0) { - padapter->mlmepriv.acm_mask = 0; - return; - } - - acm_mask = 0; - - if (pmlmeext->cur_wireless_mode == WIRELESS_11B) - aSifsTime = 10; - else - aSifsTime = 16; - - for (i = 0; i < 4; i++) { - ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03; - ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01; - - /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */ - AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * - pmlmeinfo->slotTime + aSifsTime; - - ECWMin = pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f; - ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4; - TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit); - - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - - switch (ACI) { - case 0x0: - rtl8723a_set_ac_param_be(padapter, acParm); - acm_mask |= (ACM? BIT(1):0); - edca[XMIT_BE_QUEUE] = acParm; - break; - case 0x1: - rtl8723a_set_ac_param_bk(padapter, acParm); - /* acm_mask |= (ACM? BIT(0):0); */ - edca[XMIT_BK_QUEUE] = acParm; - break; - case 0x2: - rtl8723a_set_ac_param_vi(padapter, acParm); - acm_mask |= (ACM? BIT(2):0); - edca[XMIT_VI_QUEUE] = acParm; - break; - case 0x3: - rtl8723a_set_ac_param_vo(padapter, acParm); - acm_mask |= (ACM? BIT(3):0); - edca[XMIT_VO_QUEUE] = acParm; - break; - } - - DBG_8723A("WMM(%x): %x, %x\n", ACI, ACM, acParm); - } - - if (padapter->registrypriv.acm_method == 1) - rtl8723a_set_acm_ctrl(padapter, acm_mask); - else - padapter->mlmepriv.acm_mask = acm_mask; - - inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; - - if (pregpriv->wifi_spec == 1) { - u32 j, change_inx = false; - - /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ - for (i = 0; i < 4; i++) { - for (j = i+1; j < 4; j++) { - /* compare CW and AIFS */ - if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) { - change_inx = true; - } else if ((edca[j] & 0xFFFF) == - (edca[i] & 0xFFFF)) { - /* compare TXOP */ - if ((edca[j] >> 16) > (edca[i] >> 16)) - change_inx = true; - } - - if (change_inx) { - swap(edca[i], edca[j]); - swap(inx[i], inx[j]); - change_inx = false; - } - } - } - } - - for (i = 0; i<4; i++) { - pxmitpriv->wmm_para_seq[i] = inx[i]; - DBG_8723A("wmm_para_seq(%d): %d\n", i, - pxmitpriv->wmm_para_seq[i]); - } -} - -static void bwmode_update_check(struct rtw_adapter *padapter, const u8 *p) -{ - struct ieee80211_ht_operation *pHT_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - unsigned char new_bwmode; - unsigned char new_ch_offset; - - if (!p) - return; - if (!phtpriv->ht_option) - return; - if (p[1] != sizeof(struct ieee80211_ht_operation)) - return; - - pHT_info = (struct ieee80211_ht_operation *)(p + 2); - - if ((pHT_info->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) && - pregistrypriv->cbw40_enable) { - new_bwmode = HT_CHANNEL_WIDTH_40; - - switch (pHT_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET){ - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } else { - new_bwmode = HT_CHANNEL_WIDTH_20; - new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - if (new_bwmode != pmlmeext->cur_bwmode || - new_ch_offset != pmlmeext->cur_ch_offset) { - pmlmeinfo->bwmode_updated = true; - - pmlmeext->cur_bwmode = new_bwmode; - pmlmeext->cur_ch_offset = new_ch_offset; - - /* update HT info also */ - HT_info_handler23a(padapter, p); - } else - pmlmeinfo->bwmode_updated = false; - - if (pmlmeinfo->bwmode_updated) { - struct sta_info *psta; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - - /* update ap's stainfo */ - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - if (psta) { - struct ht_priv *phtpriv_sta = &psta->htpriv; - - if (phtpriv_sta->ht_option) { - /* bwmode */ - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = - pmlmeext->cur_ch_offset; - } else { - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - } - } -} - -void HT_caps_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - unsigned int i; - u8 rf_type; - u8 max_AMPDU_len, min_MPDU_spacing; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct ieee80211_ht_cap *cap; - u8 *dstcap; - - if (!p) - return; - - if (!phtpriv->ht_option) - return; - - pmlmeinfo->HT_caps_enable = 1; - - cap = &pmlmeinfo->ht_cap; - dstcap = (u8 *)cap; - for (i = 0; i < p[1]; i++) { - if (i != 2) { - dstcap[i] &= p[i + 2]; - } else { - /* modify from fw by Thomas 2010/11/17 */ - if ((cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR) > - (p[i + 2] & IEEE80211_HT_AMPDU_PARM_FACTOR)) - max_AMPDU_len = p[i + 2] & - IEEE80211_HT_AMPDU_PARM_FACTOR; - else - max_AMPDU_len = cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - if ((cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) > - (p[i + 2] & IEEE80211_HT_AMPDU_PARM_DENSITY)) - min_MPDU_spacing = cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY; - else - min_MPDU_spacing = p[i + 2] & - IEEE80211_HT_AMPDU_PARM_DENSITY; - - cap->ampdu_params_info = - max_AMPDU_len | min_MPDU_spacing; - } - } - - rf_type = rtl8723a_get_rf_type(padapter); - - /* update the MCS rates */ - for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { - if (rf_type == RF_1T1R || rf_type == RF_1T2R) - cap->mcs.rx_mask[i] &= MCS_rate_1R23A[i]; - else - cap->mcs.rx_mask[i] &= MCS_rate_2R23A[i]; - } -} - -void HT_info_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (!p) - return; - - if (!phtpriv->ht_option) - return; - - if (p[1] != sizeof(struct ieee80211_ht_operation)) - return; - - pmlmeinfo->HT_info_enable = 1; - memcpy(&pmlmeinfo->HT_info, p + 2, p[1]); -} - -void HTOnAssocRsp23a(struct rtw_adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - /* struct registry_priv *pregpriv = &padapter->registrypriv; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - if (pmlmeinfo->HT_info_enable && pmlmeinfo->HT_caps_enable) - pmlmeinfo->HT_enable = 1; - else { - pmlmeinfo->HT_enable = 0; - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - return; - } - - /* handle A-MPDU parameter field */ - /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing - */ - max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - min_MPDU_spacing = - (pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; - - rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing); - rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len); -} - -void ERP_IE_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (p[1] > 1) - return; - - pmlmeinfo->ERP_enable = 1; - memcpy(&pmlmeinfo->ERP_IE, p + 2, p[1]); -} - -void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */ - case 0: /* off */ - psta->rtsen = 0; - psta->cts2self = 0; - break; - case 1: /* on */ - if (pregpriv->vcs_type == RTS_CTS) { - psta->rtsen = 1; - psta->cts2self = 0; - } else { - psta->rtsen = 0; - psta->cts2self = 1; - } - break; - case 2: /* auto */ - default: - if (pmlmeinfo->ERP_enable && pmlmeinfo->ERP_IE & BIT(1)) { - if (pregpriv->vcs_type == RTS_CTS) { - psta->rtsen = 1; - psta->cts2self = 0; - } else { - psta->rtsen = 0; - psta->cts2self = 1; - } - } else { - psta->rtsen = 0; - psta->cts2self = 0; - } - break; - } -} - -int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, - struct ieee80211_mgmt *mgmt, u32 pkt_len) -{ - struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network; - struct ieee80211_ht_operation *pht_info; - unsigned short val16; - u8 crypto, bcn_channel; - int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0, r; - int pie_len, ssid_len, privacy; - const u8 *p, *ssid; - - if (!is_client_associated_to_ap23a(Adapter)) - return _SUCCESS; - - if (unlikely(!ieee80211_is_beacon(mgmt->frame_control))) { - printk(KERN_WARNING "%s: received a non beacon frame!\n", - __func__); - return _FAIL; - } - - if (!ether_addr_equal(cur_network->network.MacAddress, mgmt->bssid)) { - DBG_8723A("%s: linked but recv other bssid bcn %pM %pM\n", - __func__, mgmt->bssid, - cur_network->network.MacAddress); - return _FAIL; - } - - /* check bw and channel offset */ - /* parsing HT_CAP_IE */ - pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - - /* Checking for channel */ - p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, - pie_len); - if (p) - bcn_channel = p[2]; - else { - /* In 5G, some ap do not have DSSET IE checking HT - info for channel */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, - mgmt->u.beacon.variable, pie_len); - - if (p && p[1] > 0) { - pht_info = (struct ieee80211_ht_operation *)(p + 2); - bcn_channel = pht_info->primary_chan; - } else { /* we don't find channel IE, so don't check it */ - DBG_8723A("Oops: %s we don't find channel IE, so don't " - "check it\n", __func__); - bcn_channel = Adapter->mlmeextpriv.cur_channel; - } - } - if (bcn_channel != Adapter->mlmeextpriv.cur_channel) { - DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n", - __func__, bcn_channel, - Adapter->mlmeextpriv.cur_channel); - goto _mismatch; - } - - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - ssid = p + 2; - ssid_len = p[1]; - } else { - DBG_8723A("%s marc: cannot find SSID for survey event\n", - __func__); - ssid = NULL; - ssid_len = 0; - } - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d cur_network->network.Ssid.Ssid:%s len:%d\n", - __func__, ssid, ssid_len, cur_network->network.Ssid.ssid, - cur_network->network.Ssid.ssid_len); - - if (ssid_len != cur_network->network.Ssid.ssid_len || ssid_len > 32 || - (ssid_len && - memcmp(ssid, cur_network->network.Ssid.ssid, ssid_len))) { - DBG_8723A("%s(), SSID is not match return FAIL\n", __func__); - goto _mismatch; - } - - /* check encryption info */ - val16 = le16_to_cpu(mgmt->u.beacon.capab_info); - - if (val16 & WLAN_CAPABILITY_PRIVACY) - privacy = 1; - else - privacy = 0; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n", - __func__, cur_network->network.Privacy, privacy); - if (cur_network->network.Privacy != privacy) { - DBG_8723A("%s(), privacy is not match return FAIL\n", __func__); - goto _mismatch; - } - - p = cfg80211_find_ie(WLAN_EID_RSN, mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - crypto = ENCRYP_PROTOCOL_WPA2; - if (p && p[1]) { - r = rtw_parse_wpa2_ie23a(p, p[1] + 2, &group_cipher, - &pairwise_cipher, &is_8021x); - if (r == _SUCCESS) - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher: %d, is_802x : %d\n", - __func__, pairwise_cipher, - group_cipher, is_8021x); - } - } else { - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - crypto = ENCRYP_PROTOCOL_WPA; - r = rtw_parse_wpa_ie23a(p, p[1] + 2, &group_cipher, - &pairwise_cipher, &is_8021x); - if (r == _SUCCESS) - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", - __func__, pairwise_cipher, - group_cipher, is_8021x); - } else { - if (privacy) - crypto = ENCRYP_PROTOCOL_WEP; - else - crypto = ENCRYP_PROTOCOL_OPENSYS; - } - } - - if (cur_network->BcnInfo.encryp_protocol != crypto) { - DBG_8723A("%s(): encryption mismatch, return FAIL\n", __func__); - goto _mismatch; - } - - if (crypto == ENCRYP_PROTOCOL_WPA || crypto == ENCRYP_PROTOCOL_WPA2) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s cur_network->group_cipher is %d: %d\n", __func__, - cur_network->BcnInfo.group_cipher, group_cipher); - if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || - group_cipher != cur_network->BcnInfo.group_cipher) { - DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher " - "(%x:%x) is not match, return FAIL\n", - __func__, pairwise_cipher, - cur_network->BcnInfo.pairwise_cipher, - group_cipher, - cur_network->BcnInfo.group_cipher); - goto _mismatch; - } - - if (is_8021x != cur_network->BcnInfo.is_8021x) { - DBG_8723A("%s authentication is not match, return " - "FAIL\n", __func__); - goto _mismatch; - } - } - - return _SUCCESS; - -_mismatch: - - return _FAIL; -} - -void update_beacon23a_info(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, - uint pkt_len, struct sta_info *psta) -{ - unsigned int len; - const u8 *p; - - len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, mgmt->u.beacon.variable, - len); - if (p) - bwmode_update_check(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, mgmt->u.beacon.variable, len); - if (p) { - ERP_IE_handler23a(padapter, p); - VCS_update23a(padapter, psta); - } -} - -bool is_ap_in_tkip23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) && - !memcmp(p + 2 + 12, WPA_TKIP_CIPHER, 4)) - return true; - break; - case WLAN_EID_RSN: - if (!memcmp(p + 2 + 8, RSN_TKIP_CIPHER, 4)) - return true; - break; - default: - break; - } - i += (p[1] + 2); - } - return false; - } else - return false; -} - -bool should_forbid_n_rate23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *cur_network = &pmlmepriv->cur_network.network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < cur_network->IELength;) { - p = cur_network->IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) && - (!memcmp(p + 2 + 12, - WPA_CIPHER_SUITE_CCMP23A, 4) || - !memcmp(p + 2 + 16, - WPA_CIPHER_SUITE_CCMP23A, 4))) - return false; - break; - case WLAN_EID_RSN: - if (!memcmp(p + 2 + 8, - RSN_CIPHER_SUITE_CCMP23A, 4) || - !memcmp(p + 2 + 12, - RSN_CIPHER_SUITE_CCMP23A, 4)) - return false; - default: - break; - } - - i += (p[1] + 2); - } - return true; - } else { - return false; - } -} - -bool is_ap_in_wep23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4)) - return false; - break; - case WLAN_EID_RSN: - return false; - - default: - break; - } - - i += (p[1] + 2); - } - - return true; - } else - return false; -} - -static int wifirate2_ratetbl_inx23a(unsigned char rate) -{ - int inx = 0; - - rate = rate & 0x7f; - - switch (rate) { - case 54*2: - inx = 11; - break; - case 48*2: - inx = 10; - break; - case 36*2: - inx = 9; - break; - case 24*2: - inx = 8; - break; - case 18*2: - inx = 7; - break; - case 12*2: - inx = 6; - break; - case 9*2: - inx = 5; - break; - case 6*2: - inx = 4; - break; - case 11*2: - inx = 3; - break; - case 11: - inx = 2; - break; - case 2*2: - inx = 1; - break; - case 1*2: - inx = 0; - break; - } - return inx; -} - -unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz) -{ - unsigned int i, num_of_rate; - unsigned int mask = 0; - - num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz; - - for (i = 0; i < num_of_rate; i++) { - if ((*(ptn + i)) & 0x80) - mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i)); - } - return mask; -} - -unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz) -{ - unsigned int i, num_of_rate; - unsigned int mask = 0; - - num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz; - - for (i = 0; i < num_of_rate; i++) - mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i)); - return mask; -} - -unsigned int update_MSC_rate23a(struct ieee80211_ht_cap *pHT_caps) -{ - unsigned int mask; - - mask = pHT_caps->mcs.rx_mask[0] << 12 | - pHT_caps->mcs.rx_mask[1] << 20; - - return mask; -} - -int support_short_GI23a(struct rtw_adapter *padapter, - struct ieee80211_ht_cap *pHT_caps) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char bit_offset; - - if (!pmlmeinfo->HT_enable) - return _FAIL; - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) - return _FAIL; - bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5; - - if (pHT_caps->cap_info & cpu_to_le16(0x1 << bit_offset)) - return _SUCCESS; - else - return _FAIL; -} - -unsigned char get_highest_rate_idx23a(u32 mask) -{ - int i; - unsigned char rate_idx = 0; - - for (i = 27; i >= 0; i--) { - if (mask & BIT(i)) { - rate_idx = i; - break; - } - } - return rate_idx; -} - -void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - rtw_hal_update_ra_mask23a(psta, 0); -} - -static void enable_rate_adaptive(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - Update_RA_Entry23a(padapter, psta); -} - -void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - /* rate adaptive */ - enable_rate_adaptive(padapter, psta); -} - -/* Update RRSR and Rate for USERATE */ -void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode) -{ - unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX]; - - memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX); - - if (wirelessmode == WIRELESS_11B) { - memcpy(supported_rates, rtw_basic_rate_cck, 4); - } else if (wirelessmode & WIRELESS_11B) { - memcpy(supported_rates, rtw_basic_rate_mix, 7); - } else { - memcpy(supported_rates, rtw_basic_rate_ofdm, 3); - } - - if (wirelessmode & WIRELESS_11B) - update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB); - else - update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB); - - HalSetBrateCfg23a(padapter, supported_rates); -} - -unsigned char check_assoc_AP23a(u8 *pframe, uint len) -{ - int i; - u8 epigram_vendor_flag; - u8 ralink_vendor_flag; - const u8 *p; - - epigram_vendor_flag = 0; - ralink_vendor_flag = 0; - - for (i = 0; i < len;) { - p = pframe + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, ARTHEROS_OUI1, 3) || - !memcmp(p + 2, ARTHEROS_OUI2, 3)) { - DBG_8723A("link to Artheros AP\n"); - return HT_IOT_PEER_ATHEROS; - } else if (!memcmp(p + 2, BROADCOM_OUI1, 3) || - !memcmp(p + 2, BROADCOM_OUI2, 3)) { - DBG_8723A("link to Broadcom AP\n"); - return HT_IOT_PEER_BROADCOM; - } else if (!memcmp(p + 2, MARVELL_OUI, 3)) { - DBG_8723A("link to Marvell AP\n"); - return HT_IOT_PEER_MARVELL; - } else if (!memcmp(p + 2, RALINK_OUI, 3)) { - if (!ralink_vendor_flag) - ralink_vendor_flag = 1; - else { - DBG_8723A("link to Ralink AP\n"); - return HT_IOT_PEER_RALINK; - } - } else if (!memcmp(p + 2, CISCO_OUI, 3)) { - DBG_8723A("link to Cisco AP\n"); - return HT_IOT_PEER_CISCO; - } else if (!memcmp(p + 2, REALTEK_OUI, 3)) { - DBG_8723A("link to Realtek 96B\n"); - return HT_IOT_PEER_REALTEK; - } else if (!memcmp(p + 2, AIRGOCAP_OUI, 3)) { - DBG_8723A("link to Airgo Cap\n"); - return HT_IOT_PEER_AIRGO; - } else if (!memcmp(p + 2, EPIGRAM_OUI, 3)) { - epigram_vendor_flag = 1; - if (ralink_vendor_flag) { - DBG_8723A("link to Tenda W311R AP\n"); - return HT_IOT_PEER_TENDA; - } else - DBG_8723A("Capture EPIGRAM_OUI\n"); - } else - break; - default: - break; - } - - i += (p[1] + 2); - } - - if (ralink_vendor_flag && !epigram_vendor_flag) { - DBG_8723A("link to Ralink AP\n"); - return HT_IOT_PEER_RALINK; - } else if (ralink_vendor_flag && epigram_vendor_flag) { - DBG_8723A("link to Tenda W311R AP\n"); - return HT_IOT_PEER_TENDA; - } else { - DBG_8723A("link to new AP\n"); - return HT_IOT_PEER_UNKNOWN; - } -} - -void update_IOT_info23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - switch (pmlmeinfo->assoc_AP_vendor) { - case HT_IOT_PEER_MARVELL: - pmlmeinfo->turboMode_cts2self = 1; - pmlmeinfo->turboMode_rtsen = 0; - break; - case HT_IOT_PEER_RALINK: - pmlmeinfo->turboMode_cts2self = 0; - pmlmeinfo->turboMode_rtsen = 1; - /* disable high power */ - rtl8723a_odm_support_ability_clr(padapter, (u32) - ~DYNAMIC_BB_DYNAMIC_TXPWR); - break; - case HT_IOT_PEER_REALTEK: - /* rtw_write16(padapter, 0x4cc, 0xffff); */ - /* rtw_write16(padapter, 0x546, 0x01c0); */ - /* disable high power */ - rtl8723a_odm_support_ability_clr(padapter, (u32) - ~DYNAMIC_BB_DYNAMIC_TXPWR); - break; - default: - pmlmeinfo->turboMode_cts2self = 0; - pmlmeinfo->turboMode_rtsen = 1; - break; - } -} - -void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap) -{ - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (updateCap & cShortPreamble) { - /* Short Preamble */ - if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) { - /* PREAMBLE_LONG or PREAMBLE_AUTO */ - pmlmeinfo->preamble_mode = PREAMBLE_SHORT; - rtl8723a_ack_preamble(Adapter, true); - } - } else { /* Long Preamble */ - if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) { - /* PREAMBLE_SHORT or PREAMBLE_AUTO */ - pmlmeinfo->preamble_mode = PREAMBLE_LONG; - rtl8723a_ack_preamble(Adapter, false); - } - } - if (updateCap & cIBSS) { - /* Filen: See 802.11-2007 p.91 */ - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } else { - /* Filen: See 802.11-2007 p.90 */ - if (pmlmeext->cur_wireless_mode & - (WIRELESS_11G | WIRELESS_11_24N)) { - if (updateCap & cShortSlotTime) { /* Short Slot Time */ - if (pmlmeinfo->slotTime != SHORT_SLOT_TIME) - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - } else { /* Long Slot Time */ - if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME) - pmlmeinfo->slotTime = - NON_SHORT_SLOT_TIME; - } - } else if (pmlmeext->cur_wireless_mode & - (WIRELESS_11A | WIRELESS_11_5N)) { - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - } else { - /* B Mode */ - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } - } - rtl8723a_set_slot_time(Adapter, pmlmeinfo->slotTime); -} - -void update_wireless_mode23a(struct rtw_adapter *padapter) -{ - int ratelen, network_type = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - unsigned char *rate = cur_network->SupportedRates; - - ratelen = rtw_get_rateset_len23a(cur_network->SupportedRates); - - if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) - pmlmeinfo->HT_enable = 1; - - if (pmlmeext->cur_channel > 14) { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_5N; - network_type |= WIRELESS_11A; - } else { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_24N; - - if (cckratesonly_included23a(rate, ratelen) == true) - network_type |= WIRELESS_11B; - else if (cckrates_included23a(rate, ratelen) == true) - network_type |= WIRELESS_11BG; - else - network_type |= WIRELESS_11G; - } - - pmlmeext->cur_wireless_mode = - network_type & padapter->registrypriv.wireless_mode; - - /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */ - /* change this value if having IOT issues. */ - rtl8723a_set_resp_sifs(padapter, 0x08, 0x08, 0x0a, 0x0a); - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB); - else - update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB); -} - -void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) { - /* Only B, B/G, and B/G/N AP could use CCK rate */ - memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), - rtw_basic_rate_cck, 4); - } else { - memcpy(pmlmeinfo->FW_sta_info[mac_id].SupportedRates, - rtw_basic_rate_ofdm, 3); - } -} - -int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, - uint var_ie_len, int cam_idx) -{ - int supportRateNum = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const u8 *p; - - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pvar_ie, var_ie_len); - if (!p) - return _FAIL; - - memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, p + 2, p[1]); - supportRateNum = p[1]; - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pvar_ie, var_ie_len); - if (p) - memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + - supportRateNum, p + 2, p[1]); - return _SUCCESS; -} - -void process_addba_req23a(struct rtw_adapter *padapter, - u8 *paddba_req, u8 *addr) -{ - struct sta_info *psta; - u16 tid, start_seq, param; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_priv *pstapriv = &padapter->stapriv; - struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - psta = rtw_get_stainfo23a(pstapriv, addr); - - if (psta) { - start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4; - - param = le16_to_cpu(preq->BA_para_set); - tid = (param >> 2) & 0x0f; - - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - - preorder_ctrl->indicate_seq = 0xffff; - - preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true) ? - true : false; - } -} diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c deleted file mode 100644 index 3de40cfa5f3b..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_xmit.c +++ /dev/null @@ -1,2341 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTW_XMIT_C_ - -#include -#include -#include -#include -#include -#include -#include - -static void _init_txservq(struct tx_servq *ptxservq) -{ - - INIT_LIST_HEAD(&ptxservq->tx_pending); - _rtw_init_queue23a(&ptxservq->sta_pending); - ptxservq->qcnt = 0; - -} - -void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv) -{ - - spin_lock_init(&psta_xmitpriv->lock); - - /* for (i = 0 ; i < MAX_NUMBLKS; i++) */ - /* _init_txservq(&psta_xmitpriv->blk_q[i]); */ - - _init_txservq(&psta_xmitpriv->be_q); - _init_txservq(&psta_xmitpriv->bk_q); - _init_txservq(&psta_xmitpriv->vi_q); - _init_txservq(&psta_xmitpriv->vo_q); - INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz); - INIT_LIST_HEAD(&psta_xmitpriv->apsd); - -} - -int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, - struct rtw_adapter *padapter) -{ - int i; - struct xmit_buf *pxmitbuf; - struct xmit_frame *pxframe; - int res = _SUCCESS; - u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; - u32 num_xmit_extbuf = NR_XMIT_EXTBUFF; - - spin_lock_init(&pxmitpriv->lock); - spin_lock_init(&pxmitpriv->lock_sctx); - sema_init(&pxmitpriv->xmit_sema, 0); - sema_init(&pxmitpriv->terminate_xmitthread_sema, 0); - - pxmitpriv->adapter = padapter; - - _rtw_init_queue23a(&pxmitpriv->be_pending); - _rtw_init_queue23a(&pxmitpriv->bk_pending); - _rtw_init_queue23a(&pxmitpriv->vi_pending); - _rtw_init_queue23a(&pxmitpriv->vo_pending); - _rtw_init_queue23a(&pxmitpriv->bm_pending); - - _rtw_init_queue23a(&pxmitpriv->free_xmit_queue); - - for (i = 0; i < NR_XMITFRAME; i++) { - pxframe = kzalloc(sizeof(struct xmit_frame), GFP_KERNEL); - if (!pxframe) - break; - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - list_add_tail(&pxframe->list, - &pxmitpriv->free_xmit_queue.queue); - } - - pxmitpriv->free_xmitframe_cnt = i; - - pxmitpriv->frag_len = MAX_FRAG_THRESHOLD; - - /* init xmit_buf */ - _rtw_init_queue23a(&pxmitpriv->free_xmitbuf_queue); - INIT_LIST_HEAD(&pxmitpriv->xmitbuf_list); - _rtw_init_queue23a(&pxmitpriv->pending_xmitbuf_queue); - - for (i = 0; i < NR_XMITBUFF; i++) { - pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL); - if (!pxmitbuf) - goto fail; - INIT_LIST_HEAD(&pxmitbuf->list); - INIT_LIST_HEAD(&pxmitbuf->list2); - - pxmitbuf->padapter = padapter; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf, - (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - if (res == _FAIL) { - goto fail; - } - - list_add_tail(&pxmitbuf->list, - &pxmitpriv->free_xmitbuf_queue.queue); - list_add_tail(&pxmitbuf->list2, - &pxmitpriv->xmitbuf_list); - } - - pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF; - - /* init xframe_ext queue, the same count as extbuf */ - _rtw_init_queue23a(&pxmitpriv->free_xframe_ext_queue); - - for (i = 0; i < num_xmit_extbuf; i++) { - pxframe = kzalloc(sizeof(struct xmit_frame), GFP_KERNEL); - if (!pxframe) - break; - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - pxframe->pkt = NULL; - - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - pxframe->ext_tag = 1; - - list_add_tail(&pxframe->list, - &pxmitpriv->free_xframe_ext_queue.queue); - } - pxmitpriv->free_xframe_ext_cnt = i; - - /* Init xmit extension buff */ - _rtw_init_queue23a(&pxmitpriv->free_xmit_extbuf_queue); - INIT_LIST_HEAD(&pxmitpriv->xmitextbuf_list); - - for (i = 0; i < num_xmit_extbuf; i++) { - pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL); - if (!pxmitbuf) - goto fail; - INIT_LIST_HEAD(&pxmitbuf->list); - INIT_LIST_HEAD(&pxmitbuf->list2); - - pxmitbuf->padapter = padapter; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf, - max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); - if (res == _FAIL) { - goto exit; - } - - list_add_tail(&pxmitbuf->list, - &pxmitpriv->free_xmit_extbuf_queue.queue); - list_add_tail(&pxmitbuf->list2, - &pxmitpriv->xmitextbuf_list); - } - - pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf; - - rtw_alloc_hwxmits23a(padapter); - rtw_init_hwxmits23a(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); - - for (i = 0; i < 4; i ++) - pxmitpriv->wmm_para_seq[i] = i; - - sema_init(&pxmitpriv->tx_retevt, 0); - - pxmitpriv->ack_tx = false; - mutex_init(&pxmitpriv->ack_tx_mutex); - rtw_sctx_init23a(&pxmitpriv->ack_tx_ops, 0); - tasklet_init(&padapter->xmitpriv.xmit_tasklet, - (void(*)(unsigned long))rtl8723au_xmit_tasklet, - (unsigned long)padapter); - -exit: - - return res; -fail: - goto exit; -} - -void _rtw_free_xmit_priv23a(struct xmit_priv *pxmitpriv) -{ - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct xmit_frame *pxframe, *ptmp; - struct xmit_buf *pxmitbuf, *ptmp2; - - list_for_each_entry_safe(pxframe, ptmp, - &pxmitpriv->free_xmit_queue.queue, list) { - list_del_init(&pxframe->list); - rtw_os_xmit_complete23a(padapter, pxframe); - kfree(pxframe); - } - - list_for_each_entry_safe(pxmitbuf, ptmp2, - &pxmitpriv->xmitbuf_list, list2) { - list_del_init(&pxmitbuf->list2); - rtw_os_xmit_resource_free23a(padapter, pxmitbuf); - kfree(pxmitbuf); - } - - /* free xframe_ext queue, the same count as extbuf */ - list_for_each_entry_safe(pxframe, ptmp, - &pxmitpriv->free_xframe_ext_queue.queue, - list) { - list_del_init(&pxframe->list); - rtw_os_xmit_complete23a(padapter, pxframe); - kfree(pxframe); - } - - /* free xmit extension buff */ - list_for_each_entry_safe(pxmitbuf, ptmp2, - &pxmitpriv->xmitextbuf_list, list2) { - list_del_init(&pxmitbuf->list2); - rtw_os_xmit_resource_free23a(padapter, pxmitbuf); - kfree(pxmitbuf); - } - - rtw_free_hwxmits23a(padapter); - mutex_destroy(&pxmitpriv->ack_tx_mutex); -} - -static void update_attrib_vcs_info(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe) -{ - u32 sz; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_info *psta = pattrib->psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); - return; - } - - if (pattrib->nr_frags != 1) - sz = padapter->xmitpriv.frag_len; - else /* no frag */ - sz = pattrib->last_txcmdsz; - - /* (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 (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) { - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - } else { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS; - } - } else { - while (true) { - /* IOT action */ - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS && - pattrib->ampdu_en && - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - pattrib->vcs_mode = CTS_TO_SELF; - break; - } - - /* check ERP protection */ - if (psta->rtsen || psta->cts2self) { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - - break; - } - - /* check HT op mode */ - if (pattrib->ht_en) { - u8 HTOpMode = pmlmeinfo->HT_protection; - - if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) || - (!pmlmeext->cur_bwmode && HTOpMode == 3)) { - pattrib->vcs_mode = RTS_CTS; - break; - } - } - - /* check rts */ - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - /* to do list: check MIMO power save condition. */ - - /* check AMPDU aggregation for TXOP */ - if (pattrib->ampdu_en) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - pattrib->vcs_mode = NONE_VCS; - break; - } - } -} - -static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta) -{ - /*if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS;*/ - - pattrib->mdata = 0; - pattrib->eosp = 0; - pattrib->triggered = 0; - - /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */ - pattrib->qos_en = psta->qos_option; - - pattrib->raid = psta->raid; - pattrib->ht_en = psta->htpriv.ht_option; - pattrib->bwmode = psta->htpriv.bwmode; - pattrib->ch_offset = psta->htpriv.ch_offset; - pattrib->sgi = psta->htpriv.sgi; - pattrib->ampdu_en = false; - - pattrib->retry_ctrl = false; -} - -u8 qos_acm23a(u8 acm_mask, u8 priority) -{ - u8 change_priority = priority; - - switch (priority) { - case 0: - case 3: - if (acm_mask & BIT(1)) - change_priority = 1; - break; - case 1: - case 2: - break; - case 4: - case 5: - if (acm_mask & BIT(2)) - change_priority = 0; - break; - case 6: - case 7: - if (acm_mask & BIT(3)) - change_priority = 5; - break; - default: - DBG_8723A("qos_acm23a(): invalid pattrib->priority: %d!!!\n", - priority); - change_priority = 0; - break; - } - - return change_priority; -} - -static void set_qos(struct sk_buff *skb, struct pkt_attrib *pattrib) -{ - u8 *pframe = skb->data; - struct iphdr *ip_hdr; - u8 UserPriority = 0; - - /* get UserPriority from IP hdr */ - if (pattrib->ether_type == ETH_P_IP) { - ip_hdr = (struct iphdr *)(pframe + ETH_HLEN); - UserPriority = ip_hdr->tos >> 5; - } else if (pattrib->ether_type == ETH_P_PAE) { - /* "When priority processing of data frames is supported, */ - /* a STA's SME should send EAPOL-Key frames at the highest - priority." */ - UserPriority = 7; - } - - pattrib->priority = UserPriority; - pattrib->hdrlen = sizeof(struct ieee80211_qos_hdr); - pattrib->type = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA; -} - -static int update_attrib(struct rtw_adapter *padapter, - struct sk_buff *skb, struct pkt_attrib *pattrib) -{ - struct sta_info *psta = NULL; - int bmcast; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int res = _SUCCESS; - struct ethhdr *ehdr = (struct ethhdr *) skb->data; - - pattrib->ether_type = ntohs(ehdr->h_proto); - - ether_addr_copy(pattrib->dst, ehdr->h_dest); - ether_addr_copy(pattrib->src, ehdr->h_source); - - pattrib->pctrl = 0; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ether_addr_copy(pattrib->ra, get_bssid(pmlmepriv)); - ether_addr_copy(pattrib->ta, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, get_bssid(pmlmepriv)); - } - - pattrib->pktlen = skb->len - ETH_HLEN; - - if (pattrib->ether_type == ETH_P_IP) { - /* The following is for DHCP and ARP packet, we use cck1M - to tx these packets and let LPS awake some time */ - /* to prevent DHCP protocol fail */ - pattrib->dhcp_pkt = 0; - /* MINIMUM_DHCP_PACKET_SIZE) { */ - if (pattrib->pktlen > 282 + 24) { - if (pattrib->ether_type == ETH_P_IP) {/* IP header */ - u8 *pframe = skb->data; - - pframe += ETH_HLEN; - - if ((pframe[21] == 68 && pframe[23] == 67) || - (pframe[21] == 67 && pframe[23] == 68)) { - /* 68 : UDP BOOTP client */ - /* 67 : UDP BOOTP server */ - RT_TRACE(_module_rtl871x_xmit_c_, - _drv_err_, - "======================update_attrib: get DHCP Packet\n"); - pattrib->dhcp_pkt = 1; - } - } - } - } else if (pattrib->ether_type == ETH_P_PAE) { - DBG_8723A_LEVEL(_drv_always_, "send eapol packet\n"); - } - - if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) { - rtw_set_scan_deny(padapter, 3000); - } - - /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */ - if ((pattrib->ether_type == ETH_P_ARP) || - (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) { - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SPECIAL_PACKET, 1); - } - - bmcast = is_multicast_ether_addr(pattrib->ra); - - /* get sta_info */ - if (bmcast) { - psta = rtw_get_bcmc_stainfo23a(padapter); - } else { - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - if (psta == NULL) { /* if we cannot get psta => drrp the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "update_attrib => get sta_info fail, ra:%pM\n", - pattrib->ra); - res = _FAIL; - goto exit; - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && - (!(psta->state & _FW_LINKED))) { - res = _FAIL; - goto exit; - } - } - - if (psta) { - pattrib->mac_id = psta->mac_id; - /* DBG_8723A("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */ - pattrib->psta = psta; - } else { - /* if we cannot get psta => drop the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "update_attrib => get sta_info fail, ra:%pM\n", - pattrib->ra); - res = _FAIL; - goto exit; - } - - pattrib->ack_policy = 0; - /* get ether_hdr_len */ - - /* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */ - pattrib->pkt_hdrlen = ETH_HLEN; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->type = IEEE80211_FTYPE_DATA; - pattrib->priority = 0; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE)) { - if (psta->qos_option) - set_qos(skb, pattrib); - } else { - if (pmlmepriv->qos_option) { - set_qos(skb, pattrib); - - if (pmlmepriv->acm_mask != 0) { - pattrib->priority = qos_acm23a(pmlmepriv->acm_mask, - pattrib->priority); - } - } - } - - if (psta->ieee8021x_blocked == true) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "psta->ieee8021x_blocked == true\n"); - - pattrib->encrypt = 0; - - if ((pattrib->ether_type != ETH_P_PAE) && - !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "psta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != 0x888e\n", - pattrib->ether_type); - res = _FAIL; - goto exit; - } - } else { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); - - switch (psecuritypriv->dot11AuthAlgrthm) { - case dot11AuthAlgrthm_Open: - case dot11AuthAlgrthm_Shared: - case dot11AuthAlgrthm_Auto: - pattrib->key_idx = - (u8)psecuritypriv->dot11PrivacyKeyIndex; - break; - case dot11AuthAlgrthm_8021X: - if (bmcast) - pattrib->key_idx = - (u8)psecuritypriv->dot118021XGrpKeyid; - else - pattrib->key_idx = 0; - break; - default: - pattrib->key_idx = 0; - break; - } - - } - - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - break; - - case WLAN_CIPHER_SUITE_TKIP: - pattrib->iv_len = IEEE80211_TKIP_IV_LEN; - pattrib->icv_len = IEEE80211_TKIP_ICV_LEN; - - if (!padapter->securitypriv.busetkipkey) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "padapter->securitypriv.busetkipkey(%d) == false drop packet\n", - padapter->securitypriv.busetkipkey); - res = _FAIL; - goto exit; - } - - break; - case WLAN_CIPHER_SUITE_CCMP: - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "pattrib->encrypt =%d (WLAN_CIPHER_SUITE_CCMP)\n", - pattrib->encrypt); - pattrib->iv_len = IEEE80211_CCMP_HDR_LEN; - pattrib->icv_len = IEEE80211_CCMP_MIC_LEN; - break; - - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "update_attrib: encrypt =%d\n", pattrib->encrypt); - - if (pattrib->encrypt && !psecuritypriv->hw_decrypted) { - pattrib->bswenc = true; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "update_attrib: encrypt =%d bswenc = true\n", - pattrib->encrypt); - } else { - pattrib->bswenc = false; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "update_attrib: bswenc = false\n"); - } - update_attrib_phy_info(pattrib, psta); - -exit: - - return res; -} - -static int xmitframe_addmic(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) { - struct mic_data micdata; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int curfragnum, length; - u8 *pframe, *payload, mic[8]; - u8 priority[4]= {0x0, 0x0, 0x0, 0x0}; - u8 hw_hdr_offset = 0; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - stainfo = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (!stainfo) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(stainfo->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, stainfo->state); - return _FAIL; - } - - hw_hdr_offset = TXDESC_OFFSET; - - if (pattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) { - /* encode mic code */ - if (stainfo) { - u8 null_key[16]={0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0}; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - if (bmcst) { - if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) { - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey23a(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey); - } else { - if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], - null_key, 16)) { - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey23a(&micdata, &stainfo->dot11tkiptxmickey.skey[0]); - } - - if (pframe[1] & 1) { /* ToDS == 1 */ - /* DA */ - rtw_secmicappend23a(&micdata, &pframe[16], 6); - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, - &pframe[24], 6); - else - rtw_secmicappend23a(&micdata, - &pframe[10], 6); - } else { /* ToDS == 0 */ - /* DA */ - rtw_secmicappend23a(&micdata, &pframe[4], 6); - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, - &pframe[16], 6); - else - rtw_secmicappend23a(&micdata, - &pframe[10], 6); - } - - /* if (pmlmepriv->qos_option == 1) */ - if (pattrib->qos_en) - priority[0] = (u8)pxmitframe->attrib.priority; - - rtw_secmicappend23a(&micdata, &priority[0], 4); - - payload = pframe; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; - curfragnum++) { - payload = PTR_ALIGN(payload, 4); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "=== curfragnum =%d, pframe = 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n", - curfragnum, *payload, *(payload + 1), - *(payload + 2), *(payload + 3), - *(payload + 4), *(payload + 5), - *(payload + 6), *(payload + 7)); - - payload = payload + pattrib->hdrlen + - pattrib->iv_len; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "curfragnum =%d pattrib->hdrlen =%d pattrib->iv_len =%d\n", - curfragnum, - pattrib->hdrlen, pattrib->iv_len); - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - ((pattrib->bswenc) ? - pattrib->icv_len : 0); - rtw_secmicappend23a(&micdata, payload, - length); - payload = payload + length; - } else { - length = pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - ((pattrib->bswenc) ? - pattrib->icv_len : 0); - rtw_secmicappend23a(&micdata, payload, - length); - payload = payload + length + - pattrib->icv_len; - RT_TRACE(_module_rtl871x_xmit_c_, - _drv_err_, - "curfragnum =%d length =%d pattrib->icv_len =%d\n", - curfragnum, length, - pattrib->icv_len); - } - } - rtw_secgetmic23a(&micdata, &mic[0]); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: before add mic code!!\n"); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: pattrib->last_txcmdsz =%d!!!\n", - pattrib->last_txcmdsz); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: mic[0]= 0x%.2x , mic[1]=0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\nmic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x , mic[7]= 0x%.2x !!!!\n", - mic[0], mic[1], mic[2], mic[3], - mic[4], mic[5], mic[6], mic[7]); - /* add mic code and add the mic code length - in last_txcmdsz */ - - memcpy(payload, &mic[0], 8); - pattrib->last_txcmdsz += 8; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "======== last pkt ========\n"); - payload = payload - pattrib->last_txcmdsz + 8; - for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz; - curfragnum = curfragnum + 8) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "%.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x\n", - *(payload + curfragnum), - *(payload + curfragnum + 1), - *(payload + curfragnum + 2), - *(payload + curfragnum + 3), - *(payload + curfragnum + 4), - *(payload + curfragnum + 5), - *(payload + curfragnum + 6), - *(payload + curfragnum + 7)); - } - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: rtw_get_stainfo23a ==NULL!!!\n"); - } - } - - return _SUCCESS; -} - -static int xmitframe_swencrypt(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - /* if ((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */ - if (pattrib->bswenc) { - /* DBG_8723A("start xmitframe_swencrypt\n"); */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "### xmitframe_swencrypt\n"); - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - rtw_wep_encrypt23a(padapter, pxmitframe); - break; - case WLAN_CIPHER_SUITE_TKIP: - rtw_tkip_encrypt23a(padapter, pxmitframe); - break; - case WLAN_CIPHER_SUITE_CCMP: - rtw_aes_encrypt23a(padapter, pxmitframe); - break; - default: - break; - } - - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - "### xmitframe_hwencrypt\n"); - } - - return _SUCCESS; -} - -static int rtw_make_wlanhdr(struct rtw_adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib) -{ - struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; - struct ieee80211_qos_hdr *qoshdr; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 qos_option = false; - int res = _SUCCESS; - - struct sta_info *psta; - - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - if (bmcst) { - psta = rtw_get_bcmc_stainfo23a(padapter); - } else { - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); - return _FAIL; - } - - memset(hdr, 0, WLANHDR_OFFSET); - - pwlanhdr->frame_control = cpu_to_le16(pattrib->type); - - if (pattrib->type & IEEE80211_FTYPE_DATA) { - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* to_ds = 1, fr_ds = 0; */ - /* Data transfer to AP */ - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_TODS); - ether_addr_copy(pwlanhdr->addr1, get_bssid(pmlmepriv)); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, pattrib->dst); - - if (pmlmepriv->qos_option) - qos_option = true; - - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* to_ds = 0, fr_ds = 1; */ - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_FROMDS); - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, get_bssid(pmlmepriv)); - ether_addr_copy(pwlanhdr->addr3, pattrib->src); - - if (psta->qos_option) - qos_option = true; - } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, get_bssid(pmlmepriv)); - - if (psta->qos_option) - qos_option = true; - } - else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "fw_state:%x is not allowed to xmit frame\n", - get_fwstate(pmlmepriv)); - res = _FAIL; - goto exit; - } - if (pattrib->mdata) - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - if (pattrib->encrypt) - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - if (qos_option) { - qoshdr = (struct ieee80211_qos_hdr *)hdr; - - qoshdr->qos_ctrl = cpu_to_le16( - pattrib->priority & IEEE80211_QOS_CTL_TID_MASK); - - qoshdr->qos_ctrl |= cpu_to_le16( - (pattrib->ack_policy << 5) & - IEEE80211_QOS_CTL_ACK_POLICY_MASK); - - if (pattrib->eosp) - qoshdr->qos_ctrl |= - cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - } - /* TODO: fill HT Control Field */ - - /* Update Seq Num will be handled by f/w */ - if (psta) { - psta->sta_xmitpriv.txseq_tid[pattrib->priority]++; - psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF; - pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority]; - /* We dont need to worry about frag bits here */ - pwlanhdr->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ( - pattrib->seqnum)); - /* check if enable ampdu */ - if (pattrib->ht_en && psta->htpriv.ampdu_enable) { - if (pattrib->priority >= 16) - printk(KERN_WARNING "%s: Invalid " - "pattrib->priority %i\n", - __func__, pattrib->priority); - if (psta->htpriv.agg_enable_bitmap & - BIT(pattrib->priority)) - pattrib->ampdu_en = true; - } - /* re-check if enable ampdu by BA_starting_seqctrl */ - if (pattrib->ampdu_en) { - u16 tx_seq; - - tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f]; - - /* check BA_starting_seqctrl */ - if (SN_LESS(pattrib->seqnum, tx_seq)) { - /* DBG_8723A("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */ - pattrib->ampdu_en = false;/* AGG BK */ - } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) { - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } else { - /* DBG_8723A("tx ampdu over run\n"); */ - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } - } - } - } -exit: - return res; -} - -s32 rtw_txframes_pending23a(struct rtw_adapter *padapter) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - return (!list_empty(&pxmitpriv->be_pending.queue)) || - (!list_empty(&pxmitpriv->bk_pending.queue)) || - (!list_empty(&pxmitpriv->vi_pending.queue)) || - (!list_empty(&pxmitpriv->vo_pending.queue)); -} - -s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - int priority = pattrib->priority; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return 0; - } - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return 0; - } - switch (priority) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - break; - } - return ptxservq->qcnt; -} - -/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header - * IEEE LLC/SNAP header contains 8 octets - * First 3 octets comprise the LLC portion - * SNAP portion, 5 octets, is divided into two fields: - * Organizationally Unique Identifier(OUI), 3 octets, - * type, defined by that organization, 2 octets. - */ -static int rtw_put_snap(u8 *data, u16 h_proto) -{ - if (h_proto == ETH_P_IPX || h_proto == ETH_P_AARP) - ether_addr_copy(data, bridge_tunnel_header); - else - ether_addr_copy(data, rfc1042_header); - - data += ETH_ALEN; - put_unaligned_be16(h_proto, data); - return ETH_ALEN + sizeof(u16); -} - -/* - -This sub-routine will perform all the following: - -1. remove 802.3 header. -2. create wlan_header, based on the info in pxmitframe -3. append sta's iv/ext-iv -4. append LLC -5. move frag chunk from pframe to pxmitframe->mem -6. apply sw-encrypt, if necessary. - -*/ -int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb, - struct xmit_frame *pxmitframe) -{ - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct ieee80211_hdr *hdr; - s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz; - u8 *pframe, *mem_start; - u8 hw_hdr_offset; - u8 *pbuf_start; - u8 *pdata = skb->data; - int data_len = skb->len; - s32 bmcst = is_multicast_ether_addr(pattrib->ra); - int res = _SUCCESS; - - if (pattrib->psta) - psta = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - - if (!psta) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, psta->state); - return _FAIL; - } - - if (!pxmitframe->buf_addr) { - DBG_8723A("==> %s buf_addr == NULL\n", __func__); - return _FAIL; - } - - pbuf_start = pxmitframe->buf_addr; - - hw_hdr_offset = TXDESC_OFFSET; - - mem_start = pbuf_start + hw_hdr_offset; - - if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "%s: rtw_make_wlanhdr fail; drop pkt\n", __func__); - res = _FAIL; - goto exit; - } - - pdata += pattrib->pkt_hdrlen; - data_len -= pattrib->pkt_hdrlen; - - frg_inx = 0; - frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */ - - while (1) { - llc_sz = 0; - - mpdu_len = frg_len; - - pframe = mem_start; - hdr = (struct ieee80211_hdr *)mem_start; - - pframe += pattrib->hdrlen; - mpdu_len -= pattrib->hdrlen; - - /* adding icv, if necessary... */ - if (pattrib->iv_len) { - if (psta) { - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - WEP_IV(pattrib->iv, psta->dot11txpn, - pattrib->key_idx); - break; - case WLAN_CIPHER_SUITE_TKIP: - if (bmcst) - TKIP_IV(pattrib->iv, - psta->dot11txpn, - pattrib->key_idx); - else - TKIP_IV(pattrib->iv, - psta->dot11txpn, 0); - break; - case WLAN_CIPHER_SUITE_CCMP: - if (bmcst) - AES_IV(pattrib->iv, - psta->dot11txpn, - pattrib->key_idx); - else - AES_IV(pattrib->iv, - psta->dot11txpn, 0); - break; - } - } - - memcpy(pframe, pattrib->iv, pattrib->iv_len); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - "rtw_xmiaframe_coalesce23a: keyid =%d pattrib->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n", - padapter->securitypriv.dot11PrivacyKeyIndex, - pattrib->iv[3], *pframe, *(pframe+1), - *(pframe+2), *(pframe+3)); - pframe += pattrib->iv_len; - mpdu_len -= pattrib->iv_len; - } - if (frg_inx == 0) { - llc_sz = rtw_put_snap(pframe, pattrib->ether_type); - pframe += llc_sz; - mpdu_len -= llc_sz; - } - - if (pattrib->icv_len > 0 && pattrib->bswenc) - mpdu_len -= pattrib->icv_len; - - if (bmcst) - /* don't do fragment to broadcast/multicast packets */ - mem_sz = min_t(s32, data_len, pattrib->pktlen); - else - mem_sz = min_t(s32, data_len, mpdu_len); - - memcpy(pframe, pdata, mem_sz); - - pframe += mem_sz; - pdata += mem_sz; - data_len -= mem_sz; - - if ((pattrib->icv_len >0) && (pattrib->bswenc)) { - memcpy(pframe, pattrib->icv, pattrib->icv_len); - pframe += pattrib->icv_len; - } - - frg_inx++; - - if (bmcst || data_len <= 0) { - pattrib->nr_frags = frg_inx; - - pattrib->last_txcmdsz = pattrib->hdrlen + - pattrib->iv_len + - ((pattrib->nr_frags == 1) ? - llc_sz : 0) + - ((pattrib->bswenc) ? - pattrib->icv_len : 0) + mem_sz; - hdr->frame_control &= - ~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - - break; - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "%s: There're still something in packet!\n", - __func__); - } - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - - mem_start = PTR_ALIGN(pframe, 4) + hw_hdr_offset; - memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen); - } - - if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); - DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); - res = _FAIL; - goto exit; - } - - xmitframe_swencrypt(padapter, pxmitframe); - - if (bmcst == false) - update_attrib_vcs_info(padapter, pxmitframe); - else - pattrib->vcs_mode = NONE_VCS; - -exit: - return res; -} - -void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - uint protection; - const u8 *p; - - switch (pregistrypriv->vrtl_carrier_sense) { - case DISABLE_VCS: - pxmitpriv->vcs = NONE_VCS; - break; - case ENABLE_VCS: - break; - case AUTO_VCS: - default: - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, ie, ie_len); - if (!p) - pxmitpriv->vcs = NONE_VCS; - else { - protection = (*(p + 2)) & BIT(1); - if (protection) { - if (pregistrypriv->vcs_type == RTS_CTS) - pxmitpriv->vcs = RTS_CTS; - else - pxmitpriv->vcs = CTS_TO_SELF; - } else { - pxmitpriv->vcs = NONE_VCS; - } - } - break; - } -} - -void rtw_count_tx_stats23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe, int sz) -{ - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - pxmitpriv->tx_bytes += sz; - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod++; - - psta = pxmitframe->attrib.psta; - if (psta) { - pstats = &psta->sta_stats; - pstats->tx_pkts++; - pstats->tx_bytes += sz; - } - } -} - -struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *phead; - struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - - spin_lock_irqsave(&pfree_queue->lock, irqL); - - phead = get_list_head(pfree_queue); - - if (!list_empty(phead)) { - pxmitbuf = list_first_entry(phead, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - - pxmitpriv->free_xmit_extbuf_cnt--; - pxmitbuf->priv_data = NULL; - pxmitbuf->ext_tag = true; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - } - - spin_unlock_irqrestore(&pfree_queue->lock, irqL); - - return pxmitbuf; -} - -int rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - - if (pxmitbuf == NULL) - return _FAIL; - - spin_lock_irqsave(&pfree_queue->lock, irqL); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue)); - pxmitpriv->free_xmit_extbuf_cnt++; - - spin_unlock_irqrestore(&pfree_queue->lock, irqL); - - return _SUCCESS; -} - -struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *phead; - struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - /* DBG_8723A("+rtw_alloc_xmitbuf23a\n"); */ - - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - - phead = get_list_head(pfree_xmitbuf_queue); - - if (!list_empty(phead)) { - pxmitbuf = list_first_entry(phead, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - - pxmitpriv->free_xmitbuf_cnt--; - pxmitbuf->priv_data = NULL; - pxmitbuf->ext_tag = false; - pxmitbuf->flags = XMIT_VO_QUEUE; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - } - - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - - return pxmitbuf; -} - -int rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - /* DBG_8723A("+rtw_free_xmitbuf23a\n"); */ - - if (pxmitbuf == NULL) - return _FAIL; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE); - } - - if (pxmitbuf->ext_tag) { - rtw_free_xmitbuf_ext23a(pxmitpriv, pxmitbuf); - } else { - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, - get_list_head(pfree_xmitbuf_queue)); - - pxmitpriv->free_xmitbuf_cnt++; - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - } - - return _SUCCESS; -} - -static void rtw_init_xmitframe(struct xmit_frame *pxframe) -{ - if (pxframe != NULL) { - /* default value setting */ - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib)); - /* pxframe->attrib.psta = NULL; */ - - pxframe->frame_tag = DATA_FRAMETAG; - - pxframe->pkt = NULL; - pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */ - - pxframe->ack_report = 0; - } -} - -/* -Calling context: -1. OS_TXENTRY -2. RXENTRY (rx_thread or RX_ISR/RX_CallBack) - -If we turn on USE_RXTHREAD, then, no need for critical section. -Otherwise, we must use _enter/_exit critical to protect free_xmit_queue... - -Must be very very cautious... - -*/ -static struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pxframe; - struct rtw_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - - spin_lock_bh(&pfree_xmit_queue->lock); - - pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue, - struct xmit_frame, list); - if (!pxframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe:%d\n", - pxmitpriv->free_xmitframe_cnt); - } else { - list_del_init(&pxframe->list); - pxmitpriv->free_xmitframe_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xmitframe_cnt); - } - - spin_unlock_bh(&pfree_xmit_queue->lock); - - rtw_init_xmitframe(pxframe); - - return pxframe; -} - -struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pxframe; - struct rtw_queue *queue = &pxmitpriv->free_xframe_ext_queue; - - spin_lock_bh(&queue->lock); - - pxframe = list_first_entry_or_null(&queue->queue, - struct xmit_frame, list); - if (!pxframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe23a_ext:%d\n", - pxmitpriv->free_xframe_ext_cnt); - } else { - list_del_init(&pxframe->list); - pxmitpriv->free_xframe_ext_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xframe_ext_cnt); - } - - spin_unlock_bh(&queue->lock); - - rtw_init_xmitframe(pxframe); - - return pxframe; -} - -s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe) -{ - struct rtw_queue *queue = NULL; - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct sk_buff *pndis_pkt = NULL; - - if (pxmitframe == NULL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n"); - goto exit; - } - - if (pxmitframe->pkt) { - pndis_pkt = pxmitframe->pkt; - pxmitframe->pkt = NULL; - } - - if (pxmitframe->ext_tag == 0) - queue = &pxmitpriv->free_xmit_queue; - else if (pxmitframe->ext_tag == 1) - queue = &pxmitpriv->free_xframe_ext_queue; - - if (!queue) - goto check_pkt_complete; - spin_lock_bh(&queue->lock); - - list_del_init(&pxmitframe->list); - list_add_tail(&pxmitframe->list, get_list_head(queue)); - if (pxmitframe->ext_tag == 0) { - pxmitpriv->free_xmitframe_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, - "rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xmitframe_cnt); - } else if (pxmitframe->ext_tag == 1) { - pxmitpriv->free_xframe_ext_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, - "rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n", - pxmitpriv->free_xframe_ext_cnt); - } - - spin_unlock_bh(&queue->lock); - -check_pkt_complete: - - if (pndis_pkt) - rtw_os_pkt_complete23a(padapter, pndis_pkt); - -exit: - - return _SUCCESS; -} - -void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv, - struct rtw_queue *pframequeue) -{ - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - - spin_lock_bh(&pframequeue->lock); - phead = get_list_head(pframequeue); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - spin_unlock_bh(&pframequeue->lock); - -} - -int rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - if (rtw_xmit23a_classifier(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "rtw_xmitframe_enqueue23a: drop xmit pkt for classifier fail\n"); - return _FAIL; - } - - return _SUCCESS; -} - -static struct xmit_frame * -dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, - struct tx_servq *ptxservq, struct rtw_queue *pframe_queue) -{ - struct list_head *phead; - struct xmit_frame *pxmitframe = NULL; - - phead = get_list_head(pframe_queue); - - if (!list_empty(phead)) { - pxmitframe = list_first_entry(phead, struct xmit_frame, list); - list_del_init(&pxmitframe->list); - ptxservq->qcnt--; - } - return pxmitframe; -} - -struct xmit_frame * -rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i, - int entry) -{ - struct list_head *sta_phead; - struct hw_xmit *phwxmit; - struct tx_servq *ptxservq = NULL, *ptmp; - struct rtw_queue *pframe_queue = NULL; - struct xmit_frame *pxmitframe = NULL; - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct registry_priv *pregpriv = &padapter->registrypriv; - int i, inx[4]; - - inx[0] = 0; - inx[1] = 1; - inx[2] = 2; - inx[3] = 3; - if (pregpriv->wifi_spec == 1) { - int j; - - for (j = 0; j < 4; j++) - inx[j] = pxmitpriv->wmm_para_seq[j]; - } - - spin_lock_bh(&pxmitpriv->lock); - - for (i = 0; i < entry; i++) { - phwxmit = phwxmit_i + inx[i]; - - sta_phead = get_list_head(phwxmit->sta_queue); - list_for_each_entry_safe(ptxservq, ptmp, sta_phead, - tx_pending) { - pframe_queue = &ptxservq->sta_pending; - - pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue); - - if (pxmitframe) { - phwxmit->accnt--; - - /* Remove sta node when there is no pending packets. */ - /* must be done after get_next and - before break */ - if (list_empty(&pframe_queue->queue)) - list_del_init(&ptxservq->tx_pending); - goto exit; - } - } - } -exit: - spin_unlock_bh(&pxmitpriv->lock); - return pxmitframe; -} - -struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, struct sta_info *psta, int up, u8 *ac) -{ - struct tx_servq *ptxservq = NULL; - - switch (up) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - *(ac) = 3; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : BK\n"); - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - *(ac) = 1; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : VI\n"); - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - *(ac) = 0; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : VO\n"); - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - *(ac) = 2; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : BE\n"); - break; - } - return ptxservq; -} - -/* - * Will enqueue pxmitframe to the proper queue, - * and indicate it to xx_pending list..... - */ -int rtw_xmit23a_classifier(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - u8 ac_index; - int res = _SUCCESS; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - } - if (psta == NULL) { - res = _FAIL; - DBG_8723A("rtw_xmit23a_classifier: psta == NULL\n"); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "rtw_xmit23a_classifier: psta == NULL\n"); - goto exit; - } - if (!(psta->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return _FAIL; - } - ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, - (u8 *)(&ac_index)); - - if (list_empty(&ptxservq->tx_pending)) { - list_add_tail(&ptxservq->tx_pending, - get_list_head(phwxmits[ac_index].sta_queue)); - } - - list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending)); - ptxservq->qcnt++; - phwxmits[ac_index].accnt++; -exit: - return res; -} - -void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int size; - - pxmitpriv->hwxmit_entry = HWXMIT_ENTRY; - - size = sizeof(struct hw_xmit) * (pxmitpriv->hwxmit_entry + 1); - pxmitpriv->hwxmits = kzalloc(size, GFP_KERNEL); - - hwxmits = pxmitpriv->hwxmits; - - if (pxmitpriv->hwxmit_entry == 5) { - /* pxmitpriv->bmc_txqueue.head = 0; */ - /* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */ - hwxmits[0] .sta_queue = &pxmitpriv->bm_pending; - - /* pxmitpriv->vo_txqueue.head = 0; */ - /* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */ - hwxmits[1] .sta_queue = &pxmitpriv->vo_pending; - - /* pxmitpriv->vi_txqueue.head = 0; */ - /* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */ - hwxmits[2] .sta_queue = &pxmitpriv->vi_pending; - - /* pxmitpriv->bk_txqueue.head = 0; */ - /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */ - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - - /* pxmitpriv->be_txqueue.head = 0; */ - /* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */ - hwxmits[4] .sta_queue = &pxmitpriv->be_pending; - - } else if (pxmitpriv->hwxmit_entry == 4) { - - /* pxmitpriv->vo_txqueue.head = 0; */ - /* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */ - hwxmits[0] .sta_queue = &pxmitpriv->vo_pending; - - /* pxmitpriv->vi_txqueue.head = 0; */ - /* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */ - hwxmits[1] .sta_queue = &pxmitpriv->vi_pending; - - /* pxmitpriv->be_txqueue.head = 0; */ - /* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */ - hwxmits[2] .sta_queue = &pxmitpriv->be_pending; - - /* pxmitpriv->bk_txqueue.head = 0; */ - /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */ - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - } else { - - } -} - -void rtw_free_hwxmits23a(struct rtw_adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - hwxmits = pxmitpriv->hwxmits; - kfree(hwxmits); -} - -void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry) -{ - int i; - - for (i = 0; i < entry; i++, phwxmit++) - phwxmit->accnt = 0; -} - -u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe) -{ - u32 addr; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - switch (pattrib->qsel) { - case 0: - case 3: - addr = BE_QUEUE_INX; - break; - case 1: - case 2: - addr = BK_QUEUE_INX; - break; - case 4: - case 5: - addr = VI_QUEUE_INX; - break; - case 6: - case 7: - addr = VO_QUEUE_INX; - break; - case 0x10: - addr = BCN_QUEUE_INX; - break; - case 0x11:/* BC/MC in PS (HIQ) */ - addr = HIGH_QUEUE_INX; - break; - case 0x12: - default: - addr = MGT_QUEUE_INX; - break; - } - - return addr; -} - -/* - * The main transmit(tx) entry - * - * Return - * 1 enqueue - * 0 success, hardware will handle this xmit frame(packet) - * <0 fail - */ -int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *skb) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_frame *pxmitframe = NULL; - int res; - - pxmitframe = rtw_alloc_xmitframe(pxmitpriv); - - if (pxmitframe == NULL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a: no more pxmitframe\n"); - return -1; - } - - res = update_attrib(padapter, skb, &pxmitframe->attrib); - - if (res == _FAIL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a: update attrib fail\n"); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - return -1; - } - pxmitframe->pkt = skb; - - pxmitframe->attrib.qsel = pxmitframe->attrib.priority; - -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pxmitpriv->lock); - if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) { - spin_unlock_bh(&pxmitpriv->lock); - return 1; - } - spin_unlock_bh(&pxmitpriv->lock); -#endif - - if (rtl8723au_hal_xmit(padapter, pxmitframe) == false) - return 1; - - return 0; -} - -#if defined(CONFIG_8723AU_AP_MODE) - -int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe) -{ - int ret = false; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return ret; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return false; - } - - if (!(psta->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return false; - } - - if (pattrib->triggered == 1) { - if (bmcst) - pattrib->qsel = 0x11;/* HIQ */ - return ret; - } - - if (bmcst) { - spin_lock_bh(&psta->sleep_q.lock); - - if (pstapriv->sta_dz_bitmap) { - /* if anyone sta is in ps mode */ - list_del_init(&pxmitframe->list); - - /* spin_lock_bh(&psta->sleep_q.lock); */ - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - pstapriv->tim_bitmap |= BIT(0);/* */ - pstapriv->sta_dz_bitmap |= BIT(0); - - /* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */ - - /* tx bc/mc packets after update bcn */ - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - /* spin_unlock_bh(&psta->sleep_q.lock); */ - - ret = true; - - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; - - } - - spin_lock_bh(&psta->sleep_q.lock); - - if (psta->state&WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - if (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid)) { - list_del_init(&pxmitframe->list); - - /* spin_lock_bh(&psta->sleep_q.lock); */ - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - psta->sleepq_ac_len++; - - if (((psta->has_legacy_ac) && (!wmmps_ac)) || - ((!psta->has_legacy_ac) && (wmmps_ac))) { - pstapriv->tim_bitmap |= CHKBIT(psta->aid); - - if (psta->sleepq_len == 1) { - /* update BCN for TIM IE */ - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - } - - /* spin_unlock_bh(&psta->sleep_q.lock); */ - - /* if (psta->sleepq_len > (NR_XMITFRAME>>3)) */ - /* */ - /* wakeup_sta_to_xmit23a(padapter, psta); */ - /* */ - - ret = true; - - } - - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; -} - -static void -dequeue_xmitframes_to_sleeping_queue(struct rtw_adapter *padapter, - struct sta_info *psta, - struct rtw_queue *pframequeue) -{ - int ret; - struct list_head *phead; - u8 ac_index; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib; - struct xmit_frame *pxmitframe, *ptmp; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - - phead = get_list_head(pframequeue); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - ret = xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe); - - if (ret == true) { - pattrib = &pxmitframe->attrib; - - ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); - - ptxservq->qcnt--; - phwxmits[ac_index].accnt--; - } else { - /* DBG_8723A("xmitframe_enqueue_for_sleeping_sta23a return false\n"); */ - } - } -} - -void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct sta_info *psta_bmc; - struct sta_xmit_priv *pstaxmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - pstaxmitpriv = &psta->sta_xmitpriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - - spin_lock_bh(&pxmitpriv->lock); - - psta->state |= WIFI_SLEEP_STATE; - - pstapriv->sta_dz_bitmap |= CHKBIT(psta->aid); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, - &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, - &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - - /* for BC/MC Frames */ - pstaxmitpriv = &psta_bmc->sta_xmitpriv; - dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, - &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - spin_unlock_bh(&pxmitpriv->lock); -} - -void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 update_mask = 0, wmmps_ac = 0; - struct sta_info *psta_bmc; - struct list_head *phead; - struct xmit_frame *pxmitframe = NULL, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - list_del_init(&pxmitframe->list); - - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - psta->sleepq_len--; - if (psta->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - if (wmmps_ac) { - psta->sleepq_ac_len--; - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - } - - pxmitframe->attrib.triggered = 1; - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - } - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - /* update BCN for TIM IE */ - update_mask = BIT(0); - - if (psta->state&WIFI_SLEEP_STATE) - psta->state ^= WIFI_SLEEP_STATE; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid); - } - /* spin_unlock_bh(&psta->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return; - - if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) { - /* no any sta in ps mode */ - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta_bmc->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - } - if (psta_bmc->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - /* update BCN for TIM IE */ - /* update_BCNTIM(padapter); */ - update_mask |= BIT(1); - } - /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - } - - if (update_mask) - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); -} - -void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - u8 wmmps_ac = 0; - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - /* spin_lock_bh(&psta->sleep_q.lock); */ - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (!wmmps_ac) - continue; - - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - psta->sleepq_ac_len--; - - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - - pxmitframe->attrib.triggered = 1; - - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - - if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && - (wmmps_ac)) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - /* update BCN for TIM IE */ - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - } - } - spin_unlock_bh(&pxmitpriv->lock); -} - -#endif - -void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms) -{ - sctx->timeout_ms = timeout_ms; - init_completion(&sctx->done); - sctx->status = RTW_SCTX_SUBMITTED; -} - -int rtw_sctx_wait23a(struct submit_ctx *sctx) -{ - int ret = _FAIL; - unsigned long expire; - int status = 0; - - expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : - MAX_SCHEDULE_TIMEOUT; - if (!wait_for_completion_timeout(&sctx->done, expire)) { - /* timeout, do something?? */ - status = RTW_SCTX_DONE_TIMEOUT; - DBG_8723A("%s timeout\n", __func__); - } else { - status = sctx->status; - } - - if (status == RTW_SCTX_DONE_SUCCESS) - ret = _SUCCESS; - - return ret; -} - -static bool rtw_sctx_chk_waring_status(int status) -{ - switch (status) { - case RTW_SCTX_DONE_UNKNOWN: - case RTW_SCTX_DONE_BUF_ALLOC: - case RTW_SCTX_DONE_BUF_FREE: - case RTW_SCTX_DONE_DRV_STOP: - case RTW_SCTX_DONE_DEV_REMOVE: - return true; - default: - return false; - } -} - -void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status) -{ - if (*sctx) { - if (rtw_sctx_chk_waring_status(status)) - DBG_8723A("%s status:%d\n", __func__, status); - (*sctx)->status = status; - complete(&(*sctx)->done); - *sctx = NULL; - } -} - -int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms) -{ - struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; - - pack_tx_ops->timeout_ms = timeout_ms; - pack_tx_ops->status = RTW_SCTX_SUBMITTED; - - return rtw_sctx_wait23a(pack_tx_ops); -} - diff --git a/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c b/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c deleted file mode 100644 index 747f86cddeb9..000000000000 --- a/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#include "Hal8723PwrSeq.h" - -/* - drivers should parse below arrays and do the corresponding actions -*/ -/* 3 Power on Array */ -struct wlan_pwr_cfg rtl8723AU_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/* 3 Radio off GPIO Array */ -struct wlan_pwr_cfg rtl8723AU_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_END -}; - -/* 3 Card Disable Array */ -struct wlan_pwr_cfg rtl8723AU_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_CARDDIS - RTL8723A_TRANS_END -}; - -/* 3 Card Enable Array */ -struct wlan_pwr_cfg rtl8723AU_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_CARDDIS_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/* 3 Suspend Array */ -struct wlan_pwr_cfg rtl8723AU_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_SUS - RTL8723A_TRANS_END -}; - -/* 3 Resume Array */ -struct wlan_pwr_cfg rtl8723AU_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_SUS_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/* 3 HWPDN Array */ -struct wlan_pwr_cfg rtl8723AU_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_PDN - RTL8723A_TRANS_END -}; - -/* 3 Enter LPS */ -struct wlan_pwr_cfg rtl8723AU_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STEPS+RTL8723A_TRANS_END_STEPS] = { - /* FW behavior */ - RTL8723A_TRANS_ACT_TO_LPS - RTL8723A_TRANS_END -}; - -/* 3 Leave LPS */ -struct wlan_pwr_cfg rtl8723AU_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = { - /* FW behavior */ - RTL8723A_TRANS_LPS_TO_ACT - RTL8723A_TRANS_END -}; diff --git a/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c b/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c deleted file mode 100644 index 56833da63ced..000000000000 --- a/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c +++ /dev/null @@ -1,136 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -/*Created on 2013/01/14, 15:51*/ -#include "odm_precomp.h" - -u32 Rtl8723UPHY_REG_Array_PG[Rtl8723UPHY_REG_Array_PGLength] = { - 0xe00, 0xffffffff, 0x0a0c0c0c, - 0xe04, 0xffffffff, 0x02040608, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x0a0c0d0e, - 0xe14, 0xffffffff, 0x02040608, - 0xe18, 0xffffffff, 0x0a0c0d0e, - 0xe1c, 0xffffffff, 0x02040608, - 0x830, 0xffffffff, 0x0a0c0c0c, - 0x834, 0xffffffff, 0x02040608, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x0a0c0d0e, - 0x848, 0xffffffff, 0x02040608, - 0x84c, 0xffffffff, 0x0a0c0d0e, - 0x868, 0xffffffff, 0x02040608, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x06060606, - 0xe14, 0xffffffff, 0x00020406, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x06060606, - 0x848, 0xffffffff, 0x00020406, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - }; - -u32 Rtl8723UMACPHY_Array_PG[Rtl8723UMACPHY_Array_PGLength] = { - 0x0, -}; diff --git a/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c b/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c deleted file mode 100644 index 3f9ec9e00e16..000000000000 --- a/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c +++ /dev/null @@ -1,1097 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -/* Description: */ -/* This file is for 92CE/92CU dynamic mechanism only */ - -/* include files */ - -#include "odm_precomp.h" -#include - -#define DPK_DELTA_MAPPING_NUM 13 -#define index_mapping_HP_NUM 15 -/* 091212 chiyokolin */ -static void -odm_TXPowerTrackingCallback_ThermalMeter_92C(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, delta_HP; - int ele_A, ele_D, TempCCk, X, value32; - int Y, ele_C; - s8 OFDM_index[2], CCK_index = 0, OFDM_index_old[2] = {0}; - s8 CCK_index_old = 0; - int i = 0; - u8 OFDM_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB*/ - u8 ThermalValue_HP_count = 0; - u32 ThermalValue_HP = 0; - s32 index_mapping_HP[index_mapping_HP_NUM] = { - 0, 1, 3, 4, 6, - 7, 9, 10, 12, 13, - 15, 16, 18, 19, 21 - }; - s8 index_HP; - - pdmpriv->TXPowerTrackingCallbackCnt++; /* cosa add for debug */ - pdmpriv->bTXPowerTrackingInit = true; - - if (pHalData->CurrentChannel == 14 && !pdmpriv->bCCKinCH14) - pdmpriv->bCCKinCH14 = true; - else if (pHalData->CurrentChannel != 14 && pdmpriv->bCCKinCH14) - pdmpriv->bCCKinCH14 = false; - - ThermalValue = (u8)PHY_QueryRFReg(Adapter, RF_PATH_A, RF_T_METER, - 0x1f);/* 0x24: RF Reg[4:0] */ - - rtl8723a_phy_ap_calibrate(Adapter, (ThermalValue - - pHalData->EEPROMThermalMeter)); - - if (pHalData->rf_type == RF_2T2R) - rf = 2; - else - rf = 1; - - if (ThermalValue) { - /* Query OFDM path A default setting */ - ele_D = rtl8723au_read32(Adapter, rOFDM0_XATxIQImbalance) & - bMaskOFDM_D; - for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) { - /* find the index */ - if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) { - OFDM_index_old[0] = (u8)i; - break; - } - } - - /* Query OFDM path B default setting */ - if (pHalData->rf_type == RF_2T2R) { - ele_D = rtl8723au_read32(Adapter, - rOFDM0_XBTxIQImbalance); - ele_D &= bMaskOFDM_D; - for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) { /* find the index */ - if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) { - OFDM_index_old[1] = (u8)i; - break; - } - } - } - - /* Query CCK default setting From 0xa24 */ - TempCCk = rtl8723au_read32(Adapter, rCCK0_TxFilter2) & bMaskCCK; - for (i = 0 ; i < CCK_TABLE_SIZE ; i++) { - if (pdmpriv->bCCKinCH14) { - if (!memcmp(&TempCCk, - &CCKSwingTable_Ch1423A[i][2], 4)) { - CCK_index_old = (u8)i; - break; - } - } else { - if (!memcmp(&TempCCk, - &CCKSwingTable_Ch1_Ch1323A[i][2], 4)) { - CCK_index_old = (u8)i; - break; - } - } - } - - if (!pdmpriv->ThermalValue) { - pdmpriv->ThermalValue = pHalData->EEPROMThermalMeter; - pdmpriv->ThermalValue_LCK = ThermalValue; - pdmpriv->ThermalValue_IQK = ThermalValue; - pdmpriv->ThermalValue_DPK = pHalData->EEPROMThermalMeter; - - for (i = 0; i < rf; i++) { - pdmpriv->OFDM_index_HP[i] = OFDM_index_old[i]; - pdmpriv->OFDM_index[i] = OFDM_index_old[i]; - } - pdmpriv->CCK_index_HP = CCK_index_old; - pdmpriv->CCK_index = CCK_index_old; - } - - if (pHalData->BoardType == BOARD_USB_High_PA) { - pdmpriv->ThermalValue_HP[pdmpriv->ThermalValue_HP_index] = ThermalValue; - pdmpriv->ThermalValue_HP_index++; - if (pdmpriv->ThermalValue_HP_index == HP_THERMAL_NUM) - pdmpriv->ThermalValue_HP_index = 0; - - for (i = 0; i < HP_THERMAL_NUM; i++) { - if (pdmpriv->ThermalValue_HP[i]) { - ThermalValue_HP += pdmpriv->ThermalValue_HP[i]; - ThermalValue_HP_count++; - } - } - - if (ThermalValue_HP_count) - ThermalValue = (u8)(ThermalValue_HP / ThermalValue_HP_count); - } - - delta = (ThermalValue > pdmpriv->ThermalValue) ? - (ThermalValue - pdmpriv->ThermalValue) : - (pdmpriv->ThermalValue - ThermalValue); - if (pHalData->BoardType == BOARD_USB_High_PA) { - if (pdmpriv->bDoneTxpower) - delta_HP = (ThermalValue > pdmpriv->ThermalValue) ? - (ThermalValue - pdmpriv->ThermalValue) : - (pdmpriv->ThermalValue - ThermalValue); - else - delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ? - (ThermalValue - pHalData->EEPROMThermalMeter) : - (pHalData->EEPROMThermalMeter - ThermalValue); - } else { - delta_HP = 0; - } - delta_LCK = (ThermalValue > pdmpriv->ThermalValue_LCK) ? - (ThermalValue - pdmpriv->ThermalValue_LCK) : - (pdmpriv->ThermalValue_LCK - ThermalValue); - delta_IQK = (ThermalValue > pdmpriv->ThermalValue_IQK) ? - (ThermalValue - pdmpriv->ThermalValue_IQK) : - (pdmpriv->ThermalValue_IQK - ThermalValue); - - if (delta_LCK > 1) { - pdmpriv->ThermalValue_LCK = ThermalValue; - rtl8723a_phy_lc_calibrate(Adapter); - } - - if ((delta > 0 || delta_HP > 0) && pdmpriv->TxPowerTrackControl) { - if (pHalData->BoardType == BOARD_USB_High_PA) { - pdmpriv->bDoneTxpower = true; - delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ? - (ThermalValue - pHalData->EEPROMThermalMeter) : - (pHalData->EEPROMThermalMeter - ThermalValue); - - if (delta_HP > index_mapping_HP_NUM-1) - index_HP = index_mapping_HP[index_mapping_HP_NUM-1]; - else - index_HP = index_mapping_HP[delta_HP]; - - if (ThermalValue > pHalData->EEPROMThermalMeter) { - /* set larger Tx power */ - for (i = 0; i < rf; i++) - OFDM_index[i] = pdmpriv->OFDM_index_HP[i] - index_HP; - CCK_index = pdmpriv->CCK_index_HP - index_HP; - } else { - for (i = 0; i < rf; i++) - OFDM_index[i] = pdmpriv->OFDM_index_HP[i] + index_HP; - CCK_index = pdmpriv->CCK_index_HP + index_HP; - } - - delta_HP = (ThermalValue > pdmpriv->ThermalValue) ? - (ThermalValue - pdmpriv->ThermalValue) : - (pdmpriv->ThermalValue - ThermalValue); - } else { - if (ThermalValue > pdmpriv->ThermalValue) { - for (i = 0; i < rf; i++) - pdmpriv->OFDM_index[i] -= delta; - pdmpriv->CCK_index -= delta; - } else { - for (i = 0; i < rf; i++) - pdmpriv->OFDM_index[i] += delta; - pdmpriv->CCK_index += delta; - } - } - - /* no adjust */ - if (pHalData->BoardType != BOARD_USB_High_PA) { - if (ThermalValue > pHalData->EEPROMThermalMeter) { - for (i = 0; i < rf; i++) - OFDM_index[i] = pdmpriv->OFDM_index[i]+1; - CCK_index = pdmpriv->CCK_index+1; - } else { - for (i = 0; i < rf; i++) - OFDM_index[i] = pdmpriv->OFDM_index[i]; - CCK_index = pdmpriv->CCK_index; - } - } - for (i = 0; i < rf; i++) { - if (OFDM_index[i] > (OFDM_TABLE_SIZE_92C-1)) - OFDM_index[i] = (OFDM_TABLE_SIZE_92C-1); - else if (OFDM_index[i] < OFDM_min_index) - OFDM_index[i] = OFDM_min_index; - } - - if (CCK_index > (CCK_TABLE_SIZE-1)) - CCK_index = CCK_TABLE_SIZE-1; - else if (CCK_index < 0) - CCK_index = 0; - } - - if (pdmpriv->TxPowerTrackControl && - (delta != 0 || delta_HP != 0)) { - /* Adujst OFDM Ant_A according to IQK result */ - ele_D = (OFDMSwingTable23A[OFDM_index[0]] & 0xFFC00000)>>22; - X = pdmpriv->RegE94; - Y = pdmpriv->RegE9C; - - if (X != 0) { - if ((X & 0x00000200) != 0) - X = X | 0xFFFFFC00; - ele_A = ((X * ele_D)>>8)&0x000003FF; - - /* new element C = element D x Y */ - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - ele_C = ((Y * ele_D)>>8)&0x000003FF; - - /* write new elements A, C, D to regC80 and regC94, element B is always 0 */ - value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; - rtl8723au_write32(Adapter, - rOFDM0_XATxIQImbalance, - value32); - - value32 = (ele_C&0x000003C0)>>6; - PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, value32); - - value32 = ((X * ele_D)>>7)&0x01; - PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, - BIT(31), value32); - - value32 = ((Y * ele_D)>>7)&0x01; - PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, - BIT(29), value32); - } else { - rtl8723au_write32(Adapter, - rOFDM0_XATxIQImbalance, - OFDMSwingTable23A[OFDM_index[0]]); - PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, - bMaskH4Bits, 0x00); - PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, - BIT(31) | BIT(29), 0x00); - } - - /* Adjust CCK according to IQK result */ - if (!pdmpriv->bCCKinCH14) { - rtl8723au_write8(Adapter, 0xa22, CCKSwingTable_Ch1_Ch1323A[CCK_index][0]); - rtl8723au_write8(Adapter, 0xa23, CCKSwingTable_Ch1_Ch1323A[CCK_index][1]); - rtl8723au_write8(Adapter, 0xa24, CCKSwingTable_Ch1_Ch1323A[CCK_index][2]); - rtl8723au_write8(Adapter, 0xa25, CCKSwingTable_Ch1_Ch1323A[CCK_index][3]); - rtl8723au_write8(Adapter, 0xa26, CCKSwingTable_Ch1_Ch1323A[CCK_index][4]); - rtl8723au_write8(Adapter, 0xa27, CCKSwingTable_Ch1_Ch1323A[CCK_index][5]); - rtl8723au_write8(Adapter, 0xa28, CCKSwingTable_Ch1_Ch1323A[CCK_index][6]); - rtl8723au_write8(Adapter, 0xa29, CCKSwingTable_Ch1_Ch1323A[CCK_index][7]); - } else { - rtl8723au_write8(Adapter, 0xa22, CCKSwingTable_Ch1423A[CCK_index][0]); - rtl8723au_write8(Adapter, 0xa23, CCKSwingTable_Ch1423A[CCK_index][1]); - rtl8723au_write8(Adapter, 0xa24, CCKSwingTable_Ch1423A[CCK_index][2]); - rtl8723au_write8(Adapter, 0xa25, CCKSwingTable_Ch1423A[CCK_index][3]); - rtl8723au_write8(Adapter, 0xa26, CCKSwingTable_Ch1423A[CCK_index][4]); - rtl8723au_write8(Adapter, 0xa27, CCKSwingTable_Ch1423A[CCK_index][5]); - rtl8723au_write8(Adapter, 0xa28, CCKSwingTable_Ch1423A[CCK_index][6]); - rtl8723au_write8(Adapter, 0xa29, CCKSwingTable_Ch1423A[CCK_index][7]); - } - - if (pHalData->rf_type == RF_2T2R) { - ele_D = (OFDMSwingTable23A[(u8)OFDM_index[1]] & 0xFFC00000)>>22; - - /* new element A = element D x X */ - X = pdmpriv->RegEB4; - Y = pdmpriv->RegEBC; - - if (X != 0) { - if ((X & 0x00000200) != 0) /* consider minus */ - X = X | 0xFFFFFC00; - ele_A = ((X * ele_D)>>8)&0x000003FF; - - /* new element C = element D x Y */ - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - ele_C = ((Y * ele_D)>>8)&0x00003FF; - - /* write new elements A, C, D to regC88 and regC9C, element B is always 0 */ - value32 = (ele_D<<22)|((ele_C&0x3F)<<16) | ele_A; - rtl8723au_write32(Adapter, rOFDM0_XBTxIQImbalance, value32); - - value32 = (ele_C&0x000003C0)>>6; - PHY_SetBBReg(Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, value32); - - value32 = ((X * ele_D)>>7)&0x01; - PHY_SetBBReg(Adapter, - rOFDM0_ECCAThreshold, - BIT(27), value32); - - value32 = ((Y * ele_D)>>7)&0x01; - PHY_SetBBReg(Adapter, - rOFDM0_ECCAThreshold, - BIT(25), value32); - } else { - rtl8723au_write32(Adapter, - rOFDM0_XBTxIQImbalance, - OFDMSwingTable23A[OFDM_index[1]]); - PHY_SetBBReg(Adapter, - rOFDM0_XDTxAFE, - bMaskH4Bits, 0x00); - PHY_SetBBReg(Adapter, - rOFDM0_ECCAThreshold, - BIT(27) | BIT(25), 0x00); - } - } - - } - if (delta_IQK > 3) { - pdmpriv->ThermalValue_IQK = ThermalValue; - rtl8723a_phy_iq_calibrate(Adapter, false); - } - - /* update thermal meter value */ - if (pdmpriv->TxPowerTrackControl) - pdmpriv->ThermalValue = ThermalValue; - } - pdmpriv->TXPowercount = 0; -} - -/* Description: */ -/* - Dispatch TxPower Tracking direct call ONLY for 92s. */ -/* - We shall NOT schedule Workitem within PASSIVE LEVEL, which will cause system resource */ -/* leakage under some platform. */ -/* Assumption: */ -/* PASSIVE_LEVEL when this routine is called. */ -static void ODM_TXPowerTracking92CDirectCall(struct rtw_adapter *Adapter) -{ - odm_TXPowerTrackingCallback_ThermalMeter_92C(Adapter); -} - -void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - - if (!pdmpriv->TM_Trigger) { /* at least delay 1 sec */ - PHY_SetRFReg(Adapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60); - - pdmpriv->TM_Trigger = 1; - return; - } else { - ODM_TXPowerTracking92CDirectCall(Adapter); - pdmpriv->TM_Trigger = 0; - } -} - -/* IQK */ -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 1 /* ms */ - -static u8 _PHY_PathA_IQK(struct rtw_adapter *pAdapter, bool configPathB) -{ - u32 regEAC, regE94, regE9C, regEA4; - u8 result = 0x00; - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - - /* path-A IQK setting */ - rtl8723au_write32(pAdapter, rTx_IQK_Tone_A, 0x10008c1f); - rtl8723au_write32(pAdapter, rRx_IQK_Tone_A, 0x10008c1f); - rtl8723au_write32(pAdapter, rTx_IQK_PI_A, 0x82140102); - - rtl8723au_write32(pAdapter, rRx_IQK_PI_A, configPathB ? 0x28160202 : - IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202:0x28160502); - - /* path-B IQK setting */ - if (configPathB) { - rtl8723au_write32(pAdapter, rTx_IQK_Tone_B, 0x10008c22); - rtl8723au_write32(pAdapter, rRx_IQK_Tone_B, 0x10008c22); - rtl8723au_write32(pAdapter, rTx_IQK_PI_B, 0x82140102); - rtl8723au_write32(pAdapter, rRx_IQK_PI_B, 0x28160202); - } - - /* LO calibration setting */ - rtl8723au_write32(pAdapter, rIQK_AGC_Rsp, 0x001028d1); - - /* One shot, path A LOK & IQK */ - rtl8723au_write32(pAdapter, rIQK_AGC_Pts, 0xf9000000); - rtl8723au_write32(pAdapter, rIQK_AGC_Pts, 0xf8000000); - - /* delay x ms */ - /* PlatformStallExecution(IQK_DELAY_TIME*1000); */ - udelay(IQK_DELAY_TIME*1000); - - /* Check failed */ - regEAC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2); - regE94 = rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A); - regE9C = rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A); - regEA4 = rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_A_2); - - if (!(regEAC & BIT(28)) && - (((regE94 & 0x03FF0000)>>16) != 0x142) && - (((regE9C & 0x03FF0000)>>16) != 0x42)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - - if (!(regEAC & BIT(27)) && /* if Tx is OK, check whether Rx is OK */ - (((regEA4 & 0x03FF0000)>>16) != 0x132) && - (((regEAC & 0x03FF0000)>>16) != 0x36)) - result |= 0x02; - else - DBG_8723A("Path A Rx IQK fail!!\n"); - return result; -} - -static u8 _PHY_PathB_IQK(struct rtw_adapter *pAdapter) -{ - u32 regEAC, regEB4, regEBC, regEC4, regECC; - u8 result = 0x00; - - /* One shot, path B LOK & IQK */ - rtl8723au_write32(pAdapter, rIQK_AGC_Cont, 0x00000002); - rtl8723au_write32(pAdapter, rIQK_AGC_Cont, 0x00000000); - - /* delay x ms */ - udelay(IQK_DELAY_TIME*1000); - - /* Check failed */ - regEAC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2); - regEB4 = rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B); - regEBC = rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B); - regEC4 = rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_B_2); - regECC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_B_2); - - if (!(regEAC & BIT(31)) && - (((regEB4 & 0x03FF0000)>>16) != 0x142) && - (((regEBC & 0x03FF0000)>>16) != 0x42)) - result |= 0x01; - else - return result; - - if (!(regEAC & BIT(30)) && - (((regEC4 & 0x03FF0000)>>16) != 0x132) && - (((regECC & 0x03FF0000)>>16) != 0x36)) - result |= 0x02; - else - DBG_8723A("Path B Rx IQK fail!!\n"); - return result; -} - -static void _PHY_PathAFillIQKMatrix(struct rtw_adapter *pAdapter, - bool bIQKOK, - int result[][8], - u8 final_candidate, - bool bTxOnly - ) -{ - u32 Oldval_0, X, TX0_A, reg; - s32 Y, TX0_C; - - DBG_8723A("Path A IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed"); - - if (final_candidate == 0xFF) { - return; - } else if (bIQKOK) { - Oldval_0 = rtl8723au_read32(pAdapter, rOFDM0_XATxIQImbalance); - Oldval_0 = (Oldval_0 >> 22) & 0x3FF; - - X = result[final_candidate][0]; - if ((X & 0x00000200) != 0) - X = X | 0xFFFFFC00; - TX0_A = (X * Oldval_0) >> 8; - PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A); - PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(31), - ((X * Oldval_0>>7) & 0x1)); - - Y = result[final_candidate][1]; - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - TX0_C = (Y * Oldval_0) >> 8; - PHY_SetBBReg(pAdapter, rOFDM0_XCTxAFE, 0xF0000000, - ((TX0_C&0x3C0)>>6)); - PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x003F0000, - (TX0_C&0x3F)); - PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(29), - ((Y * Oldval_0>>7) & 0x1)); - - if (bTxOnly) { - DBG_8723A("_PHY_PathAFillIQKMatrix only Tx OK\n"); - return; - } - - reg = result[final_candidate][2]; - PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0x3FF, reg); - - reg = result[final_candidate][3] & 0x3F; - PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0xFC00, reg); - - reg = (result[final_candidate][3] >> 6) & 0xF; - PHY_SetBBReg(pAdapter, rOFDM0_RxIQExtAnta, 0xF0000000, reg); - } -} - -static void _PHY_PathBFillIQKMatrix(struct rtw_adapter *pAdapter, bool bIQKOK, int result[][8], u8 final_candidate, bool bTxOnly) -{ - u32 Oldval_1, X, TX1_A, reg; - s32 Y, TX1_C; - - DBG_8723A("Path B IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed"); - - if (final_candidate == 0xFF) { - return; - } else if (bIQKOK) { - Oldval_1 = rtl8723au_read32(pAdapter, rOFDM0_XBTxIQImbalance); - Oldval_1 = (Oldval_1 >> 22) & 0x3FF; - - X = result[final_candidate][4]; - if ((X & 0x00000200) != 0) - X = X | 0xFFFFFC00; - TX1_A = (X * Oldval_1) >> 8; - PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A); - PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(27), - ((X * Oldval_1 >> 7) & 0x1)); - - Y = result[final_candidate][5]; - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - TX1_C = (Y * Oldval_1) >> 8; - PHY_SetBBReg(pAdapter, rOFDM0_XDTxAFE, 0xF0000000, - ((TX1_C & 0x3C0) >> 6)); - PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x003F0000, - (TX1_C & 0x3F)); - PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(25), - ((Y * Oldval_1 >> 7) & 0x1)); - - if (bTxOnly) - return; - - reg = result[final_candidate][6]; - PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0x3FF, reg); - - reg = result[final_candidate][7] & 0x3F; - PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0xFC00, reg); - - reg = (result[final_candidate][7] >> 6) & 0xF; - PHY_SetBBReg(pAdapter, rOFDM0_AGCRSSITable, 0x0000F000, reg); - } -} - -static void _PHY_SaveADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum) -{ - u32 i; - - for (i = 0 ; i < RegisterNum ; i++) { - ADDABackup[i] = rtl8723au_read32(pAdapter, ADDAReg[i]); - } -} - -static void _PHY_SaveMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, - u32 *MACBackup) -{ - u32 i; - - for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) { - MACBackup[i] = rtl8723au_read8(pAdapter, MACReg[i]); - } - MACBackup[i] = rtl8723au_read32(pAdapter, MACReg[i]); -} - -static void _PHY_ReloadADDARegisters(struct rtw_adapter *pAdapter, - u32 *ADDAReg, u32 *ADDABackup, - u32 RegiesterNum) -{ - u32 i; - - for (i = 0 ; i < RegiesterNum ; i++) { - rtl8723au_write32(pAdapter, ADDAReg[i], ADDABackup[i]); - } -} - -static void _PHY_ReloadMACRegisters(struct rtw_adapter *pAdapter, - u32 *MACReg, u32 *MACBackup) -{ - u32 i; - - for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) - rtl8723au_write8(pAdapter, MACReg[i], (u8)MACBackup[i]); - - rtl8723au_write32(pAdapter, MACReg[i], MACBackup[i]); -} - -static void _PHY_PathADDAOn(struct rtw_adapter *pAdapter, u32 *ADDAReg, - bool isPathAOn, bool is2T) -{ - u32 pathOn; - u32 i; - - pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4; - if (!is2T) { - pathOn = 0x0bdb25a0; - rtl8723au_write32(pAdapter, ADDAReg[0], 0x0b1b25a0); - } else { - rtl8723au_write32(pAdapter, ADDAReg[0], pathOn); - } - - for (i = 1 ; i < IQK_ADDA_REG_NUM ; i++) - rtl8723au_write32(pAdapter, ADDAReg[i], pathOn); -} - -static void _PHY_MACSettingCalibration(struct rtw_adapter *pAdapter, - u32 *MACReg, u32 *MACBackup) -{ - u32 i = 0; - - rtl8723au_write8(pAdapter, MACReg[i], 0x3F); - - for (i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++) { - rtl8723au_write8(pAdapter, MACReg[i], - (u8)(MACBackup[i] & ~BIT(3))); - } - rtl8723au_write8(pAdapter, MACReg[i], (u8)(MACBackup[i] & ~BIT(5))); -} - -static void _PHY_PathAStandBy(struct rtw_adapter *pAdapter) -{ - rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x0); - rtl8723au_write32(pAdapter, 0x840, 0x00010000); - rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x80800000); -} - -static void _PHY_PIModeSwitch(struct rtw_adapter *pAdapter, bool PIMode) -{ - u32 mode; - - mode = PIMode ? 0x01000100 : 0x01000000; - rtl8723au_write32(pAdapter, 0x820, mode); - rtl8723au_write32(pAdapter, 0x828, mode); -} - -/* -return false => do IQK again -*/ -static bool _PHY_SimularityCompare(struct rtw_adapter *pAdapter, int result[][8], u8 c1, u8 c2) -{ - u32 i, j, diff, SimularityBitMap, bound = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ - bool bResult = true; - - if (pHalData->rf_type == RF_2T2R) - bound = 8; - else - bound = 4; - - SimularityBitMap = 0; - - for (i = 0; i < bound; i++) { - diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - result[c2][i]) : (result[c2][i] - result[c1][i]); - if (diff > MAX_TOLERANCE) { - if ((i == 2 || i == 6) && !SimularityBitMap) { - if (result[c1][i]+result[c1][i+1] == 0) - final_candidate[(i/4)] = c2; - else if (result[c2][i]+result[c2][i+1] == 0) - final_candidate[(i/4)] = c1; - else - SimularityBitMap = SimularityBitMap|(1<rf_type == RF_2T2R) { - /* path B OK */ - for (i = 4; i < 8; i++) - result[3][i] = result[c1][i]; - return false; - } else { - return false; - } -} - -static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t, bool is2T) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - u32 i; - u8 PathAOK, PathBOK; - u32 ADDA_REG[IQK_ADDA_REG_NUM] = { - rFPGA0_XCD_SwitchControl, rBlue_Tooth, - rRx_Wait_CCA, rTx_CCK_RFON, - rTx_CCK_BBON, rTx_OFDM_RFON, - rTx_OFDM_BBON, rTx_To_Rx, - rTx_To_Tx, rRx_CCK, - rRx_OFDM, rRx_Wait_RIFS, - rRx_TO_Rx, rStandby, - rSleep, rPMPD_ANAEN - }; - - u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = { - REG_TXPAUSE, REG_BCN_CTRL, - REG_BCN_CTRL_1, REG_GPIO_MUXCFG - }; - - u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { - rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar, - rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB, - rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE, - rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD - }; - - const u32 retryCount = 2; - - /* Note: IQ calibration must be performed after loading */ - /* PHY_REG.txt , and radio_a, radio_b.txt */ - - u32 bbvalue; - - if (t == 0) { - bbvalue = rtl8723au_read32(pAdapter, rFPGA0_RFMOD); - - /* Save ADDA parameters, turn Path A ADDA on */ - _PHY_SaveADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM); - _PHY_SaveMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup); - _PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM); - } - _PHY_PathADDAOn(pAdapter, ADDA_REG, true, is2T); - - if (t == 0) - pdmpriv->bRfPiEnable = (u8) - PHY_QueryBBReg(pAdapter, rFPGA0_XA_HSSIParameter1, - BIT(8)); - - if (!pdmpriv->bRfPiEnable) { - /* Switch BB to PI mode to do IQ Calibration. */ - _PHY_PIModeSwitch(pAdapter, true); - } - - PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, BIT(24), 0x00); - rtl8723au_write32(pAdapter, rOFDM0_TRxPathEnable, 0x03a05600); - rtl8723au_write32(pAdapter, rOFDM0_TRMuxPar, 0x000800e4); - rtl8723au_write32(pAdapter, rFPGA0_XCD_RFInterfaceSW, 0x22204000); - PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01); - PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01); - PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00); - PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00); - - if (is2T) { - rtl8723au_write32(pAdapter, - rFPGA0_XA_LSSIParameter, 0x00010000); - rtl8723au_write32(pAdapter, - rFPGA0_XB_LSSIParameter, 0x00010000); - } - - /* MAC settings */ - _PHY_MACSettingCalibration(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup); - - /* Page B init */ - rtl8723au_write32(pAdapter, rConfig_AntA, 0x00080000); - - if (is2T) - rtl8723au_write32(pAdapter, rConfig_AntB, 0x00080000); - - /* IQ calibration setting */ - rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x80800000); - rtl8723au_write32(pAdapter, rTx_IQK, 0x01007c00); - rtl8723au_write32(pAdapter, rRx_IQK, 0x01004800); - - for (i = 0 ; i < retryCount ; i++) { - PathAOK = _PHY_PathA_IQK(pAdapter, is2T); - if (PathAOK == 0x03) { - DBG_8723A("Path A IQK Success!!\n"); - result[t][0] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A)&0x3FF0000)>>16; - result[t][1] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A)&0x3FF0000)>>16; - result[t][2] = (rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_A_2)&0x3FF0000)>>16; - result[t][3] = (rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2)&0x3FF0000)>>16; - break; - } else if (i == (retryCount-1) && PathAOK == 0x01) { - /* Tx IQK OK */ - DBG_8723A("Path A IQK Only Tx Success!!\n"); - - result[t][0] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A)&0x3FF0000)>>16; - result[t][1] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A)&0x3FF0000)>>16; - } - } - - if (0x00 == PathAOK) { - DBG_8723A("Path A IQK failed!!\n"); - } - - if (is2T) { - _PHY_PathAStandBy(pAdapter); - - /* Turn Path B ADDA on */ - _PHY_PathADDAOn(pAdapter, ADDA_REG, false, is2T); - - for (i = 0 ; i < retryCount ; i++) { - PathBOK = _PHY_PathB_IQK(pAdapter); - if (PathBOK == 0x03) { - DBG_8723A("Path B IQK Success!!\n"); - result[t][4] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B)&0x3FF0000)>>16; - result[t][5] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B)&0x3FF0000)>>16; - result[t][6] = (rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_B_2)&0x3FF0000)>>16; - result[t][7] = (rtl8723au_read32(pAdapter, rRx_Power_After_IQK_B_2)&0x3FF0000)>>16; - break; - } else if (i == (retryCount - 1) && PathBOK == 0x01) { - /* Tx IQK OK */ - DBG_8723A("Path B Only Tx IQK Success!!\n"); - result[t][4] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B)&0x3FF0000)>>16; - result[t][5] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B)&0x3FF0000)>>16; - } - } - - if (0x00 == PathBOK) { - DBG_8723A("Path B IQK failed!!\n"); - } - } - - /* Back to BB mode, load original value */ - rtl8723au_write32(pAdapter, rFPGA0_IQK, 0); - - if (t != 0) { - if (!pdmpriv->bRfPiEnable) { - /* Switch back BB to SI mode after finish IQ Calibration. */ - _PHY_PIModeSwitch(pAdapter, false); - } - - /* Reload ADDA power saving parameters */ - _PHY_ReloadADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM); - - /* Reload MAC parameters */ - _PHY_ReloadMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup); - - /* Reload BB parameters */ - _PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM); - - /* Restore RX initial gain */ - rtl8723au_write32(pAdapter, - rFPGA0_XA_LSSIParameter, 0x00032ed3); - if (is2T) { - rtl8723au_write32(pAdapter, - rFPGA0_XB_LSSIParameter, 0x00032ed3); - } - - /* load 0xe30 IQC default value */ - rtl8723au_write32(pAdapter, rTx_IQK_Tone_A, 0x01008c00); - rtl8723au_write32(pAdapter, rRx_IQK_Tone_A, 0x01008c00); - - } -} - -static void _PHY_LCCalibrate(struct rtw_adapter *pAdapter, bool is2T) -{ - u8 tmpReg; - u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal; - - /* Check continuous TX and Packet TX */ - tmpReg = rtl8723au_read8(pAdapter, 0xd03); - - if ((tmpReg&0x70) != 0) { - /* Deal with contisuous TX case */ - /* disable all continuous TX */ - rtl8723au_write8(pAdapter, 0xd03, tmpReg&0x8F); - } else { - /* Deal with Packet TX case */ - /* block all queues */ - rtl8723au_write8(pAdapter, REG_TXPAUSE, 0xFF); - } - - if ((tmpReg&0x70) != 0) { - /* 1. Read original RF mode */ - /* Path-A */ - RF_Amode = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits); - - /* Path-B */ - if (is2T) - RF_Bmode = PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits); - - /* 2. Set RF mode = standby mode */ - /* Path-A */ - PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000); - - /* Path-B */ - if (is2T) - PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000); - } - - /* 3. Read RF reg18 */ - LC_Cal = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits); - - /* 4. Set LC calibration begin */ - PHY_SetRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000); - - msleep(100); - - /* Restore original situation */ - if ((tmpReg&0x70) != 0) { /* Deal with contuous TX case */ - /* Path-A */ - rtl8723au_write8(pAdapter, 0xd03, tmpReg); - PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode); - - /* Path-B */ - if (is2T) - PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode); - } else /* Deal with Packet TX case */ - rtl8723au_write8(pAdapter, REG_TXPAUSE, 0x00); -} - -/* Analog Pre-distortion calibration */ -#define APK_BB_REG_NUM 8 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - s32 result[4][8]; /* last is final result */ - u8 i, final_candidate; - bool bPathAOK, bPathBOK; - s32 RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4; - s32 RegECC, RegTmp = 0; - bool is12simular, is13simular, is23simular; - bool bStartContTx = false, bSingleTone = false; - bool bCarrierSuppression = false; - u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { - rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance, - rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable, - rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance, - rOFDM0_XCTxAFE, rOFDM0_XDTxAFE, - rOFDM0_RxIQExtAnta - }; - - /* ignore IQK when continuous Tx */ - if (bStartContTx || bSingleTone || bCarrierSuppression) - return; - - if (bReCovery) { - _PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9); - return; - } - DBG_8723A("IQK:Start!!!\n"); - - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - result[3][i] = 0; - } - final_candidate = 0xff; - bPathAOK = false; - bPathBOK = false; - is12simular = false; - is23simular = false; - is13simular = false; - - for (i = 0; i < 3; i++) { - if (pHalData->rf_type == RF_2T2R) - _PHY_IQCalibrate(pAdapter, result, i, true); - else /* For 88C 1T1R */ - _PHY_IQCalibrate(pAdapter, result, i, false); - - if (i == 1) { - is12simular = _PHY_SimularityCompare(pAdapter, result, 0, 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - - if (i == 2) { - is13simular = _PHY_SimularityCompare(pAdapter, result, 0, 2); - if (is13simular) { - final_candidate = 0; - break; - } - - is23simular = _PHY_SimularityCompare(pAdapter, result, 1, 2); - if (is23simular) { - final_candidate = 1; - } else { - for (i = 0; i < 8; i++) - RegTmp += result[3][i]; - - if (RegTmp != 0) - final_candidate = 3; - else - final_candidate = 0xFF; - } - } - } - - for (i = 0; i < 4; i++) { - RegE94 = result[i][0]; - RegE9C = result[i][1]; - RegEA4 = result[i][2]; - RegEAC = result[i][3]; - RegEB4 = result[i][4]; - RegEBC = result[i][5]; - RegEC4 = result[i][6]; - RegECC = result[i][7]; - } - - if (final_candidate != 0xff) { - RegE94 = result[final_candidate][0]; - pdmpriv->RegE94 = RegE94; - RegE9C = result[final_candidate][1]; - pdmpriv->RegE9C = RegE9C; - RegEA4 = result[final_candidate][2]; - RegEAC = result[final_candidate][3]; - RegEB4 = result[final_candidate][4]; - pdmpriv->RegEB4 = RegEB4; - RegEBC = result[final_candidate][5]; - pdmpriv->RegEBC = RegEBC; - RegEC4 = result[final_candidate][6]; - RegECC = result[final_candidate][7]; - DBG_8723A("IQK: final_candidate is %x\n", final_candidate); - DBG_8723A("IQK: RegE94 =%x RegE9C =%x RegEA4 =%x RegEAC =%x RegEB4 =%x RegEBC =%x RegEC4 =%x RegECC =%x\n ", - RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC); - bPathAOK = bPathBOK = true; - } else { - RegE94 = RegEB4 = pdmpriv->RegE94 = pdmpriv->RegEB4 = 0x100; /* X default value */ - RegE9C = RegEBC = pdmpriv->RegE9C = pdmpriv->RegEBC = 0x0; /* Y default value */ - } - - if ((RegE94 != 0)/*&&(RegEA4 != 0)*/) - _PHY_PathAFillIQKMatrix(pAdapter, bPathAOK, result, final_candidate, (RegEA4 == 0)); - - if (pHalData->rf_type == RF_2T2R) { - if ((RegEB4 != 0)/*&&(RegEC4 != 0)*/) - _PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result, - final_candidate, (RegEC4 == 0)); - } - - _PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9); -} - -void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - struct mlme_ext_priv *pmlmeext = &pAdapter->mlmeextpriv; - bool bStartContTx = false, bSingleTone = false, bCarrierSuppression = false; - - /* ignore IQK when continuous Tx */ - if (bStartContTx || bSingleTone || bCarrierSuppression) - return; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) - return; - - if (pHalData->rf_type == RF_2T2R) - _PHY_LCCalibrate(pAdapter, true); - else /* For 88C 1T1R */ - _PHY_LCCalibrate(pAdapter, false); -} - -void -rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta) -{ -} diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c deleted file mode 100644 index 8d3ea6c0cbe6..000000000000 --- a/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c +++ /dev/null @@ -1,565 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. 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 for -* more details. -* -******************************************************************************/ - -#include "odm_precomp.h" - -static bool CheckCondition(const u32 Condition, const u32 Hex) -{ - u32 _board = (Hex & 0x000000FF); - u32 _interface = (Hex & 0x0000FF00) >> 8; - u32 _platform = (Hex & 0x00FF0000) >> 16; - u32 cond = Condition; - - if (Condition == 0xCDCDCDCD) - return true; - - cond = Condition & 0x000000FF; - if ((_board == cond) && cond != 0x00) - return false; - - cond = Condition & 0x0000FF00; - cond >>= 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = Condition & 0x00FF0000; - cond >>= 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* AGC_TAB_1T.TXT -******************************************************************************/ - -static u32 Array_AGC_TAB_1T_8723A[] = { - 0xC78, 0x7B000001, - 0xC78, 0x7B010001, - 0xC78, 0x7B020001, - 0xC78, 0x7B030001, - 0xC78, 0x7B040001, - 0xC78, 0x7B050001, - 0xC78, 0x7A060001, - 0xC78, 0x79070001, - 0xC78, 0x78080001, - 0xC78, 0x77090001, - 0xC78, 0x760A0001, - 0xC78, 0x750B0001, - 0xC78, 0x740C0001, - 0xC78, 0x730D0001, - 0xC78, 0x720E0001, - 0xC78, 0x710F0001, - 0xC78, 0x70100001, - 0xC78, 0x6F110001, - 0xC78, 0x6E120001, - 0xC78, 0x6D130001, - 0xC78, 0x6C140001, - 0xC78, 0x6B150001, - 0xC78, 0x6A160001, - 0xC78, 0x69170001, - 0xC78, 0x68180001, - 0xC78, 0x67190001, - 0xC78, 0x661A0001, - 0xC78, 0x651B0001, - 0xC78, 0x641C0001, - 0xC78, 0x631D0001, - 0xC78, 0x621E0001, - 0xC78, 0x611F0001, - 0xC78, 0x60200001, - 0xC78, 0x49210001, - 0xC78, 0x48220001, - 0xC78, 0x47230001, - 0xC78, 0x46240001, - 0xC78, 0x45250001, - 0xC78, 0x44260001, - 0xC78, 0x43270001, - 0xC78, 0x42280001, - 0xC78, 0x41290001, - 0xC78, 0x402A0001, - 0xC78, 0x262B0001, - 0xC78, 0x252C0001, - 0xC78, 0x242D0001, - 0xC78, 0x232E0001, - 0xC78, 0x222F0001, - 0xC78, 0x21300001, - 0xC78, 0x20310001, - 0xC78, 0x06320001, - 0xC78, 0x05330001, - 0xC78, 0x04340001, - 0xC78, 0x03350001, - 0xC78, 0x02360001, - 0xC78, 0x01370001, - 0xC78, 0x00380001, - 0xC78, 0x00390001, - 0xC78, 0x003A0001, - 0xC78, 0x003B0001, - 0xC78, 0x003C0001, - 0xC78, 0x003D0001, - 0xC78, 0x003E0001, - 0xC78, 0x003F0001, - 0xC78, 0x7B400001, - 0xC78, 0x7B410001, - 0xC78, 0x7B420001, - 0xC78, 0x7B430001, - 0xC78, 0x7B440001, - 0xC78, 0x7B450001, - 0xC78, 0x7A460001, - 0xC78, 0x79470001, - 0xC78, 0x78480001, - 0xC78, 0x77490001, - 0xC78, 0x764A0001, - 0xC78, 0x754B0001, - 0xC78, 0x744C0001, - 0xC78, 0x734D0001, - 0xC78, 0x724E0001, - 0xC78, 0x714F0001, - 0xC78, 0x70500001, - 0xC78, 0x6F510001, - 0xC78, 0x6E520001, - 0xC78, 0x6D530001, - 0xC78, 0x6C540001, - 0xC78, 0x6B550001, - 0xC78, 0x6A560001, - 0xC78, 0x69570001, - 0xC78, 0x68580001, - 0xC78, 0x67590001, - 0xC78, 0x665A0001, - 0xC78, 0x655B0001, - 0xC78, 0x645C0001, - 0xC78, 0x635D0001, - 0xC78, 0x625E0001, - 0xC78, 0x615F0001, - 0xC78, 0x60600001, - 0xC78, 0x49610001, - 0xC78, 0x48620001, - 0xC78, 0x47630001, - 0xC78, 0x46640001, - 0xC78, 0x45650001, - 0xC78, 0x44660001, - 0xC78, 0x43670001, - 0xC78, 0x42680001, - 0xC78, 0x41690001, - 0xC78, 0x406A0001, - 0xC78, 0x266B0001, - 0xC78, 0x256C0001, - 0xC78, 0x246D0001, - 0xC78, 0x236E0001, - 0xC78, 0x226F0001, - 0xC78, 0x21700001, - 0xC78, 0x20710001, - 0xC78, 0x06720001, - 0xC78, 0x05730001, - 0xC78, 0x04740001, - 0xC78, 0x03750001, - 0xC78, 0x02760001, - 0xC78, 0x01770001, - 0xC78, 0x00780001, - 0xC78, 0x00790001, - 0xC78, 0x007A0001, - 0xC78, 0x007B0001, - 0xC78, 0x007C0001, - 0xC78, 0x007D0001, - 0xC78, 0x007E0001, - 0xC78, 0x007F0001, - 0xC78, 0x3800001E, - 0xC78, 0x3801001E, - 0xC78, 0x3802001E, - 0xC78, 0x3803001E, - 0xC78, 0x3804001E, - 0xC78, 0x3805001E, - 0xC78, 0x3806001E, - 0xC78, 0x3807001E, - 0xC78, 0x3808001E, - 0xC78, 0x3C09001E, - 0xC78, 0x3E0A001E, - 0xC78, 0x400B001E, - 0xC78, 0x440C001E, - 0xC78, 0x480D001E, - 0xC78, 0x4C0E001E, - 0xC78, 0x500F001E, - 0xC78, 0x5210001E, - 0xC78, 0x5611001E, - 0xC78, 0x5A12001E, - 0xC78, 0x5E13001E, - 0xC78, 0x6014001E, - 0xC78, 0x6015001E, - 0xC78, 0x6016001E, - 0xC78, 0x6217001E, - 0xC78, 0x6218001E, - 0xC78, 0x6219001E, - 0xC78, 0x621A001E, - 0xC78, 0x621B001E, - 0xC78, 0x621C001E, - 0xC78, 0x621D001E, - 0xC78, 0x621E001E, - 0xC78, 0x621F001E, -}; - -#define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; v1 = Array[i]; v2 = Array[i+1]; \ - } while (0) - -void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm) -{ - u32 hex; - u32 i; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_AGC_TAB_1T_8723A); - u32 *Array = Array_AGC_TAB_1T_8723A; - - hex = board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigBB_AGC_8723A(pDM_Odm, v1, v2); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to - end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigBB_AGC_8723A(pDM_Odm, v1, v2); - READ_NEXT_PAIR(v1, v2, i); - } - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} - -/****************************************************************************** -* PHY_REG_1T.TXT -******************************************************************************/ - -static u32 Array_PHY_REG_1T_8723A[] = { - 0x800, 0x80040000, - 0x804, 0x00000003, - 0x808, 0x0000FC00, - 0x80C, 0x0000000A, - 0x810, 0x10001331, - 0x814, 0x020C3D10, - 0x818, 0x02200385, - 0x81C, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390004, - 0x828, 0x00000000, - 0x82C, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83C, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84C, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569A569A, - 0x85C, 0x001B25A4, - 0x860, 0x66F60110, - 0x864, 0x061F0130, - 0x868, 0x00000000, - 0x86C, 0x32323200, - 0x870, 0x07000760, - 0x874, 0x22004000, - 0x878, 0x00000808, - 0x87C, 0x00000000, - 0x880, 0xC0083070, - 0x884, 0x000004D5, - 0x888, 0x00000000, - 0x88C, 0xCCC000C0, - 0x890, 0x00000800, - 0x894, 0xFFFFFFFE, - 0x898, 0x40302010, - 0x89C, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90C, 0x81121111, - 0xA00, 0x00D047C8, - 0xA04, 0x80FF000C, - 0xA08, 0x8C838300, - 0xA0C, 0x2E68120F, - 0xA10, 0x9500BB78, - 0xA14, 0x11144028, - 0xA18, 0x00881117, - 0xA1C, 0x89140F00, - 0xA20, 0x1A1B0000, - 0xA24, 0x090E1317, - 0xA28, 0x00000204, - 0xA2C, 0x00D30000, - 0xA70, 0x101FBF00, - 0xA74, 0x00000007, - 0xA78, 0x00000900, - 0xC00, 0x48071D40, - 0xC04, 0x03A05611, - 0xC08, 0x000000E4, - 0xC0C, 0x6C6C6C6C, - 0xC10, 0x08800000, - 0xC14, 0x40000100, - 0xC18, 0x08800000, - 0xC1C, 0x40000100, - 0xC20, 0x00000000, - 0xC24, 0x00000000, - 0xC28, 0x00000000, - 0xC2C, 0x00000000, - 0xC30, 0x69E9AC44, - 0xFF0F011F, 0xABCD, - 0xC34, 0x469652CF, - 0xCDCDCDCD, 0xCDCD, - 0xC34, 0x469652AF, - 0xFF0F011F, 0xDEAD, - 0xC38, 0x49795994, - 0xC3C, 0x0A97971C, - 0xC40, 0x1F7C403F, - 0xC44, 0x000100B7, - 0xC48, 0xEC020107, - 0xC4C, 0x007F037F, - 0xC50, 0x69543420, - 0xC54, 0x43BC0094, - 0xC58, 0x69543420, - 0xC5C, 0x433C0094, - 0xC60, 0x00000000, - 0xFF0F011F, 0xABCD, - 0xC64, 0x7116848B, - 0xCDCDCDCD, 0xCDCD, - 0xC64, 0x7112848B, - 0xFF0F011F, 0xDEAD, - 0xC68, 0x47C00BFF, - 0xC6C, 0x00000036, - 0xC70, 0x2C7F000D, - 0xC74, 0x018610DB, - 0xC78, 0x0000001F, - 0xC7C, 0x00B91612, - 0xC80, 0x40000100, - 0xC84, 0x20F60000, - 0xC88, 0x40000100, - 0xC8C, 0x20200000, - 0xC90, 0x00121820, - 0xC94, 0x00000000, - 0xC98, 0x00121820, - 0xC9C, 0x00007F7F, - 0xCA0, 0x00000000, - 0xCA4, 0x00000080, - 0xCA8, 0x00000000, - 0xCAC, 0x00000000, - 0xCB0, 0x00000000, - 0xCB4, 0x00000000, - 0xCB8, 0x00000000, - 0xCBC, 0x28000000, - 0xCC0, 0x00000000, - 0xCC4, 0x00000000, - 0xCC8, 0x00000000, - 0xCCC, 0x00000000, - 0xCD0, 0x00000000, - 0xCD4, 0x00000000, - 0xCD8, 0x64B22427, - 0xCDC, 0x00766932, - 0xCE0, 0x00222222, - 0xCE4, 0x00000000, - 0xCE8, 0x37644302, - 0xCEC, 0x2F97D40C, - 0xD00, 0x00080740, - 0xD04, 0x00020401, - 0xD08, 0x0000907F, - 0xD0C, 0x20010201, - 0xD10, 0xA0633333, - 0xD14, 0x3333BC43, - 0xD18, 0x7A8F5B6B, - 0xD2C, 0xCC979975, - 0xD30, 0x00000000, - 0xD34, 0x80608000, - 0xD38, 0x00000000, - 0xD3C, 0x00027293, - 0xD40, 0x00000000, - 0xD44, 0x00000000, - 0xD48, 0x00000000, - 0xD4C, 0x00000000, - 0xD50, 0x6437140A, - 0xD54, 0x00000000, - 0xD58, 0x00000000, - 0xD5C, 0x30032064, - 0xD60, 0x4653DE68, - 0xD64, 0x04518A3C, - 0xD68, 0x00002101, - 0xD6C, 0x2A201C16, - 0xD70, 0x1812362E, - 0xD74, 0x322C2220, - 0xD78, 0x000E3C24, - 0xE00, 0x2A2A2A2A, - 0xE04, 0x2A2A2A2A, - 0xE08, 0x03902A2A, - 0xE10, 0x2A2A2A2A, - 0xE14, 0x2A2A2A2A, - 0xE18, 0x2A2A2A2A, - 0xE1C, 0x2A2A2A2A, - 0xE28, 0x00000000, - 0xE30, 0x1000DC1F, - 0xE34, 0x10008C1F, - 0xE38, 0x02140102, - 0xE3C, 0x681604C2, - 0xE40, 0x01007C00, - 0xE44, 0x01004800, - 0xE48, 0xFB000000, - 0xE4C, 0x000028D1, - 0xE50, 0x1000DC1F, - 0xE54, 0x10008C1F, - 0xE58, 0x02140102, - 0xE5C, 0x28160D05, - 0xE60, 0x00000008, - 0xE68, 0x001B25A4, - 0xE6C, 0x631B25A0, - 0xE70, 0x631B25A0, - 0xE74, 0x081B25A0, - 0xE78, 0x081B25A0, - 0xE7C, 0x081B25A0, - 0xE80, 0x081B25A0, - 0xE84, 0x631B25A0, - 0xE88, 0x081B25A0, - 0xE8C, 0x631B25A0, - 0xED0, 0x631B25A0, - 0xED4, 0x631B25A0, - 0xED8, 0x631B25A0, - 0xEDC, 0x001B25A0, - 0xEE0, 0x001B25A0, - 0xEEC, 0x6B1B25A0, - 0xF14, 0x00000003, - 0xF4C, 0x00000000, - 0xF00, 0x00000300, -}; - -void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm) -{ - u32 hex = 0; - u32 i = 0; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_PHY_REG_1T_8723A); - u32 *Array = Array_PHY_REG_1T_8723A; - - hex += board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to - end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2); - READ_NEXT_PAIR(v1, v2, i); - } - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} - -/****************************************************************************** -* PHY_REG_MP.TXT -******************************************************************************/ - -static u32 Array_PHY_REG_MP_8723A[] = { - 0xC30, 0x69E9AC4A, - 0xC3C, 0x0A979718, -}; - -void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm) -{ - u32 hex = 0; - u32 i; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_PHY_REG_MP_8723A); - u32 *Array = Array_PHY_REG_MP_8723A; - - hex += board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to - end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2); - READ_NEXT_PAIR(v1, v2, i); - } - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c deleted file mode 100644 index 9bf685905e68..000000000000 --- a/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c +++ /dev/null @@ -1,187 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. 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 for -* more details. -* -******************************************************************************/ - -#include "odm_precomp.h" - -static bool CheckCondition(const u32 Condition, const u32 Hex) -{ - u32 _board = (Hex & 0x000000FF); - u32 _interface = (Hex & 0x0000FF00) >> 8; - u32 _platform = (Hex & 0x00FF0000) >> 16; - u32 cond = Condition; - - if (Condition == 0xCDCDCDCD) - return true; - - cond = Condition & 0x000000FF; - if ((_board == cond) && cond != 0x00) - return false; - - cond = Condition & 0x0000FF00; - cond >>= 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = Condition & 0x00FF0000; - cond >>= 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* MAC_REG.TXT -******************************************************************************/ - -static u32 Array_MAC_REG_8723A[] = { - 0x420, 0x00000080, - 0x423, 0x00000000, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000006, - 0x437, 0x00000007, - 0x438, 0x00000000, - 0x439, 0x00000000, - 0x43A, 0x00000000, - 0x43B, 0x00000001, - 0x43C, 0x00000004, - 0x43D, 0x00000005, - 0x43E, 0x00000006, - 0x43F, 0x00000007, - 0x440, 0x0000005D, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000015, - 0x445, 0x000000F0, - 0x446, 0x0000000F, - 0x447, 0x00000000, - 0x458, 0x00000041, - 0x459, 0x000000A8, - 0x45A, 0x00000072, - 0x45B, 0x000000B9, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x462, 0x00000008, - 0x463, 0x00000003, - 0x4C8, 0x000000FF, - 0x4C9, 0x00000008, - 0x4CC, 0x000000FF, - 0x4CD, 0x000000FF, - 0x4CE, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000A2, - 0x502, 0x0000002F, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000A3, - 0x506, 0x0000005E, - 0x507, 0x00000000, - 0x508, 0x0000002B, - 0x509, 0x000000A4, - 0x50A, 0x0000005E, - 0x50B, 0x00000000, - 0x50C, 0x0000004F, - 0x50D, 0x000000A4, - 0x50E, 0x00000000, - 0x50F, 0x00000000, - 0x512, 0x0000001C, - 0x514, 0x0000000A, - 0x515, 0x00000010, - 0x516, 0x0000000A, - 0x517, 0x00000010, - 0x51A, 0x00000016, - 0x524, 0x0000000F, - 0x525, 0x0000004F, - 0x546, 0x00000040, - 0x547, 0x00000000, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55A, 0x00000002, - 0x55D, 0x000000FF, - 0x605, 0x00000030, - 0x608, 0x0000000E, - 0x609, 0x0000002A, - 0x652, 0x00000020, - 0x63C, 0x0000000A, - 0x63D, 0x0000000A, - 0x63E, 0x0000000E, - 0x63F, 0x0000000E, - 0x66E, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70A, 0x00000065, - 0x70B, 0x00000087, -}; - -void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm) -{ - #define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; v1 = Array[i]; v2 = Array[i+1]; \ - } while (0) - - u32 hex = 0; - u32 i = 0; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_MAC_REG_8723A); - u32 *Array = Array_MAC_REG_8723A; - - hex += board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c deleted file mode 100644 index 286f3ea3d263..000000000000 --- a/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c +++ /dev/null @@ -1,259 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. 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 for -* more details. -* -******************************************************************************/ - -#include "odm_precomp.h" - -static bool CheckCondition(const u32 Condition, const u32 Hex) -{ - u32 _board = (Hex & 0x000000FF); - u32 _interface = (Hex & 0x0000FF00) >> 8; - u32 _platform = (Hex & 0x00FF0000) >> 16; - u32 cond = Condition; - - if (Condition == 0xCDCDCDCD) - return true; - - cond = Condition & 0x000000FF; - if ((_board == cond) && cond != 0x00) - return false; - - cond = Condition & 0x0000FF00; - cond >>= 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = Condition & 0x00FF0000; - cond >>= 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* RadioA_1T.TXT -******************************************************************************/ - -static u32 Array_RadioA_1T_8723A[] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0xFF0F011F, 0xABCD, - 0x003, 0x00018C63, - 0xCDCDCDCD, 0xCDCD, - 0x003, 0x00039C63, - 0xFF0F011F, 0xDEAD, - 0x004, 0x000210E7, - 0x009, 0x0002044F, - 0x00A, 0x0001A3F1, - 0x00B, 0x00014787, - 0x00C, 0x000896FE, - 0x00D, 0x0000E02C, - 0x00E, 0x00039CE7, - 0x00F, 0x00000451, - 0x019, 0x00000000, - 0x01A, 0x00030355, - 0x01B, 0x00060A00, - 0x01C, 0x000FC378, - 0x01D, 0x000A1250, - 0x01E, 0x0000024F, - 0x01F, 0x00000000, - 0x020, 0x0000B614, - 0x021, 0x0006C000, - 0x022, 0x00000000, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00000483, - 0x026, 0x0004F000, - 0x027, 0x000EC7D9, - 0x028, 0x00057730, - 0x029, 0x00004783, - 0x02A, 0x00000001, - 0x02B, 0x00021334, - 0x02A, 0x00000000, - 0x02B, 0x00000054, - 0x02A, 0x00000001, - 0x02B, 0x00000808, - 0x02B, 0x00053333, - 0x02C, 0x0000000C, - 0x02A, 0x00000002, - 0x02B, 0x00000808, - 0x02B, 0x0005B333, - 0x02C, 0x0000000D, - 0x02A, 0x00000003, - 0x02B, 0x00000808, - 0x02B, 0x00063333, - 0x02C, 0x0000000D, - 0x02A, 0x00000004, - 0x02B, 0x00000808, - 0x02B, 0x0006B333, - 0x02C, 0x0000000D, - 0x02A, 0x00000005, - 0x02B, 0x00000808, - 0x02B, 0x00073333, - 0x02C, 0x0000000D, - 0x02A, 0x00000006, - 0x02B, 0x00000709, - 0x02B, 0x0005B333, - 0x02C, 0x0000000D, - 0x02A, 0x00000007, - 0x02B, 0x00000709, - 0x02B, 0x00063333, - 0x02C, 0x0000000D, - 0x02A, 0x00000008, - 0x02B, 0x0000060A, - 0x02B, 0x0004B333, - 0x02C, 0x0000000D, - 0x02A, 0x00000009, - 0x02B, 0x0000060A, - 0x02B, 0x00053333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000A, - 0x02B, 0x0000060A, - 0x02B, 0x0005B333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000B, - 0x02B, 0x0000060A, - 0x02B, 0x00063333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000C, - 0x02B, 0x0000060A, - 0x02B, 0x0006B333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000D, - 0x02B, 0x0000060A, - 0x02B, 0x00073333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000E, - 0x02B, 0x0000050B, - 0x02B, 0x00066666, - 0x02C, 0x0000001A, - 0x02A, 0x000E0000, - 0x010, 0x0004000F, - 0x011, 0x000E31FC, - 0x010, 0x0006000F, - 0x011, 0x000FF9F8, - 0x010, 0x0002000F, - 0x011, 0x000203F9, - 0x010, 0x0003000F, - 0x011, 0x000FF500, - 0x010, 0x00000000, - 0x011, 0x00000000, - 0x010, 0x0008000F, - 0x011, 0x0003F100, - 0x010, 0x0009000F, - 0x011, 0x00023100, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000B0000, - 0x012, 0x000FC000, - 0x013, 0x000287B3, - 0x013, 0x000244B7, - 0x013, 0x000204AB, - 0x013, 0x0001C49F, - 0x013, 0x00018493, - 0x013, 0x0001429B, - 0x013, 0x00010299, - 0x013, 0x0000C29C, - 0x013, 0x000081A0, - 0x013, 0x000040AC, - 0x013, 0x00000020, - 0x014, 0x0001944C, - 0x014, 0x00059444, - 0x014, 0x0009944C, - 0x014, 0x000D9444, - 0xFF0F011F, 0xABCD, - 0x015, 0x0000F424, - 0x015, 0x0004F424, - 0x015, 0x0008F424, - 0x015, 0x000CF424, - 0xCDCDCDCD, 0xCDCD, - 0x015, 0x0000F474, - 0x015, 0x0004F477, - 0x015, 0x0008F455, - 0x015, 0x000CF455, - 0xFF0F011F, 0xDEAD, - 0x016, 0x00000339, - 0x016, 0x00040339, - 0x016, 0x00080339, - 0xFF0F011F, 0xABCD, - 0x016, 0x000C0356, - 0xCDCDCDCD, 0xCDCD, - 0x016, 0x000C0366, - 0xFF0F011F, 0xDEAD, - 0x000, 0x00010159, - 0x018, 0x0000F401, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x01F, 0x00000003, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x01E, 0x00000247, - 0x01F, 0x00000000, - 0x000, 0x00030159, -}; - -void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *pDM_Odm) -{ - #define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; v1 = Array[i]; v2 = Array[i+1];\ - } while (0) - - u32 hex = 0; - u32 i = 0; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_RadioA_1T_8723A); - u32 *Array = Array_RadioA_1T_8723A; - - hex += board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigRFReg_8723A(pDM_Odm, v1, v2, RF_PATH_A, v1); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigRFReg_8723A(pDM_Odm, v1, v2, - RF_PATH_A, v1); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} diff --git a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c deleted file mode 100644 index 0a3d96e840cc..000000000000 --- a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c +++ /dev/null @@ -1,156 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -/*++ -Copyright (c) Realtek Semiconductor Corp. All rights reserved. - -Module Name: - HalPwrSeqCmd.c - -Abstract: - Implement HW Power sequence configuration CMD handling routine for - Realtek devices. - -Major Change History: - When Who What - ---------- --------------- ------------------------------- - 2011-10-26 Lucas Modify to be compatible with SD4-CE driver. - 2011-07-07 Roger Create. - ---*/ -#include -#include - -/* */ -/* Description: */ -/* This routine deal with the Power Configuration CMDs parsing - for RTL8723/RTL8188E Series IC. */ -/* */ -/* Assumption: */ -/* We should follow specific format which was released from - HW SD. */ -/* */ -/* 2011.07.07, added by Roger. */ -/* */ -u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion, - u8 FabVersion, u8 InterfaceType, - struct wlan_pwr_cfg PwrSeqCmd[]) -{ - struct wlan_pwr_cfg PwrCfgCmd; - u8 bPollingBit; - u32 AryIdx = 0; - u8 value; - u32 offset; - u32 pollingCount = 0; /* polling autoload done. */ - u32 maxPollingCnt = 5000; - - do { - PwrCfgCmd = PwrSeqCmd[AryIdx]; - - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: offset(%#x) cut_msk(%#x) fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) msk(%#x) value(%#x)\n", - GET_PWR_CFG_OFFSET(PwrCfgCmd), - GET_PWR_CFG_CUT_MASK(PwrCfgCmd), - GET_PWR_CFG_FAB_MASK(PwrCfgCmd), - GET_PWR_CFG_INTF_MASK(PwrCfgCmd), - GET_PWR_CFG_BASE(PwrCfgCmd), - GET_PWR_CFG_CMD(PwrCfgCmd), - GET_PWR_CFG_MASK(PwrCfgCmd), - GET_PWR_CFG_VALUE(PwrCfgCmd)); - - /* 2 Only Handle the command whose FAB, CUT, and Interface are - matched */ - if ((GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) && - (GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) && - (GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)) { - switch (GET_PWR_CFG_CMD(PwrCfgCmd)) { - case PWR_CMD_READ: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_READ\n"); - break; - - case PWR_CMD_WRITE: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_WRITE\n"); - offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); - - /* Read the value from system register */ - value = rtl8723au_read8(padapter, offset); - - value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd)); - value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) & - GET_PWR_CFG_MASK(PwrCfgCmd)); - - /* Write the value back to system register */ - rtl8723au_write8(padapter, offset, value); - break; - - case PWR_CMD_POLLING: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_POLLING\n"); - - bPollingBit = false; - offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); - do { - value = rtl8723au_read8(padapter, - offset); - - value &= GET_PWR_CFG_MASK(PwrCfgCmd); - if (value == - (GET_PWR_CFG_VALUE(PwrCfgCmd) & - GET_PWR_CFG_MASK(PwrCfgCmd))) - bPollingBit = true; - else - udelay(10); - - if (pollingCount++ > maxPollingCnt) { - DBG_8723A("Fail to polling " - "Offset[%#x]\n", - offset); - return false; - } - } while (!bPollingBit); - - break; - - case PWR_CMD_DELAY: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_DELAY\n"); - if (GET_PWR_CFG_VALUE(PwrCfgCmd) == - PWRSEQ_DELAY_US) - udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd)); - else - udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd) * - 1000); - break; - - case PWR_CMD_END: - /* When this command is parsed, end - the process */ - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_END\n"); - return true; - - default: - RT_TRACE(_module_hal_init_c_, _drv_err_, - "HalPwrSeqCmdParsing23a: Unknown CMD!!\n"); - break; - } - } - - AryIdx++; /* Add Array Index */ - } while (1); - - return true; -} diff --git a/drivers/staging/rtl8723au/hal/hal_com.c b/drivers/staging/rtl8723au/hal/hal_com.c deleted file mode 100644 index 9d7b11b63957..000000000000 --- a/drivers/staging/rtl8723au/hal/hal_com.c +++ /dev/null @@ -1,853 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#include -#include - -#include -#include -#include -#include - -#define _HAL_INIT_C_ - -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -/* return the final channel plan decision */ -/* hw_channel_plan: channel plan from HW (efuse/eeprom) */ -/* sw_channel_plan: channel plan from SW (registry/module param) */ -/* def_channel_plan: channel plan used when the former two is invalid */ -u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan, - u8 sw_channel_plan, u8 def_channel_plan, - bool AutoLoadFail) -{ - u8 swConfig; - u8 chnlPlan; - - swConfig = true; - if (!AutoLoadFail) { - if (!rtw_is_channel_plan_valid(sw_channel_plan)) - swConfig = false; - if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK) - swConfig = false; - } - - if (swConfig == true) - chnlPlan = sw_channel_plan; - else - chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK); - - if (!rtw_is_channel_plan_valid(chnlPlan)) - chnlPlan = def_channel_plan; - - return chnlPlan; -} - -u8 MRateToHwRate23a(u8 rate) -{ - u8 ret = DESC_RATE1M; - - switch (rate) { - /* CCK and OFDM non-HT rates */ - case IEEE80211_CCK_RATE_1MB: - ret = DESC_RATE1M; - break; - case IEEE80211_CCK_RATE_2MB: - ret = DESC_RATE2M; - break; - case IEEE80211_CCK_RATE_5MB: - ret = DESC_RATE5_5M; - break; - case IEEE80211_CCK_RATE_11MB: - ret = DESC_RATE11M; - break; - case IEEE80211_OFDM_RATE_6MB: - ret = DESC_RATE6M; - break; - case IEEE80211_OFDM_RATE_9MB: - ret = DESC_RATE9M; - break; - case IEEE80211_OFDM_RATE_12MB: - ret = DESC_RATE12M; - break; - case IEEE80211_OFDM_RATE_18MB: - ret = DESC_RATE18M; - break; - case IEEE80211_OFDM_RATE_24MB: - ret = DESC_RATE24M; - break; - case IEEE80211_OFDM_RATE_36MB: - ret = DESC_RATE36M; - break; - case IEEE80211_OFDM_RATE_48MB: - ret = DESC_RATE48M; - break; - case IEEE80211_OFDM_RATE_54MB: - ret = DESC_RATE54M; - break; - - /* HT rates since here */ - /* case MGN_MCS0: ret = DESC_RATEMCS0; break; */ - /* case MGN_MCS1: ret = DESC_RATEMCS1; break; */ - /* case MGN_MCS2: ret = DESC_RATEMCS2; break; */ - /* case MGN_MCS3: ret = DESC_RATEMCS3; break; */ - /* case MGN_MCS4: ret = DESC_RATEMCS4; break; */ - /* case MGN_MCS5: ret = DESC_RATEMCS5; break; */ - /* case MGN_MCS6: ret = DESC_RATEMCS6; break; */ - /* case MGN_MCS7: ret = DESC_RATEMCS7; break; */ - - default: - break; - } - return ret; -} - -void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 i, is_brate, brate; - u16 brate_cfg = 0; - u8 rate_index; - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK; - brate = mBratesOS[i] & 0x7f; - - if (is_brate) { - switch (brate) { - case IEEE80211_CCK_RATE_1MB: - brate_cfg |= RATE_1M; - break; - case IEEE80211_CCK_RATE_2MB: - brate_cfg |= RATE_2M; - break; - case IEEE80211_CCK_RATE_5MB: - brate_cfg |= RATE_5_5M; - break; - case IEEE80211_CCK_RATE_11MB: - brate_cfg |= RATE_11M; - break; - case IEEE80211_OFDM_RATE_6MB: - brate_cfg |= RATE_6M; - break; - case IEEE80211_OFDM_RATE_9MB: - brate_cfg |= RATE_9M; - break; - case IEEE80211_OFDM_RATE_12MB: - brate_cfg |= RATE_12M; - break; - case IEEE80211_OFDM_RATE_18MB: - brate_cfg |= RATE_18M; - break; - case IEEE80211_OFDM_RATE_24MB: - brate_cfg |= RATE_24M; - break; - case IEEE80211_OFDM_RATE_36MB: - brate_cfg |= RATE_36M; - break; - case IEEE80211_OFDM_RATE_48MB: - brate_cfg |= RATE_48M; - break; - case IEEE80211_OFDM_RATE_54MB: - brate_cfg |= RATE_54M; - break; - } - } - } - - /* 2007.01.16, by Emily */ - /* Select RRSR (in Legacy-OFDM and CCK) */ - /* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, - and 1M from the Basic rate. */ - /* We do not use other rates. */ - /* 2011.03.30 add by Luke Lee */ - /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */ - /* because CCK 2M has poor TXEVM */ - /* CCK 5.5M & 11M ACK should be enabled for better - performance */ - - brate_cfg = (brate_cfg | 0xd) & 0x15d; - pHalData->BasicRateSet = brate_cfg; - brate_cfg |= 0x01; /* default enable 1M ACK rate */ - DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg); - - /* Set RRSR rate table. */ - rtl8723au_write8(padapter, REG_RRSR, brate_cfg & 0xff); - rtl8723au_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff); - rtl8723au_write8(padapter, REG_RRSR + 2, - rtl8723au_read8(padapter, REG_RRSR + 2) & 0xf0); - - rate_index = 0; - /* Set RTS initial rate */ - while (brate_cfg > 0x1) { - brate_cfg >>= 1; - rate_index++; - } - /* Ziv - Check */ - rtl8723au_write8(padapter, REG_INIRTS_RATE_SEL, rate_index); -} - -static void _OneOutPipeMapping(struct rtw_adapter *pAdapter) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); - - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD */ -} - -static void _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); - - if (bWIFICfg) { /* WMM */ - /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ - /* 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */ - /* 0:H, 1:L */ - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ - } else { /* typical setting */ - /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ - /* 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */ - /* 0:H, 1:L */ - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ - } -} - -static void _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); - - if (bWIFICfg) { /* for WMM */ - /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ - /* 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */ - /* 0:H, 1:N, 2:L */ - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ - } else { /* typical setting */ - /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ - /* 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */ - /* 0:H, 1:N, 2:L */ - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ - } -} - -bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe) -{ - struct registry_priv *pregistrypriv = &pAdapter->registrypriv; - bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false; - bool result = true; - - switch (NumOutPipe) { - case 2: - _TwoOutPipeMapping(pAdapter, bWIFICfg); - break; - case 3: - _ThreeOutPipeMapping(pAdapter, bWIFICfg); - break; - case 1: - _OneOutPipeMapping(pAdapter); - break; - default: - result = false; - break; - } - - return result; -} - -/* -* C2H event format: -* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID -* BITS [127:120] [119:16] [15:8] [7:4] [3:0] -*/ - -void c2h_evt_clear23a(struct rtw_adapter *adapter) -{ - rtl8723au_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); -} - -int c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf) -{ - int ret = _FAIL; - struct c2h_evt_hdr *c2h_evt; - int i; - u8 trigger; - - if (buf == NULL) - goto exit; - - trigger = rtl8723au_read8(adapter, REG_C2HEVT_CLEAR); - - if (trigger == C2H_EVT_HOST_CLOSE) - goto exit; /* Not ready */ - if (trigger != C2H_EVT_FW_CLOSE) - goto clear_evt; /* Not a valid value */ - - c2h_evt = (struct c2h_evt_hdr *)buf; - - memset(c2h_evt, 0, 16); - - *buf = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL); - *(buf + 1) = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1); - - RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read23a(): ", - &c2h_evt, sizeof(c2h_evt)); - - if (0) { - DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n", - __func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq, - trigger); - } - - /* Read the content */ - for (i = 0; i < c2h_evt->plen; i++) - c2h_evt->payload[i] = rtl8723au_read8(adapter, - REG_C2HEVT_MSG_NORMAL + - sizeof(*c2h_evt) + i); - - RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, - "c2h_evt_read23a(): Command Content:\n", c2h_evt->payload, - c2h_evt->plen); - - ret = _SUCCESS; - -clear_evt: - /* - * Clear event to notify FW we have read the command. - * If this field isn't clear, the FW won't update the - * next command message. - */ - c2h_evt_clear23a(adapter); -exit: - return ret; -} - -void -rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet) -{ - u8 SecMinSpace; - - if (MinSpacingToSet <= 7) { - switch (padapter->securitypriv.dot11PrivacyAlgrthm) { - case 0: - case WLAN_CIPHER_SUITE_CCMP: - SecMinSpace = 0; - break; - - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SecMinSpace = 6; - break; - default: - SecMinSpace = 7; - break; - } - - if (MinSpacingToSet < SecMinSpace) - MinSpacingToSet = SecMinSpace; - - MinSpacingToSet |= - rtl8723au_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8; - rtl8723au_write8(padapter, REG_AMPDU_MIN_SPACE, - MinSpacingToSet); - } -} - -void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet) -{ - u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; - u8 MaxAggNum; - u8 *pRegToSet; - u8 index = 0; - - pRegToSet = RegToSet_Normal; /* 0xb972a841; */ - - if (rtl8723a_BT_enabled(padapter) && - rtl8723a_BT_using_antenna_1(padapter)) - MaxAggNum = 0x8; - else - MaxAggNum = 0xF; - - if (FactorToSet <= 3) { - FactorToSet = 1 << (FactorToSet + 2); - if (FactorToSet > MaxAggNum) - FactorToSet = MaxAggNum; - - for (index = 0; index < 4; index++) { - if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4)) - pRegToSet[index] = (pRegToSet[index] & 0x0f) | - (FactorToSet << 4); - - if ((pRegToSet[index] & 0x0f) > FactorToSet) - pRegToSet[index] = (pRegToSet[index] & 0xf0) | - FactorToSet; - - rtl8723au_write8(padapter, REG_AGGLEN_LMT + index, - pRegToSet[index]); - } - } -} - -void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl) -{ - u8 hwctrl = 0; - - if (ctrl != 0) { - hwctrl |= AcmHw_HwEn; - - if (ctrl & BIT(1)) /* BE */ - hwctrl |= AcmHw_BeqEn; - - if (ctrl & BIT(2)) /* VI */ - hwctrl |= AcmHw_ViqEn; - - if (ctrl & BIT(3)) /* VO */ - hwctrl |= AcmHw_VoqEn; - } - - DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl); - rtl8723au_write8(padapter, REG_ACMHWCTRL, hwctrl); -} - -void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status) -{ - u8 val8; - - val8 = rtl8723au_read8(padapter, MSR) & 0x0c; - val8 |= status; - rtl8723au_write8(padapter, MSR, val8); -} - -void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status) -{ - u8 val8; - - val8 = rtl8723au_read8(padapter, MSR) & 0x03; - val8 |= status << 2; - rtl8723au_write8(padapter, MSR, val8); -} - -void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val) -{ - if (val) - SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0); - else - SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT); -} - -void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val) -{ - u32 val32; - - val32 = rtl8723au_read32(padapter, REG_RCR); - if (val) - val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN; - else - val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtl8723au_write32(padapter, REG_RCR, val32); -} - -void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag) -{ - if (flag) { /* under sitesurvey */ - u32 v32; - - /* config RCR to receive different BSSID & not - to receive data frame */ - v32 = rtl8723au_read32(padapter, REG_RCR); - v32 &= ~(RCR_CBSSID_BCN); - rtl8723au_write32(padapter, REG_RCR, v32); - /* reject all data frame */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0); - - /* disable update TSF */ - SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0); - } else { /* sitesurvey done */ - - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo; - u32 v32; - - pmlmeinfo = &pmlmeext->mlmext_info; - - if ((is_client_associated_to_ap23a(padapter) == true) || - ((pmlmeinfo->state & 0x03) == MSR_ADHOC) || - ((pmlmeinfo->state & 0x03) == MSR_AP)) { - /* enable to rx data frame */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF); - - /* enable update TSF */ - SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT); - } - - v32 = rtl8723au_read32(padapter, REG_RCR); - v32 |= RCR_CBSSID_BCN; - rtl8723au_write32(padapter, REG_RCR, v32); - } - - rtl8723a_BT_wifiscan_notify(padapter, flag ? true : false); -} - -void rtl8723a_on_rcr_am(struct rtw_adapter *padapter) -{ - rtl8723au_write32(padapter, REG_RCR, - rtl8723au_read32(padapter, REG_RCR) | RCR_AM); - DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__, - rtl8723au_read32(padapter, REG_RCR)); -} - -void rtl8723a_off_rcr_am(struct rtw_adapter *padapter) -{ - rtl8723au_write32(padapter, REG_RCR, - rtl8723au_read32(padapter, REG_RCR) & (~RCR_AM)); - DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__, - rtl8723au_read32(padapter, REG_RCR)); -} - -void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime) -{ - u8 u1bAIFS, aSifsTime; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - rtl8723au_write8(padapter, REG_SLOT, slottime); - - if (pmlmeinfo->WMM_enable == 0) { - if (pmlmeext->cur_wireless_mode == WIRELESS_11B) - aSifsTime = 10; - else - aSifsTime = 16; - - u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime); - - /* Temporary removed, 2008.06.20. */ - rtl8723au_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS); - rtl8723au_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS); - rtl8723au_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS); - rtl8723au_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS); - } -} - -void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 regTmp; - - /* Joseph marked out for Netgear 3500 TKIP - channel 7 issue.(Temporarily) */ - regTmp = (pHalData->nCur40MhzPrimeSC) << 5; - /* regTmp = 0; */ - if (bShortPreamble) - regTmp |= 0x80; - rtl8723au_write8(padapter, REG_RRSR + 2, regTmp); -} - -void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec) -{ - rtl8723au_write8(padapter, REG_SECCFG, sec); -} - -void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex) -{ - u8 i; - u32 ulCommand = 0; - u32 ulContent = 0; - u32 ulEncAlgo = CAM_AES; - - 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 |= CAM_VALID; */ - } else { - ulContent = 0; - } - /* polling bit, and No Write enable, and address */ - ulCommand = CAM_CONTENT_COUNT * ucIndex + i; - ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; - /* write content 0 is equall to mark invalid */ - /* delay_ms(40); */ - rtl8723au_write32(padapter, WCAMI, ulContent); - /* delay_ms(40); */ - rtl8723au_write32(padapter, REG_CAMCMD, ulCommand); - } -} - -void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter) -{ - rtl8723au_write32(padapter, REG_CAMCMD, CAM_POLLINIG | BIT(30)); -} - -void rtl8723a_cam_write(struct rtw_adapter *padapter, - u8 entry, u16 ctrl, const u8 *mac, const u8 *key) -{ - u32 cmd; - unsigned int i, val, addr; - int j; - - addr = entry << 3; - - for (j = 5; j >= 0; j--) { - switch (j) { - case 0: - val = ctrl | (mac[0] << 16) | (mac[1] << 24); - break; - case 1: - val = mac[2] | (mac[3] << 8) | - (mac[4] << 16) | (mac[5] << 24); - break; - default: - i = (j - 2) << 2; - val = key[i] | (key[i+1] << 8) | - (key[i+2] << 16) | (key[i+3] << 24); - break; - } - - rtl8723au_write32(padapter, WCAMI, val); - cmd = CAM_POLLINIG | CAM_WRITE | (addr + j); - rtl8723au_write32(padapter, REG_CAMCMD, cmd); - - /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/ - } -} - -void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter) -{ -#define RW_RELEASE_EN BIT(18) -#define RXDMA_IDLE BIT(17) - - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - u8 trycnt = 100; - - /* pause tx */ - rtl8723au_write8(padapter, REG_TXPAUSE, 0xff); - - /* keep sn */ - padapter->xmitpriv.nqos_ssn = rtl8723au_read8(padapter, REG_NQOS_SEQ); - - if (pwrpriv->bkeepfwalive != true) { - u32 v32; - - /* RX DMA stop */ - v32 = rtl8723au_read32(padapter, REG_RXPKT_NUM); - v32 |= RW_RELEASE_EN; - rtl8723au_write32(padapter, REG_RXPKT_NUM, v32); - do { - v32 = rtl8723au_read32(padapter, - REG_RXPKT_NUM) & RXDMA_IDLE; - if (!v32) - break; - } while (trycnt--); - if (trycnt == 0) - DBG_8723A("Stop RX DMA failed......\n"); - - /* RQPN Load 0 */ - rtl8723au_write16(padapter, REG_RQPN_NPQ, 0); - rtl8723au_write32(padapter, REG_RQPN, 0x80000000); - mdelay(10); - } -} - -void rtl8723a_bcn_valid(struct rtw_adapter *padapter) -{ - /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, - write 1 to clear, Clear by sw */ - rtl8723au_write8(padapter, REG_TDECTRL + 2, - rtl8723au_read8(padapter, REG_TDECTRL + 2) | BIT(0)); -} - -bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter) -{ - bool retval; - - retval = (rtl8723au_read8(padapter, REG_TDECTRL + 2) & BIT(0)) ? true : false; - - return retval; -} - -void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval) -{ - rtl8723au_write16(padapter, REG_BCN_INTERVAL, interval); -} - -void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter, - u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2) -{ - /* SIFS_Timer = 0x0a0a0808; */ - /* RESP_SIFS for CCK */ - /* SIFS_T2T_CCK (0x08) */ - rtl8723au_write8(padapter, REG_R2T_SIFS, r2t1); - /* SIFS_R2T_CCK(0x08) */ - rtl8723au_write8(padapter, REG_R2T_SIFS + 1, r2t2); - /* RESP_SIFS for OFDM */ - /* SIFS_T2T_OFDM (0x0a) */ - rtl8723au_write8(padapter, REG_T2T_SIFS, t2t1); - /* SIFS_R2T_OFDM(0x0a) */ - rtl8723au_write8(padapter, REG_T2T_SIFS + 1, t2t2); -} - -void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo) -{ - rtl8723au_write32(padapter, REG_EDCA_VO_PARAM, vo); -} - -void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi) -{ - rtl8723au_write32(padapter, REG_EDCA_VI_PARAM, vi); -} - -void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->AcParam_BE = be; - rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, be); -} - -void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk) -{ - rtl8723au_write32(padapter, REG_EDCA_BK_PARAM, bk); -} - -void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val) -{ - rtl8723au_write8(padapter, REG_RXDMA_AGG_PG_TH, val); -} - -void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable; - - if (rx_gain == 0xff) /* restore rx gain */ - ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue); - else { - pDigTable->BackupIGValue = pDigTable->CurIGValue; - ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain); - } -} - -void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->odmpriv.SupportAbility = pHalData->odmpriv.BK_SupportAbility; -} - -void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->odmpriv.BK_SupportAbility = pHalData->odmpriv.SupportAbility; -} - -void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (val == DYNAMIC_ALL_FUNC_ENABLE) - pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag; - else - pHalData->odmpriv.SupportAbility |= val; -} - -void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->odmpriv.SupportAbility &= val; -} - -void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val) -{ - rtl8723au_write8(padapter, REG_USB_HRPWM, val); -} - -u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - return pHalData->rf_type; -} - -bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter) -{ - bool retval; - u32 valRCR; - - /* When we halt NIC, we should check if FW LPS is leave. */ - - if ((padapter->bSurpriseRemoved == true) || - (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) { - /* If it is in HW/SW Radio OFF or IPS state, we do - not check Fw LPS Leave, because Fw is unload. */ - retval = true; - } else { - valRCR = rtl8723au_read32(padapter, REG_RCR); - if (valRCR & 0x00070000) - retval = false; - else - retval = true; - } - - return retval; -} - -bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter) -{ - u32 hgq; - - hgq = rtl8723au_read32(padapter, REG_HGQ_INFORMATION); - - return ((hgq & 0x0000ff00) == 0) ? true : false; -} diff --git a/drivers/staging/rtl8723au/hal/hal_intf.c b/drivers/staging/rtl8723au/hal/hal_intf.c deleted file mode 100644 index 5383e692546f..000000000000 --- a/drivers/staging/rtl8723au/hal/hal_intf.c +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#define _HAL_INTF_C_ -#include -#include - -#include - -#include - -void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level) -{ - struct rtw_adapter *padapter; - struct mlme_priv *pmlmepriv; - - if (!psta) - return; - - padapter = psta->padapter; - - pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { -#ifdef CONFIG_8723AU_AP_MODE - add_RATid23a(padapter, psta, rssi_level); -#endif - } else - rtl8723a_update_ramask(padapter, psta->mac_id, rssi_level); -} diff --git a/drivers/staging/rtl8723au/hal/odm.c b/drivers/staging/rtl8723au/hal/odm.c deleted file mode 100644 index e279c34b3fc6..000000000000 --- a/drivers/staging/rtl8723au/hal/odm.c +++ /dev/null @@ -1,1732 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#include "odm_precomp.h" -#include "usb_ops_linux.h" - -static const u16 dB_Invert_Table[8][12] = { - {1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4}, - {4, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16}, - {18, 20, 22, 25, 28, 32, 35, 40, 45, 50, 56, 63}, - {71, 79, 89, 100, 112, 126, 141, 158, 178, 200, 224, 251}, - {282, 316, 355, 398, 447, 501, 562, 631, 708, 794, 891, 1000}, - {1122, 1259, 1413, 1585, 1778, 1995, 2239, 2512, 2818, 3162, 3548, 3981}, - {4467, 5012, 5623, 6310, 7079, 7943, 8913, 10000, 11220, 12589, 14125, 15849}, - {17783, 19953, 22387, 25119, 28184, 31623, 35481, 39811, 44668, 50119, 56234, 65535} -}; - -static u32 EDCAParam[HT_IOT_PEER_MAX][3] = { /* UL DL */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */ - {0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */ - {0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */ - {0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */ - {0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */ - {0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */ - {0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP => 92U AP */ - {0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */ -}; - -/* EDCA Parameter for AP/ADSL by Mingzhi 2011-11-22 */ - -/* Global var */ -u32 OFDMSwingTable23A[OFDM_TABLE_SIZE_92D] = { - 0x7f8001fe, /* 0, +6.0dB */ - 0x788001e2, /* 1, +5.5dB */ - 0x71c001c7, /* 2, +5.0dB */ - 0x6b8001ae, /* 3, +4.5dB */ - 0x65400195, /* 4, +4.0dB */ - 0x5fc0017f, /* 5, +3.5dB */ - 0x5a400169, /* 6, +3.0dB */ - 0x55400155, /* 7, +2.5dB */ - 0x50800142, /* 8, +2.0dB */ - 0x4c000130, /* 9, +1.5dB */ - 0x47c0011f, /* 10, +1.0dB */ - 0x43c0010f, /* 11, +0.5dB */ - 0x40000100, /* 12, +0dB */ - 0x3c8000f2, /* 13, -0.5dB */ - 0x390000e4, /* 14, -1.0dB */ - 0x35c000d7, /* 15, -1.5dB */ - 0x32c000cb, /* 16, -2.0dB */ - 0x300000c0, /* 17, -2.5dB */ - 0x2d4000b5, /* 18, -3.0dB */ - 0x2ac000ab, /* 19, -3.5dB */ - 0x288000a2, /* 20, -4.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x24000090, /* 22, -5.0dB */ - 0x22000088, /* 23, -5.5dB */ - 0x20000080, /* 24, -6.0dB */ - 0x1e400079, /* 25, -6.5dB */ - 0x1c800072, /* 26, -7.0dB */ - 0x1b00006c, /* 27. -7.5dB */ - 0x19800066, /* 28, -8.0dB */ - 0x18000060, /* 29, -8.5dB */ - 0x16c0005b, /* 30, -9.0dB */ - 0x15800056, /* 31, -9.5dB */ - 0x14400051, /* 32, -10.0dB */ - 0x1300004c, /* 33, -10.5dB */ - 0x12000048, /* 34, -11.0dB */ - 0x11000044, /* 35, -11.5dB */ - 0x10000040, /* 36, -12.0dB */ - 0x0f00003c,/* 37, -12.5dB */ - 0x0e400039,/* 38, -13.0dB */ - 0x0d800036,/* 39, -13.5dB */ - 0x0cc00033,/* 40, -14.0dB */ - 0x0c000030,/* 41, -14.5dB */ - 0x0b40002d,/* 42, -15.0dB */ -}; - -u8 CCKSwingTable_Ch1_Ch1323A[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ -}; - -u8 CCKSwingTable_Ch1423A[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */ -}; - -/* Local Function predefine. */ - -/* START------------COMMON INFO RELATED--------------- */ -void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm); - -static void odm_CommonInfoSelfUpdate(struct hal_data_8723a *pHalData); - -void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm); - -void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm); - -/* START---------------DIG--------------------------- */ -void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm); - -void odm_DIG23aInit(struct dm_odm_t *pDM_Odm); - -void odm_DIG23a(struct rtw_adapter *adapter); - -void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm); -/* END---------------DIG--------------------------- */ - -/* START-------BB POWER SAVE----------------------- */ -void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm); - - -/* END---------BB POWER SAVE----------------------- */ - -void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm); - -static void odm_RSSIMonitorCheck(struct dm_odm_t *pDM_Odm); -void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm); - -static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm); - -void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm); - -static void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm); - -static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm); -static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm); - -#define RxDefaultAnt1 0x65a9 -#define RxDefaultAnt2 0x569a - -bool odm_StaDefAntSel(struct dm_odm_t *pDM_Odm, - u32 OFDM_Ant1_Cnt, - u32 OFDM_Ant2_Cnt, - u32 CCK_Ant1_Cnt, - u32 CCK_Ant2_Cnt, - u8 *pDefAnt - ); - -void odm_SetRxIdleAnt(struct dm_odm_t *pDM_Odm, - u8 Ant, - bool bDualPath -); - -/* 3 Export Interface */ - -/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */ -void ODM23a_DMInit(struct dm_odm_t *pDM_Odm) -{ - /* For all IC series */ - odm_CommonInfoSelfInit23a(pDM_Odm); - odm_CmnInfoInit_Debug23a(pDM_Odm); - odm_DIG23aInit(pDM_Odm); - odm_RateAdaptiveMaskInit23a(pDM_Odm); - - odm23a_DynBBPSInit(pDM_Odm); - odm_DynamicTxPower23aInit(pDM_Odm); - odm_TXPowerTrackingInit(pDM_Odm); - ODM_EdcaTurboInit23a(pDM_Odm); -} - -/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */ -/* You can not add any dummy function here, be care, you can only use DM structure */ -/* to perform any new ODM_DM. */ -void ODM_DMWatchdog23a(struct rtw_adapter *adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(adapter); - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct pwrctrl_priv *pwrctrlpriv = &adapter->pwrctrlpriv; - - /* 2012.05.03 Luke: For all IC series */ - odm_CmnInfoUpdate_Debug23a(pDM_Odm); - odm_CommonInfoSelfUpdate(pHalData); - odm_FalseAlarmCounterStatistics23a(pDM_Odm); - odm_RSSIMonitorCheck(pDM_Odm); - - /* 8723A or 8189ES platform */ - /* NeilChen--2012--08--24-- */ - /* Fix Leave LPS issue */ - if ((pDM_Odm->Adapter->pwrctrlpriv.pwr_mode != PS_MODE_ACTIVE) &&/* in LPS mode */ - (pDM_Odm->SupportICType & ODM_RTL8723A)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("----Step1: odm_DIG23a is in LPS mode\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Step2: 8723AS is in LPS mode\n")); - odm_DIG23abyRSSI_LPS(pDM_Odm); - } else { - odm_DIG23a(adapter); - } - - odm_CCKPacketDetectionThresh23a(pDM_Odm); - - if (pwrctrlpriv->bpower_saving) - return; - - odm_RefreshRateAdaptiveMask(pDM_Odm); - - - odm_EdcaTurboCheck23a(pDM_Odm); -} - -/* */ -/* Init /.. Fixed HW value. Only init time. */ -/* */ -void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm, - enum odm_cmninfo CmnInfo, - u32 Value - ) -{ - /* ODM_RT_TRACE(pDM_Odm,); */ - - /* */ - /* This section is used for init value */ - /* */ - switch (CmnInfo) { - /* Fixed ODM value. */ - case ODM_CMNINFO_MP_TEST_CHIP: - pDM_Odm->bIsMPChip = (u8)Value; - break; - case ODM_CMNINFO_IC_TYPE: - pDM_Odm->SupportICType = Value; - break; - case ODM_CMNINFO_CUT_VER: - pDM_Odm->CutVersion = (u8)Value; - break; - case ODM_CMNINFO_FAB_VER: - pDM_Odm->FabVersion = (u8)Value; - break; - case ODM_CMNINFO_BOARD_TYPE: - pDM_Odm->BoardType = (u8)Value; - break; - case ODM_CMNINFO_EXT_LNA: - pDM_Odm->ExtLNA = (u8)Value; - break; - case ODM_CMNINFO_EXT_PA: - pDM_Odm->ExtPA = (u8)Value; - break; - case ODM_CMNINFO_EXT_TRSW: - pDM_Odm->ExtTRSW = (u8)Value; - break; - case ODM_CMNINFO_BINHCT_TEST: - pDM_Odm->bInHctTest = (bool)Value; - break; - case ODM_CMNINFO_BWIFI_TEST: - pDM_Odm->bWIFITest = (bool)Value; - break; - case ODM_CMNINFO_SMART_CONCURRENT: - pDM_Odm->bDualMacSmartConcurrent = (bool)Value; - break; - /* To remove the compiler warning, must add an empty default statement to handle the other values. */ - default: - /* do nothing */ - break; - } -} - -void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, - u16 Index, void *pValue) -{ - /* Hook call by reference pointer. */ - switch (CmnInfo) { - /* Dynamic call by reference pointer. */ - case ODM_CMNINFO_STA_STATUS: - pDM_Odm->pODM_StaInfo[Index] = (struct sta_info *)pValue; - break; - /* To remove the compiler warning, must add an empty default statement to handle the other values. */ - default: - /* do nothing */ - break; - } -} - -/* Update Band/CHannel/.. The values are dynamic but non-per-packet. */ -void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value) -{ - /* This init variable may be changed in run time. */ - switch (CmnInfo) { - case ODM_CMNINFO_WIFI_DIRECT: - pDM_Odm->bWIFI_Direct = (bool)Value; - break; - case ODM_CMNINFO_WIFI_DISPLAY: - pDM_Odm->bWIFI_Display = (bool)Value; - break; - case ODM_CMNINFO_LINK: - pDM_Odm->bLinked = (bool)Value; - break; - case ODM_CMNINFO_RSSI_MIN: - pDM_Odm->RSSI_Min = (u8)Value; - break; - case ODM_CMNINFO_DBG_COMP: - pDM_Odm->DebugComponents = Value; - break; - case ODM_CMNINFO_DBG_LEVEL: - pDM_Odm->DebugLevel = (u32)Value; - break; - case ODM_CMNINFO_RA_THRESHOLD_HIGH: - pDM_Odm->RateAdaptive.HighRSSIThresh = (u8)Value; - break; - case ODM_CMNINFO_RA_THRESHOLD_LOW: - pDM_Odm->RateAdaptive.LowRSSIThresh = (u8)Value; - break; - } - -} - -void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm) -{ - u32 val32; - - val32 = rtl8723au_read32(pDM_Odm->Adapter, rFPGA0_XA_HSSIParameter2); - if (val32 & BIT(9)) - pDM_Odm->bCckHighPower = true; - else - pDM_Odm->bCckHighPower = false; - - pDM_Odm->RFPathRxEnable = - rtl8723au_read32(pDM_Odm->Adapter, rOFDM0_TRxPathEnable) & 0x0F; - - ODM_InitDebugSetting23a(pDM_Odm); -} - -static void odm_CommonInfoSelfUpdate(struct hal_data_8723a *pHalData) -{ - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct sta_info *pEntry; - u8 EntryCnt = 0; - u8 i; - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - pEntry = pDM_Odm->pODM_StaInfo[i]; - if (pEntry) - EntryCnt++; - } - if (EntryCnt == 1) - pDM_Odm->bOneEntryOnly = true; - else - pDM_Odm->bOneEntryOnly = false; -} - -void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm) -{ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoInit_Debug23a ==>\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportAbility = 0x%x\n", pDM_Odm->SupportAbility)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportICType = 0x%x\n", pDM_Odm->SupportICType)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CutVersion =%d\n", pDM_Odm->CutVersion)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("FabVersion =%d\n", pDM_Odm->FabVersion)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("BoardType =%d\n", pDM_Odm->BoardType)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtLNA =%d\n", pDM_Odm->ExtLNA)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtPA =%d\n", pDM_Odm->ExtPA)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtTRSW =%d\n", pDM_Odm->ExtTRSW)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bInHctTest =%d\n", pDM_Odm->bInHctTest)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFITest =%d\n", pDM_Odm->bWIFITest)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bDualMacSmartConcurrent =%d\n", pDM_Odm->bDualMacSmartConcurrent)); - -} - -void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm) -{ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoUpdate_Debug23a ==>\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Direct =%d\n", pDM_Odm->bWIFI_Direct)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Display =%d\n", pDM_Odm->bWIFI_Display)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bLinked =%d\n", pDM_Odm->bLinked)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI_Min =%d\n", pDM_Odm->RSSI_Min)); -} - -void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm, u8 CurrentIGI) -{ - struct rtw_adapter *adapter = pDM_Odm->Adapter; - struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; - u32 val32; - - if (pDM_DigTable->CurIGValue != CurrentIGI) { - val32 = rtl8723au_read32(adapter, ODM_REG_IGI_A_11N); - val32 &= ~ODM_BIT_IGI_11N; - val32 |= CurrentIGI; - rtl8723au_write32(adapter, ODM_REG_IGI_A_11N, val32); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("CurrentIGI(0x%02x). \n", CurrentIGI)); - pDM_DigTable->CurIGValue = CurrentIGI; - } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("ODM_Write_DIG23a():CurrentIGI = 0x%x \n", CurrentIGI)); -} - -/* Need LPS mode for CE platform --2012--08--24--- */ -/* 8723AS/8189ES */ -void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *pAdapter = pDM_Odm->Adapter; - struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u8 RSSI_Lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */ - u8 bFwCurrentInPSMode = false; - u8 CurrentIGI = pDM_Odm->RSSI_Min; - - if (!(pDM_Odm->SupportICType & ODM_RTL8723A)) - return; - - CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG; - bFwCurrentInPSMode = pAdapter->pwrctrlpriv.bFwCurrentInPSMode; - - /* Using FW PS mode to make IGI */ - if (bFwCurrentInPSMode) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("---Neil---odm_DIG23a is in LPS mode\n")); - /* Adjust by FA in LPS MODE */ - if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS) - CurrentIGI = CurrentIGI+2; - else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS) - CurrentIGI = CurrentIGI+1; - else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS) - CurrentIGI = CurrentIGI-1; - } else { - CurrentIGI = RSSI_Lower; - } - - /* Lower bound checking */ - - /* RSSI Lower bound check */ - if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC) - RSSI_Lower = (pDM_Odm->RSSI_Min-10); - else - RSSI_Lower = DM_DIG_MIN_NIC; - - /* Upper and Lower Bound checking */ - if (CurrentIGI > DM_DIG_MAX_NIC) - CurrentIGI = DM_DIG_MAX_NIC; - else if (CurrentIGI < RSSI_Lower) - CurrentIGI = RSSI_Lower; - - ODM_Write_DIG23a(pDM_Odm, CurrentIGI); -} - -void odm_DIG23aInit(struct dm_odm_t *pDM_Odm) -{ - struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; - u32 val32; - - val32 = rtl8723au_read32(pDM_Odm->Adapter, ODM_REG_IGI_A_11N); - pDM_DigTable->CurIGValue = val32 & ODM_BIT_IGI_11N; - - pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW; - pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH; - pDM_DigTable->FALowThresh = DM_FALSEALARM_THRESH_LOW; - pDM_DigTable->FAHighThresh = DM_FALSEALARM_THRESH_HIGH; - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - } else { - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - } - pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT; - pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX; - pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN; - pDM_DigTable->PreCCK_CCAThres = 0xFF; - pDM_DigTable->CurCCK_CCAThres = 0x83; - pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC; - pDM_DigTable->LargeFAHit = 0; - pDM_DigTable->Recover_cnt = 0; - pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC; - pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC; - pDM_DigTable->bMediaConnect_0 = false; - pDM_DigTable->bMediaConnect_1 = false; -} - -void odm_DIG23a(struct rtw_adapter *adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(adapter); - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; - struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u8 DIG_Dynamic_MIN; - u8 DIG_MaxOfMin; - bool FirstConnect, FirstDisConnect; - u8 dm_dig_max, dm_dig_min; - u8 CurrentIGI = pDM_DigTable->CurIGValue; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a() ==>\n")); - if (adapter->mlmepriv.bScanInProcess) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a() Return: In Scan Progress \n")); - return; - } - - DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0; - FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0); - FirstDisConnect = (!pDM_Odm->bLinked) && - (pDM_DigTable->bMediaConnect_0); - - /* 1 Boundary Decision */ - if ((pDM_Odm->SupportICType & ODM_RTL8723A) && - (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR || pDM_Odm->ExtLNA)) { - dm_dig_max = DM_DIG_MAX_NIC_HP; - dm_dig_min = DM_DIG_MIN_NIC_HP; - DIG_MaxOfMin = DM_DIG_MAX_AP_HP; - } else { - dm_dig_max = DM_DIG_MAX_NIC; - dm_dig_min = DM_DIG_MIN_NIC; - DIG_MaxOfMin = DM_DIG_MAX_AP; - } - - if (pDM_Odm->bLinked) { - /* 2 8723A Series, offset need to be 10 */ - if (pDM_Odm->SupportICType == ODM_RTL8723A) { - /* 2 Upper Bound */ - if ((pDM_Odm->RSSI_Min + 10) > DM_DIG_MAX_NIC) - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - else if ((pDM_Odm->RSSI_Min + 10) < DM_DIG_MIN_NIC) - pDM_DigTable->rx_gain_range_max = DM_DIG_MIN_NIC; - else - pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 10; - - /* 2 If BT is Concurrent, need to set Lower Bound */ - DIG_Dynamic_MIN = DM_DIG_MIN_NIC; - } else { - /* 2 Modify DIG upper bound */ - if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max) - pDM_DigTable->rx_gain_range_max = dm_dig_max; - else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min) - pDM_DigTable->rx_gain_range_max = dm_dig_min; - else - pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20; - - /* 2 Modify DIG lower bound */ - if (pDM_Odm->bOneEntryOnly) { - if (pDM_Odm->RSSI_Min < dm_dig_min) - DIG_Dynamic_MIN = dm_dig_min; - else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin) - DIG_Dynamic_MIN = DIG_MaxOfMin; - else - DIG_Dynamic_MIN = pDM_Odm->RSSI_Min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a() : bOneEntryOnly = true, DIG_Dynamic_MIN = 0x%x\n", - DIG_Dynamic_MIN)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a() : pDM_Odm->RSSI_Min =%d\n", - pDM_Odm->RSSI_Min)); - } else { - DIG_Dynamic_MIN = dm_dig_min; - } - } - } else { - pDM_DigTable->rx_gain_range_max = dm_dig_max; - DIG_Dynamic_MIN = dm_dig_min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() : No Link\n")); - } - - /* 1 Modify DIG lower bound, deal with abnormally large false alarm */ - if (pFalseAlmCnt->Cnt_all > 10000) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("dm_DIG(): Abnornally false alarm case. \n")); - - if (pDM_DigTable->LargeFAHit != 3) - pDM_DigTable->LargeFAHit++; - if (pDM_DigTable->ForbiddenIGI < CurrentIGI) { - pDM_DigTable->ForbiddenIGI = CurrentIGI; - pDM_DigTable->LargeFAHit = 1; - } - - if (pDM_DigTable->LargeFAHit >= 3) { - if ((pDM_DigTable->ForbiddenIGI+1) > pDM_DigTable->rx_gain_range_max) - pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max; - else - pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1); - pDM_DigTable->Recover_cnt = 3600; /* 3600 = 2hr */ - } - } else { - /* Recovery mechanism for IGI lower bound */ - if (pDM_DigTable->Recover_cnt != 0) { - pDM_DigTable->Recover_cnt--; - } else { - if (pDM_DigTable->LargeFAHit < 3) { - if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_MIN) { - pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ - pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a(): Normal Case: At Lower Bound\n")); - } else { - pDM_DigTable->ForbiddenIGI--; - pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a(): Normal Case: Approach Lower Bound\n")); - } - } else { - pDM_DigTable->LargeFAHit = 0; - } - } - } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): pDM_DigTable->LargeFAHit =%d\n", pDM_DigTable->LargeFAHit)); - - /* 1 Adjust initial gain by false alarm */ - if (pDM_Odm->bLinked) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG AfterLink\n")); - if (FirstConnect) { - CurrentIGI = pDM_Odm->RSSI_Min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("DIG: First Connect\n")); - } else { - if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2) - CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */ - else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1) - CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */ - else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0) - CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue-1; */ - } - } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG BeforeLink\n")); - if (FirstDisConnect) { - CurrentIGI = pDM_DigTable->rx_gain_range_min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): First DisConnect \n")); - } else { - /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */ - if (pFalseAlmCnt->Cnt_all > 10000) - CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */ - else if (pFalseAlmCnt->Cnt_all > 8000) - CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */ - else if (pFalseAlmCnt->Cnt_all < 500) - CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue-1; */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): England DIG \n")); - } - } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG End Adjust IGI\n")); - /* 1 Check initial gain by upper/lower bound */ - if (CurrentIGI > pDM_DigTable->rx_gain_range_max) - CurrentIGI = pDM_DigTable->rx_gain_range_max; - if (CurrentIGI < pDM_DigTable->rx_gain_range_min) - CurrentIGI = pDM_DigTable->rx_gain_range_min; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): rx_gain_range_max = 0x%x, rx_gain_range_min = 0x%x\n", - pDM_DigTable->rx_gain_range_max, pDM_DigTable->rx_gain_range_min)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): TotalFA =%d\n", pFalseAlmCnt->Cnt_all)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): CurIGValue = 0x%x\n", CurrentIGI)); - - /* 2 High power RSSI threshold */ - - ODM_Write_DIG23a(pDM_Odm, CurrentIGI);/* ODM_Write_DIG23a(pDM_Odm, pDM_DigTable->CurIGValue); */ - pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; - pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; -} - -/* 3 ============================================================ */ -/* 3 FASLE ALARM CHECK */ -/* 3 ============================================================ */ - -void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *adapter = pDM_Odm->Adapter; - struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u32 ret_value, val32; - - /* hold ofdm counter */ - /* hold page C counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_HOLDC_11N); - val32 |= BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_HOLDC_11N, val32); - /* hold page D counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N); - val32 |= BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32); - ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE1_11N); - FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff); - FalseAlmCnt->Cnt_SB_Search_fail = (ret_value & 0xffff0000)>>16; - ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE2_11N); - FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff); - FalseAlmCnt->Cnt_Parity_Fail = (ret_value & 0xffff0000)>>16; - ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE3_11N); - FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff); - FalseAlmCnt->Cnt_Crc8_fail = (ret_value & 0xffff0000)>>16; - ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE4_11N); - FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff); - - FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + - FalseAlmCnt->Cnt_Rate_Illegal + - FalseAlmCnt->Cnt_Crc8_fail + - FalseAlmCnt->Cnt_Mcs_fail + - FalseAlmCnt->Cnt_Fast_Fsync + - FalseAlmCnt->Cnt_SB_Search_fail; - /* hold cck counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N); - val32 |= (BIT(12) | BIT(14)); - rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32); - - ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_FA_LSB_11N) & 0xff; - FalseAlmCnt->Cnt_Cck_fail = ret_value; - ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_FA_MSB_11N) >> 16; - FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff00); - - ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_CCA_CNT_11N); - FalseAlmCnt->Cnt_CCK_CCA = - ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8); - - FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync + - FalseAlmCnt->Cnt_SB_Search_fail + - FalseAlmCnt->Cnt_Parity_Fail + - FalseAlmCnt->Cnt_Rate_Illegal + - FalseAlmCnt->Cnt_Crc8_fail + - FalseAlmCnt->Cnt_Mcs_fail + - FalseAlmCnt->Cnt_Cck_fail); - - FalseAlmCnt->Cnt_CCA_all = - FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA; - - if (pDM_Odm->SupportICType >= ODM_RTL8723A) { - /* reset false alarm counter registers */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTC_11N); - val32 |= BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTC_11N, val32); - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTC_11N); - val32 &= ~BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTC_11N, val32); - - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N); - val32 |= BIT(27); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32); - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N); - val32 &= ~BIT(27); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32); - - /* update ofdm counter */ - /* update page C counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_HOLDC_11N); - val32 &= ~BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_HOLDC_11N, val32); - - /* update page D counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N); - val32 &= ~BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32); - - /* reset CCK CCA counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N); - val32 &= ~(BIT(12) | BIT(13) | BIT(14) | BIT(15)); - rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32); - - val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N); - val32 |= (BIT(13) | BIT(15)); - rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32); - } - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Enter odm_FalseAlarmCounterStatistics23a\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Cnt_Fast_Fsync =%d, Cnt_SB_Search_fail =%d\n", - FalseAlmCnt->Cnt_Fast_Fsync, - FalseAlmCnt->Cnt_SB_Search_fail)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Cnt_Parity_Fail =%d, Cnt_Rate_Illegal =%d\n", - FalseAlmCnt->Cnt_Parity_Fail, - FalseAlmCnt->Cnt_Rate_Illegal)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Cnt_Crc8_fail =%d, Cnt_Mcs_fail =%d\n", - FalseAlmCnt->Cnt_Crc8_fail, FalseAlmCnt->Cnt_Mcs_fail)); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Cnt_Cck_fail =%d\n", FalseAlmCnt->Cnt_Cck_fail)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Cnt_Ofdm_fail =%d\n", FalseAlmCnt->Cnt_Ofdm_fail)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Total False Alarm =%d\n", FalseAlmCnt->Cnt_all)); -} - -/* 3 ============================================================ */ -/* 3 CCK Packet Detect Threshold */ -/* 3 ============================================================ */ - -void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm) -{ - struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u8 CurCCK_CCAThres; - - if (pDM_Odm->ExtLNA) - return; - - if (pDM_Odm->bLinked) { - if (pDM_Odm->RSSI_Min > 25) { - CurCCK_CCAThres = 0xcd; - } else if (pDM_Odm->RSSI_Min <= 25 && pDM_Odm->RSSI_Min > 10) { - CurCCK_CCAThres = 0x83; - } else { - if (FalseAlmCnt->Cnt_Cck_fail > 1000) - CurCCK_CCAThres = 0x83; - else - CurCCK_CCAThres = 0x40; - } - } else { - if (FalseAlmCnt->Cnt_Cck_fail > 1000) - CurCCK_CCAThres = 0x83; - else - CurCCK_CCAThres = 0x40; - } - - ODM_Write_CCK_CCA_Thres23a(pDM_Odm, CurCCK_CCAThres); -} - -void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8 CurCCK_CCAThres) -{ - struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; - - if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) - rtl8723au_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), - CurCCK_CCAThres); - pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres; - pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres; -} - -/* 3 ============================================================ */ -/* 3 BB Power Save */ -/* 3 ============================================================ */ -void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm) -{ - struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; - - pDM_PSTable->PreCCAState = CCA_MAX; - pDM_PSTable->CurCCAState = CCA_MAX; - pDM_PSTable->PreRFState = RF_MAX; - pDM_PSTable->CurRFState = RF_MAX; - pDM_PSTable->Rssi_val_min = 0; - pDM_PSTable->initialize = 0; -} - - -void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal) -{ - struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; - struct rtw_adapter *adapter = pDM_Odm->Adapter; - u32 val32; - u8 Rssi_Up_bound = 30; - u8 Rssi_Low_bound = 25; - if (pDM_PSTable->initialize == 0) { - - pDM_PSTable->Reg874 = - rtl8723au_read32(adapter, 0x874) & 0x1CC000; - pDM_PSTable->RegC70 = - rtl8723au_read32(adapter, 0xc70) & BIT(3); - pDM_PSTable->Reg85C = - rtl8723au_read32(adapter, 0x85c) & 0xFF000000; - pDM_PSTable->RegA74 = rtl8723au_read32(adapter, 0xa74) & 0xF000; - pDM_PSTable->initialize = 1; - } - - if (!bForceInNormal) { - if (pDM_Odm->RSSI_Min != 0xFF) { - if (pDM_PSTable->PreRFState == RF_Normal) { - if (pDM_Odm->RSSI_Min >= Rssi_Up_bound) - pDM_PSTable->CurRFState = RF_Save; - else - pDM_PSTable->CurRFState = RF_Normal; - } else { - if (pDM_Odm->RSSI_Min <= Rssi_Low_bound) - pDM_PSTable->CurRFState = RF_Normal; - else - pDM_PSTable->CurRFState = RF_Save; - } - } else { - pDM_PSTable->CurRFState = RF_MAX; - } - } else { - pDM_PSTable->CurRFState = RF_Normal; - } - - if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) { - if (pDM_PSTable->CurRFState == RF_Save) { - /* 8723 RSSI report will be wrong. - * Set 0x874[5]= 1 when enter BB power saving mode. */ - /* Suggested by SD3 Yu-Nan. 2011.01.20. */ - /* Reg874[5]= 1b'1 */ - if (pDM_Odm->SupportICType == ODM_RTL8723A) { - val32 = rtl8723au_read32(adapter, 0x874); - val32 |= BIT(5); - rtl8723au_write32(adapter, 0x874, val32); - } - /* Reg874[20:18]= 3'b010 */ - val32 = rtl8723au_read32(adapter, 0x874); - val32 &= ~(BIT(18) | BIT(20)); - val32 |= BIT(19); - rtl8723au_write32(adapter, 0x874, val32); - /* RegC70[3]= 1'b0 */ - val32 = rtl8723au_read32(adapter, 0xc70); - val32 &= ~BIT(3); - rtl8723au_write32(adapter, 0xc70, val32); - /* Reg85C[31:24]= 0x63 */ - val32 = rtl8723au_read32(adapter, 0x85c); - val32 &= 0x00ffffff; - val32 |= 0x63000000; - rtl8723au_write32(adapter, 0x85c, val32); - /* Reg874[15:14]= 2'b10 */ - val32 = rtl8723au_read32(adapter, 0x874); - val32 &= ~BIT(14); - val32 |= BIT(15); - rtl8723au_write32(adapter, 0x874, val32); - /* RegA75[7:4]= 0x3 */ - val32 = rtl8723au_read32(adapter, 0xa74); - val32 &= ~(BIT(14) | BIT(15)); - val32 |= (BIT(12) | BIT(13)); - rtl8723au_write32(adapter, 0xa74, val32); - /* Reg818[28]= 1'b0 */ - val32 = rtl8723au_read32(adapter, 0x818); - val32 &= ~BIT(28); - rtl8723au_write32(adapter, 0x818, val32); - /* Reg818[28]= 1'b1 */ - val32 = rtl8723au_read32(adapter, 0x818); - val32 |= BIT(28); - rtl8723au_write32(adapter, 0x818, val32); - } else { - val32 = rtl8723au_read32(adapter, 0x874); - val32 |= pDM_PSTable->Reg874; - rtl8723au_write32(adapter, 0x874, val32); - - val32 = rtl8723au_read32(adapter, 0xc70); - val32 |= pDM_PSTable->RegC70; - rtl8723au_write32(adapter, 0xc70, val32); - - val32 = rtl8723au_read32(adapter, 0x85c); - val32 |= pDM_PSTable->Reg85C; - rtl8723au_write32(adapter, 0x85c, val32); - - val32 = rtl8723au_read32(adapter, 0xa74); - val32 |= pDM_PSTable->RegA74; - rtl8723au_write32(adapter, 0xa74, val32); - - val32 = rtl8723au_read32(adapter, 0x818); - val32 &= ~BIT(28); - rtl8723au_write32(adapter, 0x818, val32); - - /* Reg874[5]= 1b'0 */ - if (pDM_Odm->SupportICType == ODM_RTL8723A) { - val32 = rtl8723au_read32(adapter, 0x874); - val32 &= ~BIT(5); - rtl8723au_write32(adapter, 0x874, val32); - } - } - pDM_PSTable->PreRFState = pDM_PSTable->CurRFState; - } -} - -/* 3 ============================================================ */ -/* 3 RATR MASK */ -/* 3 ============================================================ */ -/* 3 ============================================================ */ -/* 3 Rate Adaptive */ -/* 3 ============================================================ */ - -void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm) -{ - struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive; - - pOdmRA->Type = DM_Type_ByDriver; - - pOdmRA->RATRState = DM_RATR_STA_INIT; - pOdmRA->HighRSSIThresh = 50; - pOdmRA->LowRSSIThresh = 20; -} - -u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid, - u32 ra_mask, u8 rssi_level) -{ - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct sta_info *pEntry; - u32 rate_bitmap = 0x0fffffff; - u8 WirelessMode; - - pEntry = pDM_Odm->pODM_StaInfo[macid]; - if (!pEntry) - return ra_mask; - - WirelessMode = pEntry->wireless_mode; - - switch (WirelessMode) { - case ODM_WM_B: - if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */ - rate_bitmap = 0x0000000d; - else - rate_bitmap = 0x0000000f; - break; - case (ODM_WM_A|ODM_WM_G): - if (rssi_level == DM_RATR_STA_HIGH) - rate_bitmap = 0x00000f00; - else - rate_bitmap = 0x00000ff0; - break; - case (ODM_WM_B|ODM_WM_G): - if (rssi_level == DM_RATR_STA_HIGH) - rate_bitmap = 0x00000f00; - else if (rssi_level == DM_RATR_STA_MIDDLE) - rate_bitmap = 0x00000ff0; - else - rate_bitmap = 0x00000ff5; - break; - case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G): - case (ODM_WM_A|ODM_WM_B|ODM_WM_G|ODM_WM_N24G): - if (pHalData->rf_type == RF_1T2R || - pHalData->rf_type == RF_1T1R) { - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x000f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x000ff000; - } else { - if (pHalData->CurrentChannelBW == - HT_CHANNEL_WIDTH_40) - rate_bitmap = 0x000ff015; - else - rate_bitmap = 0x000ff005; - } - } else { - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x0f8f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x0f8ff000; - } else { - if (pHalData->CurrentChannelBW == - HT_CHANNEL_WIDTH_40) - rate_bitmap = 0x0f8ff015; - else - rate_bitmap = 0x0f8ff005; - } - } - break; - default: - /* case WIRELESS_11_24N: */ - /* case WIRELESS_11_5N: */ - if (pHalData->rf_type == RF_1T2R) - rate_bitmap = 0x000fffff; - else - rate_bitmap = 0x0fffffff; - break; - } - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, - (" ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x \n", - rssi_level, WirelessMode, rate_bitmap)); - - return rate_bitmap; -} - -/*----------------------------------------------------------------------------- - * Function: odm_RefreshRateAdaptiveMask() - * - * Overview: Update rate table mask according to rssi - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - *When Who Remark - *05/27/2009 hpfan Create Version 0. - * - *---------------------------------------------------------------------------*/ -static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *pAdapter = pDM_Odm->Adapter; - u32 smoothed; - u8 i; - - if (pAdapter->bDriverStopped) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, - ("<---- %s: driver is going to unload\n", - __func__)); - return; - } - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i]; - if (pstat) { - smoothed = pstat->rssi_stat.UndecoratedSmoothedPWDB; - if (ODM_RAStateCheck23a(pDM_Odm, smoothed, false, - &pstat->rssi_level)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, - ODM_DBG_LOUD, - ("RSSI:%d, RSSI_LEVEL:%d\n", - smoothed, - pstat->rssi_level)); - rtw_hal_update_ra_mask23a(pstat, - pstat->rssi_level); - } - } - } -} - -/* Return Value: bool */ -/* - true: RATRState is changed. */ -bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate, - u8 *pRATRState) -{ - struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive; - const u8 GoUpGap = 5; - u8 HighRSSIThreshForRA = pRA->HighRSSIThresh; - u8 LowRSSIThreshForRA = pRA->LowRSSIThresh; - u8 RATRState; - - /* Threshold Adjustment: */ - /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */ - /* Here GoUpGap is added to solve the boundary's level alternation issue. */ - switch (*pRATRState) { - case DM_RATR_STA_INIT: - case DM_RATR_STA_HIGH: - break; - case DM_RATR_STA_MIDDLE: - HighRSSIThreshForRA += GoUpGap; - break; - case DM_RATR_STA_LOW: - HighRSSIThreshForRA += GoUpGap; - LowRSSIThreshForRA += GoUpGap; - break; - default: - ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !", - *pRATRState)); - break; - } - - /* Decide RATRState by RSSI. */ - if (RSSI > HighRSSIThreshForRA) - RATRState = DM_RATR_STA_HIGH; - else if (RSSI > LowRSSIThreshForRA) - RATRState = DM_RATR_STA_MIDDLE; - else - RATRState = DM_RATR_STA_LOW; - - if (*pRATRState != RATRState || bForceUpdate) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, - ("RSSI Level %d -> %d\n", *pRATRState, RATRState)); - *pRATRState = RATRState; - return true; - } - return false; -} - -/* 3 ============================================================ */ -/* 3 Dynamic Tx Power */ -/* 3 ============================================================ */ - -void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - - /* - * This is never changed, so we should be able to clean up the - * code checking for different values in rtl8723a_rf6052.c - */ - pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; -} - -static void -FindMinimumRSSI(struct rtw_adapter *pAdapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - - /* 1 1.Determine the minimum RSSI */ - - if (!pDM_Odm->bLinked && !pdmpriv->EntryMinUndecoratedSmoothedPWDB) - pdmpriv->MinUndecoratedPWDBForDM = 0; - else - pdmpriv->MinUndecoratedPWDBForDM = - pdmpriv->EntryMinUndecoratedSmoothedPWDB; -} - -static void odm_RSSIMonitorCheck(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - int i; - int MaxDB = 0, MinDB = 0xff; - u8 sta_cnt = 0; - u32 tmpdb; - u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */ - struct sta_info *psta; - - if (!pDM_Odm->bLinked) - return; - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - psta = pDM_Odm->pODM_StaInfo[i]; - if (psta) { - if (psta->rssi_stat.UndecoratedSmoothedPWDB < MinDB) - MinDB = psta->rssi_stat.UndecoratedSmoothedPWDB; - - if (psta->rssi_stat.UndecoratedSmoothedPWDB > MaxDB) - MaxDB = psta->rssi_stat.UndecoratedSmoothedPWDB; - - if (psta->rssi_stat.UndecoratedSmoothedPWDB != -1) { - tmpdb = psta->rssi_stat.UndecoratedSmoothedPWDB; - PWDB_rssi[sta_cnt++] = psta->mac_id | - (tmpdb << 16); - } - } - } - - for (i = 0; i < sta_cnt; i++) { - if (PWDB_rssi[i] != (0)) - rtl8723a_set_rssi_cmd(Adapter, PWDB_rssi[i]); - } - - pdmpriv->EntryMaxUndecoratedSmoothedPWDB = MaxDB; - - if (MinDB != 0xff) /* If associated entry is found */ - pdmpriv->EntryMinUndecoratedSmoothedPWDB = MinDB; - else - pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0; - - FindMinimumRSSI(Adapter);/* get pdmpriv->MinUndecoratedPWDBForDM */ - - ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, - pdmpriv->MinUndecoratedPWDBForDM); -} - -/* endif */ -/* 3 ============================================================ */ -/* 3 Tx Power Tracking */ -/* 3 ============================================================ */ - -static void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - - pdmpriv->bTXPowerTracking = true; - pdmpriv->TXPowercount = 0; - pdmpriv->bTXPowerTrackingInit = false; - pdmpriv->TxPowerTrackControl = true; - MSG_8723A("pdmpriv->TxPowerTrackControl = %d\n", - pdmpriv->TxPowerTrackControl); - - pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true; -} - -/* EDCA Turbo */ -static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; - Adapter->recvpriv.bIsAnyNonBEPkts = false; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Orginial VO PARAM: 0x%x\n", - rtl8723au_read32(Adapter, ODM_EDCA_VO_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Orginial VI PARAM: 0x%x\n", - rtl8723au_read32(Adapter, ODM_EDCA_VI_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Orginial BE PARAM: 0x%x\n", - rtl8723au_read32(Adapter, ODM_EDCA_BE_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Orginial BK PARAM: 0x%x\n", - rtl8723au_read32(Adapter, ODM_EDCA_BK_PARAM))); -} - -static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct xmit_priv *pxmitpriv = &Adapter->xmitpriv; - struct recv_priv *precvpriv = &Adapter->recvpriv; - struct registry_priv *pregpriv = &Adapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u32 trafficIndex; - u32 edca_param; - u64 cur_tx_bytes; - u64 cur_rx_bytes; - - /* For AP/ADSL use struct rtl8723a_priv * */ - /* For CE/NIC use struct rtw_adapter * */ - - /* - * 2011/09/29 MH In HW integration first stage, we provide 4 - * different handle to operate at the same time. In the stage2/3, - * we need to prive universal interface and merge all HW dynamic - * mechanism. - */ - - if ((pregpriv->wifi_spec == 1))/* (pmlmeinfo->HT_enable == 0)) */ - goto dm_CheckEdcaTurbo_EXIT; - - if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX) - goto dm_CheckEdcaTurbo_EXIT; - - if (rtl8723a_BT_disable_EDCA_turbo(Adapter)) - goto dm_CheckEdcaTurbo_EXIT; - - /* Check if the status needs to be changed. */ - if (!precvpriv->bIsAnyNonBEPkts) { - cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes; - cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes; - - /* traffic, TX or RX */ - if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) || - (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) { - if (cur_tx_bytes > (cur_rx_bytes << 2)) { - /* Uplink TP is present. */ - trafficIndex = UP_LINK; - } else { /* Balance TP is present. */ - trafficIndex = DOWN_LINK; - } - } else { - if (cur_rx_bytes > (cur_tx_bytes << 2)) { - /* Downlink TP is present. */ - trafficIndex = DOWN_LINK; - } else { /* Balance TP is present. */ - trafficIndex = UP_LINK; - } - } - - if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) || - (!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) { - if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) && - (pmlmeext->cur_wireless_mode & WIRELESS_11_24N)) - edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex]; - else - edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex]; - rtl8723au_write32(Adapter, REG_EDCA_BE_PARAM, - edca_param); - - pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex; - } - - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true; - } else { - /* Turn Off EDCA turbo here. */ - /* Restore original EDCA according to the declaration of AP. */ - if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) { - rtl8723au_write32(Adapter, REG_EDCA_BE_PARAM, - pHalData->AcParam_BE); - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; - } - } - -dm_CheckEdcaTurbo_EXIT: - /* Set variables for next time. */ - precvpriv->bIsAnyNonBEPkts = false; - pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes; - precvpriv->last_rx_bytes = precvpriv->rx_bytes; -} - -u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, - u8 initial_gain_psd) -{ - struct rtw_adapter *adapter = pDM_Odm->Adapter; - u32 psd_report, val32; - - /* Set DCO frequency index, offset = (40MHz/SamplePts)*point */ - val32 = rtl8723au_read32(adapter, 0x808); - val32 &= ~0x3ff; - val32 |= (point & 0x3ff); - rtl8723au_write32(adapter, 0x808, val32); - - /* Start PSD calculation, Reg808[22]= 0->1 */ - val32 = rtl8723au_read32(adapter, 0x808); - val32 |= BIT(22); - rtl8723au_write32(adapter, 0x808, val32); - /* Need to wait for HW PSD report */ - udelay(30); - val32 = rtl8723au_read32(adapter, 0x808); - val32 &= ~BIT(22); - rtl8723au_write32(adapter, 0x808, val32); - /* Read PSD report, Reg8B4[15:0] */ - psd_report = rtl8723au_read32(adapter, 0x8B4) & 0x0000FFFF; - - psd_report = (u32)(ConvertTo_dB23a(psd_report)) + - (u32)(initial_gain_psd-0x1c); - - return psd_report; -} - -u32 ConvertTo_dB23a(u32 Value) -{ - u8 i; - u8 j; - u32 dB; - - Value = Value & 0xFFFF; - - for (i = 0; i < 8; i++) { - if (Value <= dB_Invert_Table[i][11]) - break; - } - - if (i >= 8) - return 96; /* maximum 96 dB */ - - for (j = 0; j < 12; j++) { - if (Value <= dB_Invert_Table[i][j]) - break; - } - - dB = i*12 + j + 1; - - return dB; -} - -/* */ -/* Description: */ -/* Set Single/Dual Antenna default setting for products that do not - * do detection in advance. */ -/* */ -/* Added by Joseph, 2012.03.22 */ -/* */ -void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm) -{ - struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table; - - pDM_SWAT_Table->ANTA_ON = true; - pDM_SWAT_Table->ANTB_ON = true; -} - -/* 2 8723A ANT DETECT */ - -static void odm_PHY_SaveAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg, - u32 *AFEBackup, u32 RegisterNum) -{ - u32 i; - - for (i = 0 ; i < RegisterNum ; i++) - AFEBackup[i] = rtl8723au_read32(pDM_Odm->Adapter, AFEReg[i]); -} - -static void odm_PHY_ReloadAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg, - u32 *AFEBackup, u32 RegiesterNum) -{ - u32 i; - - for (i = 0 ; i < RegiesterNum; i++) - rtl8723au_write32(pDM_Odm->Adapter, AFEReg[i], AFEBackup[i]); -} - -/* 2 8723A ANT DETECT */ -/* Description: */ -/* Implement IQK single tone for RF DPK loopback and BB PSD scanning. */ -/* This function is cooperated with BB team Neil. */ -bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode) -{ - struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table; - struct rtw_adapter *adapter = pDM_Odm->Adapter; - u32 CurrentChannel, RfLoopReg; - u8 n; - u32 Reg88c, Regc08, Reg874, Regc50, val32; - u8 initial_gain = 0x5a; - u32 PSD_report_tmp; - u32 AntA_report = 0x0, AntB_report = 0x0, AntO_report = 0x0; - bool bResult = true; - u32 AFE_Backup[16]; - u32 AFE_REG_8723A[16] = { - rRx_Wait_CCA, rTx_CCK_RFON, - rTx_CCK_BBON, rTx_OFDM_RFON, - rTx_OFDM_BBON, rTx_To_Rx, - rTx_To_Tx, rRx_CCK, - rRx_OFDM, rRx_Wait_RIFS, - rRx_TO_Rx, rStandby, - rSleep, rPMPD_ANAEN, - rFPGA0_XCD_SwitchControl, rBlue_Tooth}; - - if (!(pDM_Odm->SupportICType & ODM_RTL8723A)) - return bResult; - - if (!(pDM_Odm->SupportAbility&ODM_BB_ANT_DIV)) - return bResult; - /* 1 Backup Current RF/BB Settings */ - - CurrentChannel = ODM_GetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, - bRFRegOffsetMask); - RfLoopReg = ODM_GetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask); - /* change to Antenna A */ - val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE); - val32 &= ~0x300; - val32 |= 0x100; /* Enable antenna A */ - rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32); - - /* Step 1: USE IQK to transmitter single tone */ - - udelay(10); - - /* Store A Path Register 88c, c08, 874, c50 */ - Reg88c = rtl8723au_read32(adapter, rFPGA0_AnalogParameter4); - Regc08 = rtl8723au_read32(adapter, rOFDM0_TRMuxPar); - Reg874 = rtl8723au_read32(adapter, rFPGA0_XCD_RFInterfaceSW); - Regc50 = rtl8723au_read32(adapter, rOFDM0_XAAGCCore1); - - /* Store AFE Registers */ - odm_PHY_SaveAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16); - - /* Set PSD 128 pts */ - val32 = rtl8723au_read32(adapter, rFPGA0_PSDFunction); - val32 &= ~(BIT(14) | BIT(15)); - rtl8723au_write32(adapter, rFPGA0_PSDFunction, val32); - - /* To SET CH1 to do */ - ODM_SetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask, 0x01); - - /* AFE all on step */ - rtl8723au_write32(adapter, rRx_Wait_CCA, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_CCK_RFON, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_CCK_BBON, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_OFDM_RFON, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_OFDM_BBON, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_To_Rx, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_To_Tx, 0x6FDB25A4); - rtl8723au_write32(adapter, rRx_CCK, 0x6FDB25A4); - rtl8723au_write32(adapter, rRx_OFDM, 0x6FDB25A4); - rtl8723au_write32(adapter, rRx_Wait_RIFS, 0x6FDB25A4); - rtl8723au_write32(adapter, rRx_TO_Rx, 0x6FDB25A4); - rtl8723au_write32(adapter, rStandby, 0x6FDB25A4); - rtl8723au_write32(adapter, rSleep, 0x6FDB25A4); - rtl8723au_write32(adapter, rPMPD_ANAEN, 0x6FDB25A4); - rtl8723au_write32(adapter, rFPGA0_XCD_SwitchControl, 0x6FDB25A4); - rtl8723au_write32(adapter, rBlue_Tooth, 0x6FDB25A4); - - /* 3 wire Disable */ - rtl8723au_write32(adapter, rFPGA0_AnalogParameter4, 0xCCF000C0); - - /* BB IQK Setting */ - rtl8723au_write32(adapter, rOFDM0_TRMuxPar, 0x000800E4); - rtl8723au_write32(adapter, rFPGA0_XCD_RFInterfaceSW, 0x22208000); - - /* IQK setting tone@ 4.34Mhz */ - rtl8723au_write32(adapter, rTx_IQK_Tone_A, 0x10008C1C); - rtl8723au_write32(adapter, rTx_IQK, 0x01007c00); - - /* Page B init */ - rtl8723au_write32(adapter, rConfig_AntA, 0x00080000); - rtl8723au_write32(adapter, rConfig_AntA, 0x0f600000); - rtl8723au_write32(adapter, rRx_IQK, 0x01004800); - rtl8723au_write32(adapter, rRx_IQK_Tone_A, 0x10008c1f); - rtl8723au_write32(adapter, rTx_IQK_PI_A, 0x82150008); - rtl8723au_write32(adapter, rRx_IQK_PI_A, 0x28150008); - rtl8723au_write32(adapter, rIQK_AGC_Rsp, 0x001028d0); - - /* RF loop Setting */ - ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x0, 0xFFFFF, 0x50008); - - /* IQK Single tone start */ - rtl8723au_write32(adapter, rFPGA0_IQK, 0x80800000); - rtl8723au_write32(adapter, rIQK_AGC_Pts, 0xf8000000); - udelay(1000); - PSD_report_tmp = 0x0; - - for (n = 0; n < 2; n++) { - PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain); - if (PSD_report_tmp > AntA_report) - AntA_report = PSD_report_tmp; - } - - PSD_report_tmp = 0x0; - - val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE); - val32 &= ~0x300; - val32 |= 0x200; /* Enable antenna B */ - rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32); - udelay(10); - - for (n = 0; n < 2; n++) { - PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain); - if (PSD_report_tmp > AntB_report) - AntB_report = PSD_report_tmp; - } - - /* change to open case */ - /* change to Ant A and B all open case */ - val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE); - val32 &= ~0x300; - rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32); - udelay(10); - - for (n = 0; n < 2; n++) { - PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain); - if (PSD_report_tmp > AntO_report) - AntO_report = PSD_report_tmp; - } - - /* Close IQK Single Tone function */ - rtl8723au_write32(adapter, rFPGA0_IQK, 0x00000000); - PSD_report_tmp = 0x0; - - /* 1 Return to antanna A */ - val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE); - val32 &= ~0x300; - val32 |= 0x100; /* Enable antenna A */ - rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32); - rtl8723au_write32(adapter, rFPGA0_AnalogParameter4, Reg88c); - rtl8723au_write32(adapter, rOFDM0_TRMuxPar, Regc08); - rtl8723au_write32(adapter, rFPGA0_XCD_RFInterfaceSW, Reg874); - val32 = rtl8723au_read32(adapter, rOFDM0_XAAGCCore1); - val32 &= ~0x7f; - val32 |= 0x40; - rtl8723au_write32(adapter, rOFDM0_XAAGCCore1, val32); - - rtl8723au_write32(adapter, rOFDM0_XAAGCCore1, Regc50); - ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, - CurrentChannel); - ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask, RfLoopReg); - - /* Reload AFE Registers */ - odm_PHY_ReloadAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("psd_report_A[%d]= %d \n", 2416, AntA_report)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("psd_report_B[%d]= %d \n", 2416, AntB_report)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("psd_report_O[%d]= %d \n", 2416, AntO_report)); - - /* 2 Test Ant B based on Ant A is ON */ - if (mode == ANTTESTB) { - if (AntA_report >= 100) { - if (AntB_report > (AntA_report+1)) { - pDM_SWAT_Table->ANTB_ON = false; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Single Antenna A\n")); - } else { - pDM_SWAT_Table->ANTB_ON = true; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Dual Antenna is A and B\n")); - } - } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n")); - pDM_SWAT_Table->ANTB_ON = false; /* Set Antenna B off as default */ - bResult = false; - } - } else if (mode == ANTTESTALL) { - /* 2 Test Ant A and B based on DPDT Open */ - if ((AntO_report >= 100) & (AntO_report < 118)) { - if (AntA_report > (AntO_report+1)) { - pDM_SWAT_Table->ANTA_ON = false; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, ("Ant A is OFF")); - } else { - pDM_SWAT_Table->ANTA_ON = true; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, ("Ant A is ON")); - } - - if (AntB_report > (AntO_report+2)) { - pDM_SWAT_Table->ANTB_ON = false; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, ("Ant B is OFF")); - } else { - pDM_SWAT_Table->ANTB_ON = true; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, ("Ant B is ON")); - } - } - } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("ODM_SingleDualAntennaDetection(): Need to check again\n")); - /* Set Antenna A on as default */ - pDM_SWAT_Table->ANTA_ON = true; - /* Set Antenna B off as default */ - pDM_SWAT_Table->ANTB_ON = false; - bResult = false; - } - - return bResult; -} diff --git a/drivers/staging/rtl8723au/hal/odm_HWConfig.c b/drivers/staging/rtl8723au/hal/odm_HWConfig.c deleted file mode 100644 index 0562f61bd1dc..000000000000 --- a/drivers/staging/rtl8723au/hal/odm_HWConfig.c +++ /dev/null @@ -1,396 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -/* */ -/* include files */ -/* */ - -#include "odm_precomp.h" - -static u8 odm_QueryRxPwrPercentage(s8 AntPower) -{ - if ((AntPower <= -100) || (AntPower >= 20)) - return 0; - else if (AntPower >= 0) - return 100; - else - return 100 + AntPower; -} - -static s32 odm_SignalScaleMapping_92CSeries(struct dm_odm_t *pDM_Odm, s32 CurrSig) -{ - s32 RetSig = 0; - - if (CurrSig >= 51 && CurrSig <= 100) - RetSig = 100; - else if (CurrSig >= 41 && CurrSig <= 50) - RetSig = 80 + ((CurrSig - 40)*2); - else if (CurrSig >= 31 && CurrSig <= 40) - RetSig = 66 + (CurrSig - 30); - else if (CurrSig >= 21 && CurrSig <= 30) - RetSig = 54 + (CurrSig - 20); - else if (CurrSig >= 10 && CurrSig <= 20) - RetSig = 42 + (((CurrSig - 10) * 2) / 3); - else if (CurrSig >= 5 && CurrSig <= 9) - RetSig = 22 + (((CurrSig - 5) * 3) / 2); - else if (CurrSig >= 1 && CurrSig <= 4) - RetSig = 6 + (((CurrSig - 1) * 3) / 2); - else - RetSig = CurrSig; - - return RetSig; -} - -static s32 odm_SignalScaleMapping(struct dm_odm_t *pDM_Odm, s32 CurrSig) -{ - return odm_SignalScaleMapping_92CSeries(pDM_Odm, CurrSig); -} - -static u8 -odm_EVMdbToPercentage( - s8 Value - ) -{ - /* */ - /* -33dB~0dB to 0%~99% */ - /* */ - s8 ret_val; - - ret_val = Value; - - if (ret_val >= 0) - ret_val = 0; - if (ret_val <= -33) - ret_val = -33; - - ret_val = 0 - ret_val; - ret_val *= 3; - - if (ret_val == 99) - ret_val = 100; - - return ret_val; -} - -static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm, - struct phy_info *pPhyInfo, - u8 *pPhyStatus, - struct odm_packet_info *pPktinfo) -{ - struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus; - u8 i, Max_spatial_stream; - s8 rx_pwr[4], rx_pwr_all = 0; - u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT; - u8 RSSI, total_rssi = 0; - u8 isCCKrate = 0; - u8 rf_rx_num = 0; - u8 cck_highpwr = 0; - - isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false; - pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1; - pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1; - - if (isCCKrate) { - u8 report; - u8 cck_agc_rpt; - - pDM_Odm->PhyDbgInfo.NumQryPhyStatusCCK++; - /* (1)Hardware does not provide RSSI for CCK */ - /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ - - cck_highpwr = pDM_Odm->bCckHighPower; - - cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a; - - /* The RSSI formula should be modified according to the gain table */ - if (!cck_highpwr) { - report = (cck_agc_rpt & 0xc0)>>6; - switch (report) { - /* Modify the RF RNA gain value to -40, -20, -2, 14 by Jenyu's suggestion */ - /* Note: different RF with the different RNA gain. */ - case 0x3: - rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); - break; - case 0x2: - rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); - break; - case 0x1: - rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); - break; - case 0x0: - rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); - break; - } - } else { - report = (cck_agc_rpt & 0x60)>>5; - switch (report) { - case 0x3: - rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1); - break; - case 0x2: - rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f)<<1); - break; - case 0x1: - rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1); - break; - case 0x0: - rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1); - break; - } - } - - PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all); - - /* Modification for ext-LNA board */ - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - if ((cck_agc_rpt>>7) == 0) { - PWDB_ALL = (PWDB_ALL > 94) ? 100 : (PWDB_ALL+6); - } else { - if (PWDB_ALL > 38) - PWDB_ALL -= 16; - else - PWDB_ALL = (PWDB_ALL <= 16) ? (PWDB_ALL>>2) : (PWDB_ALL-12); - } - - /* CCK modification */ - if (PWDB_ALL > 25 && PWDB_ALL <= 60) - PWDB_ALL += 6; - } else { /* Modification for int-LNA board */ - if (PWDB_ALL > 99) - PWDB_ALL -= 8; - else if (PWDB_ALL > 50 && PWDB_ALL <= 68) - PWDB_ALL += 4; - } - pPhyInfo->RxPWDBAll = PWDB_ALL; - pPhyInfo->BTRxRSSIPercentage = PWDB_ALL; - pPhyInfo->RecvSignalPower = rx_pwr_all; - /* (3) Get Signal Quality (EVM) */ - if (pPktinfo->bPacketMatchBSSID) { - u8 SQ, SQ_rpt; - - SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all; - - if (SQ_rpt > 64) - SQ = 0; - else if (SQ_rpt < 20) - SQ = 100; - else - SQ = ((64-SQ_rpt) * 100) / 44; - - pPhyInfo->SignalQuality = SQ; - pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ; - pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1; - } - } else { /* is OFDM rate */ - pDM_Odm->PhyDbgInfo.NumQryPhyStatusOFDM++; - - /* (1)Get RSSI for HT rate */ - - for (i = RF_PATH_A; i < RF_PATH_MAX; i++) { - /* 2008/01/30 MH we will judge RF RX path now. */ - if (pDM_Odm->RFPathRxEnable & BIT(i)) - rf_rx_num++; - - rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F)*2) - 110; - - pPhyInfo->RxPwr[i] = rx_pwr[i]; - - /* Translate DBM to percentage. */ - RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]); - total_rssi += RSSI; - - /* Modification for ext-LNA board */ - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - if ((pPhyStaRpt->path_agc[i].trsw) == 1) - RSSI = (RSSI > 94) ? 100 : (RSSI+6); - else - RSSI = (RSSI <= 16) ? (RSSI>>3) : (RSSI-16); - - if ((RSSI <= 34) && (RSSI >= 4)) - RSSI -= 4; - } - - pPhyInfo->RxMIMOSignalStrength[i] = (u8) RSSI; - - /* Get Rx snr value in DB */ - pPhyInfo->RxSNR[i] = pDM_Odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2); - } - - /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ - rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f)-110; - - PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all); - PWDB_ALL_BT = PWDB_ALL; - - pPhyInfo->RxPWDBAll = PWDB_ALL; - pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT; - pPhyInfo->RxPower = rx_pwr_all; - pPhyInfo->RecvSignalPower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15) - Max_spatial_stream = 2; /* both spatial stream make sense */ - else - Max_spatial_stream = 1; /* only spatial stream 1 makes sense */ - - for (i = 0; i < Max_spatial_stream; i++) { - /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */ - /* fill most significant bit to "zero" when doing shifting operation which may change a negative */ - /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */ - EVM = odm_EVMdbToPercentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */ - - if (pPktinfo->bPacketMatchBSSID) { - if (i == RF_PATH_A) { - /* Fill value in RFD, Get the first spatial stream only */ - pPhyInfo->SignalQuality = (u8)(EVM & 0xff); - } - pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff); - } - } - } - /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */ - /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */ - if (isCCKrate) { - pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, PWDB_ALL));/* PWDB_ALL; */ - } else { - if (rf_rx_num != 0) - pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, total_rssi /= rf_rx_num)); - } -} - -static void odm_Process_RSSIForDM(struct dm_odm_t *pDM_Odm, - struct phy_info *pPhyInfo, - struct odm_packet_info *pPktinfo) -{ - s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK; - s32 UndecoratedSmoothedOFDM, RSSI_Ave; - u8 isCCKrate = 0; - u8 RSSI_max, RSSI_min, i; - u32 OFDM_pkt = 0; - u32 Weighting = 0; - struct sta_info *pEntry; - - if (pPktinfo->StationID == 0xFF) - return; - - pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->StationID]; - if (!pEntry) - return; - if ((!pPktinfo->bPacketMatchBSSID)) - return; - - isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false; - - /* Smart Antenna Debug Message------------------*/ - - UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK; - UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM; - UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB; - - if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) { - if (!isCCKrate) { /* ofdm rate */ - if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) { - RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - } else { - if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) { - RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]; - } else { - RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]; - RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - } - if ((RSSI_max - RSSI_min) < 3) - RSSI_Ave = RSSI_max; - else if ((RSSI_max - RSSI_min) < 6) - RSSI_Ave = RSSI_max - 1; - else if ((RSSI_max - RSSI_min) < 10) - RSSI_Ave = RSSI_max - 2; - else - RSSI_Ave = RSSI_max - 3; - } - - /* 1 Process OFDM RSSI */ - if (UndecoratedSmoothedOFDM <= 0) { - /* initialize */ - UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll; - } else { - if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) { - UndecoratedSmoothedOFDM = - (((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) + - (RSSI_Ave)) / (Rx_Smooth_Factor); - UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1; - } else { - UndecoratedSmoothedOFDM = - (((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) + - (RSSI_Ave)) / (Rx_Smooth_Factor); - } - } - pEntry->rssi_stat.PacketMap = - (pEntry->rssi_stat.PacketMap<<1) | BIT(0); - } else { - RSSI_Ave = pPhyInfo->RxPWDBAll; - - /* 1 Process CCK RSSI */ - if (UndecoratedSmoothedCCK <= 0) { - /* initialize */ - UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll; - } else { - if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) { - UndecoratedSmoothedCCK = - (((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) + - (pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor); - UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1; - } else { - UndecoratedSmoothedCCK = - (((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) + - (pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor); - } - } - pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1; - } - - /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */ - if (pEntry->rssi_stat.ValidBit >= 64) - pEntry->rssi_stat.ValidBit = 64; - else - pEntry->rssi_stat.ValidBit++; - - for (i = 0; i < pEntry->rssi_stat.ValidBit; i++) - OFDM_pkt += - (u8)(pEntry->rssi_stat.PacketMap>>i) & BIT(0); - - if (pEntry->rssi_stat.ValidBit == 64) { - Weighting = ((OFDM_pkt<<4) > 64)?64:(OFDM_pkt<<4); - UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6; - } else { - if (pEntry->rssi_stat.ValidBit != 0) - UndecoratedSmoothedPWDB = (OFDM_pkt*UndecoratedSmoothedOFDM+(pEntry->rssi_stat.ValidBit-OFDM_pkt)*UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit; - else - UndecoratedSmoothedPWDB = 0; - } - pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK; - pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM; - pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB; - } -} - -void ODM_PhyStatusQuery23a(struct dm_odm_t *pDM_Odm, struct phy_info *pPhyInfo, - u8 *pPhyStatus, struct odm_packet_info *pPktinfo) -{ - odm_RxPhyStatus92CSeries_Parsing(pDM_Odm, pPhyInfo, - pPhyStatus, pPktinfo); - - odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo); -} diff --git a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c b/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c deleted file mode 100644 index a63c6cb88bc9..000000000000 --- a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#include "odm_precomp.h" -#include "usb_ops_linux.h" - -void -odm_ConfigRFReg_8723A( - struct dm_odm_t *pDM_Odm, - u32 Addr, - u32 Data, - enum RF_RADIO_PATH RF_PATH, - u32 RegAddr - ) -{ - if (Addr == 0xfe) { - msleep(50); - } else if (Addr == 0xfd) { - mdelay(5); - } else if (Addr == 0xfc) { - mdelay(1); - } else if (Addr == 0xfb) { - udelay(50); - } else if (Addr == 0xfa) { - udelay(5); - } else if (Addr == 0xf9) { - udelay(1); - } else { - ODM_SetRFReg(pDM_Odm, RF_PATH, RegAddr, bRFRegOffsetMask, Data); - /* Add 1us delay between BB/RF register setting. */ - udelay(1); - } -} - -void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u8 data) -{ - rtl8723au_write8(pDM_Odm->Adapter, addr, data); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===> %s: [MAC_REG] %08X %08X\n", __func__, addr, data)); -} - -void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data) -{ - rtl8723au_write32(pDM_Odm->Adapter, addr, data); - /* Add 1us delay between BB/RF register setting. */ - udelay(1); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===> %s: [AGC_TAB] %08X %08X\n", __func__, addr, data)); -} - -void -odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data) -{ - if (addr == 0xfe) - msleep(50); - else if (addr == 0xfd) - mdelay(5); - else if (addr == 0xfc) - mdelay(1); - else if (addr == 0xfb) - udelay(50); - else if (addr == 0xfa) - udelay(5); - else if (addr == 0xf9) - udelay(1); - else if (addr == 0xa24) - pDM_Odm->RFCalibrateInfo.RegA24 = data; - rtl8723au_write32(pDM_Odm->Adapter, addr, data); - - /* Add 1us delay between BB/RF register setting. */ - udelay(1); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===> %s: [PHY_REG] %08X %08X\n", __func__, addr, data)); -} diff --git a/drivers/staging/rtl8723au/hal/odm_debug.c b/drivers/staging/rtl8723au/hal/odm_debug.c deleted file mode 100644 index cb2bdda6b0eb..000000000000 --- a/drivers/staging/rtl8723au/hal/odm_debug.c +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#include "odm_precomp.h" - -void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm) -{ - pDM_Odm->DebugLevel = ODM_DBG_TRACE; - pDM_Odm->DebugComponents = 0; -} - -u32 GlobalDebugLevel23A; - -void rt_trace(int comp, int level, const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - pr_info(DRIVER_PREFIX " [0x%08x,%d] %pV", comp, level, &vaf); - - va_end(args); -} diff --git a/drivers/staging/rtl8723au/hal/odm_interface.c b/drivers/staging/rtl8723au/hal/odm_interface.c deleted file mode 100644 index d8f67902708e..000000000000 --- a/drivers/staging/rtl8723au/hal/odm_interface.c +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -/* */ -/* include files */ -/* */ - -#include "odm_precomp.h" -/* */ -/* ODM IO Relative API. */ -/* */ -#include - -void ODM_SetRFReg( - struct dm_odm_t *pDM_Odm, - enum RF_RADIO_PATH eRFPath, - u32 RegAddr, - u32 BitMask, - u32 Data - ) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - - PHY_SetRFReg(Adapter, eRFPath, RegAddr, BitMask, Data); -} - -u32 ODM_GetRFReg( - struct dm_odm_t *pDM_Odm, - enum RF_RADIO_PATH eRFPath, - u32 RegAddr, - u32 BitMask - ) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - - return PHY_QueryRFReg(Adapter, eRFPath, RegAddr, BitMask); -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c deleted file mode 100644 index bfcbd7a349cf..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ /dev/null @@ -1,11265 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#include -#include -#include - -#define DIS_PS_RX_BCN - -u32 BTCoexDbgLevel = _bt_dbg_off_; - -#define RTPRINT(_Comp, _Level, Fmt)\ -do {\ - if ((BTCoexDbgLevel == _bt_dbg_on_)) {\ - printk Fmt;\ - } \ -} while (0) - -#define RTPRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)\ -if ((BTCoexDbgLevel == _bt_dbg_on_)) {\ - u32 __i; \ - u8 *ptr = (u8 *)_Ptr; \ - printk printstr; \ - printk(" "); \ - for (__i = 0; __i < 6; __i++) \ - printk("%02X%s", ptr[__i], (__i == 5)?"":"-"); \ - printk("\n"); \ -} -#define RTPRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)\ -if ((BTCoexDbgLevel == _bt_dbg_on_)) {\ - u32 __i; \ - u8 *ptr = (u8 *)_HexData; \ - printk(_TitleString); \ - for (__i = 0; __i < (u32)_HexDataLen; __i++) { \ - printk("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?" ":" ");\ - if (((__i + 1) % 16) == 0) \ - printk("\n"); \ - } \ - printk("\n"); \ -} -/* Added by Annie, 2005-11-22. */ -#define MAX_STR_LEN 64 -/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. */ -#define PRINTABLE(_ch) (_ch >= ' ' && _ch <= '~') -#define RT_PRINT_STR(_Comp, _Level, _TitleString, _Ptr, _Len) \ - { \ - u32 __i; \ - u8 buffer[MAX_STR_LEN]; \ - u32 length = (_Len < MAX_STR_LEN) ? _Len : (MAX_STR_LEN-1);\ - memset(buffer, 0, MAX_STR_LEN); \ - memcpy(buffer, (u8 *)_Ptr, length); \ - for (__i = 0; __i < length; __i++) { \ - if (!PRINTABLE(buffer[__i])) \ - buffer[__i] = '?'; \ - } \ - buffer[length] = '\0'; \ - printk(_TitleString); \ - printk(": %d, <%s>\n", _Len, buffer); \ - } - -#define DCMD_Printf(...) -#define RT_ASSERT(...) - - -#define GetDefaultAdapter(padapter) padapter - -#define PlatformZeroMemory(ptr, sz) memset(ptr, 0, sz) - -#define GET_UNDECORATED_AVERAGE_RSSI(padapter) \ - (GET_HAL_DATA(padapter)->dmpriv.EntryMinUndecoratedSmoothedPWDB) -#define RT_RF_CHANGE_SOURCE u32 - -enum { - RT_JOIN_INFRA = 1, - RT_JOIN_IBSS = 2, - RT_START_IBSS = 3, - RT_NO_ACTION = 4, -}; - -/* power saving */ - -/* ===== Below this line is sync from SD7 driver COMMOM/BT.c ===== */ - -static u8 BT_Operation(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->BtOperationOn) - return true; - else - return false; -} - -static u8 BT_IsLegalChannel(struct rtw_adapter *padapter, u8 channel) -{ - struct rt_channel_info *pChanneList = NULL; - u8 channelLen, i; - - pChanneList = padapter->mlmeextpriv.channel_set; - channelLen = padapter->mlmeextpriv.max_chan_nums; - - for (i = 0; i < channelLen; i++) { - RTPRINT(FIOCTL, IOCTL_STATE, - ("Check if chnl(%d) in channel plan contains bt target chnl(%d) for BT connection\n", - pChanneList[i].ChannelNum, channel)); - if ((channel == pChanneList[i].ChannelNum) || - (channel == pChanneList[i].ChannelNum + 2)) - return channel; - } - return 0; -} - -void BT_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt) -{ - BTDM_SignalCompensation(padapter, rssi_wifi, rssi_bt); -} - -void rtl8723a_BT_wifiscan_notify(struct rtw_adapter *padapter, u8 scanType) -{ - BTHCI_WifiScanNotify(padapter, scanType); - BTDM_CheckAntSelMode(padapter); - BTDM_WifiScanNotify(padapter, scanType); -} - -void rtl8723a_BT_wifiassociate_notify(struct rtw_adapter *padapter, u8 action) -{ - /* action : */ - /* true = associate start */ - /* false = associate finished */ - if (action) - BTDM_CheckAntSelMode(padapter); - - BTDM_WifiAssociateNotify(padapter, action); -} - -void BT_HaltProcess(struct rtw_adapter *padapter) -{ - BTDM_ForHalt(padapter); -} - -/* ===== End of sync from SD7 driver COMMOM/BT.c ===== */ - -#define i64fmt "ll" -#define UINT64_C(v) (v) - -#define FillOctetString(_os, _octet, _len) \ - (_os).Octet = (u8 *)(_octet); \ - (_os).Length = (_len); - -static enum rt_status PlatformIndicateBTEvent( - struct rtw_adapter *padapter, - void *pEvntData, - u32 dataLen - ) -{ - enum rt_status rt_status = RT_STATUS_FAILURE; - - RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("BT event start, %d bytes data to Transferred!!\n", dataLen)); - RTPRINT_DATA(FIOCTL, IOCTL_BT_EVENT_DETAIL, "To transfer Hex Data :\n", - pEvntData, dataLen); - - BT_EventParse(padapter, pEvntData, dataLen); - - printk(KERN_WARNING "%s: Linux has no way to report BT event!!\n", __func__); - - RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("BT event end, %s\n", - (rt_status == RT_STATUS_SUCCESS) ? "SUCCESS" : "FAIL")); - - return rt_status; -} - -/* ===== Below this line is sync from SD7 driver COMMOM/bt_hci.c ===== */ - -static u8 bthci_GetLocalChannel(struct rtw_adapter *padapter) -{ - return padapter->mlmeextpriv.cur_channel; -} - -static u8 bthci_GetCurrentEntryNum(struct rtw_adapter *padapter, u8 PhyHandle) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - u8 i; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if ((pBTInfo->BtAsocEntry[i].bUsed) && - (pBTInfo->BtAsocEntry[i].PhyLinkCmdData.BtPhyLinkhandle == PhyHandle)) - return i; - } - - return 0xFF; -} - -static void bthci_DecideBTChannel(struct rtw_adapter *padapter, u8 EntryNum) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_hci_info *pBtHciInfo; - struct chnl_txpower_triple *pTriple_subband = NULL; - struct common_triple *pTriple; - u8 i, j, localchnl, firstRemoteLegalChnlInTriplet = 0; - u8 regulatory_skipLen = 0; - u8 subbandTripletCnt = 0; - - pmlmepriv = &padapter->mlmepriv; - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtHciInfo = &pBTInfo->BtHciInfo; - - pBtMgnt->CheckChnlIsSuit = true; - localchnl = bthci_GetLocalChannel(padapter); - - pTriple = (struct common_triple *) - &pBtHciInfo->BTPreChnllist[COUNTRY_STR_LEN]; - - /* contains country string, len is 3 */ - for (i = 0; i < (pBtHciInfo->BtPreChnlListLen-COUNTRY_STR_LEN); i += 3, pTriple++) { - /* */ - /* check every triplet, an triplet may be */ - /* regulatory extension identifier or sub-band triplet */ - /* */ - if (pTriple->byte_1st == 0xc9) { - /* Regulatory Extension Identifier, skip it */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), - ("Find Regulatory ID, regulatory class = %d\n", pTriple->byte_2nd)); - regulatory_skipLen += 3; - pTriple_subband = NULL; - continue; - } else { /* Sub-band triplet */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Find Sub-band triplet \n")); - subbandTripletCnt++; - pTriple_subband = (struct chnl_txpower_triple *)pTriple; - /* if remote first legal channel not found, then find first remote channel */ - /* and it's legal for our channel plan. */ - - /* search the sub-band triplet and find if remote channel is legal to our channel plan. */ - for (j = pTriple_subband->FirstChnl; j < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls); j++) { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" Check if chnl(%d) is legal\n", j)); - if (BT_IsLegalChannel(padapter, j)) { - /* remote channel is legal for our channel plan. */ - firstRemoteLegalChnlInTriplet = j; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), - ("Find first remote legal channel : %d\n", - firstRemoteLegalChnlInTriplet)); - - /* If we find a remote legal channel in the sub-band triplet */ - /* and only BT connection is established(local not connect to any AP or IBSS), */ - /* then we just switch channel to remote channel. */ - if (!(check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_ADHOC_STATE|WIFI_AP_STATE) || - BTHCI_HsConnectionEstablished(padapter))) { - pBtMgnt->BTChannel = firstRemoteLegalChnlInTriplet; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Remote legal channel (%d) is selected, Local not connect to any!!\n", pBtMgnt->BTChannel)); - return; - } else { - if ((localchnl >= firstRemoteLegalChnlInTriplet) && - (localchnl < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls))) { - pBtMgnt->BTChannel = localchnl; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Local channel (%d) is selected, wifi or BT connection exists\n", pBtMgnt->BTChannel)); - return; - } - } - break; - } - } - } - } - - if (subbandTripletCnt) { - /* if any preferred channel triplet exists */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("There are %d sub band triplet exists, ", subbandTripletCnt)); - if (firstRemoteLegalChnlInTriplet == 0) { - /* no legal channel is found, reject the connection. */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("no legal channel is found!!\n")); - } else { - /* Remote Legal channel is found but not match to local */ - /* wifi connection exists), so reject the connection. */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), - ("Remote Legal channel is found but not match to local(wifi connection exists)!!\n")); - } - pBtMgnt->CheckChnlIsSuit = false; - } else { - /* There are not any preferred channel triplet exists */ - /* Use current legal channel as the bt channel. */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("No sub band triplet exists!!\n")); - } - pBtMgnt->BTChannel = localchnl; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Local channel (%d) is selected!!\n", pBtMgnt->BTChannel)); -} - -/* Success:return true */ -/* Fail:return false */ -static u8 bthci_GetAssocInfo(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTInfo; - struct bt_hci_info *pBtHciInfo; - u8 tempBuf[256]; - u8 i = 0; - u8 BaseMemoryShift = 0; - u16 TotalLen = 0; - struct amp_assoc_structure *pAmpAsoc; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("GetAssocInfo start\n")); - pBTInfo = GET_BT_INFO(padapter); - pBtHciInfo = &pBTInfo->BtHciInfo; - - if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar == 0) { - if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen < (MAX_AMP_ASSOC_FRAG_LEN)) - TotalLen = pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen; - else if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen == (MAX_AMP_ASSOC_FRAG_LEN)) - TotalLen = MAX_AMP_ASSOC_FRAG_LEN; - } else if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar > 0) - TotalLen = pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar; - - while ((pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar >= BaseMemoryShift) || TotalLen > BaseMemoryShift) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("GetAssocInfo, TotalLen =%d, BaseMemoryShift =%d\n", TotalLen, BaseMemoryShift)); - memcpy(tempBuf, - (u8 *)pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment+BaseMemoryShift, - TotalLen-BaseMemoryShift); - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, "GetAssocInfo :\n", - tempBuf, TotalLen-BaseMemoryShift); - - pAmpAsoc = (struct amp_assoc_structure *)tempBuf; - le16_to_cpus(&pAmpAsoc->Length); - BaseMemoryShift += 3 + pAmpAsoc->Length; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("TypeID = 0x%x, ", pAmpAsoc->TypeID)); - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, "Hex Data: \n", pAmpAsoc->Data, pAmpAsoc->Length); - switch (pAmpAsoc->TypeID) { - case AMP_MAC_ADDR: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_MAC_ADDR\n")); - if (pAmpAsoc->Length > 6) - return false; - memcpy(pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr, pAmpAsoc->Data, 6); - RTPRINT_ADDR(FIOCTL, IOCTL_BT_HCICMD, ("Remote Mac address \n"), pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr); - break; - case AMP_PREFERRED_CHANNEL_LIST: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_PREFERRED_CHANNEL_LIST\n")); - pBtHciInfo->BtPreChnlListLen = pAmpAsoc->Length; - memcpy(pBtHciInfo->BTPreChnllist, - pAmpAsoc->Data, - pBtHciInfo->BtPreChnlListLen); - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, "Preferred channel list : \n", pBtHciInfo->BTPreChnllist, pBtHciInfo->BtPreChnlListLen); - bthci_DecideBTChannel(padapter, EntryNum); - break; - case AMP_CONNECTED_CHANNEL: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_CONNECTED_CHANNEL\n")); - pBtHciInfo->BTConnectChnlListLen = pAmpAsoc->Length; - memcpy(pBtHciInfo->BTConnectChnllist, - pAmpAsoc->Data, - pBtHciInfo->BTConnectChnlListLen); - break; - case AMP_80211_PAL_CAP_LIST: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_80211_PAL_CAP_LIST\n")); - pBTInfo->BtAsocEntry[EntryNum].BTCapability = *(u32 *)(pAmpAsoc->Data); - if (pBTInfo->BtAsocEntry[EntryNum].BTCapability & 0x00000001) { - /* TODO: */ - - /* Signifies PAL capable of utilizing received activity reports. */ - } - if (pBTInfo->BtAsocEntry[EntryNum].BTCapability & 0x00000002) { - /* TODO: */ - /* Signifies PAL is capable of utilizing scheduling information received in an activity reports. */ - } - break; - case AMP_80211_PAL_VISION: - pBtHciInfo->BTPalVersion = *(u8 *)(pAmpAsoc->Data); - pBtHciInfo->BTPalCompanyID = *(u16 *)(((u8 *)(pAmpAsoc->Data))+1); - pBtHciInfo->BTPalsubversion = *(u16 *)(((u8 *)(pAmpAsoc->Data))+3); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("==> AMP_80211_PAL_VISION PalVersion 0x%x, PalCompanyID 0x%x, Palsubversion 0x%x\n", - pBtHciInfo->BTPalVersion, - pBtHciInfo->BTPalCompanyID, - pBtHciInfo->BTPalsubversion)); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> Unsupport TypeID !!\n")); - break; - } - i++; - } - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("GetAssocInfo end\n")); - - return true; -} - -static u8 bthci_AddEntry(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - u8 i; - - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if (pBTInfo->BtAsocEntry[i].bUsed == false) { - pBTInfo->BtAsocEntry[i].bUsed = true; - pBtMgnt->CurrentConnectEntryNum = i; - break; - } - } - - if (i == MAX_BT_ASOC_ENTRY_NUM) { - RTPRINT(FIOCTL, IOCTL_STATE, ("bthci_AddEntry(), Add entry fail!!\n")); - return false; - } - return true; -} - -static u8 bthci_DiscardTxPackets(struct rtw_adapter *padapter, u16 LLH) -{ - return false; -} - -static u8 -bthci_CheckLogLinkBehavior( - struct rtw_adapter *padapter, - struct hci_flow_spec TxFlowSpec - ) -{ - u8 ID = TxFlowSpec.Identifier; - u8 ServiceType = TxFlowSpec.ServiceType; - u16 MaxSDUSize = TxFlowSpec.MaximumSDUSize; - u32 SDUInterArrivatime = TxFlowSpec.SDUInterArrivalTime; - u8 match = false; - - switch (ID) { - case 1: - if (ServiceType == BT_LL_BE) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX best effort flowspec\n")); - } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 0xffff)) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX guaranteed latency flowspec\n")); - } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 2500)) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX guaranteed Large latency flowspec\n")); - } - break; - case 2: - if (ServiceType == BT_LL_BE) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX best effort flowspec\n")); - - } - break; - case 3: - if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 1492)) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX guaranteed latency flowspec\n")); - } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 2500)) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX guaranteed Large latency flowspec\n")); - } - break; - case 4: - if (ServiceType == BT_LL_BE) { - if ((SDUInterArrivatime == 0xffffffff) && (ServiceType == BT_LL_BE) && (MaxSDUSize == 1492)) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX/RX aggregated best effort flowspec\n")); - } - } else if (ServiceType == BT_LL_GU) { - if (SDUInterArrivatime == 100) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX/RX guaranteed bandwidth flowspec\n")); - } - } - break; - default: - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = Unknow Type !!!!!!!!\n")); - break; - } - - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), - ("ID = 0x%x, ServiceType = 0x%x, MaximumSDUSize = 0x%x, SDUInterArrivalTime = 0x%x, AccessLatency = 0x%x, FlushTimeout = 0x%x\n", - TxFlowSpec.Identifier, TxFlowSpec.ServiceType, MaxSDUSize, - SDUInterArrivatime, TxFlowSpec.AccessLatency, TxFlowSpec.FlushTimeout)); - return match; -} - -static u16 bthci_AssocMACAddr(struct rtw_adapter *padapter, void *pbuf) -{ - struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf; - pAssoStrc->TypeID = AMP_MAC_ADDR; - pAssoStrc->Length = 0x06; - memcpy(&pAssoStrc->Data[0], padapter->eeprompriv.mac_addr, 6); - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), - ("AssocMACAddr : \n"), pAssoStrc, pAssoStrc->Length+3); - - return pAssoStrc->Length + 3; -} - -static u16 -bthci_PALCapabilities( - struct rtw_adapter *padapter, - void *pbuf - ) -{ - struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf; - - pAssoStrc->TypeID = AMP_80211_PAL_CAP_LIST; - pAssoStrc->Length = 0x04; - - pAssoStrc->Data[0] = 0x00; - pAssoStrc->Data[1] = 0x00; - - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("PALCapabilities:\n"), pAssoStrc, pAssoStrc->Length+3); - RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("PALCapabilities \n")); - - RTPRINT(FIOCTL, IOCTL_BT_LOGO, (" TypeID = 0x%x,\n Length = 0x%x,\n Content = 0x0000\n", - pAssoStrc->TypeID, - pAssoStrc->Length)); - - return pAssoStrc->Length + 3; -} - -static u16 bthci_AssocPreferredChannelList(struct rtw_adapter *padapter, - void *pbuf, u8 EntryNum) -{ - struct bt_30info *pBTInfo; - struct amp_assoc_structure *pAssoStrc; - struct amp_pref_chnl_regulatory *pReg; - struct chnl_txpower_triple *pTriple; - char ctrString[3] = {'X', 'X', 'X'}; - u32 len = 0; - u8 preferredChnl; - - pBTInfo = GET_BT_INFO(padapter); - pAssoStrc = (struct amp_assoc_structure *)pbuf; - pReg = (struct amp_pref_chnl_regulatory *)&pAssoStrc->Data[3]; - - preferredChnl = bthci_GetLocalChannel(padapter); - pAssoStrc->TypeID = AMP_PREFERRED_CHANNEL_LIST; - - /* locale unknown */ - memcpy(&pAssoStrc->Data[0], &ctrString[0], 3); - pReg->reXId = 201; - pReg->regulatoryClass = 254; - pReg->coverageClass = 0; - len += 6; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("PREFERRED_CHNL_LIST\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("XXX, 201, 254, 0\n")); - /* at the following, chnl 1~11 should be contained */ - pTriple = (struct chnl_txpower_triple *)&pAssoStrc->Data[len]; - - /* (1) if any wifi or bt HS connection exists */ - if ((pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_CREATOR) || - (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE | - WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | - WIFI_AP_STATE)) || - BTHCI_HsConnectionEstablished(padapter)) { - pTriple->FirstChnl = preferredChnl; - pTriple->NumChnls = 1; - pTriple->MaxTxPowerInDbm = 20; - len += 3; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("First Channel = %d, Channel Num = %d, MaxDbm = %d\n", - pTriple->FirstChnl, - pTriple->NumChnls, - pTriple->MaxTxPowerInDbm)); - } - - pAssoStrc->Length = (u16)len; - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, ("AssocPreferredChannelList : \n"), pAssoStrc, pAssoStrc->Length+3); - - return pAssoStrc->Length + 3; -} - -static u16 bthci_AssocPALVer(struct rtw_adapter *padapter, void *pbuf) -{ - struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf; - u8 *pu1Tmp; - u16 *pu2Tmp; - - pAssoStrc->TypeID = AMP_80211_PAL_VISION; - pAssoStrc->Length = 0x5; - pu1Tmp = &pAssoStrc->Data[0]; - *pu1Tmp = 0x1; /* PAL Version */ - pu2Tmp = (u16 *)&pAssoStrc->Data[1]; - *pu2Tmp = 0x5D; /* SIG Company identifier of 802.11 PAL vendor */ - pu2Tmp = (u16 *)&pAssoStrc->Data[3]; - *pu2Tmp = 0x1; /* PAL Sub-version specifier */ - - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("AssocPALVer : \n"), pAssoStrc, pAssoStrc->Length+3); - RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("AssocPALVer \n")); - - RTPRINT(FIOCTL, IOCTL_BT_LOGO, (" TypeID = 0x%x,\n Length = 0x%x,\n PAL Version = 0x01,\n PAL vendor = 0x01,\n PAL Sub-version specifier = 0x01\n", - pAssoStrc->TypeID, - pAssoStrc->Length)); - return pAssoStrc->Length + 3; -} - -static u8 bthci_CheckRfStateBeforeConnect(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo; - enum rt_rf_power_state RfState; - - pBTInfo = GET_BT_INFO(padapter); - - RfState = padapter->pwrctrlpriv.rf_pwrstate; - - if (RfState != rf_on) { - mod_timer(&pBTInfo->BTPsDisableTimer, - jiffies + msecs_to_jiffies(50)); - return false; - } - return true; -} - -static void bthci_ResponderStartToScan(struct rtw_adapter *padapter) -{ -} - -static u8 bthci_PhyLinkConnectionInProgress(struct rtw_adapter *padapter, u8 PhyLinkHandle) -{ - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->bPhyLinkInProgress && - (pBtMgnt->BtCurrentPhyLinkhandle == PhyLinkHandle)) - return true; - return false; -} - -static void bthci_ResetFlowSpec(struct rtw_adapter *padapter, u8 EntryNum, u8 index) -{ - struct bt_30info *pBTinfo; - - pBTinfo = GET_BT_INFO(padapter); - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtLogLinkhandle = 0; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtPhyLinkhandle = 0; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].bLLCompleteEventIsSet = false; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].bLLCancelCMDIsSetandComplete = false; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtTxFlowSpecID = 0; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].TxPacketCount = 0; - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.Identifier = 0x01; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.ServiceType = SERVICE_BEST_EFFORT; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.MaximumSDUSize = 0xffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.SDUInterArrivalTime = 0xffffffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.AccessLatency = 0xffffffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.FlushTimeout = 0xffffffff; - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.Identifier = 0x01; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.ServiceType = SERVICE_BEST_EFFORT; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.MaximumSDUSize = 0xffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.SDUInterArrivalTime = 0xffffffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.AccessLatency = 0xffffffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.FlushTimeout = 0xffffffff; -} - -static void bthci_ResetEntry(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTinfo; - struct bt_mgnt *pBtMgnt; - u8 j; - - pBTinfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTinfo->BtMgnt; - - pBTinfo->BtAsocEntry[EntryNum].bUsed = false; - pBTinfo->BtAsocEntry[EntryNum].BtCurrentState = HCI_STATE_DISCONNECTED; - pBTinfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED; - - pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen = 0; - pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle = 0; - if (pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment != NULL) - memset(pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment, 0, TOTAL_ALLOCIATE_ASSOC_LEN); - pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar = 0; - - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType = 0; - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle = 0; - memset(pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, 0, - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen); - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen = 0; - - /* 0x640; 0.625ms*1600 = 1000ms, 0.625ms*16000 = 10000ms */ - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout = 0x3e80; - - pBTinfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_NONE; - - pBTinfo->BtAsocEntry[EntryNum].mAssoc = false; - pBTinfo->BtAsocEntry[EntryNum].b4waySuccess = false; - - /* Reset BT WPA */ - pBTinfo->BtAsocEntry[EntryNum].KeyReplayCounter = 0; - pBTinfo->BtAsocEntry[EntryNum].BTWPAAuthState = STATE_WPA_AUTH_UNINITIALIZED; - - pBTinfo->BtAsocEntry[EntryNum].bSendSupervisionPacket = false; - pBTinfo->BtAsocEntry[EntryNum].NoRxPktCnt = 0; - pBTinfo->BtAsocEntry[EntryNum].ShortRangeMode = 0; - pBTinfo->BtAsocEntry[EntryNum].rxSuvpPktCnt = 0; - - for (j = 0; j < MAX_LOGICAL_LINK_NUM; j++) - bthci_ResetFlowSpec(padapter, EntryNum, j); - - pBtMgnt->BTAuthCount = 0; - pBtMgnt->BTAsocCount = 0; - pBtMgnt->BTCurrentConnectType = BT_DISCONNECT; - pBtMgnt->BTReceiveConnectPkt = BT_DISCONNECT; - - HALBT_RemoveKey(padapter, EntryNum); -} - -static void bthci_RemoveEntryByEntryNum(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - bthci_ResetEntry(padapter, EntryNum); - - if (pBtMgnt->CurrentBTConnectionCnt > 0) - pBtMgnt->CurrentBTConnectionCnt--; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], CurrentBTConnectionCnt = %d!!\n", - pBtMgnt->CurrentBTConnectionCnt)); - - if (pBtMgnt->CurrentBTConnectionCnt > 0) { - pBtMgnt->BtOperationOn = true; - } else { - pBtMgnt->BtOperationOn = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], Bt Operation OFF!!\n")); - } - - if (!pBtMgnt->BtOperationOn) { - del_timer_sync(&pBTInfo->BTHCIDiscardAclDataTimer); - del_timer_sync(&pBTInfo->BTBeaconTimer); - pBtMgnt->bStartSendSupervisionPkt = false; - } -} - -static u8 -bthci_CommandCompleteHeader( - u8 *pbuf, - u16 OGF, - u16 OCF, - enum hci_status status - ) -{ - struct packet_irp_hcievent_data *PPacketIrpEvent = (struct packet_irp_hcievent_data *)pbuf; - u8 NumHCI_Comm = 0x1; - - PPacketIrpEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE; - PPacketIrpEvent->Data[0] = NumHCI_Comm; /* packet # */ - PPacketIrpEvent->Data[1] = HCIOPCODELOW(OCF, OGF); - PPacketIrpEvent->Data[2] = HCIOPCODEHIGHT(OCF, OGF); - - if (OGF == OGF_EXTENSION) { - if (OCF == HCI_SET_RSSI_VALUE) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT_PERIODICAL), - ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n", - NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF)); - } else { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_EXT), - ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n", - NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF)); - } - } else { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), - ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n", - NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF)); - } - return 3; -} - -static u8 bthci_ExtensionEventHeaderRtk(u8 *pbuf, u8 extensionEvent) -{ - struct packet_irp_hcievent_data *PPacketIrpEvent = (struct packet_irp_hcievent_data *)pbuf; - PPacketIrpEvent->EventCode = HCI_EVENT_EXTENSION_RTK; - PPacketIrpEvent->Data[0] = extensionEvent; /* extension event code */ - - return 1; -} - -static enum rt_status -bthci_IndicateEvent( - struct rtw_adapter *padapter, - void *pEvntData, - u32 dataLen - ) -{ - return PlatformIndicateBTEvent(padapter, pEvntData, dataLen); -} - -static void -bthci_EventWriteRemoteAmpAssoc( - struct rtw_adapter *padapter, - enum hci_status status, - u8 PLHandle - ) -{ - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_WRITE_REMOTE_AMP_ASSOC, - status); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("PhyLinkHandle = 0x%x, status = %d\n", PLHandle, status)); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = PLHandle; - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); -} - -static void -bthci_EventEnhancedFlushComplete( - struct rtw_adapter *padapter, - u16 LLH - ) -{ - u8 localBuf[4] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("EventEnhancedFlushComplete, LLH = 0x%x\n", LLH)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_ENHANCED_FLUSH_COMPLETE; - PPacketIrpEvent->Length = 2; - /* Logical link handle */ - PPacketIrpEvent->Data[0] = TWOBYTE_LOWBYTE(LLH); - PPacketIrpEvent->Data[1] = TWOBYTE_HIGHTBYTE(LLH); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); -} - -static void -bthci_EventShortRangeModeChangeComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - u8 ShortRangeState, - u8 EntryNum - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Short Range Mode Change Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Short Range Mode Change Complete, Status = %d\n , PLH = 0x%x\n, Short_Range_Mode_State = 0x%x\n", - HciStatus, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, ShortRangeState)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE; - PPacketIrpEvent->Length = 3; - PPacketIrpEvent->Data[0] = HciStatus; - PPacketIrpEvent->Data[1] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - PPacketIrpEvent->Data[2] = ShortRangeState; - bthci_IndicateEvent(padapter, PPacketIrpEvent, 5); -} - -static void bthci_EventSendFlowSpecModifyComplete(struct rtw_adapter *padapter, - enum hci_status HciStatus, - u16 logicHandle) -{ - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE)) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), - ("[BT event], Flow Spec Modify Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), - ("[BT event], Flow Spec Modify Complete, status = 0x%x, LLH = 0x%x\n", HciStatus, logicHandle)); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE; - PPacketIrpEvent->Length = 3; - - PPacketIrpEvent->Data[0] = HciStatus; - /* Logical link handle */ - PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(logicHandle); - PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(logicHandle); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 5); -} - -static void -bthci_EventExtWifiScanNotify( - struct rtw_adapter *padapter, - u8 scanType - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 len = 0; - u8 localBuf[7] = ""; - u8 *pRetPar; - u8 *pu1Temp; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!pBtMgnt->BtOperationOn) - return; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_ExtensionEventHeaderRtk(&localBuf[0], HCI_EVENT_EXT_WIFI_SCAN_NOTIFY); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pu1Temp = (u8 *)&pRetPar[0]; - *pu1Temp = scanType; - len += 1; - - PPacketIrpEvent->Length = len; - - if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Wifi scan notify, scan type = %d\n", - scanType)); - } -} - -static void -bthci_EventAMPReceiverReport( - struct rtw_adapter *padapter, - u8 Reason - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (pBtHciInfo->bTestNeedReport) { - u8 localBuf[20] = ""; - u32 *pu4Temp; - u16 *pu2Temp; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), (" HCI_EVENT_AMP_RECEIVER_REPORT\n")); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_RECEIVER_REPORT; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = pBtHciInfo->TestCtrType; - - PPacketIrpEvent->Data[1] = Reason; - - pu4Temp = (u32 *)&PPacketIrpEvent->Data[2]; - *pu4Temp = pBtHciInfo->TestEventType; - - pu2Temp = (u16 *)&PPacketIrpEvent->Data[6]; - *pu2Temp = pBtHciInfo->TestNumOfFrame; - - pu2Temp = (u16 *)&PPacketIrpEvent->Data[8]; - *pu2Temp = pBtHciInfo->TestNumOfErrFrame; - - pu4Temp = (u32 *)&PPacketIrpEvent->Data[10]; - *pu4Temp = pBtHciInfo->TestNumOfBits; - - pu4Temp = (u32 *)&PPacketIrpEvent->Data[14]; - *pu4Temp = pBtHciInfo->TestNumOfErrBits; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 20); - - /* Return to Idel state with RX and TX off. */ - - } - - pBtHciInfo->TestNumOfFrame = 0x00; -} - -static void -bthci_EventChannelSelected( - struct rtw_adapter *padapter, - u8 EntryNum - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[3] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_CHANNEL_SELECT)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Channel Selected, Ignore to send this event due to event mask page 2\n")); - return; - } - - RTPRINT(FIOCTL, IOCTL_BT_EVENT|IOCTL_STATE, - ("[BT event], Channel Selected, PhyLinkHandle %d\n", - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_CHANNEL_SELECT; - PPacketIrpEvent->Length = 1; - PPacketIrpEvent->Data[0] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - bthci_IndicateEvent(padapter, PPacketIrpEvent, 3); -} - -static void -bthci_EventDisconnectPhyLinkComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - enum hci_status Reason, - u8 EntryNum - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Disconnect Physical Link Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Disconnect Physical Link Complete, Status = 0x%x, PLH = 0x%x Reason = 0x%x\n", - HciStatus, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, Reason)); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE; - PPacketIrpEvent->Length = 3; - PPacketIrpEvent->Data[0] = HciStatus; - PPacketIrpEvent->Data[1] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - PPacketIrpEvent->Data[2] = Reason; - bthci_IndicateEvent(padapter, PPacketIrpEvent, 5); -} - -static void -bthci_EventPhysicalLinkComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - u8 EntryNum, - u8 PLHandle - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 localBuf[4] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u8 PL_handle; - - pBtMgnt->bPhyLinkInProgress = false; - pBtDbg->dbgHciInfo.hciCmdPhyLinkStatus = HciStatus; - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_PHY_LINK_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Physical Link Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - - if (EntryNum == 0xff) { - /* connection not started yet, just use the input physical link handle to response. */ - PL_handle = PLHandle; - } else { - /* connection is under progress, use the phy link handle we recorded. */ - PL_handle = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent = false; - } - - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Physical Link Complete, Status = 0x%x PhyLinkHandle = 0x%x\n", HciStatus, - PL_handle)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_PHY_LINK_COMPLETE; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = HciStatus; - PPacketIrpEvent->Data[1] = PL_handle; - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); - -} - -static void -bthci_EventCommandStatus( - struct rtw_adapter *padapter, - u8 OGF, - u16 OCF, - enum hci_status HciStatus - ) -{ - - u8 localBuf[6] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u8 Num_Hci_Comm = 0x1; - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], CommandStatus, Opcode = 0x%02x%02x, OGF = 0x%x, OCF = 0x%x, Status = 0x%x, Num_HCI_COMM = 0x%x\n", - (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), OGF, OCF, HciStatus, Num_Hci_Comm)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_COMMAND_STATUS; - PPacketIrpEvent->Length = 4; - PPacketIrpEvent->Data[0] = HciStatus; /* current pending */ - PPacketIrpEvent->Data[1] = Num_Hci_Comm; /* packet # */ - PPacketIrpEvent->Data[2] = HCIOPCODELOW(OCF, OGF); - PPacketIrpEvent->Data[3] = HCIOPCODEHIGHT(OCF, OGF); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 6); - -} - -static void -bthci_EventLogicalLinkComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - u8 PhyLinkHandle, - u16 LogLinkHandle, - u8 LogLinkIndex, - u8 EntryNum - ) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[7] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_LOGICAL_LINK_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Logical Link Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Logical Link Complete, PhyLinkHandle = 0x%x, LogLinkHandle = 0x%x, Status = 0x%x\n", - PhyLinkHandle, LogLinkHandle, HciStatus)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_LOGICAL_LINK_COMPLETE; - PPacketIrpEvent->Length = 5; - - PPacketIrpEvent->Data[0] = HciStatus;/* status code */ - /* Logical link handle */ - PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(LogLinkHandle); - PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(LogLinkHandle); - /* Physical link handle */ - PPacketIrpEvent->Data[3] = TWOBYTE_LOWBYTE(PhyLinkHandle); - /* corresponding Tx flow spec ID */ - if (HciStatus == HCI_STATUS_SUCCESS) { - PPacketIrpEvent->Data[4] = - pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData[LogLinkIndex].Tx_Flow_Spec.Identifier; - } else { - PPacketIrpEvent->Data[4] = 0x0; - } - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 7); -} - -static void -bthci_EventDisconnectLogicalLinkComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - u16 LogLinkHandle, - enum hci_status Reason - ) -{ - u8 localBuf[6] = ""; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Logical Link Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Logical Link Complete, Status = 0x%x, LLH = 0x%x Reason = 0x%x\n", HciStatus, LogLinkHandle, Reason)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE; - PPacketIrpEvent->Length = 4; - - PPacketIrpEvent->Data[0] = HciStatus; - /* Logical link handle */ - PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(LogLinkHandle); - PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(LogLinkHandle); - /* Disconnect reason */ - PPacketIrpEvent->Data[3] = Reason; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 6); -} - -static void -bthci_EventFlushOccurred( - struct rtw_adapter *padapter, - u16 LogLinkHandle - ) -{ - u8 localBuf[4] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("bthci_EventFlushOccurred(), LLH = 0x%x\n", LogLinkHandle)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_FLUSH_OCCRUED; - PPacketIrpEvent->Length = 2; - /* Logical link handle */ - PPacketIrpEvent->Data[0] = TWOBYTE_LOWBYTE(LogLinkHandle); - PPacketIrpEvent->Data[1] = TWOBYTE_HIGHTBYTE(LogLinkHandle); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); -} - -static enum hci_status -bthci_BuildPhysicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd, - u16 OCF -) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 EntryNum, PLH; - - /* Send HCI Command status event to AMP. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - HCI_STATUS_SUCCESS); - - PLH = *((u8 *)pHciCmd->Data); - - /* Check if resource or bt connection is under progress, if yes, reject the link creation. */ - if (!bthci_AddEntry(padapter)) { - status = HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE; - bthci_EventPhysicalLinkComplete(padapter, status, INVALID_ENTRY_NUM, PLH); - return status; - } - - EntryNum = pBtMgnt->CurrentConnectEntryNum; - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle = PLH; - pBtMgnt->BtCurrentPhyLinkhandle = PLH; - - if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment == NULL) { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Create/Accept PhysicalLink, AMP controller is busy\n")); - status = HCI_STATUS_CONTROLLER_BUSY; - bthci_EventPhysicalLinkComplete(padapter, status, INVALID_ENTRY_NUM, PLH); - return status; - } - - /* Record Key and the info */ - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen = (*((u8 *)pHciCmd->Data+1)); - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType = (*((u8 *)pHciCmd->Data+2)); - memcpy(pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, - (((u8 *)pHciCmd->Data+3)), pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen); - memcpy(pBTInfo->BtAsocEntry[EntryNum].PMK, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, PMK_LEN); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildPhysicalLink, EntryNum = %d, PLH = 0x%x KeyLen = 0x%x, KeyType = 0x%x\n", - EntryNum, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType)); - RTPRINT_DATA(FIOCTL, (IOCTL_BT_LOGO|IOCTL_BT_HCICMD), ("BtAMPKey\n"), pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen); - RTPRINT_DATA(FIOCTL, (IOCTL_BT_LOGO|IOCTL_BT_HCICMD), ("PMK\n"), pBTInfo->BtAsocEntry[EntryNum].PMK, - PMK_LEN); - - if (OCF == HCI_CREATE_PHYSICAL_LINK) { - /* These macros require braces */ - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_CREATE_PHY_LINK, EntryNum); - } else if (OCF == HCI_ACCEPT_PHYSICAL_LINK) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ACCEPT_PHY_LINK, EntryNum); - } - - return status; -} - -static void -bthci_BuildLogicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd, - u16 OCF - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt; - u8 PhyLinkHandle, EntryNum; - static u16 AssignLogHandle = 1; - - struct hci_flow_spec TxFlowSpec; - struct hci_flow_spec RxFlowSpec; - u32 MaxSDUSize, ArriveTime, Bandwidth; - - PhyLinkHandle = *((u8 *)pHciCmd->Data); - - EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle); - - memcpy(&TxFlowSpec, - &pHciCmd->Data[1], sizeof(struct hci_flow_spec)); - memcpy(&RxFlowSpec, - &pHciCmd->Data[17], sizeof(struct hci_flow_spec)); - - MaxSDUSize = TxFlowSpec.MaximumSDUSize; - ArriveTime = TxFlowSpec.SDUInterArrivalTime; - - if (bthci_CheckLogLinkBehavior(padapter, TxFlowSpec) && bthci_CheckLogLinkBehavior(padapter, RxFlowSpec)) - Bandwidth = BTTOTALBANDWIDTH; - else if (MaxSDUSize == 0xffff && ArriveTime == 0xffffffff) - Bandwidth = BTTOTALBANDWIDTH; - else - Bandwidth = MaxSDUSize*8*1000/(ArriveTime+244); - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, - ("BuildLogicalLink, PhyLinkHandle = 0x%x, MaximumSDUSize = 0x%x, SDUInterArrivalTime = 0x%x, Bandwidth = 0x%x\n", - PhyLinkHandle, MaxSDUSize, ArriveTime, Bandwidth)); - - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Invalid Physical Link handle = 0x%x, status = HCI_STATUS_UNKNOW_CONNECT_ID, return\n", PhyLinkHandle)); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - /* When we receive Create/Accept logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - status); - return; - } - - if (!pBtMgnt->bLogLinkInProgress) { - if (bthci_PhyLinkConnectionInProgress(padapter, PhyLinkHandle)) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Physical link connection in progress, status = HCI_STATUS_CMD_DISALLOW, return\n")); - status = HCI_STATUS_CMD_DISALLOW; - - pBtMgnt->bPhyLinkInProgressStartLL = true; - /* When we receive Create/Accept logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - status); - - return; - } - - if (Bandwidth > BTTOTALBANDWIDTH) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("status = HCI_STATUS_QOS_REJECT, Bandwidth = 0x%x, return\n", Bandwidth)); - status = HCI_STATUS_QOS_REJECT; - - /* When we receive Create/Accept logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - status); - } else { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("status = HCI_STATUS_SUCCESS\n")); - status = HCI_STATUS_SUCCESS; - - /* When we receive Create/Accept logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - status); - - } - - if (pBTinfo->BtAsocEntry[EntryNum].BtCurrentState != HCI_STATE_CONNECTED) { - bthci_EventLogicalLinkComplete(padapter, - HCI_STATUS_CMD_DISALLOW, 0, 0, 0, EntryNum); - } else { - u8 i, find = 0; - - pBtMgnt->bLogLinkInProgress = true; - - /* find an unused logical link index and copy the data */ - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle == 0) { - enum hci_status LogCompEventstatus = HCI_STATUS_SUCCESS; - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtPhyLinkhandle = *((u8 *)pHciCmd->Data); - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle = AssignLogHandle; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildLogicalLink, EntryNum = %d, physical link handle = 0x%x, logical link handle = 0x%x\n", - EntryNum, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle)); - memcpy(&pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].Tx_Flow_Spec, - &TxFlowSpec, sizeof(struct hci_flow_spec)); - memcpy(&pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].Rx_Flow_Spec, - &RxFlowSpec, sizeof(struct hci_flow_spec)); - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCompleteEventIsSet = false; - - if (pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCancelCMDIsSetandComplete) - LogCompEventstatus = HCI_STATUS_UNKNOW_CONNECT_ID; - bthci_EventLogicalLinkComplete(padapter, - LogCompEventstatus, - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtPhyLinkhandle, - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle, i, EntryNum); - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCompleteEventIsSet = true; - - find = 1; - pBtMgnt->BtCurrentLogLinkhandle = AssignLogHandle; - AssignLogHandle++; - break; - } - } - - if (!find) { - bthci_EventLogicalLinkComplete(padapter, - HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE, 0, 0, 0, EntryNum); - } - pBtMgnt->bLogLinkInProgress = false; - } - } else { - bthci_EventLogicalLinkComplete(padapter, - HCI_STATUS_CONTROLLER_BUSY, 0, 0, 0, EntryNum); - } - -} - -static void -bthci_StartBeaconAndConnect( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd, - u8 CurrentAssocNum - ) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("StartBeaconAndConnect, CurrentAssocNum =%d, AMPRole =%d\n", - CurrentAssocNum, - pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole)); - - if (!pBtMgnt->CheckChnlIsSuit) { - bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_CONNECT_REJ_NOT_SUIT_CHNL_FOUND, CurrentAssocNum, INVALID_PL_HANDLE); - bthci_RemoveEntryByEntryNum(padapter, CurrentAssocNum); - return; - } - - if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR) { - snprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32, - "AMP-%pMF", padapter->eeprompriv.mac_addr); - } else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER) { - snprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32, - "AMP-%pMF", pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr); - } - - FillOctetString(pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid, pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 21); - pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid.Length = 21; - - /* To avoid set the start ap or connect twice, or the original connection will be disconnected. */ - if (!pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = true; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress ON!!\n")); - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_STARTING, STATE_CMD_MAC_START_COMPLETE, CurrentAssocNum); - - /* 20100325 Joseph: Check RF ON/OFF. */ - /* If RF OFF, it reschedule connecting operation after 50ms. */ - if (!bthci_CheckRfStateBeforeConnect(padapter)) - return; - - if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR) { - /* These macros need braces */ - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTING, STATE_CMD_MAC_CONNECT_COMPLETE, CurrentAssocNum); - } else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER) { - bthci_ResponderStartToScan(padapter); - } - } - RT_PRINT_STR(_module_rtl871x_mlme_c_, _drv_notice_, - "StartBeaconAndConnect, SSID:\n", - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].BTSsid.Octet, - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].BTSsid.Length); -} - -static void bthci_ResetBtMgnt(struct bt_mgnt *pBtMgnt) -{ - pBtMgnt->BtOperationOn = false; - pBtMgnt->bBTConnectInProgress = false; - pBtMgnt->bLogLinkInProgress = false; - pBtMgnt->bPhyLinkInProgress = false; - pBtMgnt->bPhyLinkInProgressStartLL = false; - pBtMgnt->DisconnectEntryNum = 0xff; - pBtMgnt->bStartSendSupervisionPkt = false; - pBtMgnt->JoinerNeedSendAuth = false; - pBtMgnt->CurrentBTConnectionCnt = 0; - pBtMgnt->BTCurrentConnectType = BT_DISCONNECT; - pBtMgnt->BTReceiveConnectPkt = BT_DISCONNECT; - pBtMgnt->BTAuthCount = 0; - pBtMgnt->btLogoTest = 0; -} - -static void bthci_ResetBtHciInfo(struct bt_hci_info *pBtHciInfo) -{ - pBtHciInfo->BTEventMask = 0; - pBtHciInfo->BTEventMaskPage2 = 0; - pBtHciInfo->ConnAcceptTimeout = 10000; - pBtHciInfo->PageTimeout = 0x30; - pBtHciInfo->LocationDomainAware = 0x0; - pBtHciInfo->LocationDomain = 0x5858; - pBtHciInfo->LocationDomainOptions = 0x58; - pBtHciInfo->LocationOptions = 0x0; - pBtHciInfo->FlowControlMode = 0x1; /* 0:Packet based data flow control mode(BR/EDR), 1: Data block based data flow control mode(AMP). */ - - pBtHciInfo->enFlush_LLH = 0; - pBtHciInfo->FLTO_LLH = 0; - - /* Test command only */ - pBtHciInfo->bTestIsEnd = true; - pBtHciInfo->bInTestMode = false; - pBtHciInfo->bTestNeedReport = false; - pBtHciInfo->TestScenario = 0xff; - pBtHciInfo->TestReportInterval = 0x01; - pBtHciInfo->TestCtrType = 0x5d; - pBtHciInfo->TestEventType = 0x00; - pBtHciInfo->TestNumOfFrame = 0; - pBtHciInfo->TestNumOfErrFrame = 0; - pBtHciInfo->TestNumOfBits = 0; - pBtHciInfo->TestNumOfErrBits = 0; -} - -static void bthci_ResetBtSec(struct rtw_adapter *padapter, struct bt_security *pBtSec) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - - /* Set BT used HW or SW encrypt !! */ - if (GET_HAL_DATA(padapter)->bBTMode) - pBtSec->bUsedHwEncrypt = true; - else - pBtSec->bUsedHwEncrypt = false; - RT_TRACE(_module_rtl871x_security_c_, _drv_info_, - "%s: bUsedHwEncrypt =%d\n", __func__, pBtSec->bUsedHwEncrypt); - - pBtSec->RSNIE.Octet = pBtSec->RSNIEBuf; -} - -static void bthci_ResetBtExtInfo(struct bt_mgnt *pBtMgnt) -{ - u8 i; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = 0; - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = 0; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = 0; - pBtMgnt->ExtConfig.linkInfo[i].BTProfile = BT_PROFILE_NONE; - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = BT_SPEC_2_1_EDR; - pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI = 0; - pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE; - pBtMgnt->ExtConfig.linkInfo[i].linkRole = BT_LINK_MASTER; - } - - pBtMgnt->ExtConfig.CurrentConnectHandle = 0; - pBtMgnt->ExtConfig.CurrentIncomingTrafficMode = 0; - pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode = 0; - pBtMgnt->ExtConfig.MIN_BT_RSSI = 0; - pBtMgnt->ExtConfig.NumberOfHandle = 0; - pBtMgnt->ExtConfig.NumberOfSCO = 0; - pBtMgnt->ExtConfig.CurrentBTStatus = 0; - pBtMgnt->ExtConfig.HCIExtensionVer = 0; - - pBtMgnt->ExtConfig.bManualControl = false; - pBtMgnt->ExtConfig.bBTBusy = false; - pBtMgnt->ExtConfig.bBTA2DPBusy = false; -} - -static enum hci_status bthci_CmdReset(struct rtw_adapter *_padapter, u8 bNeedSendEvent) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct rtw_adapter *padapter; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_hci_info *pBtHciInfo; - struct bt_security *pBtSec; - struct bt_dgb *pBtDbg; - u8 i; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_CmdReset()\n")); - - padapter = GetDefaultAdapter(_padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtHciInfo = &pBTInfo->BtHciInfo; - pBtSec = &pBTInfo->BtSec; - pBtDbg = &pBTInfo->BtDbg; - - pBTInfo->padapter = padapter; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) - bthci_ResetEntry(padapter, i); - - bthci_ResetBtMgnt(pBtMgnt); - bthci_ResetBtHciInfo(pBtHciInfo); - bthci_ResetBtSec(padapter, pBtSec); - - pBtMgnt->BTChannel = BT_Default_Chnl; - pBtMgnt->CheckChnlIsSuit = true; - - pBTInfo->BTBeaconTmrOn = false; - - pBtMgnt->bCreateSpportQos = true; - - del_timer_sync(&pBTInfo->BTHCIDiscardAclDataTimer); - del_timer_sync(&pBTInfo->BTBeaconTimer); - - HALBT_SetRtsCtsNoLenLimit(padapter); - /* */ - /* Maybe we need to take care Group != AES case !! */ - /* now we Pairwise and Group all used AES !! */ - - bthci_ResetBtExtInfo(pBtMgnt); - - /* send command complete event here when all data are received. */ - if (bNeedSendEvent) { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_RESET, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWriteRemoteAMPAssoc( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 CurrentAssocNum; - u8 PhyLinkHandle; - - pBtDbg->dbgHciInfo.hciCmdCntWriteRemoteAmpAssoc++; - PhyLinkHandle = *((u8 *)pHciCmd->Data); - CurrentAssocNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle); - - if (CurrentAssocNum == 0xff) { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, No such Handle in the Entry\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle); - return status; - } - - if (pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment == NULL) { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, AMP controller is busy\n")); - status = HCI_STATUS_CONTROLLER_BUSY; - bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle); - return status; - } - - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.BtPhyLinkhandle = PhyLinkHandle;/* u8 *)pHciCmd->Data); */ - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar = *((u16 *)((u8 *)pHciCmd->Data+1)); - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen = *((u16 *)((u8 *)pHciCmd->Data+3)); - - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, LenSoFar = 0x%x, AssocRemLen = 0x%x\n", - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar, - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen)); - - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), - ("WriteRemoteAMPAssoc fragment \n"), - pHciCmd->Data, - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen+5); - if ((pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen) > MAX_AMP_ASSOC_FRAG_LEN) { - memcpy(((u8 *)pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment+(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar*(sizeof(u8)))), - (u8 *)pHciCmd->Data+5, - MAX_AMP_ASSOC_FRAG_LEN); - } else { - memcpy((u8 *)(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment)+(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar*(sizeof(u8))), - ((u8 *)pHciCmd->Data+5), - (pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen)); - - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), "WriteRemoteAMPAssoc :\n", - pHciCmd->Data+5, pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen); - - if (!bthci_GetAssocInfo(padapter, CurrentAssocNum)) - status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE; - - bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle); - - bthci_StartBeaconAndConnect(padapter, pHciCmd, CurrentAssocNum); - } - - return status; -} - -/* 7.3.13 */ -static enum hci_status bthci_CmdReadConnectionAcceptTimeout(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_CONNECTION_ACCEPT_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pu2Temp = (u16 *)&pRetPar[1]; /* Conn_Accept_Timeout */ - *pu2Temp = pBtHciInfo->ConnAcceptTimeout; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -/* 7.3.14 */ -static enum hci_status -bthci_CmdWriteConnectionAcceptTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u16 *pu2Temp; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pu2Temp = (u16 *)&pHciCmd->Data[0]; - pBtHciInfo->ConnAcceptTimeout = *pu2Temp; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("ConnAcceptTimeout = 0x%x", - pBtHciInfo->ConnAcceptTimeout)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdReadPageTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_PAGE_TIMEOUT, - status); - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Read PageTimeout = 0x%x\n", pBtHciInfo->PageTimeout)); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pu2Temp = (u16 *)&pRetPar[1]; /* Page_Timeout */ - *pu2Temp = pBtHciInfo->PageTimeout; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdWritePageTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u16 *pu2Temp; - - pu2Temp = (u16 *)&pHciCmd->Data[0]; - pBtHciInfo->PageTimeout = *pu2Temp; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Write PageTimeout = 0x%x\n", - pBtHciInfo->PageTimeout)); - - /* send command complete event here when all data are received. */ - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_PAGE_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdReadLinkSupervisionTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u8 physicalLinkHandle, EntryNum; - - physicalLinkHandle = *((u8 *)pHciCmd->Data); - - EntryNum = bthci_GetCurrentEntryNum(padapter, physicalLinkHandle); - - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLinkSupervisionTimeout, No such Handle in the Entry\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - return status; - } - - if (pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle != physicalLinkHandle) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - { - u8 localBuf[10] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_LINK_SUPERVISION_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - pRetPar[1] = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - pRetPar[2] = 0; - pu2Temp = (u16 *)&pRetPar[3]; /* Conn_Accept_Timeout */ - *pu2Temp = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout; - len += 5; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWriteLinkSupervisionTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u8 physicalLinkHandle, EntryNum; - - physicalLinkHandle = *((u8 *)pHciCmd->Data); - - EntryNum = bthci_GetCurrentEntryNum(padapter, physicalLinkHandle); - - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("WriteLinkSupervisionTimeout, No such Handle in the Entry\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } else { - if (pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle != physicalLinkHandle) { - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } else { - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout = *((u16 *)(((u8 *)pHciCmd->Data)+2)); - RTPRINT(FIOCTL, IOCTL_STATE, ("BT Write LinkSuperversionTimeout[%d] = 0x%x\n", - EntryNum, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout)); - } - } - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_LINK_SUPERVISION_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - pRetPar[1] = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - pRetPar[2] = 0; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdEnhancedFlush( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTinfo->BtHciInfo; - u16 logicHandle; - u8 Packet_Type; - - logicHandle = *((u16 *)&pHciCmd->Data[0]); - Packet_Type = pHciCmd->Data[2]; - - if (Packet_Type != 0) - status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE; - else - pBtHciInfo->enFlush_LLH = logicHandle; - - if (bthci_DiscardTxPackets(padapter, pBtHciInfo->enFlush_LLH)) - bthci_EventFlushOccurred(padapter, pBtHciInfo->enFlush_LLH); - - /* should send command status event */ - bthci_EventCommandStatus(padapter, - OGF_SET_EVENT_MASK_COMMAND, - HCI_ENHANCED_FLUSH, - status); - - if (pBtHciInfo->enFlush_LLH) { - bthci_EventEnhancedFlushComplete(padapter, pBtHciInfo->enFlush_LLH); - pBtHciInfo->enFlush_LLH = 0; - } - - return status; -} - -static enum hci_status -bthci_CmdReadLogicalLinkAcceptTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - - pu2Temp = (u16 *)&pRetPar[1]; /* Conn_Accept_Timeout */ - *pu2Temp = pBtHciInfo->LogicalAcceptTimeout; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdWriteLogicalLinkAcceptTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pBtHciInfo->LogicalAcceptTimeout = *((u16 *)pHciCmd->Data); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdSetEventMask( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 *pu8Temp; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pu8Temp = (u8 *)&pHciCmd->Data[0]; - pBtHciInfo->BTEventMask = *pu8Temp; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("BTEventMask = 0x%"i64fmt"x\n", - pBtHciInfo->BTEventMask)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_SET_EVENT_MASK, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -/* 7.3.69 */ -static enum hci_status -bthci_CmdSetEventMaskPage2( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 *pu8Temp; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pu8Temp = (u8 *)&pHciCmd->Data[0]; - pBtHciInfo->BTEventMaskPage2 = *pu8Temp; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("BTEventMaskPage2 = 0x%"i64fmt"x\n", - pBtHciInfo->BTEventMaskPage2)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_SET_EVENT_MASK_PAGE_2, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdReadLocationData( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[12] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_LOCATION_DATA, - status); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainAware = 0x%x\n", pBtHciInfo->LocationDomainAware)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Domain = 0x%x\n", pBtHciInfo->LocationDomain)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainOptions = 0x%x\n", pBtHciInfo->LocationDomainOptions)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Options = 0x%x\n", pBtHciInfo->LocationOptions)); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - - pRetPar[1] = pBtHciInfo->LocationDomainAware; /* 0x0; Location_Domain_Aware */ - pu2Temp = (u16 *)&pRetPar[2]; /* Location_Domain */ - *pu2Temp = pBtHciInfo->LocationDomain; /* 0x5858; */ - pRetPar[4] = pBtHciInfo->LocationDomainOptions; /* 0x58; Location_Domain_Options */ - pRetPar[5] = pBtHciInfo->LocationOptions; /* 0x0; Location_Options */ - len += 6; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdWriteLocationData( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u16 *pu2Temp; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pBtHciInfo->LocationDomainAware = pHciCmd->Data[0]; - pu2Temp = (u16 *)&pHciCmd->Data[1]; - pBtHciInfo->LocationDomain = *pu2Temp; - pBtHciInfo->LocationDomainOptions = pHciCmd->Data[3]; - pBtHciInfo->LocationOptions = pHciCmd->Data[4]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainAware = 0x%x\n", pBtHciInfo->LocationDomainAware)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Domain = 0x%x\n", pBtHciInfo->LocationDomain)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainOptions = 0x%x\n", pBtHciInfo->LocationDomainOptions)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Options = 0x%x\n", pBtHciInfo->LocationOptions)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_LOCATION_DATA, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdReadFlowControlMode( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[7] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_FLOW_CONTROL_MODE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - pRetPar[1] = pBtHciInfo->FlowControlMode; /* Flow Control Mode */ - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdWriteFlowControlMode( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pBtHciInfo->FlowControlMode = pHciCmd->Data[0]; - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_FLOW_CONTROL_MODE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdReadBestEffortFlushTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u16 i, j, logicHandle; - u32 BestEffortFlushTimeout = 0xffffffff; - u8 find = 0; - - logicHandle = *((u16 *)pHciCmd->Data); - /* find an matched logical link index and copy the data */ - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) { - BestEffortFlushTimeout = pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BestEffortFlushTimeout; - find = 1; - break; - } - } - } - - if (!find) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - { - u8 localBuf[10] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u32 *pu4Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - pu4Temp = (u32 *)&pRetPar[1]; /* Best_Effort_Flush_Timeout */ - *pu4Temp = BestEffortFlushTimeout; - len += 5; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - return status; -} - -static enum hci_status -bthci_CmdWriteBestEffortFlushTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u16 i, j, logicHandle; - u32 BestEffortFlushTimeout = 0xffffffff; - u8 find = 0; - - logicHandle = *((u16 *)pHciCmd->Data); - BestEffortFlushTimeout = *((u32 *)(pHciCmd->Data+1)); - - /* find an matched logical link index and copy the data */ - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) { - pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BestEffortFlushTimeout = BestEffortFlushTimeout; - find = 1; - break; - } - } - } - - if (!find) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - return status; -} - -static enum hci_status -bthci_CmdShortRangeMode( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - u8 PhyLinkHandle, EntryNum, ShortRangeMode; - - PhyLinkHandle = pHciCmd->Data[0]; - ShortRangeMode = pHciCmd->Data[1]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PLH = 0x%x, Short_Range_Mode = 0x%x\n", PhyLinkHandle, ShortRangeMode)); - - EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle); - if (EntryNum != 0xff) { - pBTInfo->BtAsocEntry[EntryNum].ShortRangeMode = ShortRangeMode; - } else { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("No such PLH(0x%x)\n", PhyLinkHandle)); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } - - bthci_EventCommandStatus(padapter, - OGF_SET_EVENT_MASK_COMMAND, - HCI_SHORT_RANGE_MODE, - status); - - bthci_EventShortRangeModeChangeComplete(padapter, status, ShortRangeMode, EntryNum); - - return status; -} - -static enum hci_status bthci_CmdReadLocalSupportedCommands(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar, *pSupportedCmds; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - /* send command complete event here when all data are received. */ - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_LOCAL_SUPPORTED_COMMANDS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - pSupportedCmds = &pRetPar[1]; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[5]= 0xc0\nBit [6]= Set Event Mask, [7]= Reset\n")); - pSupportedCmds[5] = 0xc0; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[6]= 0x01\nBit [0]= Set Event Filter\n")); - pSupportedCmds[6] = 0x01; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[7]= 0x0c\nBit [2]= Read Connection Accept Timeout, [3]= Write Connection Accept Timeout\n")); - pSupportedCmds[7] = 0x0c; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[10]= 0x80\nBit [7]= Host Number Of Completed Packets\n")); - pSupportedCmds[10] = 0x80; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[11]= 0x03\nBit [0]= Read Link Supervision Timeout, [1]= Write Link Supervision Timeout\n")); - pSupportedCmds[11] = 0x03; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[14]= 0xa8\nBit [3]= Read Local Version Information, [5]= Read Local Supported Features, [7]= Read Buffer Size\n")); - pSupportedCmds[14] = 0xa8; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[15]= 0x1c\nBit [2]= Read Failed Contact Count, [3]= Reset Failed Contact Count, [4]= Get Link Quality\n")); - pSupportedCmds[15] = 0x1c; - /* pSupportedCmds[16] = 0x04; */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[19]= 0x40\nBit [6]= Enhanced Flush\n")); - pSupportedCmds[19] = 0x40; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[21]= 0xff\nBit [0]= Create Physical Link, [1]= Accept Physical Link, [2]= Disconnect Physical Link, [3]= Create Logical Link\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" [4]= Accept Logical Link, [5]= Disconnect Logical Link, [6]= Logical Link Cancel, [7]= Flow Spec Modify\n")); - pSupportedCmds[21] = 0xff; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[22]= 0xff\nBit [0]= Read Logical Link Accept Timeout, [1]= Write Logical Link Accept Timeout, [2]= Set Event Mask Page 2, [3]= Read Location Data\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" [4]= Write Location Data, [5]= Read Local AMP Info, [6]= Read Local AMP_ASSOC, [7]= Write Remote AMP_ASSOC\n")); - pSupportedCmds[22] = 0xff; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[23]= 0x07\nBit [0]= Read Flow Control Mode, [1]= Write Flow Control Mode, [2]= Read Data Block Size\n")); - pSupportedCmds[23] = 0x07; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[24]= 0x1c\nBit [2]= Read Best Effort Flush Timeout, [3]= Write Best Effort Flush Timeout, [4]= Short Range Mode\n")); - pSupportedCmds[24] = 0x1c; - len += 64; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status bthci_CmdReadLocalSupportedFeatures(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - /* send command complete event here when all data are received. */ - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_LOCAL_SUPPORTED_FEATURES, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 9; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status bthci_CmdReadLocalAMPAssoc(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 PhyLinkHandle, EntryNum; - - pBtDbg->dbgHciInfo.hciCmdCntReadLocalAmpAssoc++; - PhyLinkHandle = *((u8 *)pHciCmd->Data); - EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle); - - if ((EntryNum == 0xff) && PhyLinkHandle != 0) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, EntryNum = %d !!!!!, physical link handle = 0x%x\n", - EntryNum, PhyLinkHandle)); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } else if (pBtMgnt->bPhyLinkInProgressStartLL) { - status = HCI_STATUS_UNKNOW_CONNECT_ID; - pBtMgnt->bPhyLinkInProgressStartLL = false; - } else { - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle = *((u8 *)pHciCmd->Data); - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar = *((u16 *)((u8 *)pHciCmd->Data+1)); - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.MaxRemoteASSOCLen = *((u16 *)((u8 *)pHciCmd->Data+3)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("ReadLocalAMPAssoc, LenSoFar =%d, MaxRemoteASSOCLen =%d\n", - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar, - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.MaxRemoteASSOCLen)); - } - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, EntryNum = %d !!!!!, physical link handle = 0x%x, LengthSoFar = %x \n", - EntryNum, PhyLinkHandle, pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar)); - - /* send command complete event here when all data are received. */ - { - struct packet_irp_hcievent_data *PPacketIrpEvent; - - /* PVOID buffer = padapter->IrpHCILocalbuf.Ptr; */ - u8 localBuf[TmpLocalBufSize] = ""; - u16 *pRemainLen; - u32 totalLen = 0; - u16 typeLen = 0, remainLen = 0, ret_index = 0; - u8 *pRetPar; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - totalLen += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_READ_LOCAL_AMP_ASSOC, - status); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, Remaining_Len =%d \n", remainLen)); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[totalLen]; - pRetPar[0] = status; /* status */ - pRetPar[1] = *((u8 *)pHciCmd->Data); - pRemainLen = (u16 *)&pRetPar[2]; /* AMP_ASSOC_Remaining_Length */ - totalLen += 4; /* 0]~[3] */ - ret_index = 4; - - typeLen = bthci_AssocMACAddr(padapter, &pRetPar[ret_index]); - totalLen += typeLen; - remainLen += typeLen; - ret_index += typeLen; - typeLen = bthci_AssocPreferredChannelList(padapter, &pRetPar[ret_index], EntryNum); - totalLen += typeLen; - remainLen += typeLen; - ret_index += typeLen; - typeLen = bthci_PALCapabilities(padapter, &pRetPar[ret_index]); - totalLen += typeLen; - remainLen += typeLen; - ret_index += typeLen; - typeLen = bthci_AssocPALVer(padapter, &pRetPar[ret_index]); - totalLen += typeLen; - remainLen += typeLen; - PPacketIrpEvent->Length = (u8)totalLen; - *pRemainLen = remainLen; /* AMP_ASSOC_Remaining_Length */ - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, Remaining_Len =%d \n", remainLen)); - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("AMP_ASSOC_fragment : \n"), PPacketIrpEvent->Data, totalLen); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, totalLen+2); - } - - return status; -} - -static enum hci_status bthci_CmdReadFailedContactCounter(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 handle; - - handle = *((u16 *)pHciCmd->Data); - /* send command complete event here when all data are received. */ - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_READ_FAILED_CONTACT_COUNTER, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = TWOBYTE_LOWBYTE(handle); - pRetPar[2] = TWOBYTE_HIGHTBYTE(handle); - pRetPar[3] = TWOBYTE_LOWBYTE(pBtHciInfo->FailContactCount); - pRetPar[4] = TWOBYTE_HIGHTBYTE(pBtHciInfo->FailContactCount); - len += 5; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdResetFailedContactCounter( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u16 handle; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - handle = *((u16 *)pHciCmd->Data); - pBtHciInfo->FailContactCount = 0; - - /* send command complete event here when all data are received. */ - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_RESET_FAILED_CONTACT_COUNTER, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = TWOBYTE_LOWBYTE(handle); - pRetPar[2] = TWOBYTE_HIGHTBYTE(handle); - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -/* */ -/* BT 3.0+HS [Vol 2] 7.4.1 */ -/* */ -static enum hci_status -bthci_CmdReadLocalVersionInformation( - struct rtw_adapter *padapter - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - /* send command complete event here when all data are received. */ - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_LOCAL_VERSION_INFORMATION, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = 0x05; /* HCI_Version */ - pu2Temp = (u16 *)&pRetPar[2]; /* HCI_Revision */ - *pu2Temp = 0x0001; - pRetPar[4] = 0x05; /* LMP/PAL_Version */ - pu2Temp = (u16 *)&pRetPar[5]; /* Manufacturer_Name */ - *pu2Temp = 0x005d; - pu2Temp = (u16 *)&pRetPar[7]; /* LMP/PAL_Subversion */ - *pu2Temp = 0x0001; - len += 9; - PPacketIrpEvent->Length = len; - - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LOCAL_VERSION_INFORMATION\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("Status %x\n", status)); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI_Version = 0x05\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI_Revision = 0x0001\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LMP/PAL_Version = 0x05\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("Manufacturer_Name = 0x0001\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LMP/PAL_Subversion = 0x0001\n")); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -/* 7.4.7 */ -static enum hci_status bthci_CmdReadDataBlockSize(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_DATA_BLOCK_SIZE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = HCI_STATUS_SUCCESS; /* status */ - pu2Temp = (u16 *)&pRetPar[1]; /* Max_ACL_Data_Packet_Length */ - *pu2Temp = Max80211PALPDUSize; - - pu2Temp = (u16 *)&pRetPar[3]; /* Data_Block_Length */ - *pu2Temp = Max80211PALPDUSize; - pu2Temp = (u16 *)&pRetPar[5]; /* Total_Num_Data_Blocks */ - *pu2Temp = BTTotalDataBlockNum; - len += 7; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -/* 7.4.5 */ -static enum hci_status bthci_CmdReadBufferSize(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_BUFFER_SIZE, - status); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Synchronous_Data_Packet_Length = 0x%x\n", BTSynDataPacketLength)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Total_Num_ACL_Data_Packets = 0x%x\n", BTTotalDataBlockNum)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Total_Num_Synchronous_Data_Packets = 0x%x\n", BTTotalDataBlockNum)); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pu2Temp = (u16 *)&pRetPar[1]; /* HC_ACL_Data_Packet_Length */ - *pu2Temp = Max80211PALPDUSize; - - pRetPar[3] = BTSynDataPacketLength; /* HC_Synchronous_Data_Packet_Length */ - pu2Temp = (u16 *)&pRetPar[4]; /* HC_Total_Num_ACL_Data_Packets */ - *pu2Temp = BTTotalDataBlockNum; - pu2Temp = (u16 *)&pRetPar[6]; /* HC_Total_Num_Synchronous_Data_Packets */ - *pu2Temp = BTTotalDataBlockNum; - len += 8; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status bthci_CmdReadLocalAMPInfo(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - u32 *pu4Temp; - u32 TotalBandwidth = BTTOTALBANDWIDTH, MaxBandGUBandwidth = BTMAXBANDGUBANDWIDTH; - u8 ControlType = 0x01, AmpStatus = 0x01; - u32 MaxFlushTimeout = 10000, BestEffortFlushTimeout = 5000; - u16 MaxPDUSize = Max80211PALPDUSize, PalCap = 0x1, AmpAssocLen = Max80211AMPASSOCLen, MinLatency = 20; - - if ((ppwrctrl->rfoff_reason & RF_CHANGE_BY_HW) || - (ppwrctrl->rfoff_reason & RF_CHANGE_BY_SW)) { - AmpStatus = AMP_STATUS_NO_CAPACITY_FOR_BT; - } - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_READ_LOCAL_AMP_INFO, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = AmpStatus; /* AMP_Status */ - pu4Temp = (u32 *)&pRetPar[2]; /* Total_Bandwidth */ - *pu4Temp = TotalBandwidth; /* 0x19bfcc00;0x7530; */ - pu4Temp = (u32 *)&pRetPar[6]; /* Max_Guaranteed_Bandwidth */ - *pu4Temp = MaxBandGUBandwidth; /* 0x19bfcc00;0x4e20; */ - pu4Temp = (u32 *)&pRetPar[10]; /* Min_Latency */ - *pu4Temp = MinLatency; /* 150; */ - pu4Temp = (u32 *)&pRetPar[14]; /* Max_PDU_Size */ - *pu4Temp = MaxPDUSize; - pRetPar[18] = ControlType; /* Controller_Type */ - pu2Temp = (u16 *)&pRetPar[19]; /* PAL_Capabilities */ - *pu2Temp = PalCap; - pu2Temp = (u16 *)&pRetPar[21]; /* AMP_ASSOC_Length */ - *pu2Temp = AmpAssocLen; - pu4Temp = (u32 *)&pRetPar[23]; /* Max_Flush_Timeout */ - *pu4Temp = MaxFlushTimeout; - pu4Temp = (u32 *)&pRetPar[27]; /* Best_Effort_Flush_Timeout */ - *pu4Temp = BestEffortFlushTimeout; - len += 31; - PPacketIrpEvent->Length = len; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("AmpStatus = 0x%x\n", - AmpStatus)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("TotalBandwidth = 0x%x, MaxBandGUBandwidth = 0x%x, MinLatency = 0x%x, \n MaxPDUSize = 0x%x, ControlType = 0x%x\n", - TotalBandwidth, MaxBandGUBandwidth, MinLatency, MaxPDUSize, ControlType)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PalCap = 0x%x, AmpAssocLen = 0x%x, MaxFlushTimeout = 0x%x, BestEffortFlushTimeout = 0x%x\n", - PalCap, AmpAssocLen, MaxFlushTimeout, BestEffortFlushTimeout)); - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdCreatePhysicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntCreatePhyLink++; - - return bthci_BuildPhysicalLink(padapter, - pHciCmd, HCI_CREATE_PHYSICAL_LINK); -} - -static enum hci_status -bthci_CmdReadLinkQuality( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - u16 PLH; - u8 EntryNum, LinkQuality = 0x55; - - PLH = *((u16 *)&pHciCmd->Data[0]); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PLH = 0x%x\n", PLH)); - - EntryNum = bthci_GetCurrentEntryNum(padapter, (u8)PLH); - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("No such PLH(0x%x)\n", PLH)); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } - - { - u8 localBuf[11] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_READ_LINK_QUALITY, - status); - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, (" PLH = 0x%x\n Link Quality = 0x%x\n", PLH, LinkQuality)); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - *((u16 *)&pRetPar[1]) = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; /* Handle */ - pRetPar[3] = 0x55; /* Link Quailty */ - len += 4; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdCreateLogicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntCreateLogLink++; - - bthci_BuildLogicalLink(padapter, pHciCmd, - HCI_CREATE_LOGICAL_LINK); - - return HCI_STATUS_SUCCESS; -} - -static enum hci_status -bthci_CmdAcceptLogicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntAcceptLogLink++; - - bthci_BuildLogicalLink(padapter, pHciCmd, - HCI_ACCEPT_LOGICAL_LINK); - - return HCI_STATUS_SUCCESS; -} - -static enum hci_status -bthci_CmdDisconnectLogicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTinfo->BtDbg; - u16 logicHandle; - u8 i, j, find = 0, LogLinkCount = 0; - - pBtDbg->dbgHciInfo.hciCmdCntDisconnectLogLink++; - - logicHandle = *((u16 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectLogicalLink, logicHandle = 0x%x\n", logicHandle)); - - /* find an created logical link index and clear the data */ - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectLogicalLink, logicHandle is matched 0x%x\n", logicHandle)); - bthci_ResetFlowSpec(padapter, j, i); - find = 1; - pBtMgnt->DisconnectEntryNum = j; - break; - } - } - } - - if (!find) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - /* To check each */ - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[pBtMgnt->DisconnectEntryNum].LogLinkCmdData[i].BtLogLinkhandle != 0) - LogLinkCount++; - } - - /* When we receive Create logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - HCI_DISCONNECT_LOGICAL_LINK, - status); - /* */ - /* When we determines the logical link is established, we should send command complete event. */ - /* */ - if (status == HCI_STATUS_SUCCESS) { - bthci_EventDisconnectLogicalLinkComplete(padapter, status, - logicHandle, HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST); - } - - if (LogLinkCount == 0) - mod_timer(&pBTinfo->BTDisconnectPhyLinkTimer, - jiffies + msecs_to_jiffies(100)); - - return status; -} - -static enum hci_status -bthci_CmdLogicalLinkCancel(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt; - u8 CurrentEntryNum, CurrentLogEntryNum; - - u8 physicalLinkHandle, TxFlowSpecID, i; - u16 CurrentLogicalHandle; - - physicalLinkHandle = *((u8 *)pHciCmd->Data); - TxFlowSpecID = *(((u8 *)pHciCmd->Data)+1); - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, physicalLinkHandle = 0x%x, TxFlowSpecID = 0x%x\n", - physicalLinkHandle, TxFlowSpecID)); - - CurrentEntryNum = pBtMgnt->CurrentConnectEntryNum; - CurrentLogicalHandle = pBtMgnt->BtCurrentLogLinkhandle; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("CurrentEntryNum = 0x%x, CurrentLogicalHandle = 0x%x\n", - CurrentEntryNum, CurrentLogicalHandle)); - - CurrentLogEntryNum = 0xff; - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if ((CurrentLogicalHandle == pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[i].BtLogLinkhandle) && - (physicalLinkHandle == pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[i].BtPhyLinkhandle)) { - CurrentLogEntryNum = i; - break; - } - } - - if (CurrentLogEntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, CurrentLogEntryNum == 0xff !!!!\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - return status; - } else { - if (pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].bLLCompleteEventIsSet) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, LLCompleteEventIsSet!!!!\n")); - status = HCI_STATUS_ACL_CONNECT_EXISTS; - } - } - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - LINK_CONTROL_COMMANDS, - HCI_LOGICAL_LINK_CANCEL, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].BtPhyLinkhandle; - pRetPar[2] = pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].BtTxFlowSpecID; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].bLLCancelCMDIsSetandComplete = true; - - return status; -} - -static enum hci_status -bthci_CmdFlowSpecModify(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u8 i, j, find = 0; - u16 logicHandle; - - logicHandle = *((u16 *)pHciCmd->Data); - /* find an matched logical link index and copy the data */ - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) { - memcpy(&pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Tx_Flow_Spec, - &pHciCmd->Data[2], sizeof(struct hci_flow_spec)); - memcpy(&pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Rx_Flow_Spec, - &pHciCmd->Data[18], sizeof(struct hci_flow_spec)); - - bthci_CheckLogLinkBehavior(padapter, pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Tx_Flow_Spec); - find = 1; - break; - } - } - } - RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("FlowSpecModify, LLH = 0x%x, \n", logicHandle)); - - /* When we receive Flow Spec Modify command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - HCI_FLOW_SPEC_MODIFY, - HCI_STATUS_SUCCESS); - - if (!find) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - bthci_EventSendFlowSpecModifyComplete(padapter, status, logicHandle); - - return status; -} - -static enum hci_status -bthci_CmdAcceptPhysicalLink(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntAcceptPhyLink++; - - return bthci_BuildPhysicalLink(padapter, - pHciCmd, HCI_ACCEPT_PHYSICAL_LINK); -} - -static enum hci_status -bthci_CmdDisconnectPhysicalLink(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 PLH, CurrentEntryNum, PhysLinkDisconnectReason; - - pBtDbg->dbgHciInfo.hciCmdCntDisconnectPhyLink++; - - PLH = *((u8 *)pHciCmd->Data); - PhysLinkDisconnectReason = *((u8 *)pHciCmd->Data+1); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK PhyHandle = 0x%x, Reason = 0x%x\n", - PLH, PhysLinkDisconnectReason)); - - CurrentEntryNum = bthci_GetCurrentEntryNum(padapter, PLH); - - if (CurrentEntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, - ("DisconnectPhysicalLink, No such Handle in the Entry\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } else { - pBTInfo->BtAsocEntry[CurrentEntryNum].PhyLinkDisconnectReason = - (enum hci_status)PhysLinkDisconnectReason; - } - /* Send HCI Command status event to AMP. */ - bthci_EventCommandStatus(padapter, LINK_CONTROL_COMMANDS, - HCI_DISCONNECT_PHYSICAL_LINK, status); - - if (status != HCI_STATUS_SUCCESS) - return status; - - /* The macros below require { and } in the if statement */ - if (pBTInfo->BtAsocEntry[CurrentEntryNum].BtCurrentState == HCI_STATE_DISCONNECTED) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_DISCONNECT_PHY_LINK, CurrentEntryNum); - } else { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_DISCONNECT_PHY_LINK, CurrentEntryNum); - } - return status; -} - -static enum hci_status -bthci_CmdSetACLLinkDataFlowMode(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - pBtMgnt->ExtConfig.CurrentConnectHandle = *((u16 *)pHciCmd->Data); - pBtMgnt->ExtConfig.CurrentIncomingTrafficMode = *((u8 *)pHciCmd->Data)+2; - pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode = *((u8 *)pHciCmd->Data)+3; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Connection Handle = 0x%x, Incoming Traffic mode = 0x%x, Outgoing Traffic mode = 0x%x", - pBtMgnt->ExtConfig.CurrentConnectHandle, - pBtMgnt->ExtConfig.CurrentIncomingTrafficMode, - pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode)); - - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_ACL_LINK_DATA_FLOW_MODE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - pu2Temp = (u16 *)&pRetPar[1]; - *pu2Temp = pBtMgnt->ExtConfig.CurrentConnectHandle; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdSetACLLinkStatus(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 i; - u8 *pTriple; - - pBtDbg->dbgHciInfo.hciCmdCntSetAclLinkStatus++; - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "SetACLLinkStatus, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - /* Only Core Stack v251 and later version support this command. */ - pBtMgnt->bSupportProfile = true; - - pBtMgnt->ExtConfig.NumberOfHandle = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfHandle = 0x%x\n", pBtMgnt->ExtConfig.NumberOfHandle)); - - pTriple = &pHciCmd->Data[1]; - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]); - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = pTriple[2]; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = pTriple[3]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, - ("Connection_Handle = 0x%x, Incoming Traffic mode = 0x%x, Outgoing Traffic Mode = 0x%x\n", - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle, - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode, - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode)); - pTriple += 4; - } - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_ACL_LINK_STATUS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdSetSCOLinkStatus( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntSetScoLinkStatus++; - pBtMgnt->ExtConfig.NumberOfSCO = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfSCO = 0x%x\n", - pBtMgnt->ExtConfig.NumberOfSCO)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_SCO_LINK_STATUS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdSetRSSIValue( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - s8 min_bt_rssi = 0; - u8 i; - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - if (pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle == *((u16 *)&pHciCmd->Data[0])) { - pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI = (s8)(pHciCmd->Data[2]); - RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, - ("Connection_Handle = 0x%x, RSSI = %d \n", - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle, - pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI)); - } - /* get the minimum bt rssi value */ - if (pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI <= min_bt_rssi) - min_bt_rssi = pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI; - } - - pBtMgnt->ExtConfig.MIN_BT_RSSI = min_bt_rssi; - RTPRINT(FBT, BT_TRACE, ("[bt rssi], the min rssi is %d\n", min_bt_rssi)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_RSSI_VALUE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdSetCurrentBluetoothStatus( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - pBtMgnt->ExtConfig.CurrentBTStatus = *((u8 *)&pHciCmd->Data[0]); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("SetCurrentBluetoothStatus, CurrentBTStatus = 0x%x\n", - pBtMgnt->ExtConfig.CurrentBTStatus)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_CURRENT_BLUETOOTH_STATUS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdExtensionVersionNotify( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntExtensionVersionNotify++; - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "ExtensionVersionNotify, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - pBtMgnt->ExtConfig.HCIExtensionVer = *((u16 *)&pHciCmd->Data[0]); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = 0x%x\n", pBtMgnt->ExtConfig.HCIExtensionVer)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_EXTENSION_VERSION_NOTIFY, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdLinkStatusNotify( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 i; - u8 *pTriple; - - pBtDbg->dbgHciInfo.hciCmdCntLinkStatusNotify++; - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "LinkStatusNotify, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - /* Current only RTL8723 support this command. */ - pBtMgnt->bSupportProfile = true; - - pBtMgnt->ExtConfig.NumberOfHandle = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfHandle = 0x%x\n", pBtMgnt->ExtConfig.NumberOfHandle)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = %d\n", pBtMgnt->ExtConfig.HCIExtensionVer)); - - pTriple = &pHciCmd->Data[1]; - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - if (pBtMgnt->ExtConfig.HCIExtensionVer < 1) { - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]); - pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2]; - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, - ("Connection_Handle = 0x%x, BTProfile =%d, BTSpec =%d\n", - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle, - pBtMgnt->ExtConfig.linkInfo[i].BTProfile, - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec)); - pTriple += 4; - } else if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1) { - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]); - pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2]; - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3]; - pBtMgnt->ExtConfig.linkInfo[i].linkRole = pTriple[4]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, - ("Connection_Handle = 0x%x, BTProfile =%d, BTSpec =%d, LinkRole =%d\n", - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle, - pBtMgnt->ExtConfig.linkInfo[i].BTProfile, - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec, - pBtMgnt->ExtConfig.linkInfo[i].linkRole)); - pTriple += 5; - } - - } - BTHCI_UpdateBTProfileRTKToMoto(padapter); - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_LINK_STATUS_NOTIFY, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdBtOperationNotify( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "Bt Operation notify, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - pBtMgnt->ExtConfig.btOperationCode = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("btOperationCode = 0x%x\n", pBtMgnt->ExtConfig.btOperationCode)); - switch (pBtMgnt->ExtConfig.btOperationCode) { - case HCI_BT_OP_NONE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Operation None!!\n")); - break; - case HCI_BT_OP_INQUIRY_START: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Inquire start!!\n")); - break; - case HCI_BT_OP_INQUIRY_FINISH: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Inquire finished!!\n")); - break; - case HCI_BT_OP_PAGING_START: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging is started!!\n")); - break; - case HCI_BT_OP_PAGING_SUCCESS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging complete successfully!!\n")); - break; - case HCI_BT_OP_PAGING_UNSUCCESS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging complete unsuccessfully!!\n")); - break; - case HCI_BT_OP_PAIRING_START: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Pairing start!!\n")); - break; - case HCI_BT_OP_PAIRING_FINISH: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Pairing finished!!\n")); - break; - case HCI_BT_OP_BT_DEV_ENABLE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : BT Device is enabled!!\n")); - break; - case HCI_BT_OP_BT_DEV_DISABLE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : BT Device is disabled!!\n")); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Unknown, error!!\n")); - break; - } - BTDM_AdjustForBtOperation(padapter); - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_BT_OPERATION_NOTIFY, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdEnableWifiScanNotify(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "Enable Wifi scan notify, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - pBtMgnt->ExtConfig.bEnableWifiScanNotify = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("bEnableWifiScanNotify = %d\n", pBtMgnt->ExtConfig.bEnableWifiScanNotify)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_ENABLE_WIFI_SCAN_NOTIFY, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWIFICurrentChannel(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - u8 chnl = pmlmeext->cur_channel; - - if (pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) { - if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - chnl += 2; - else if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - chnl -= 2; - } - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Current Channel = 0x%x\n", chnl)); - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_WIFI_CURRENT_CHANNEL, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = chnl; /* current channel */ - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWIFICurrentBandwidth(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - enum ht_channel_width bw; - u8 CurrentBW = 0; - - bw = padapter->mlmeextpriv.cur_bwmode; - - if (bw == HT_CHANNEL_WIDTH_20) - CurrentBW = 0; - else if (bw == HT_CHANNEL_WIDTH_40) - CurrentBW = 1; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Current BW = 0x%x\n", - CurrentBW)); - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_WIFI_CURRENT_BANDWIDTH, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = CurrentBW; /* current BW */ - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWIFIConnectionStatus( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 connectStatus = HCI_WIFI_NOT_CONNECTED; - - if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE)) { - if (padapter->stapriv.asoc_sta_count >= 3) - connectStatus = HCI_WIFI_CONNECTED; - else - connectStatus = HCI_WIFI_NOT_CONNECTED; - } else if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_ASOC_STATE)) { - connectStatus = HCI_WIFI_CONNECTED; - } else if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) { - connectStatus = HCI_WIFI_CONNECT_IN_PROGRESS; - } else { - connectStatus = HCI_WIFI_NOT_CONNECTED; - } - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_WIFI_CONNECTION_STATUS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = connectStatus; /* connect status */ - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdEnableDeviceUnderTestMode( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - pBtHciInfo->bInTestMode = true; - pBtHciInfo->bTestIsEnd = false; - - /* send command complete event here when all data are received. */ - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_TESTING_COMMANDS, - HCI_ENABLE_DEVICE_UNDER_TEST_MODE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdAMPTestEnd(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (!pBtHciInfo->bInTestMode) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status = HCI_STATUS_CMD_DISALLOW\n")); - status = HCI_STATUS_CMD_DISALLOW; - return status; - } - - pBtHciInfo->bTestIsEnd = true; - - del_timer_sync(&pBTInfo->BTTestSendPacketTimer); - - rtl8723a_check_bssid(padapter, true); - - /* send command complete event here when all data are received. */ - { - u8 localBuf[4] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("AMP Test End Event \n")); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_TEST_END; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = status; - PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); - } - - bthci_EventAMPReceiverReport(padapter, 0x01); - - return status; -} - -static enum hci_status -bthci_CmdAMPTestCommand(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (!pBtHciInfo->bInTestMode) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status = HCI_STATUS_CMD_DISALLOW\n")); - status = HCI_STATUS_CMD_DISALLOW; - return status; - } - - pBtHciInfo->TestScenario = *((u8 *)pHciCmd->Data); - - if (pBtHciInfo->TestScenario == 0x01) - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n")); - else if (pBtHciInfo->TestScenario == 0x02) - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n")); - else - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("No Such Test !!!!!!!!!!!!!!!!!! \n")); - - if (pBtHciInfo->bTestIsEnd) { - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("AMP Test End Event \n")); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_TEST_END; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = status; - PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario ; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); - - /* Return to Idel state with RX and TX off. */ - - return status; - } - - /* should send command status event */ - bthci_EventCommandStatus(padapter, - OGF_TESTING_COMMANDS, - HCI_AMP_TEST_COMMAND, - status); - - /* The HCI_AMP_Start Test Event shall be generated when the */ - /* HCI_AMP_Test_Command has completed and the first data is ready to be sent */ - /* or received. */ - - { - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), (" HCI_AMP_Start Test Event \n")); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_START_TEST; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = status; - PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario ; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); - - /* Return to Idel state with RX and TX off. */ - } - - if (pBtHciInfo->TestScenario == 0x01) { - /* - When in a transmitter test scenario and the frames/bursts count have been - transmitted the HCI_AMP_Test_End event shall be sent. - */ - mod_timer(&pBTInfo->BTTestSendPacketTimer, - jiffies + msecs_to_jiffies(50)); - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n")); - } else if (pBtHciInfo->TestScenario == 0x02) { - rtl8723a_check_bssid(padapter, false); - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n")); - } - - return status; -} - -static enum hci_status -bthci_CmdEnableAMPReceiverReports(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (!pBtHciInfo->bInTestMode) { - status = HCI_STATUS_CMD_DISALLOW; - /* send command complete event here when all data are received. */ - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_TESTING_COMMANDS, - HCI_ENABLE_AMP_RECEIVER_REPORTS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - return status; - } - - pBtHciInfo->bTestNeedReport = *((u8 *)pHciCmd->Data); - pBtHciInfo->TestReportInterval = (*((u8 *)pHciCmd->Data+2)); - - bthci_EventAMPReceiverReport(padapter, 0x00); - - /* send command complete event here when all data are received. */ - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_TESTING_COMMANDS, - HCI_ENABLE_AMP_RECEIVER_REPORTS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdHostBufferSize(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct packet_irp_hcievent_data *PPacketIrpEvent; - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].ACLPacketsData.ACLDataPacketLen = *((u16 *)pHciCmd->Data); - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].SyncDataPacketLen = *((u8 *)(pHciCmd->Data+2)); - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].TotalNumACLDataPackets = *((u16 *)(pHciCmd->Data+3)); - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].TotalSyncNumDataPackets = *((u16 *)(pHciCmd->Data+5)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_HOST_BUFFER_SIZE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_UnknownCMD(struct rtw_adapter *padapter, struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_UNKNOW_HCI_CMD; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntUnknown++; - bthci_EventCommandStatus(padapter, - (u8)pHciCmd->OGF, - pHciCmd->OCF, - status); - - return status; -} - -static enum hci_status -bthci_HandleOGFInformationalParameters(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - - switch (pHciCmd->OCF) { - case HCI_READ_LOCAL_VERSION_INFORMATION: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_VERSION_INFORMATION\n")); - status = bthci_CmdReadLocalVersionInformation(padapter); - break; - case HCI_READ_LOCAL_SUPPORTED_COMMANDS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_SUPPORTED_COMMANDS\n")); - status = bthci_CmdReadLocalSupportedCommands(padapter); - break; - case HCI_READ_LOCAL_SUPPORTED_FEATURES: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_SUPPORTED_FEATURES\n")); - status = bthci_CmdReadLocalSupportedFeatures(padapter); - break; - case HCI_READ_BUFFER_SIZE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_BUFFER_SIZE\n")); - status = bthci_CmdReadBufferSize(padapter); - break; - case HCI_READ_DATA_BLOCK_SIZE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_DATA_BLOCK_SIZE\n")); - status = bthci_CmdReadDataBlockSize(padapter); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFInformationalParameters(), Unknown case = 0x%x\n", pHciCmd->OCF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFSetEventMaskCMD(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - - switch (pHciCmd->OCF) { - case HCI_SET_EVENT_MASK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_MASK\n")); - status = bthci_CmdSetEventMask(padapter, pHciCmd); - break; - case HCI_RESET: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_RESET\n")); - status = bthci_CmdReset(padapter, true); - break; - case HCI_READ_CONNECTION_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_CONNECTION_ACCEPT_TIMEOUT\n")); - status = bthci_CmdReadConnectionAcceptTimeout(padapter); - break; - case HCI_SET_EVENT_FILTER: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_FILTER\n")); - break; - case HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT\n")); - status = bthci_CmdWriteConnectionAcceptTimeout(padapter, pHciCmd); - break; - case HCI_READ_PAGE_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_PAGE_TIMEOUT\n")); - status = bthci_CmdReadPageTimeout(padapter, pHciCmd); - break; - case HCI_WRITE_PAGE_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_PAGE_TIMEOUT\n")); - status = bthci_CmdWritePageTimeout(padapter, pHciCmd); - break; - case HCI_HOST_NUMBER_OF_COMPLETED_PACKETS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_HOST_NUMBER_OF_COMPLETED_PACKETS\n")); - break; - case HCI_READ_LINK_SUPERVISION_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LINK_SUPERVISION_TIMEOUT\n")); - status = bthci_CmdReadLinkSupervisionTimeout(padapter, pHciCmd); - break; - case HCI_WRITE_LINK_SUPERVISION_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LINK_SUPERVISION_TIMEOUT\n")); - status = bthci_CmdWriteLinkSupervisionTimeout(padapter, pHciCmd); - break; - case HCI_ENHANCED_FLUSH: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENHANCED_FLUSH\n")); - status = bthci_CmdEnhancedFlush(padapter, pHciCmd); - break; - case HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT\n")); - status = bthci_CmdReadLogicalLinkAcceptTimeout(padapter, pHciCmd); - break; - case HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT\n")); - status = bthci_CmdWriteLogicalLinkAcceptTimeout(padapter, pHciCmd); - break; - case HCI_SET_EVENT_MASK_PAGE_2: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_MASK_PAGE_2\n")); - status = bthci_CmdSetEventMaskPage2(padapter, pHciCmd); - break; - case HCI_READ_LOCATION_DATA: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCATION_DATA\n")); - status = bthci_CmdReadLocationData(padapter, pHciCmd); - break; - case HCI_WRITE_LOCATION_DATA: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LOCATION_DATA\n")); - status = bthci_CmdWriteLocationData(padapter, pHciCmd); - break; - case HCI_READ_FLOW_CONTROL_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_FLOW_CONTROL_MODE\n")); - status = bthci_CmdReadFlowControlMode(padapter, pHciCmd); - break; - case HCI_WRITE_FLOW_CONTROL_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_FLOW_CONTROL_MODE\n")); - status = bthci_CmdWriteFlowControlMode(padapter, pHciCmd); - break; - case HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT\n")); - status = bthci_CmdReadBestEffortFlushTimeout(padapter, pHciCmd); - break; - case HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT\n")); - status = bthci_CmdWriteBestEffortFlushTimeout(padapter, pHciCmd); - break; - case HCI_SHORT_RANGE_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SHORT_RANGE_MODE\n")); - status = bthci_CmdShortRangeMode(padapter, pHciCmd); - break; - case HCI_HOST_BUFFER_SIZE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_HOST_BUFFER_SIZE\n")); - status = bthci_CmdHostBufferSize(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFSetEventMaskCMD(), Unknown case = 0x%x\n", pHciCmd->OCF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFStatusParameters(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - - switch (pHciCmd->OCF) { - case HCI_READ_FAILED_CONTACT_COUNTER: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_FAILED_CONTACT_COUNTER\n")); - status = bthci_CmdReadFailedContactCounter(padapter, pHciCmd); - break; - case HCI_RESET_FAILED_CONTACT_COUNTER: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_RESET_FAILED_CONTACT_COUNTER\n")); - status = bthci_CmdResetFailedContactCounter(padapter, pHciCmd); - break; - case HCI_READ_LINK_QUALITY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LINK_QUALITY\n")); - status = bthci_CmdReadLinkQuality(padapter, pHciCmd); - break; - case HCI_READ_RSSI: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_RSSI\n")); - break; - case HCI_READ_LOCAL_AMP_INFO: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_AMP_INFO\n")); - status = bthci_CmdReadLocalAMPInfo(padapter); - break; - case HCI_READ_LOCAL_AMP_ASSOC: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_AMP_ASSOC\n")); - status = bthci_CmdReadLocalAMPAssoc(padapter, pHciCmd); - break; - case HCI_WRITE_REMOTE_AMP_ASSOC: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_REMOTE_AMP_ASSOC\n")); - status = bthci_CmdWriteRemoteAMPAssoc(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFStatusParameters(), Unknown case = 0x%x\n", pHciCmd->OCF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFLinkControlCMD(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - - switch (pHciCmd->OCF) { - case HCI_CREATE_PHYSICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_CREATE_PHYSICAL_LINK\n")); - status = bthci_CmdCreatePhysicalLink(padapter, pHciCmd); - break; - case HCI_ACCEPT_PHYSICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ACCEPT_PHYSICAL_LINK\n")); - status = bthci_CmdAcceptPhysicalLink(padapter, pHciCmd); - break; - case HCI_DISCONNECT_PHYSICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK\n")); - status = bthci_CmdDisconnectPhysicalLink(padapter, pHciCmd); - break; - case HCI_CREATE_LOGICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_CREATE_LOGICAL_LINK\n")); - status = bthci_CmdCreateLogicalLink(padapter, pHciCmd); - break; - case HCI_ACCEPT_LOGICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ACCEPT_LOGICAL_LINK\n")); - status = bthci_CmdAcceptLogicalLink(padapter, pHciCmd); - break; - case HCI_DISCONNECT_LOGICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_LOGICAL_LINK\n")); - status = bthci_CmdDisconnectLogicalLink(padapter, pHciCmd); - break; - case HCI_LOGICAL_LINK_CANCEL: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_LOGICAL_LINK_CANCEL\n")); - status = bthci_CmdLogicalLinkCancel(padapter, pHciCmd); - break; - case HCI_FLOW_SPEC_MODIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_FLOW_SPEC_MODIFY\n")); - status = bthci_CmdFlowSpecModify(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFLinkControlCMD(), Unknown case = 0x%x\n", pHciCmd->OCF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFTestingCMD(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - switch (pHciCmd->OCF) { - case HCI_ENABLE_DEVICE_UNDER_TEST_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENABLE_DEVICE_UNDER_TEST_MODE\n")); - bthci_CmdEnableDeviceUnderTestMode(padapter, pHciCmd); - break; - case HCI_AMP_TEST_END: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_AMP_TEST_END\n")); - bthci_CmdAMPTestEnd(padapter, pHciCmd); - break; - case HCI_AMP_TEST_COMMAND: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_AMP_TEST_COMMAND\n")); - bthci_CmdAMPTestCommand(padapter, pHciCmd); - break; - case HCI_ENABLE_AMP_RECEIVER_REPORTS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENABLE_AMP_RECEIVER_REPORTS\n")); - bthci_CmdEnableAMPReceiverReports(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFExtension(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - switch (pHciCmd->OCF) { - case HCI_SET_ACL_LINK_DATA_FLOW_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_ACL_LINK_DATA_FLOW_MODE\n")); - status = bthci_CmdSetACLLinkDataFlowMode(padapter, pHciCmd); - break; - case HCI_SET_ACL_LINK_STATUS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_ACL_LINK_STATUS\n")); - status = bthci_CmdSetACLLinkStatus(padapter, pHciCmd); - break; - case HCI_SET_SCO_LINK_STATUS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_SCO_LINK_STATUS\n")); - status = bthci_CmdSetSCOLinkStatus(padapter, pHciCmd); - break; - case HCI_SET_RSSI_VALUE: - RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("HCI_SET_RSSI_VALUE\n")); - status = bthci_CmdSetRSSIValue(padapter, pHciCmd); - break; - case HCI_SET_CURRENT_BLUETOOTH_STATUS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_CURRENT_BLUETOOTH_STATUS\n")); - status = bthci_CmdSetCurrentBluetoothStatus(padapter, pHciCmd); - break; - /* The following is for RTK8723 */ - - case HCI_EXTENSION_VERSION_NOTIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_EXTENSION_VERSION_NOTIFY\n")); - status = bthci_CmdExtensionVersionNotify(padapter, pHciCmd); - break; - case HCI_LINK_STATUS_NOTIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_LINK_STATUS_NOTIFY\n")); - status = bthci_CmdLinkStatusNotify(padapter, pHciCmd); - break; - case HCI_BT_OPERATION_NOTIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_BT_OPERATION_NOTIFY\n")); - status = bthci_CmdBtOperationNotify(padapter, pHciCmd); - break; - case HCI_ENABLE_WIFI_SCAN_NOTIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_ENABLE_WIFI_SCAN_NOTIFY\n")); - status = bthci_CmdEnableWifiScanNotify(padapter, pHciCmd); - break; - - /* The following is for IVT */ - case HCI_WIFI_CURRENT_CHANNEL: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CURRENT_CHANNEL\n")); - status = bthci_CmdWIFICurrentChannel(padapter, pHciCmd); - break; - case HCI_WIFI_CURRENT_BANDWIDTH: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CURRENT_BANDWIDTH\n")); - status = bthci_CmdWIFICurrentBandwidth(padapter, pHciCmd); - break; - case HCI_WIFI_CONNECTION_STATUS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CONNECTION_STATUS\n")); - status = bthci_CmdWIFIConnectionStatus(padapter, pHciCmd); - break; - - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static void -bthci_StateStarting(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Starting], ")); - switch (StateCmd) { - case STATE_CMD_CONNECT_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n")); - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT; - pBtMgnt->bNeedNotifyAMPNoCap = true; - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID; - - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_MAC_START_COMPLETE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_START_COMPLETE\n")); - if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_CREATOR) - bthci_EventChannelSelected(padapter, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateConnecting(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Connecting], ")); - switch (StateCmd) { - case STATE_CMD_CONNECT_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n")); - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT; - pBtMgnt->bNeedNotifyAMPNoCap = true; - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_MAC_CONNECT_COMPLETE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_COMPLETE\n")); - - if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_JOINER) { - RT_TRACE(_module_rtl871x_security_c_, _drv_info_, - "StateConnecting\n"); - } - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID; - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_DisconnectPeer(padapter, EntryNum); - - break; - case STATE_CMD_MAC_CONNECT_CANCEL_INDICATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_CANCEL_INDICATE\n")); - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONTROLLER_BUSY; - /* Because this state cmd is caused by the BTHCI_EventAMPStatusChange(), */ - /* we don't need to send event in the following BTHCI_DisconnectPeer() again. */ - pBtMgnt->bNeedNotifyAMPNoCap = false; - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateConnected(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 i; - u16 logicHandle = 0; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Connected], ")); - switch (StateCmd) { - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - /* When we are trying to disconnect the phy link, we should disconnect log link first, */ - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle != 0) { - logicHandle = pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle; - - bthci_EventDisconnectLogicalLinkComplete(padapter, HCI_STATUS_SUCCESS, - logicHandle, pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason); - - pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle = 0; - } - } - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - - case STATE_CMD_MAC_DISCONNECT_INDICATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_DISCONNECT_INDICATE\n")); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - /* TODO: Remote Host not local host */ - HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST, - EntryNum); - BTHCI_DisconnectPeer(padapter, EntryNum); - - break; - case STATE_CMD_ENTER_STATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ENTER_STATE\n")); - - if (pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n")); - } - pBTInfo->BtAsocEntry[EntryNum].BtCurrentState = HCI_STATE_CONNECTED; - pBTInfo->BtAsocEntry[EntryNum].b4waySuccess = true; - pBtMgnt->bStartSendSupervisionPkt = true; - - /* for rate adaptive */ - - rtl8723a_update_ramask(padapter, - MAX_FW_SUPPORT_MACID_NUM-1-EntryNum, 0); - - HalSetBrateCfg23a(padapter, padapter->mlmepriv.cur_network.network.SupportedRates); - BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateAuth(struct rtw_adapter *padapter, enum hci_state_with_cmd StateCmd, - u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Authenticating], ")); - switch (StateCmd) { - case STATE_CMD_CONNECT_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n")); - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT; - pBtMgnt->bNeedNotifyAMPNoCap = true; - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID; - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_4WAY_FAILED: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_4WAY_FAILED\n")); - - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_AUTH_FAIL; - pBtMgnt->bNeedNotifyAMPNoCap = true; - - BTHCI_DisconnectPeer(padapter, EntryNum); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - break; - case STATE_CMD_4WAY_SUCCESSED: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_4WAY_SUCCESSED\n")); - - bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_SUCCESS, EntryNum, INVALID_PL_HANDLE); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTED, STATE_CMD_ENTER_STATE, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateDisconnecting(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Disconnecting], ")); - switch (StateCmd) { - case STATE_CMD_MAC_CONNECT_CANCEL_INDICATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_CANCEL_INDICATE\n")); - if (pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent) { - bthci_EventPhysicalLinkComplete(padapter, - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus, - EntryNum, INVALID_PL_HANDLE); - } - - if (pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n")); - } - - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ENTER_STATE, EntryNum); - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateDisconnected(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Disconnected], ")); - switch (StateCmd) { - case STATE_CMD_CREATE_PHY_LINK: - case STATE_CMD_ACCEPT_PHY_LINK: - if (StateCmd == STATE_CMD_CREATE_PHY_LINK) - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CREATE_PHY_LINK\n")); - else - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ACCEPT_PHY_LINK\n")); - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT PS], Disable IPS and LPS\n")); - ips_leave23a(padapter); - LPS_Leave23a(padapter); - - pBtMgnt->bPhyLinkInProgress = true; - pBtMgnt->BTCurrentConnectType = BT_DISCONNECT; - pBtMgnt->CurrentBTConnectionCnt++; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], CurrentBTConnectionCnt = %d\n", - pBtMgnt->CurrentBTConnectionCnt)); - pBtMgnt->BtOperationOn = true; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], Bt Operation ON!! CurrentConnectEntryNum = %d\n", - pBtMgnt->CurrentConnectEntryNum)); - - if (pBtMgnt->bBTConnectInProgress) { - bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_CONTROLLER_BUSY, INVALID_ENTRY_NUM, pBtMgnt->BtCurrentPhyLinkhandle); - bthci_RemoveEntryByEntryNum(padapter, EntryNum); - return; - } - - if (StateCmd == STATE_CMD_CREATE_PHY_LINK) - pBTInfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_CREATOR; - else - pBTInfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_JOINER; - - /* 1. MAC not yet in selected channel */ - while (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)) { - RTPRINT(FIOCTL, IOCTL_STATE, ("Scan/Roaming/Wifi Link is in Progress, wait 200 ms\n")); - mdelay(200); - } - /* 2. MAC already in selected channel */ - RTPRINT(FIOCTL, IOCTL_STATE, ("Channel is Ready\n")); - mod_timer(&pBTInfo->BTHCIJoinTimeoutTimer, - jiffies + msecs_to_jiffies(pBtHciInfo->ConnAcceptTimeout)); - - pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent = true; - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - if (pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent) { - bthci_EventPhysicalLinkComplete(padapter, - HCI_STATUS_UNKNOW_CONNECT_ID, - EntryNum, INVALID_PL_HANDLE); - } - - if (pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n")); - } - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ENTER_STATE, EntryNum); - bthci_RemoveEntryByEntryNum(padapter, EntryNum); - break; - case STATE_CMD_ENTER_STATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ENTER_STATE\n")); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -void BTHCI_EventParse(struct rtw_adapter *padapter, void *pEvntData, u32 dataLen) -{ -} - -u8 BTHCI_HsConnectionEstablished(struct rtw_adapter *padapter) -{ - u8 bBtConnectionExist = false; - struct bt_30info *pBtinfo = GET_BT_INFO(padapter); - u8 i; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if (pBtinfo->BtAsocEntry[i].b4waySuccess) { - bBtConnectionExist = true; - break; - } - } - -/*RTPRINT(FIOCTL, IOCTL_STATE, (" BTHCI_HsConnectionEstablished(), connection exist = %d\n", bBtConnectionExist)); */ - - return bBtConnectionExist; -} - -static u8 -BTHCI_CheckProfileExist(struct rtw_adapter *padapter, - enum bt_traffic_mode_profile Profile) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 IsPRofile = false; - u8 i = 0; - - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - if (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile == Profile) { - IsPRofile = true; - break; - } - } - - return IsPRofile; -} - -void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 i = 0; - - pBtMgnt->ExtConfig.NumberOfSCO = 0; - - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE; - - if (pBtMgnt->ExtConfig.linkInfo[i].BTProfile == BT_PROFILE_SCO) - pBtMgnt->ExtConfig.NumberOfSCO++; - - pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = pBtMgnt->ExtConfig.linkInfo[i].BTProfile; - switch (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile) { - case BT_PROFILE_SCO: - break; - case BT_PROFILE_PAN: - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_BE; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_BE; - break; - case BT_PROFILE_A2DP: - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_GULB; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_GULB; - break; - case BT_PROFILE_HID: - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_GUL; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_BE; - break; - default: - break; - } - } - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RTK, NumberOfHandle = %d, NumberOfSCO = %d\n", - pBtMgnt->ExtConfig.NumberOfHandle, pBtMgnt->ExtConfig.NumberOfSCO)); -} - -void BTHCI_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bEnableWifiScanNotify) - bthci_EventExtWifiScanNotify(padapter, scanType); -} - -void -BTHCI_StateMachine( - struct rtw_adapter *padapter, - u8 StateToEnter, - enum hci_state_with_cmd StateCmd, - u8 EntryNum - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, error EntryNum = 0x%x \n", EntryNum)); - return; - } - RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, EntryNum = 0x%x, CurrentState = 0x%x, BtNextState = 0x%x, StateCmd = 0x%x , StateToEnter = 0x%x\n", - EntryNum, pBTInfo->BtAsocEntry[EntryNum].BtCurrentState, pBTInfo->BtAsocEntry[EntryNum].BtNextState, StateCmd, StateToEnter)); - - if (pBTInfo->BtAsocEntry[EntryNum].BtNextState & StateToEnter) { - pBTInfo->BtAsocEntry[EntryNum].BtCurrentState = StateToEnter; - - switch (StateToEnter) { - case HCI_STATE_STARTING: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTING | HCI_STATE_CONNECTING; - bthci_StateStarting(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_CONNECTING: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_CONNECTING | HCI_STATE_DISCONNECTING | HCI_STATE_AUTHENTICATING; - bthci_StateConnecting(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_AUTHENTICATING: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTING | HCI_STATE_CONNECTED; - bthci_StateAuth(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_CONNECTED: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_CONNECTED | HCI_STATE_DISCONNECTING; - bthci_StateConnected(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_DISCONNECTING: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED | HCI_STATE_DISCONNECTING; - bthci_StateDisconnecting(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_DISCONNECTED: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED | HCI_STATE_STARTING | HCI_STATE_CONNECTING; - bthci_StateDisconnected(padapter, StateCmd, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, Unknown state to enter!!!\n")); - break; - } - } else { - RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, Wrong state to enter\n")); - } - - /* 20100325 Joseph: Disable/Enable IPS/LPS according to BT status. */ - if (!pBtMgnt->bBTConnectInProgress && !pBtMgnt->BtOperationOn) { - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT PS], ips_enter23a()\n")); - ips_enter23a(padapter); - } -} - -void BTHCI_DisconnectPeer(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, (" BTHCI_DisconnectPeer()\n")); - - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, EntryNum); - - if (pBTInfo->BtAsocEntry[EntryNum].bUsed) { -/*BTPKT_SendDeauthentication(padapter, pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr, unspec_reason); not porting yet */ - } - - if (pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n")); - } - - bthci_RemoveEntryByEntryNum(padapter, EntryNum); - - if (pBtMgnt->bNeedNotifyAMPNoCap) { - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT AMPStatus], set to invalid in BTHCI_DisconnectPeer()\n")); - BTHCI_EventAMPStatusChange(padapter, AMP_STATUS_NO_CAPACITY_FOR_BT); - } -} - -void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar, *pTriple; - u8 len = 0, i, j, handleNum = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp, *pPackets, *pHandle, *pDblocks; - u8 sent = 0; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Num Of Completed DataBlocks, Ignore to send NumOfCompletedDataBlocksEvent due to event mask page 2\n")); - return; - } - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[0]; - pTriple = &pRetPar[3]; - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle) { - handleNum++; - pHandle = (u16 *)&pTriple[0]; /* Handle[i] */ - pPackets = (u16 *)&pTriple[2]; /* Num_Of_Completed_Packets[i] */ - pDblocks = (u16 *)&pTriple[4]; /* Num_Of_Completed_Blocks[i] */ - *pHandle = pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle; - *pPackets = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount; - *pDblocks = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount; - if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount) { - sent = 1; - RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, - ("[BT event], Num Of Completed DataBlocks, Handle = 0x%x, Num_Of_Completed_Packets = 0x%x, Num_Of_Completed_Blocks = 0x%x\n", - *pHandle, *pPackets, *pDblocks)); - } - pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount = 0; - len += 6; - pTriple += len; - } - } - } - - pRetPar[2] = handleNum; /* Number_of_Handles */ - len += 1; - pu2Temp = (u16 *)&pRetPar[0]; - *pu2Temp = BTTotalDataBlockNum; - len += 2; - - PPacketIrpEvent->EventCode = HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS; - PPacketIrpEvent->Length = len; - if (handleNum && sent) - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); -} - -void BTHCI_EventAMPStatusChange(struct rtw_adapter *padapter, u8 AMP_Status) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u8 len = 0; - u8 localBuf[7] = ""; - u8 *pRetPar; - - if (AMP_Status == AMP_STATUS_NO_CAPACITY_FOR_BT) { - pBtMgnt->BTNeedAMPStatusChg = true; - pBtMgnt->bNeedNotifyAMPNoCap = false; - - BTHCI_DisconnectAll(padapter); - } else if (AMP_Status == AMP_STATUS_FULL_CAPACITY_FOR_BT) { - pBtMgnt->BTNeedAMPStatusChg = false; - } - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[0]; - - pRetPar[0] = 0; /* Status */ - len += 1; - pRetPar[1] = AMP_Status; /* AMP_Status */ - len += 1; - - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_STATUS_CHANGE; - PPacketIrpEvent->Length = len; - if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS) - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_STATE), ("[BT event], AMP Status Change, AMP_Status = %d\n", AMP_Status)); -} - -void BTHCI_DisconnectAll(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - u8 i; - - RTPRINT(FIOCTL, IOCTL_STATE, (" DisconnectALL()\n")); - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if (pBTInfo->BtAsocEntry[i].b4waySuccess) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTED, STATE_CMD_DISCONNECT_PHY_LINK, i); - } else if (pBTInfo->BtAsocEntry[i].bUsed) { - if (pBTInfo->BtAsocEntry[i].BtCurrentState == HCI_STATE_CONNECTING) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, i); - } else if (pBTInfo->BtAsocEntry[i].BtCurrentState == HCI_STATE_DISCONNECTING) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, i); - } - } - } -} - -enum hci_status -BTHCI_HandleHCICMD( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI Command start, OGF = 0x%x, OCF = 0x%x, Length = 0x%x\n", - pHciCmd->OGF, pHciCmd->OCF, pHciCmd->Length)); - if (pHciCmd->Length) { - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), "HCI Command, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - } - if (pHciCmd->OGF == OGF_EXTENSION) { - if (pHciCmd->OCF == HCI_SET_RSSI_VALUE) - RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("[BT cmd], ")); - else - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT cmd], ")); - } else { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("[BT cmd], ")); - } - - pBtDbg->dbgHciInfo.hciCmdCnt++; - - switch (pHciCmd->OGF) { - case LINK_CONTROL_COMMANDS: - status = bthci_HandleOGFLinkControlCMD(padapter, pHciCmd); - break; - case HOLD_MODE_COMMAND: - break; - case OGF_SET_EVENT_MASK_COMMAND: - status = bthci_HandleOGFSetEventMaskCMD(padapter, pHciCmd); - break; - case OGF_INFORMATIONAL_PARAMETERS: - status = bthci_HandleOGFInformationalParameters(padapter, pHciCmd); - break; - case OGF_STATUS_PARAMETERS: - status = bthci_HandleOGFStatusParameters(padapter, pHciCmd); - break; - case OGF_TESTING_COMMANDS: - status = bthci_HandleOGFTestingCMD(padapter, pHciCmd); - break; - case OGF_EXTENSION: - status = bthci_HandleOGFExtension(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI Command(), Unknown OGF = 0x%x\n", pHciCmd->OGF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("HCI Command execution end!!\n")); - - return status; -} - -/* ===== End of sync from SD7 driver COMMOM/bt_hci.c ===== */ - -static const char *const BtStateString[] = { - "BT_DISABLED", - "BT_NO_CONNECTION", - "BT_CONNECT_IDLE", - "BT_INQ_OR_PAG", - "BT_ACL_ONLY_BUSY", - "BT_SCO_ONLY_BUSY", - "BT_ACL_SCO_BUSY", - "BT_ACL_INQ_OR_PAG", - "BT_STATE_NOT_DEFINED" -}; - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.c ===== */ - -static void btdm_SetFwIgnoreWlanAct(struct rtw_adapter *padapter, u8 bEnable) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[1] = {0}; - - if (bEnable) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Ignore Wlan_Act !!\n")); - H2C_Parameter[0] |= BIT(0); /* function enable */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT don't ignore Wlan_Act !!\n")); - } - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], set FW for BT Ignore Wlan_Act, write 0x25 = 0x%02x\n", - H2C_Parameter[0])); - - FillH2CCmd(padapter, BT_IGNORE_WLAN_ACT_EID, 1, H2C_Parameter); -} - -static void btdm_NotifyFwScan(struct rtw_adapter *padapter, u8 scanType) -{ - u8 H2C_Parameter[1] = {0}; - - if (scanType == true) - H2C_Parameter[0] = 0x1; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Notify FW for wifi scan, write 0x3b = 0x%02x\n", - H2C_Parameter[0])); - - FillH2CCmd(padapter, 0x3b, 1, H2C_Parameter); -} - -static void btdm_1AntSetPSMode(struct rtw_adapter *padapter, - u8 enable, u8 smartps, u8 mode) -{ - struct pwrctrl_priv *pwrctrl; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Current LPS(%s, %d), smartps =%d\n", enable == true?"ON":"OFF", mode, smartps)); - - pwrctrl = &padapter->pwrctrlpriv; - - if (enable == true) { - rtw_set_ps_mode23a(padapter, PS_MODE_MIN, smartps, mode); - } else { - rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0); - LPS_RF_ON_check23a(padapter, 100); - } -} - -static void btdm_1AntTSFSwitch(struct rtw_adapter *padapter, u8 enable) -{ - u8 oldVal, newVal; - - oldVal = rtl8723au_read8(padapter, 0x550); - - if (enable) - newVal = oldVal | EN_BCN_FUNCTION; - else - newVal = oldVal & ~EN_BCN_FUNCTION; - - if (oldVal != newVal) - rtl8723au_write8(padapter, 0x550, newVal); -} - -static u8 btdm_Is1AntPsTdmaStateChange(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - if ((pBtdm8723->bPrePsTdmaOn != pBtdm8723->bCurPsTdmaOn) || - (pBtdm8723->prePsTdma != pBtdm8723->curPsTdma)) - return true; - else - return false; -} - -/* Before enter TDMA, make sure Power Saving is enable! */ -static void -btdm_1AntPsTdma( - struct rtw_adapter *padapter, - u8 bTurnOn, - u8 type - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - pBtdm8723->bCurPsTdmaOn = bTurnOn; - pBtdm8723->curPsTdma = type; - if (bTurnOn) { - switch (type) { - case 1: /* A2DP Level-1 or FTP/OPP */ - default: - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* wide duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x0, 0x58); - } - break; - case 2: /* A2DP Level-2 */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* normal duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0x12, 0x12, 0x0, 0x58); - } - break; - case 3: /* BT FTP/OPP */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* normal duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0x30, 0x03, 0x10, 0x58); - - } - break; - case 4: /* for wifi scan & BT is connected */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* protect 3 beacons in 3-beacon period & no Tx pause at BT slot */ - BTDM_SetFw3a(padapter, 0x93, 0x15, 0x03, 0x14, 0x0); - } - break; - case 5: /* for WiFi connected-busy & BT is Non-Connected-Idle */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* SCO mode, Ant fixed at WiFi, WLAN_Act toggle */ - BTDM_SetFw3a(padapter, 0x61, 0x15, 0x03, 0x31, 0x00); - } - break; - case 9: /* ACL high-retry type - 2 */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* narrow duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0xa, 0xa, 0x0, 0x58); /* narrow duration for WiFi */ - } - break; - case 10: /* for WiFi connect idle & BT ACL busy or WiFi Connected-Busy & BT is Inquiry */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0x13, 0xa, 0xa, 0x0, 0x40); - break; - case 11: /* ACL high-retry type - 3 */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* narrow duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0x05, 0x05, 0x00, 0x58); - } - break; - case 12: /* for WiFi Connected-Busy & BT is Connected-Idle */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* Allow High-Pri BT */ - BTDM_SetFw3a(padapter, 0xeb, 0x0a, 0x03, 0x31, 0x18); - } - break; - case 20: /* WiFi only busy , TDMA mode for power saving */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0x13, 0x25, 0x25, 0x00, 0x00); - break; - case 27: /* WiFi DHCP/Site Survey & BT SCO busy */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xa3, 0x25, 0x03, 0x31, 0x98); - break; - case 28: /* WiFi DHCP/Site Survey & BT idle */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0x69, 0x25, 0x03, 0x31, 0x00); - break; - case 29: /* WiFi DHCP/Site Survey & BT ACL busy */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - BTDM_SetFw3a(padapter, 0xeb, 0x1a, 0x1a, 0x01, 0x18); - rtl8723au_write32(padapter, 0x6c0, 0x5afa5afa); - rtl8723au_write32(padapter, 0x6c4, 0x5afa5afa); - } - break; - case 30: /* WiFi idle & BT Inquiry */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0x93, 0x15, 0x03, 0x14, 0x00); - break; - case 31: /* BT HID */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x00, 0x58); - break; - case 32: /* BT SCO & Inquiry */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xab, 0x0a, 0x03, 0x11, 0x98); - break; - case 33: /* BT SCO & WiFi site survey */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xa3, 0x25, 0x03, 0x30, 0x98); - break; - case 34: /* BT HID & WiFi site survey */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x00, 0x18); - break; - case 35: /* BT HID & WiFi Connecting */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x00, 0x18); - break; - } - } else { - /* disable PS-TDMA */ - switch (type) { - case 8: - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* Antenna control by PTA, 0x870 = 0x310 */ - BTDM_SetFw3a(padapter, 0x8, 0x0, 0x0, 0x0, 0x0); - } - break; - case 0: - default: - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* Antenna control by PTA, 0x870 = 0x310 */ - BTDM_SetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0); - } - /* Switch Antenna to BT */ - rtl8723au_write16(padapter, 0x860, 0x210); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 0x860 = 0x210, Switch Antenna to BT\n")); - break; - case 9: - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* Antenna control by PTA, 0x870 = 0x310 */ - BTDM_SetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0); - } - /* Switch Antenna to WiFi */ - rtl8723au_write16(padapter, 0x860, 0x110); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 0x860 = 0x110, Switch Antenna to WiFi\n")); - break; - } - } - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Current TDMA(%s, %d)\n", - pBtdm8723->bCurPsTdmaOn?"ON":"OFF", pBtdm8723->curPsTdma)); - - /* update pre state */ - pBtdm8723->bPrePsTdmaOn = pBtdm8723->bCurPsTdmaOn; - pBtdm8723->prePsTdma = pBtdm8723->curPsTdma; -} - -static void -_btdm_1AntSetPSTDMA(struct rtw_adapter *padapter, u8 bPSEn, u8 smartps, - u8 psOption, u8 bTDMAOn, u8 tdmaType) -{ - struct pwrctrl_priv *pwrctrl; - struct hal_data_8723a *pHalData; - struct btdm_8723a_1ant *pBtdm8723; - u8 psMode; - u8 bSwitchPS; - - if (!check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) && - (get_fwstate(&padapter->mlmepriv) != WIFI_NULL_STATE)) { - btdm_1AntPsTdma(padapter, bTDMAOn, tdmaType); - return; - } - psOption &= ~BIT(0); - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Set LPS(%s, %d) TDMA(%s, %d)\n", - bPSEn == true?"ON":"OFF", psOption, - bTDMAOn == true?"ON":"OFF", tdmaType)); - - pwrctrl = &padapter->pwrctrlpriv; - pHalData = GET_HAL_DATA(padapter); - pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - if (bPSEn) { - if (pBtdm8723->bWiFiHalt) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi in Halt!!\n")); - return; - } - - if (pwrctrl->bInSuspend) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi in Suspend!!\n")); - return; - } - - if (padapter->bDriverStopped) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi driver stopped!!\n")); - return; - } - - if (padapter->bSurpriseRemoved) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi Surprise Removed!!\n")); - return; - } - - psMode = PS_MODE_MIN; - } else { - psMode = PS_MODE_ACTIVE; - psOption = 0; - } - - if (psMode != pwrctrl->pwr_mode) { - bSwitchPS = true; - } else if (psMode != PS_MODE_ACTIVE) { - if (psOption != pwrctrl->bcn_ant_mode) - bSwitchPS = true; - else if (smartps != pwrctrl->smart_ps) - bSwitchPS = true; - else - bSwitchPS = false; - } else { - bSwitchPS = false; - } - - if (bSwitchPS) { - /* disable TDMA */ - if (pBtdm8723->bCurPsTdmaOn) { - if (!bTDMAOn) { - btdm_1AntPsTdma(padapter, false, tdmaType); - } else { - if (!rtl8723a_BT_enabled(padapter) || - (pHalData->bt_coexist.halCoex8723.c2hBtInfo == BT_INFO_STATE_NO_CONNECTION) || - (pHalData->bt_coexist.halCoex8723.c2hBtInfo == BT_INFO_STATE_CONNECT_IDLE) || - (tdmaType == 29)) - btdm_1AntPsTdma(padapter, false, 9); - else - btdm_1AntPsTdma(padapter, false, 0); - } - } - - /* change Power Save State */ - btdm_1AntSetPSMode(padapter, bPSEn, smartps, psOption); - } - - btdm_1AntPsTdma(padapter, bTDMAOn, tdmaType); -} - -static void -btdm_1AntSetPSTDMA(struct rtw_adapter *padapter, u8 bPSEn, - u8 psOption, u8 bTDMAOn, u8 tdmaType) -{ - _btdm_1AntSetPSTDMA(padapter, bPSEn, 0, psOption, bTDMAOn, tdmaType); -} - -static void btdm_1AntWifiParaAdjust(struct rtw_adapter *padapter, u8 bEnable) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - if (bEnable) { - pBtdm8723->curWifiPara = 1; - if (pBtdm8723->preWifiPara != pBtdm8723->curWifiPara) - BTDM_SetSwPenaltyTxRateAdaptive(padapter, BT_TX_RATE_ADAPTIVE_LOW_PENALTY); - } else { - pBtdm8723->curWifiPara = 2; - if (pBtdm8723->preWifiPara != pBtdm8723->curWifiPara) - BTDM_SetSwPenaltyTxRateAdaptive(padapter, BT_TX_RATE_ADAPTIVE_NORMAL); - } - -} - -static void btdm_1AntPtaParaReload(struct rtw_adapter *padapter) -{ - /* PTA parameter */ - rtl8723au_write8(padapter, 0x6cc, 0x0); /* 1-Ant coex */ - rtl8723au_write32(padapter, 0x6c8, 0xffff); /* wifi break table */ - rtl8723au_write32(padapter, 0x6c4, 0x55555555); /* coex table */ - - /* Antenna switch control parameter */ - rtl8723au_write32(padapter, 0x858, 0xaaaaaaaa); - if (IS_8723A_A_CUT(GET_HAL_DATA(padapter)->VersionID)) { - /* SPDT(connected with TRSW) control by hardware PTA */ - rtl8723au_write32(padapter, 0x870, 0x0); - rtl8723au_write8(padapter, 0x40, 0x24); - } else { - rtl8723au_write8(padapter, 0x40, 0x20); - /* set antenna at bt side if ANTSW is software control */ - rtl8723au_write16(padapter, 0x860, 0x210); - /* SPDT(connected with TRSW) control by hardware PTA */ - rtl8723au_write32(padapter, 0x870, 0x300); - /* ANTSW keep by GNT_BT */ - rtl8723au_write32(padapter, 0x874, 0x22804000); - } - - /* coexistence parameters */ - rtl8723au_write8(padapter, 0x778, 0x1); /* enable RTK mode PTA */ - - /* BT don't ignore WLAN_Act */ - btdm_SetFwIgnoreWlanAct(padapter, false); -} - -/* - * Return - *1: upgrade (add WiFi duration time) - *0: keep - *-1: downgrade (add BT duration time) - */ -static s8 btdm_1AntTdmaJudgement(struct rtw_adapter *padapter, u8 retry) -{ - struct hal_data_8723a *pHalData; - struct btdm_8723a_1ant *pBtdm8723; - static s8 up, dn, m = 1, WaitCount; - s8 ret; - - pHalData = GET_HAL_DATA(padapter); - pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - ret = 0; - - if (pBtdm8723->psTdmaMonitorCnt == 0) { - up = 0; - dn = 0; - m = 1; - WaitCount = 0; - } else { - WaitCount++; - } - - if (retry == 0) { - /* no retry in the last 2-second duration */ - up++; - dn--; - if (dn < 0) - dn = 0; - if (up >= 3*m) { - /* retry = 0 in consecutive 3m*(2s), add WiFi duration */ - ret = 1; - up = 0; - dn = 0; - WaitCount = 0; - } - } else if (retry <= 3) { - /* retry<= 3 in the last 2-second duration */ - up--; - dn++; - if (up < 0) - up = 0; - - if (dn == 2) { - /* retry<= 3 in consecutive 2*(2s), minus WiFi duration (add BT duration) */ - ret = -1; - - /* record how many time downgrad WiFi duration */ - if (WaitCount <= 2) - m++; - else - m = 1; - /* the max number of m is 20 */ - /* the longest time of upgrade WiFi duration is 20*3*2s = 120s */ - if (m >= 20) - m = 20; - up = 0; - dn = 0; - WaitCount = 0; - } - } else { - /* retry count > 3 */ - /* retry>3, minus WiFi duration (add BT duration) */ - ret = -1; - - /* record how many time downgrad WiFi duration */ - if (WaitCount == 1) - m++; - else - m = 1; - if (m >= 20) - m = 20; - - up = 0; - dn = 0; - WaitCount = 0; - } - return ret; -} - -static void btdm_1AntTdmaDurationAdjustForACL(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - if (pBtdm8723->psTdmaGlobalCnt != pBtdm8723->psTdmaMonitorCnt) { - pBtdm8723->psTdmaMonitorCnt = 0; - pBtdm8723->psTdmaGlobalCnt = 0; - } - if (pBtdm8723->psTdmaMonitorCnt == 0) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else { - /* Now we only have 4 level Ps Tdma, */ - /* if that's not the following 4 level(will changed by wifi scan, dhcp...), */ - /* then we have to adjust it back to the previous record one. */ - if ((pBtdm8723->curPsTdma != 1) && - (pBtdm8723->curPsTdma != 2) && - (pBtdm8723->curPsTdma != 9) && - (pBtdm8723->curPsTdma != 11)) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType); - } else { - s32 judge; - - judge = btdm_1AntTdmaJudgement(padapter, pHalData->bt_coexist.halCoex8723.btRetryCnt); - if (judge == -1) { - if (pBtdm8723->curPsTdma == 1) { - /* Decrease WiFi duration for high BT retry */ - if (pHalData->bt_coexist.halCoex8723.btInfoExt) - pBtdm8723->psTdmaDuAdjType = 9; - else - pBtdm8723->psTdmaDuAdjType = 2; - btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType); - } else if (pBtdm8723->curPsTdma == 2) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, 9); - pBtdm8723->psTdmaDuAdjType = 9; - } else if (pBtdm8723->curPsTdma == 9) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } - } else if (judge == 1) { - if (pBtdm8723->curPsTdma == 11) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, 9); - pBtdm8723->psTdmaDuAdjType = 9; - } else if (pBtdm8723->curPsTdma == 9) { - if (pHalData->bt_coexist.halCoex8723.btInfoExt) - pBtdm8723->psTdmaDuAdjType = 9; - else - pBtdm8723->psTdmaDuAdjType = 2; - btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType); - } else if (pBtdm8723->curPsTdma == 2) { - if (pHalData->bt_coexist.halCoex8723.btInfoExt) - pBtdm8723->psTdmaDuAdjType = 9; - else - pBtdm8723->psTdmaDuAdjType = 1; - btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType); - } - } - } - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], ACL current TDMA(%s, %d)\n", - (pBtdm8723->bCurPsTdmaOn ? "ON" : "OFF"), pBtdm8723->curPsTdma)); - } - pBtdm8723->psTdmaMonitorCnt++; -} - -static void btdm_1AntCoexProcessForWifiConnect(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv; - struct hal_data_8723a *pHalData; - struct bt_coexist_8723a *pBtCoex; - struct btdm_8723a_1ant *pBtdm8723; - u8 BtState; - - pmlmepriv = &padapter->mlmepriv; - pHalData = GET_HAL_DATA(padapter); - pBtCoex = &pHalData->bt_coexist.halCoex8723; - pBtdm8723 = &pBtCoex->btdm1Ant; - BtState = pBtCoex->c2hBtInfo; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], WiFi is %s\n", - BTDM_IsWifiBusy(padapter)?"Busy":"IDLE")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is %s\n", - BtStateString[BtState])); - - padapter->pwrctrlpriv.btcoex_rfon = false; - - if (!BTDM_IsWifiBusy(padapter) && - !check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) && - (BtState == BT_INFO_STATE_NO_CONNECTION || - BtState == BT_INFO_STATE_CONNECT_IDLE)) { - switch (BtState) { - case BT_INFO_STATE_NO_CONNECTION: - _btdm_1AntSetPSTDMA(padapter, true, 2, 0x26, false, 9); - break; - case BT_INFO_STATE_CONNECT_IDLE: - _btdm_1AntSetPSTDMA(padapter, true, 2, 0x26, false, 0); - break; - } - } else { - switch (BtState) { - case BT_INFO_STATE_NO_CONNECTION: - case BT_INFO_STATE_CONNECT_IDLE: - /* WiFi is Busy */ - btdm_1AntSetPSTDMA(padapter, false, 0, true, 5); - rtl8723au_write32(padapter, 0x6c0, 0x5a5a5a5a); - rtl8723au_write32(padapter, 0x6c4, 0x5a5a5a5a); - break; - case BT_INFO_STATE_ACL_INQ_OR_PAG: - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is " - "BT_INFO_STATE_ACL_INQ_OR_PAG\n")); - case BT_INFO_STATE_INQ_OR_PAG: - padapter->pwrctrlpriv.btcoex_rfon = true; - btdm_1AntSetPSTDMA(padapter, true, 0, true, 30); - break; - case BT_INFO_STATE_SCO_ONLY_BUSY: - case BT_INFO_STATE_ACL_SCO_BUSY: - if (true == pBtCoex->bC2hBtInquiryPage) - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 32); - else { -#ifdef BTCOEX_CMCC_TEST - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 23); -#else /* !BTCOEX_CMCC_TEST */ - btdm_1AntSetPSTDMA(padapter, false, 0, - false, 8); - rtl8723au_write32(padapter, 0x6c0, 0x5a5a5a5a); - rtl8723au_write32(padapter, 0x6c4, 0x5a5a5a5a); -#endif /* !BTCOEX_CMCC_TEST */ - } - break; - case BT_INFO_STATE_ACL_ONLY_BUSY: - padapter->pwrctrlpriv.btcoex_rfon = true; - if (pBtCoex->c2hBtProfile == BT_INFO_HID) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is HID\n")); - btdm_1AntSetPSTDMA(padapter, true, 0, true, 31); - } else if (pBtCoex->c2hBtProfile == BT_INFO_FTP) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is FTP/OPP\n")); - btdm_1AntSetPSTDMA(padapter, true, 0, true, 3); - } else if (pBtCoex->c2hBtProfile == (BT_INFO_A2DP|BT_INFO_FTP)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is A2DP_FTP\n")); - btdm_1AntSetPSTDMA(padapter, true, 0, true, 11); - } else { - if (pBtCoex->c2hBtProfile == BT_INFO_A2DP) - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is " - "A2DP\n")); - else - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is " - "UNKNOWN(0x%02X)! Use A2DP " - "Profile\n", - pBtCoex->c2hBtProfile)); - btdm_1AntTdmaDurationAdjustForACL(padapter); - } - break; - } - } - - pBtdm8723->psTdmaGlobalCnt++; -} - -static void -btdm_1AntUpdateHalRAMask(struct rtw_adapter *padapter, u32 mac_id, u32 filter) -{ - u8 init_rate = 0; - u8 raid, arg; - u32 mask; - u8 shortGIrate = false; - int supportRateNum = 0; - struct sta_info *psta; - struct hal_data_8723a *pHalData; - struct dm_priv *pdmpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - struct wlan_bssid_ex *cur_network; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, MACID =%d, filter = 0x%08x!!\n", - __func__, mac_id, filter)); - - pHalData = GET_HAL_DATA(padapter); - pdmpriv = &pHalData->dmpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - cur_network = &pmlmeinfo->network; - - if (mac_id >= NUM_STA) { /* CAM_SIZE */ - RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, MACID =%d illegal!!\n", - __func__, mac_id)); - return; - } - - psta = pmlmeinfo->FW_sta_info[mac_id].psta; - if (!psta) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, Can't find station!!\n", - __func__)); - return; - } - - raid = psta->raid; - - switch (mac_id) { - case 0:/* for infra mode */ - supportRateNum = - rtw_get_rateset_len23a(cur_network->SupportedRates); - mask = update_supported_rate23a(cur_network->SupportedRates, - supportRateNum); - mask |= (pmlmeinfo->HT_enable) ? - update_MSC_rate23a(&pmlmeinfo->ht_cap):0; - if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap)) - shortGIrate = true; - break; - case 1:/* for broadcast/multicast */ - supportRateNum = rtw_get_rateset_len23a( - pmlmeinfo->FW_sta_info[mac_id].SupportedRates); - mask = update_basic_rate23a(cur_network->SupportedRates, - supportRateNum); - break; - default: /* for each sta in IBSS */ - supportRateNum = rtw_get_rateset_len23a( - pmlmeinfo->FW_sta_info[mac_id].SupportedRates); - mask = update_supported_rate23a(cur_network->SupportedRates, - supportRateNum); - break; - } - mask |= ((raid<<28)&0xf0000000); - mask &= 0xffffffff; - mask &= ~filter; - init_rate = get_highest_rate_idx23a(mask)&0x3f; - - arg = mac_id&0x1f;/* MACID */ - arg |= BIT(7); - if (true == shortGIrate) - arg |= BIT(5); - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Update FW RAID entry, MASK = 0x%08x, " - "arg = 0x%02x\n", mask, arg)); - - rtl8723a_set_raid_cmd(padapter, mask, arg); - - psta->init_rate = init_rate; - pdmpriv->INIDATA_RATE[mac_id] = init_rate; -} - -static void -btdm_1AntUpdateHalRAMaskForSCO(struct rtw_adapter *padapter, u8 forceUpdate) -{ - struct btdm_8723a_1ant *pBtdm8723; - struct sta_priv *pstapriv; - struct wlan_bssid_ex *cur_network; - struct sta_info *psta; - u32 macid; - u32 filter = 0; - - pBtdm8723 = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant; - - if (pBtdm8723->bRAChanged == true && forceUpdate == false) - return; - - pstapriv = &padapter->stapriv; - cur_network = &padapter->mlmeextpriv.mlmext_info.network; - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - macid = psta->mac_id; - - filter |= BIT(_1M_RATE_); - filter |= BIT(_2M_RATE_); - filter |= BIT(_5M_RATE_); - filter |= BIT(_11M_RATE_); - filter |= BIT(_6M_RATE_); - filter |= BIT(_9M_RATE_); - - btdm_1AntUpdateHalRAMask(padapter, macid, filter); - - pBtdm8723->bRAChanged = true; -} - -static void btdm_1AntRecoverHalRAMask(struct rtw_adapter *padapter) -{ - struct btdm_8723a_1ant *pBtdm8723; - struct sta_priv *pstapriv; - struct wlan_bssid_ex *cur_network; - struct sta_info *psta; - - pBtdm8723 = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant; - - if (pBtdm8723->bRAChanged == false) - return; - - pstapriv = &padapter->stapriv; - cur_network = &padapter->mlmeextpriv.mlmext_info.network; - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - - Update_RA_Entry23a(padapter, psta); - - pBtdm8723->bRAChanged = false; -} - -static void -btdm_1AntBTStateChangeHandler(struct rtw_adapter *padapter, - enum bt_state_1ant oldState, - enum bt_state_1ant newState) -{ - struct hal_data_8723a *phaldata; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT state change, %s => %s\n", - BtStateString[oldState], - BtStateString[newState])); - - /* BT default ignore wlan active, */ - /* WiFi MUST disable this when BT is enable */ - if (newState > BT_INFO_STATE_DISABLED) - btdm_SetFwIgnoreWlanAct(padapter, false); - - if ((check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) && - (BTDM_IsWifiConnectionExist(padapter))) { - if ((newState == BT_INFO_STATE_SCO_ONLY_BUSY) || - (newState == BT_INFO_STATE_ACL_SCO_BUSY)) { - btdm_1AntUpdateHalRAMaskForSCO(padapter, false); - } else { - /* Recover original RA setting */ - btdm_1AntRecoverHalRAMask(padapter); - } - } else { - phaldata = GET_HAL_DATA(padapter); - phaldata->bt_coexist.halCoex8723.btdm1Ant.bRAChanged = false; - } - - if (oldState == newState) - return; - - if (oldState == BT_INFO_STATE_ACL_ONLY_BUSY) { - struct hal_data_8723a *Hal = GET_HAL_DATA(padapter); - Hal->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCnt = 0; - Hal->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCntForSCO = 0; - } - - if ((oldState == BT_INFO_STATE_SCO_ONLY_BUSY) || - (oldState == BT_INFO_STATE_ACL_SCO_BUSY)) { - struct hal_data_8723a *Hal = GET_HAL_DATA(padapter); - Hal->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCntForSCO = 0; - } - - /* Active 2Ant mechanism when BT Connected */ - if ((oldState == BT_INFO_STATE_DISABLED) || - (oldState == BT_INFO_STATE_NO_CONNECTION)) { - if ((newState != BT_INFO_STATE_DISABLED) && - (newState != BT_INFO_STATE_NO_CONNECTION)) { - BTDM_SetSwRfRxLpfCorner(padapter, - BT_RF_RX_LPF_CORNER_SHRINK); - BTDM_AGCTable(padapter, BT_AGCTABLE_ON); - BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON); - } - } else { - if ((newState == BT_INFO_STATE_DISABLED) || - (newState == BT_INFO_STATE_NO_CONNECTION)) { - BTDM_SetSwRfRxLpfCorner(padapter, - BT_RF_RX_LPF_CORNER_RESUME); - BTDM_AGCTable(padapter, BT_AGCTABLE_OFF); - BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF); - } - } -} - -static void btdm_1AntBtCoexistHandler(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_coexist_8723a *pBtCoex8723; - struct btdm_8723a_1ant *pBtdm8723; - - pHalData = GET_HAL_DATA(padapter); - pBtCoex8723 = &pHalData->bt_coexist.halCoex8723; - pBtdm8723 = &pBtCoex8723->btdm1Ant; - padapter->pwrctrlpriv.btcoex_rfon = false; - if (!rtl8723a_BT_enabled(padapter)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is disabled\n")); - - if (BTDM_IsWifiConnectionExist(padapter)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is connected\n")); - - if (BTDM_IsWifiBusy(padapter)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Wifi is busy\n")); - btdm_1AntSetPSTDMA(padapter, false, 0, - false, 9); - } else { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Wifi is idle\n")); - _btdm_1AntSetPSTDMA(padapter, true, 2, 1, - false, 9); - } - } else { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is disconnected\n")); - - btdm_1AntSetPSTDMA(padapter, false, 0, false, 9); - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is enabled\n")); - - if (BTDM_IsWifiConnectionExist(padapter)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is connected\n")); - - btdm_1AntWifiParaAdjust(padapter, true); - btdm_1AntCoexProcessForWifiConnect(padapter); - } else { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is disconnected\n")); - - /* Antenna switch at BT side(0x870 = 0x300, - 0x860 = 0x210) after PSTDMA off */ - btdm_1AntWifiParaAdjust(padapter, false); - btdm_1AntSetPSTDMA(padapter, false, 0, false, 0); - } - } - - btdm_1AntBTStateChangeHandler(padapter, pBtCoex8723->prec2hBtInfo, - pBtCoex8723->c2hBtInfo); - pBtCoex8723->prec2hBtInfo = pBtCoex8723->c2hBtInfo; -} - -void BTDM_1AntSignalCompensation(struct rtw_adapter *padapter, - u8 *rssi_wifi, u8 *rssi_bt) -{ - struct hal_data_8723a *pHalData; - struct btdm_8723a_1ant *pBtdm8723; - u8 RSSI_WiFi_Cmpnstn, RSSI_BT_Cmpnstn; - - pHalData = GET_HAL_DATA(padapter); - pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - RSSI_WiFi_Cmpnstn = 0; - RSSI_BT_Cmpnstn = 0; - - switch (pBtdm8723->curPsTdma) { - case 1: /* WiFi 52ms */ - RSSI_WiFi_Cmpnstn = 11; /* 22*0.48 */ - break; - case 2: /* WiFi 36ms */ - RSSI_WiFi_Cmpnstn = 14; /* 22*0.64 */ - break; - case 9: /* WiFi 20ms */ - RSSI_WiFi_Cmpnstn = 18; /* 22*0.80 */ - break; - case 11: /* WiFi 10ms */ - RSSI_WiFi_Cmpnstn = 20; /* 22*0.90 */ - break; - case 4: /* WiFi 21ms */ - RSSI_WiFi_Cmpnstn = 17; /* 22*0.79 */ - break; - case 16: /* WiFi 24ms */ - RSSI_WiFi_Cmpnstn = 18; /* 22*0.76 */ - break; - case 18: /* WiFi 37ms */ - RSSI_WiFi_Cmpnstn = 14; /* 22*0.64 */ - break; - case 23: /* Level-1, Antenna switch to BT at all time */ - case 24: /* Level-2, Antenna switch to BT at all time */ - case 25: /* Level-3a, Antenna switch to BT at all time */ - case 26: /* Level-3b, Antenna switch to BT at all time */ - case 27: /* Level-3b, Antenna switch to BT at all time */ - case 33: /* BT SCO & WiFi site survey */ - RSSI_WiFi_Cmpnstn = 22; - break; - default: - break; - } - - if (rssi_wifi && RSSI_WiFi_Cmpnstn) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], 1AntSgnlCmpnstn, case %d, WiFiCmpnstn " - "=%d(%d => %d)\n", pBtdm8723->curPsTdma, - RSSI_WiFi_Cmpnstn, *rssi_wifi, - *rssi_wifi+RSSI_WiFi_Cmpnstn)); - *rssi_wifi += RSSI_WiFi_Cmpnstn; - } - - if (rssi_bt && RSSI_BT_Cmpnstn) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], 1AntSgnlCmpnstn, case %d, BTCmpnstn " - "=%d(%d => %d)\n", pBtdm8723->curPsTdma, - RSSI_BT_Cmpnstn, *rssi_bt, *rssi_bt+RSSI_BT_Cmpnstn)); - *rssi_bt += RSSI_BT_Cmpnstn; - } -} - -static void BTDM_1AntParaInit(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_coexist_8723a *pBtCoex; - struct btdm_8723a_1ant *pBtdm8723; - - pHalData = GET_HAL_DATA(padapter); - pBtCoex = &pHalData->bt_coexist.halCoex8723; - pBtdm8723 = &pBtCoex->btdm1Ant; - - /* Enable counter statistics */ - rtl8723au_write8(padapter, 0x76e, 0x4); - btdm_1AntPtaParaReload(padapter); - - pBtdm8723->wifiRssiThresh = 48; - - pBtdm8723->bWiFiHalt = false; - pBtdm8723->bRAChanged = false; - - if ((pBtCoex->c2hBtInfo != BT_INFO_STATE_DISABLED) && - (pBtCoex->c2hBtInfo != BT_INFO_STATE_NO_CONNECTION)) { - BTDM_SetSwRfRxLpfCorner(padapter, BT_RF_RX_LPF_CORNER_SHRINK); - BTDM_AGCTable(padapter, BT_AGCTABLE_ON); - BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON); - } -} - -static void BTDM_1AntForHalt(struct rtw_adapter *padapter) -{ - RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for halt\n")); - - GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bWiFiHalt = - true; - - btdm_1AntWifiParaAdjust(padapter, false); - - /* don't use btdm_1AntSetPSTDMA() here */ - /* it will call rtw_set_ps_mode23a() and request pwrpriv->lock. */ - /* This will lead to deadlock, if this function is called in IPS */ - /* Lucas@20130205 */ - btdm_1AntPsTdma(padapter, false, 0); - - btdm_SetFwIgnoreWlanAct(padapter, true); -} - -static void BTDM_1AntLpsLeave(struct rtw_adapter *padapter) -{ - RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for LPS Leave\n")); - - /* Prevent from entering LPS again */ - GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bWiFiHalt = - true; - - btdm_1AntSetPSTDMA(padapter, false, 0, false, 8); -/*btdm_1AntPsTdma(padapter, false, 8); */ -} - -static void BTDM_1AntWifiAssociateNotify(struct rtw_adapter *padapter, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - RTPRINT(FBT, BT_TRACE, - ("\n[BTCoex], 1Ant for associate, type =%d\n", type)); - - if (type) { - rtl8723a_CheckAntenna_Selection(padapter); - if (!rtl8723a_BT_enabled(padapter)) - btdm_1AntSetPSTDMA(padapter, false, 0, false, 9); - else { - struct bt_coexist_8723a *pBtCoex; - u8 BtState; - - pBtCoex = &pHalData->bt_coexist.halCoex8723; - BtState = pBtCoex->c2hBtInfo; - - btdm_1AntTSFSwitch(padapter, true); - - if (BtState == BT_INFO_STATE_NO_CONNECTION || - BtState == BT_INFO_STATE_CONNECT_IDLE) { - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 28); - } else if (BtState == BT_INFO_STATE_SCO_ONLY_BUSY || - BtState == BT_INFO_STATE_ACL_SCO_BUSY) { - btdm_1AntSetPSTDMA(padapter, false, 0, - false, 8); - rtl8723au_write32(padapter, 0x6c0, 0x5a5a5a5a); - rtl8723au_write32(padapter, 0x6c4, 0x5a5a5a5a); - } else if (BtState == BT_INFO_STATE_ACL_ONLY_BUSY || - BtState == BT_INFO_STATE_ACL_INQ_OR_PAG) { - if (pBtCoex->c2hBtProfile == BT_INFO_HID) - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 35); - else - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 29); - } - } - } else { - if (!rtl8723a_BT_enabled(padapter)) { - if (!BTDM_IsWifiConnectionExist(padapter)) { - btdm_1AntPsTdma(padapter, false, 0); - btdm_1AntTSFSwitch(padapter, false); - } - } - - btdm_1AntBtCoexistHandler(padapter); - } -} - -static void -BTDM_1AntMediaStatusNotify(struct rtw_adapter *padapter, - enum rt_media_status mstatus) -{ - struct bt_coexist_8723a *pBtCoex; - - pBtCoex = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723; - - RTPRINT(FBT, BT_TRACE, - ("\n\n[BTCoex]******************************\n")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], MediaStatus, WiFi %s !!\n", - mstatus == RT_MEDIA_CONNECT?"CONNECT":"DISCONNECT")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex]******************************\n")); - - if (RT_MEDIA_CONNECT == mstatus) { - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) { - if (pBtCoex->c2hBtInfo == BT_INFO_STATE_SCO_ONLY_BUSY || - pBtCoex->c2hBtInfo == BT_INFO_STATE_ACL_SCO_BUSY) - btdm_1AntUpdateHalRAMaskForSCO(padapter, true); - } - - padapter->pwrctrlpriv.DelayLPSLastTimeStamp = jiffies; - BTDM_1AntForDhcp(padapter); - } else { - /* DBG_8723A("%s rtl8723a_DeinitAntenna_Selection\n", - __func__); */ - rtl8723a_DeinitAntenna_Selection(padapter); - btdm_1AntBtCoexistHandler(padapter); - pBtCoex->btdm1Ant.bRAChanged = false; - } -} - -void BTDM_1AntForDhcp(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - u8 BtState; - struct bt_coexist_8723a *pBtCoex; - struct btdm_8723a_1ant *pBtdm8723; - - pHalData = GET_HAL_DATA(padapter); - pBtCoex = &pHalData->bt_coexist.halCoex8723; - BtState = pBtCoex->c2hBtInfo; - pBtdm8723 = &pBtCoex->btdm1Ant; - - RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for DHCP\n")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, WiFi is %s\n", - BTDM_IsWifiBusy(padapter)?"Busy":"IDLE")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, %s\n", - BtStateString[BtState])); - - BTDM_1AntWifiAssociateNotify(padapter, true); -} - -static void BTDM_1AntWifiScanNotify(struct rtw_adapter *padapter, u8 scanType) -{ - struct hal_data_8723a *pHalData; - u8 BtState; - struct bt_coexist_8723a *pBtCoex; - struct btdm_8723a_1ant *pBtdm8723; - - pHalData = GET_HAL_DATA(padapter); - BtState = pHalData->bt_coexist.halCoex8723.c2hBtInfo; - pBtCoex = &pHalData->bt_coexist.halCoex8723; - pBtdm8723 = &pBtCoex->btdm1Ant; - - RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for wifi scan =%d!!\n", - scanType)); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for wifi scan, WiFi is %s\n", - BTDM_IsWifiBusy(padapter)?"Busy":"IDLE")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for wifi scan, %s\n", - BtStateString[BtState])); - - if (scanType) { - rtl8723a_CheckAntenna_Selection(padapter); - if (!rtl8723a_BT_enabled(padapter)) { - btdm_1AntSetPSTDMA(padapter, false, 0, false, 9); - } else if (BTDM_IsWifiConnectionExist(padapter) == false) { - BTDM_1AntWifiAssociateNotify(padapter, true); - } else { - if ((BtState == BT_INFO_STATE_SCO_ONLY_BUSY) || - (BtState == BT_INFO_STATE_ACL_SCO_BUSY)) { - if (pBtCoex->bC2hBtInquiryPage) { - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 32); - } else { - padapter->pwrctrlpriv.btcoex_rfon = - true; - btdm_1AntSetPSTDMA(padapter, true, 0, - true, 33); - } - } else if (true == pBtCoex->bC2hBtInquiryPage) { - padapter->pwrctrlpriv.btcoex_rfon = true; - btdm_1AntSetPSTDMA(padapter, true, 0, true, 30); - } else if (BtState == BT_INFO_STATE_ACL_ONLY_BUSY) { - padapter->pwrctrlpriv.btcoex_rfon = true; - if (pBtCoex->c2hBtProfile == BT_INFO_HID) - btdm_1AntSetPSTDMA(padapter, true, 0, - true, 34); - else - btdm_1AntSetPSTDMA(padapter, true, 0, - true, 4); - } else { - padapter->pwrctrlpriv.btcoex_rfon = true; - btdm_1AntSetPSTDMA(padapter, true, 0, true, 5); - } - } - - btdm_NotifyFwScan(padapter, 1); - } else { - /* WiFi_Finish_Scan */ - btdm_NotifyFwScan(padapter, 0); - btdm_1AntBtCoexistHandler(padapter); - } -} - -static void BTDM_1AntFwC2hBtInfo8723A(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_coexist_8723a *pBtCoex; - u8 u1tmp, btState; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtCoex = &pHalData->bt_coexist.halCoex8723; - - u1tmp = pBtCoex->c2hBtInfoOriginal; - /* sco BUSY bit is not used on voice over PCM platform */ - btState = u1tmp & 0xF; - pBtCoex->c2hBtProfile = u1tmp & 0xE0; - - /* default set bt to idle state. */ - pBtMgnt->ExtConfig.bBTBusy = false; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE; - - /* check BIT2 first ==> check if bt is under inquiry or page scan */ - if (btState & BIT(2)) - pBtCoex->bC2hBtInquiryPage = true; - else - pBtCoex->bC2hBtInquiryPage = false; - btState &= ~BIT(2); - - if (!(btState & BIT(0))) - pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION; - else { - if (btState == 0x1) - pBtCoex->c2hBtInfo = BT_INFO_STATE_CONNECT_IDLE; - else if (btState == 0x9) { - if (pBtCoex->bC2hBtInquiryPage == true) - pBtCoex->c2hBtInfo = - BT_INFO_STATE_ACL_INQ_OR_PAG; - else - pBtCoex->c2hBtInfo = - BT_INFO_STATE_ACL_ONLY_BUSY; - pBtMgnt->ExtConfig.bBTBusy = true; - } else if (btState == 0x3) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_SCO_ONLY_BUSY; - pBtMgnt->ExtConfig.bBTBusy = true; - } else if (btState == 0xb) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_ACL_SCO_BUSY; - pBtMgnt->ExtConfig.bBTBusy = true; - } else - pBtCoex->c2hBtInfo = BT_INFO_STATE_MAX; - if (pBtMgnt->ExtConfig.bBTBusy) - pHalData->bt_coexist.CurrentState &= - ~BT_COEX_STATE_BT_IDLE; - } - - if (BT_INFO_STATE_NO_CONNECTION == pBtCoex->c2hBtInfo || - BT_INFO_STATE_CONNECT_IDLE == pBtCoex->c2hBtInfo) { - if (pBtCoex->bC2hBtInquiryPage) - pBtCoex->c2hBtInfo = BT_INFO_STATE_INQ_OR_PAG; - } - - RTPRINT(FBT, BT_TRACE, ("[BTC2H], %s(%d)\n", - BtStateString[pBtCoex->c2hBtInfo], pBtCoex->c2hBtInfo)); - - if (pBtCoex->c2hBtProfile != BT_INFO_HID) - pBtCoex->c2hBtProfile &= ~BT_INFO_HID; -} - -void BTDM_1AntBtCoexist8723A(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv; - struct hal_data_8723a *pHalData; - unsigned long delta_time; - - pmlmepriv = &padapter->mlmepriv; - pHalData = GET_HAL_DATA(padapter); - - if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)) { - /* already done in BTDM_1AntForScan() */ - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is under scan progress!!\n")); - return; - } - - if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is under link progress!!\n")); - return; - } - - /* under DHCP(Special packet) */ - delta_time = jiffies - padapter->pwrctrlpriv.DelayLPSLastTimeStamp; - delta_time = jiffies_to_msecs(delta_time); - if (delta_time < 500) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is under DHCP " - "progress(%li ms)!!\n", delta_time)); - return; - } - - BTDM_CheckWiFiState(padapter); - - btdm_1AntBtCoexistHandler(padapter); -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.c ===== */ - -/* local function start with btdm_ */ -static u8 btdm_ActionAlgorithm(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - u8 bScoExist = false, bBtLinkExist = false, bBtHsModeExist = false; - u8 algorithm = BT_2ANT_COEX_ALGO_UNDEFINED; - - if (pBtMgnt->ExtConfig.NumberOfHandle) - bBtLinkExist = true; - if (pBtMgnt->ExtConfig.NumberOfSCO) - bScoExist = true; - if (BT_HsConnectionEstablished(padapter)) - bBtHsModeExist = true; - - /* here we get BT status first */ - /* 1) initialize */ - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE; - - if ((bScoExist) || (bBtHsModeExist) || - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID))) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO or HID or HS exists, set BT non-idle !!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } else { - /* A2dp profile */ - if ((pBtMgnt->ExtConfig.NumberOfHandle == 1) && - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP))) { - if (BTDM_BtTxRxCounterL(padapter) < 100) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP, low priority tx+rx < 100, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP, low priority tx+rx >= 100, set BT non-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } - } - /* Pan profile */ - if ((pBtMgnt->ExtConfig.NumberOfHandle == 1) && - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN))) { - if (BTDM_BtTxRxCounterL(padapter) < 600) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, low priority tx+rx < 600, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } else { - if (pHalData->bt_coexist.halCoex8723.lowPriorityTx) { - if ((pHalData->bt_coexist.halCoex8723.lowPriorityRx / - pHalData->bt_coexist.halCoex8723.lowPriorityTx) > 9) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, low priority rx/tx > 9, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } - } - } - if (BT_2ANT_BT_STATUS_CONNECTED_IDLE != pBtdm8723->btStatus) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, set BT non-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } - } - /* Pan+A2dp profile */ - if ((pBtMgnt->ExtConfig.NumberOfHandle == 2) && - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) && - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN))) { - if (BTDM_BtTxRxCounterL(padapter) < 600) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, low priority tx+rx < 600, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } else { - if (pHalData->bt_coexist.halCoex8723.lowPriorityTx) { - if ((pHalData->bt_coexist.halCoex8723.lowPriorityRx / - pHalData->bt_coexist.halCoex8723.lowPriorityTx) > 9) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, low priority rx/tx > 9, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } - } - } - if (BT_2ANT_BT_STATUS_CONNECTED_IDLE != pBtdm8723->btStatus) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, set BT non-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } - } - } - if (BT_2ANT_BT_STATUS_IDLE != pBtdm8723->btStatus) - pBtMgnt->ExtConfig.bBTBusy = true; - else - pBtMgnt->ExtConfig.bBTBusy = false; - - if (!bBtLinkExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], No profile exists!!!\n")); - return algorithm; - } - - if (pBtMgnt->ExtConfig.NumberOfHandle == 1) { - if (bScoExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO only\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID only\n")); - algorithm = BT_2ANT_COEX_ALGO_HID; - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP only\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(HS) only\n")); - algorithm = BT_2ANT_COEX_ALGO_PANHS; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(EDR) only\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d \n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } - } else if (pBtMgnt->ExtConfig.NumberOfHandle == 2) { - if (bScoExist) { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID\n")); - algorithm = BT_2ANT_COEX_ALGO_HID; - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP\n")); - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched ACL profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } - } else if (pBtMgnt->ExtConfig.NumberOfHandle == 3) { - if (bScoExist) { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP\n")); - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP + PAN(EDR)\n")); - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANHS; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } - } else if (pBtMgnt->ExtConfig.NumberOfHandle >= 3) { - if (bScoExist) { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - if (bBtHsModeExist) - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n")); - else - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(EDR)\n")); - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } - return algorithm; -} - -static u8 btdm_NeedToDecBtPwr(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 bRet = false; - - if (BT_Operation(padapter)) { - if (pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB > 47) { - RTPRINT(FBT, BT_TRACE, ("Need to decrease bt power for HS mode!!\n")); - bRet = true; - } else { - RTPRINT(FBT, BT_TRACE, ("NO Need to decrease bt power for HS mode!!\n")); - } - } else { - if (BTDM_IsWifiConnectionExist(padapter)) { - RTPRINT(FBT, BT_TRACE, ("Need to decrease bt power for Wifi is connected!!\n")); - bRet = true; - } - } - return bRet; -} - -static void -btdm_SetCoexTable(struct rtw_adapter *padapter, u32 val0x6c0, - u32 val0x6c8, u8 val0x6cc) -{ - RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6c0 = 0x%x\n", val0x6c0)); - rtl8723au_write32(padapter, 0x6c0, val0x6c0); - - RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6c8 = 0x%x\n", val0x6c8)); - rtl8723au_write32(padapter, 0x6c8, val0x6c8); - - RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6cc = 0x%x\n", val0x6cc)); - rtl8723au_write8(padapter, 0x6cc, val0x6cc); -} - -static void -btdm_SetSwFullTimeDacSwing(struct rtw_adapter *padapter, u8 bSwDacSwingOn, - u32 swDacSwingLvl) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (bSwDacSwingOn) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SwDacSwing = 0x%x\n", swDacSwingLvl)); - PHY_SetBBReg(padapter, 0x880, 0xff000000, swDacSwingLvl); - pHalData->bt_coexist.bSWCoexistAllOff = false; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SwDacSwing Off!\n")); - PHY_SetBBReg(padapter, 0x880, 0xff000000, 0xc0); - } -} - -static void -btdm_SetFwDacSwingLevel(struct rtw_adapter *padapter, u8 dacSwingLvl) -{ - u8 H2C_Parameter[1] = {0}; - - H2C_Parameter[0] = dacSwingLvl; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Set Dac Swing Level = 0x%x\n", dacSwingLvl)); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], write 0x29 = 0x%x\n", H2C_Parameter[0])); - - FillH2CCmd(padapter, 0x29, 1, H2C_Parameter); -} - -static void btdm_2AntDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Dec BT power = %s\n", - ((bDecBtPwr) ? "ON" : "OFF"))); - pBtdm8723->bCurDecBtPwr = bDecBtPwr; - - if (pBtdm8723->bPreDecBtPwr == pBtdm8723->bCurDecBtPwr) - return; - - BTDM_SetFwDecBtPwr(padapter, pBtdm8723->bCurDecBtPwr); - - pBtdm8723->bPreDecBtPwr = pBtdm8723->bCurDecBtPwr; -} - -static void -btdm_2AntFwDacSwingLvl(struct rtw_adapter *padapter, u8 fwDacSwingLvl) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], set FW Dac Swing level = %d\n", fwDacSwingLvl)); - pBtdm8723->curFwDacSwingLvl = fwDacSwingLvl; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], preFwDacSwingLvl =%d, curFwDacSwingLvl =%d\n", */ - /*pBtdm8723->preFwDacSwingLvl, pBtdm8723->curFwDacSwingLvl)); */ - - if (pBtdm8723->preFwDacSwingLvl == pBtdm8723->curFwDacSwingLvl) - return; - - btdm_SetFwDacSwingLevel(padapter, pBtdm8723->curFwDacSwingLvl); - - pBtdm8723->preFwDacSwingLvl = pBtdm8723->curFwDacSwingLvl; -} - -static void -btdm_2AntRfShrink(struct rtw_adapter *padapter, u8 bRxRfShrinkOn) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn Rx RF Shrink = %s\n", - ((bRxRfShrinkOn) ? "ON" : "OFF"))); - pBtdm8723->bCurRfRxLpfShrink = bRxRfShrinkOn; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreRfRxLpfShrink =%d, bCurRfRxLpfShrink =%d\n", */ - /*pBtdm8723->bPreRfRxLpfShrink, pBtdm8723->bCurRfRxLpfShrink)); */ - - if (pBtdm8723->bPreRfRxLpfShrink == pBtdm8723->bCurRfRxLpfShrink) - return; - - BTDM_SetSwRfRxLpfCorner(padapter, (u8)pBtdm8723->bCurRfRxLpfShrink); - - pBtdm8723->bPreRfRxLpfShrink = pBtdm8723->bCurRfRxLpfShrink; -} - -static void -btdm_2AntLowPenaltyRa(struct rtw_adapter *padapter, u8 bLowPenaltyRa) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn LowPenaltyRA = %s\n", - ((bLowPenaltyRa) ? "ON" : "OFF"))); - pBtdm8723->bCurLowPenaltyRa = bLowPenaltyRa; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreLowPenaltyRa =%d, bCurLowPenaltyRa =%d\n", */ - /*pBtdm8723->bPreLowPenaltyRa, pBtdm8723->bCurLowPenaltyRa)); */ - - if (pBtdm8723->bPreLowPenaltyRa == pBtdm8723->bCurLowPenaltyRa) - return; - - BTDM_SetSwPenaltyTxRateAdaptive(padapter, (u8)pBtdm8723->bCurLowPenaltyRa); - - pBtdm8723->bPreLowPenaltyRa = pBtdm8723->bCurLowPenaltyRa; -} - -static void -btdm_2AntDacSwing(struct rtw_adapter *padapter, - u8 bDacSwingOn, u32 dacSwingLvl) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn DacSwing =%s, dacSwingLvl = 0x%x\n", - (bDacSwingOn ? "ON" : "OFF"), dacSwingLvl)); - pBtdm8723->bCurDacSwingOn = bDacSwingOn; - pBtdm8723->curDacSwingLvl = dacSwingLvl; - - if ((pBtdm8723->bPreDacSwingOn == pBtdm8723->bCurDacSwingOn) && - (pBtdm8723->preDacSwingLvl == pBtdm8723->curDacSwingLvl)) - return; - - mdelay(30); - btdm_SetSwFullTimeDacSwing(padapter, bDacSwingOn, dacSwingLvl); - - pBtdm8723->bPreDacSwingOn = pBtdm8723->bCurDacSwingOn; - pBtdm8723->preDacSwingLvl = pBtdm8723->curDacSwingLvl; -} - -static void btdm_2AntAdcBackOff(struct rtw_adapter *padapter, u8 bAdcBackOff) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn AdcBackOff = %s\n", - ((bAdcBackOff) ? "ON" : "OFF"))); - pBtdm8723->bCurAdcBackOff = bAdcBackOff; - - if (pBtdm8723->bPreAdcBackOff == pBtdm8723->bCurAdcBackOff) - return; - - BTDM_BBBackOffLevel(padapter, (u8)pBtdm8723->bCurAdcBackOff); - - pBtdm8723->bPreAdcBackOff = pBtdm8723->bCurAdcBackOff; -} - -static void btdm_2AntAgcTable(struct rtw_adapter *padapter, u8 bAgcTableEn) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], %s Agc Table\n", ((bAgcTableEn) ? "Enable" : "Disable"))); - pBtdm8723->bCurAgcTableEn = bAgcTableEn; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreAgcTableEn =%d, bCurAgcTableEn =%d\n", */ - /*pBtdm8723->bPreAgcTableEn, pBtdm8723->bCurAgcTableEn)); */ - - if (pBtdm8723->bPreAgcTableEn == pBtdm8723->bCurAgcTableEn) - return; - - BTDM_AGCTable(padapter, (u8)bAgcTableEn); - - pBtdm8723->bPreAgcTableEn = pBtdm8723->bCurAgcTableEn; -} - -static void -btdm_2AntCoexTable(struct rtw_adapter *padapter, - u32 val0x6c0, u32 val0x6c8, u8 val0x6cc) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], write Coex Table 0x6c0 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - val0x6c0, val0x6c8, val0x6cc)); - pBtdm8723->curVal0x6c0 = val0x6c0; - pBtdm8723->curVal0x6c8 = val0x6c8; - pBtdm8723->curVal0x6cc = val0x6cc; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n", */ - /*pBtdm8723->preVal0x6c0, pBtdm8723->preVal0x6c8, pBtdm8723->preVal0x6cc)); */ - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n", */ - /*pBtdm8723->curVal0x6c0, pBtdm8723->curVal0x6c8, pBtdm8723->curVal0x6cc)); */ - - if ((pBtdm8723->preVal0x6c0 == pBtdm8723->curVal0x6c0) && - (pBtdm8723->preVal0x6c8 == pBtdm8723->curVal0x6c8) && - (pBtdm8723->preVal0x6cc == pBtdm8723->curVal0x6cc)) - return; - - btdm_SetCoexTable(padapter, val0x6c0, val0x6c8, val0x6cc); - - pBtdm8723->preVal0x6c0 = pBtdm8723->curVal0x6c0; - pBtdm8723->preVal0x6c8 = pBtdm8723->curVal0x6c8; - pBtdm8723->preVal0x6cc = pBtdm8723->curVal0x6cc; -} - -static void btdm_2AntIgnoreWlanAct(struct rtw_adapter *padapter, u8 bEnable) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn Ignore WlanAct %s\n", (bEnable ? "ON" : "OFF"))); - pBtdm8723->bCurIgnoreWlanAct = bEnable; - - - if (pBtdm8723->bPreIgnoreWlanAct == pBtdm8723->bCurIgnoreWlanAct) - return; - - btdm_SetFwIgnoreWlanAct(padapter, bEnable); - pBtdm8723->bPreIgnoreWlanAct = pBtdm8723->bCurIgnoreWlanAct; -} - -static void -btdm_2AntSetFw3a(struct rtw_adapter *padapter, u8 byte1, u8 byte2, - u8 byte3, u8 byte4, u8 byte5) -{ - u8 H2C_Parameter[5] = {0}; - - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* byte1[1:0] != 0 means enable pstdma */ - /* for 2Ant bt coexist, if byte1 != 0 means enable pstdma */ - if (byte1) - pHalData->bt_coexist.bFWCoexistAllOff = false; - H2C_Parameter[0] = byte1; - H2C_Parameter[1] = byte2; - H2C_Parameter[2] = byte3; - H2C_Parameter[3] = byte4; - H2C_Parameter[4] = byte5; - - pHalData->bt_coexist.fw3aVal[0] = byte1; - pHalData->bt_coexist.fw3aVal[1] = byte2; - pHalData->bt_coexist.fw3aVal[2] = byte3; - pHalData->bt_coexist.fw3aVal[3] = byte4; - pHalData->bt_coexist.fw3aVal[4] = byte5; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x3a(5bytes) = 0x%x%08x\n", - H2C_Parameter[0], - H2C_Parameter[1]<<24|H2C_Parameter[2]<<16|H2C_Parameter[3]<<8|H2C_Parameter[4])); - - FillH2CCmd(padapter, 0x3a, 5, H2C_Parameter); - } - -static void btdm_2AntPsTdma(struct rtw_adapter *padapter, u8 bTurnOn, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - u32 btTxRxCnt = 0; - u8 bTurnOnByCnt = false; - u8 psTdmaTypeByCnt = 0; - - btTxRxCnt = BTDM_BtTxRxCounterH(padapter)+BTDM_BtTxRxCounterL(padapter); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT TxRx Counters = %d\n", btTxRxCnt)); - if (btTxRxCnt > 3000) { - bTurnOnByCnt = true; - psTdmaTypeByCnt = 8; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], For BTTxRxCounters, turn %s PS TDMA, type =%d\n", - (bTurnOnByCnt ? "ON" : "OFF"), psTdmaTypeByCnt)); - pBtdm8723->bCurPsTdmaOn = bTurnOnByCnt; - pBtdm8723->curPsTdma = psTdmaTypeByCnt; - } else { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn %s PS TDMA, type =%d\n", - (bTurnOn ? "ON" : "OFF"), type)); - pBtdm8723->bCurPsTdmaOn = bTurnOn; - pBtdm8723->curPsTdma = type; - } - - if ((pBtdm8723->bPrePsTdmaOn == pBtdm8723->bCurPsTdmaOn) && - (pBtdm8723->prePsTdma == pBtdm8723->curPsTdma)) - return; - - if (bTurnOn) { - switch (type) { - case 1: - default: - btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0xa1, 0x98); - break; - case 2: - btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0xa1, 0x98); - break; - case 3: - btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0xa1, 0x98); - break; - case 4: - btdm_2AntSetFw3a(padapter, 0xa3, 0x5, 0x5, 0xa1, 0x80); - break; - case 5: - btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x20, 0x98); - break; - case 6: - btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0x20, 0x98); - break; - case 7: - btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0x20, 0x98); - break; - case 8: - btdm_2AntSetFw3a(padapter, 0xa3, 0x5, 0x5, 0x20, 0x80); - break; - case 9: - btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0xa1, 0x98); - break; - case 10: - btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0xa1, 0x98); - break; - case 11: - btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0xa1, 0x98); - break; - case 12: - btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0xa1, 0x98); - break; - case 13: - btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x20, 0x98); - break; - case 14: - btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0x20, 0x98); - break; - case 15: - btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0x20, 0x98); - break; - case 16: - btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0x20, 0x98); - break; - case 17: - btdm_2AntSetFw3a(padapter, 0xa3, 0x2f, 0x2f, 0x20, 0x80); - break; - case 18: - btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0xa1, 0x98); - break; - case 19: - btdm_2AntSetFw3a(padapter, 0xe3, 0x25, 0x25, 0xa1, 0x98); - break; - case 20: - btdm_2AntSetFw3a(padapter, 0xe3, 0x25, 0x25, 0x20, 0x98); - break; - } - } else { - /* disable PS tdma */ - switch (type) { - case 0: - btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0); - break; - case 1: - btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x0, 0x0); - break; - default: - btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0); - break; - } - } - - /* update pre state */ - pBtdm8723->bPrePsTdmaOn = pBtdm8723->bCurPsTdmaOn; - pBtdm8723->prePsTdma = pBtdm8723->curPsTdma; -} - -static void btdm_2AntBtInquiryPage(struct rtw_adapter *padapter) -{ - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, true, 8); -} - -static u8 btdm_HoldForBtInqPage(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u32 curTime = jiffies; - - if (pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage) { - /* bt inquiry or page is started. */ - if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime == 0) { - pHalData->bt_coexist.halCoex8723.btInqPageStartTime = curTime; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page is started at time : 0x%lx \n", - pHalData->bt_coexist.halCoex8723.btInqPageStartTime)); - } - } - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page started time : 0x%lx, curTime : 0x%x \n", - pHalData->bt_coexist.halCoex8723.btInqPageStartTime, curTime)); - - if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime) { - if (((curTime - pHalData->bt_coexist.halCoex8723.btInqPageStartTime)/1000000) >= 10) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page >= 10sec!!!")); - pHalData->bt_coexist.halCoex8723.btInqPageStartTime = 0; - } - } - - if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime) { - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, true, 8); - return true; - } else { - return false; - } -} - -static u8 btdm_Is2Ant8723ACommonAction(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - u8 bCommon = false; - - RTPRINT(FBT, BT_TRACE, ("%s :BTDM_IsWifiConnectionExist =%x check_fwstate =%x pmlmepriv->fw_state = 0x%x\n", __func__, BTDM_IsWifiConnectionExist(padapter), check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)), padapter->mlmepriv.fw_state)); - - if ((!BTDM_IsWifiConnectionExist(padapter)) && - (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) && - (BT_2ANT_BT_STATUS_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi idle + Bt idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, false); - btdm_2AntRfShrink(padapter, false); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, false); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else if (((BTDM_IsWifiConnectionExist(padapter)) || - (check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) && - (BT_2ANT_BT_STATUS_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + BT idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, false); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, true); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else if ((!BTDM_IsWifiConnectionExist(padapter)) && - (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) && - (BT_2ANT_BT_STATUS_CONNECTED_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi idle + Bt connected idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, true); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, false); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else if (((BTDM_IsWifiConnectionExist(padapter)) || - (check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) && - (BT_2ANT_BT_STATUS_CONNECTED_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + Bt connected idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, true); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, true); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else if ((!BTDM_IsWifiConnectionExist(padapter)) && - (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) && - (BT_2ANT_BT_STATUS_NON_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi idle + BT non-idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, true); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, false); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + BT non-idle!!\n")); - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, true); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - - bCommon = false; - } - return bCommon; -} - -static void -btdm_2AntTdmaDurationAdjust(struct rtw_adapter *padapter, u8 bScoHid, - u8 bTxPause, u8 maxInterval) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - static s32 up, dn, m, n, WaitCount; - s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */ - u8 retryCount = 0; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TdmaDurationAdjust()\n")); - - if (pBtdm8723->bResetTdmaAdjust) { - pBtdm8723->bResetTdmaAdjust = false; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], first run TdmaDurationAdjust()!!\n")); - if (bScoHid) { - if (bTxPause) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } - } else { - if (bTxPause) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } - } - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - WaitCount = 0; - } else { - /* accquire the BT TRx retry count from BT_Info byte2 */ - retryCount = pHalData->bt_coexist.halCoex8723.btRetryCnt; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], retryCount = %d\n", retryCount)); - result = 0; - WaitCount++; - - if (retryCount == 0) { /* no retry in the last 2-second duration */ - up++; - dn--; - - if (dn <= 0) - dn = 0; - - if (up >= n) { /* if ³sÄò n ­Ó2¬í retry count¬°0, «h½Õ¼eWiFi duration */ - WaitCount = 0; - n = 3; - up = 0; - dn = 0; - result = 1; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Increase wifi duration!!\n")); - } - } else if (retryCount <= 3) { /* <= 3 retry in the last 2-second duration */ - up--; - dn++; - - if (up <= 0) - up = 0; - - if (dn == 2) { /* if ³sÄò 2 ­Ó2¬í retry count< 3, «h½Õ¯¶WiFi duration */ - if (WaitCount <= 2) - m++; /* ÁקK¤@ª½¦b¨â­Ólevel¤¤¨Ó¦^ */ - else - m = 1; - - if (m >= 20) /* m ³Ì¤j­È = 20 ' ³Ì¤j120¬í recheck¬O§_½Õ¾ã WiFi duration. */ - m = 20; - - n = 3*m; - up = 0; - dn = 0; - WaitCount = 0; - result = -1; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Decrease wifi duration for retryCounter<3!!\n")); - } - } else { /* retry count > 3, ¥u­n1¦¸ retry count > 3, «h½Õ¯¶WiFi duration */ - if (WaitCount == 1) - m++; /* ÁקK¤@ª½¦b¨â­Ólevel¤¤¨Ó¦^ */ - else - m = 1; - - if (m >= 20) /* m ³Ì¤j­È = 20 ' ³Ì¤j120¬í recheck¬O§_½Õ¾ã WiFi duration. */ - m = 20; - n = 3*m; - up = 0; - dn = 0; - WaitCount = 0; - result = -1; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Decrease wifi duration for retryCounter>3!!\n")); - } - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], max Interval = %d\n", maxInterval)); - if (maxInterval == 1) { - if (bTxPause) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n")); - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 5); - pBtdm8723->psTdmaDuAdjType = 5; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } - if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 13); - pBtdm8723->psTdmaDuAdjType = 13; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - - if (result == -1) { - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } else if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 5); - pBtdm8723->psTdmaDuAdjType = 5; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 13); - pBtdm8723->psTdmaDuAdjType = 13; - } - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n")); - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 1); - pBtdm8723->psTdmaDuAdjType = 1; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } - if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 9); - pBtdm8723->psTdmaDuAdjType = 9; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - - if (result == -1) { - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } else if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 1); - pBtdm8723->psTdmaDuAdjType = 1; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 9); - pBtdm8723->psTdmaDuAdjType = 9; - } - } - } - } else if (maxInterval == 2) { - if (bTxPause) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n")); - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } - if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - if (result == -1) { - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } else if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n")); - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } - if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - if (result == -1) { - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } else if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } - } - } - } else if (maxInterval == 3) { - if (bTxPause) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n")); - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } - if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - if (result == -1) { - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } else if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n")); - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } - if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - if (result == -1) { - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } else if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } - } - } - } - } - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PsTdma type : recordPsTdma =%d\n", pBtdm8723->psTdmaDuAdjType)); - /* if current PsTdma not match with the recorded one (when scan, dhcp...), */ - /* then we have to adjust it back to the previous record one. */ - if (pBtdm8723->curPsTdma != pBtdm8723->psTdmaDuAdjType) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PsTdma type dismatch!!!, curPsTdma =%d, recordPsTdma =%d\n", - pBtdm8723->curPsTdma, pBtdm8723->psTdmaDuAdjType)); - - if (!check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) - btdm_2AntPsTdma(padapter, true, pBtdm8723->psTdmaDuAdjType); - else - RTPRINT(FBT, BT_TRACE, ("[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n")); - } -} - -/* default Action */ -/* SCO only or SCO+PAN(HS) */ -static void btdm_2Ant8723ASCOAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 11); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 15); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 11); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 15); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723AHIDAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 9); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 13); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 9); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 13); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ -static void btdm_2Ant8723AA2DPAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 1); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 1); - } - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 1); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 1); - } - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723APANEDRAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 2); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntPsTdma(padapter, true, 6); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 2); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 6); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* PAN(HS) only */ -static void btdm_2Ant8723APANHSAction(struct rtw_adapter *padapter) -{ - u8 btRssiState; - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntDecBtPwr(padapter, true); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntDecBtPwr(padapter, false); - } - btdm_2AntPsTdma(padapter, false, 0); - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0); - - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high\n")); - /* fw mechanism */ - btdm_2AntDecBtPwr(padapter, true); - btdm_2AntPsTdma(padapter, false, 0); - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low\n")); - /* fw mechanism */ - btdm_2AntDecBtPwr(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* PAN(EDR)+A2DP */ -static void btdm_2Ant8723APANEDRA2DPAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1, btInfoExt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - /* fw mechanism */ - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 4); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 2); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - /* fw mechanism */ - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 8); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 6); - } - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - /* fw mechanism */ - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 4); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 2); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - /* fw mechanism */ - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 8); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 6); - } - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723APANEDRHIDAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 10); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntPsTdma(padapter, true, 14); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 10); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 14); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* HID+A2DP+PAN(EDR) */ -static void btdm_2Ant8723AHIDA2DPPANEDRAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1, btInfoExt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 12); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 10); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 16); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 14); - } - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 37, 0); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0); - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 12); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 10); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 16); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 14); - } - } - - /* sw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723AHIDA2DPAction(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 btRssiState, btRssiState1, btInfoExt; - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, false, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, false, 1); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, true, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, true, 1); - } - } - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0); - - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, false, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, false, 1); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, true, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, true, 1); - } - } - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - /* sw mechanism */ - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723AA2dp(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 btRssiState, btRssiState1, btInfoExt; - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - /* coex table */ - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - btdm_2AntIgnoreWlanAct(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 1); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 1); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 1); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 1); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* extern function start with BTDM_ */ -static void BTDM_2AntParaInit(struct rtw_adapter *padapter) -{ - - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 2Ant Parameter Init!!\n")); - - /* Enable counter statistics */ - rtl8723au_write8(padapter, 0x76e, 0x4); - rtl8723au_write8(padapter, 0x778, 0x3); - rtl8723au_write8(padapter, 0x40, 0x20); - - /* force to reset coex mechanism */ - pBtdm8723->preVal0x6c0 = 0x0; - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - pBtdm8723->bPrePsTdmaOn = true; - btdm_2AntPsTdma(padapter, false, 0); - - pBtdm8723->preFwDacSwingLvl = 0x10; - btdm_2AntFwDacSwingLvl(padapter, 0x20); - - pBtdm8723->bPreDecBtPwr = true; - btdm_2AntDecBtPwr(padapter, false); - - pBtdm8723->bPreAgcTableEn = true; - btdm_2AntAgcTable(padapter, false); - - pBtdm8723->bPreAdcBackOff = true; - btdm_2AntAdcBackOff(padapter, false); - - pBtdm8723->bPreLowPenaltyRa = true; - btdm_2AntLowPenaltyRa(padapter, false); - - pBtdm8723->bPreRfRxLpfShrink = true; - btdm_2AntRfShrink(padapter, false); - - pBtdm8723->bPreDacSwingOn = true; - btdm_2AntDacSwing(padapter, false, 0xc0); - - pBtdm8723->bPreIgnoreWlanAct = true; - btdm_2AntIgnoreWlanAct(padapter, false); -} - -static void BTDM_2AntHwCoexAllOff8723A(struct rtw_adapter *padapter) -{ - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); -} - -static void BTDM_2AntFwCoexAllOff8723A(struct rtw_adapter *padapter) -{ - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, false); -} - -static void BTDM_2AntSwCoexAllOff8723A(struct rtw_adapter *padapter) -{ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntLowPenaltyRa(padapter, false); - btdm_2AntRfShrink(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); -} - -static void BTDM_2AntFwC2hBtInfo8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - u8 btInfo = 0; - u8 algorithm = BT_2ANT_COEX_ALGO_UNDEFINED; - u8 bBtLinkExist = false, bBtHsModeExist = false; - - btInfo = pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal; - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE; - - /* check BIT2 first ==> check if bt is under inquiry or page scan */ - if (btInfo & BIT(2)) { - if (!pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage) { - pBtMgnt->ExtConfig.bHoldForBtOperation = true; - pBtMgnt->ExtConfig.bHoldPeriodCnt = 1; - btdm_2AntBtInquiryPage(padapter); - } else { - pBtMgnt->ExtConfig.bHoldPeriodCnt++; - btdm_HoldForBtInqPage(padapter); - } - pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage = true; - - } else { - pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage = false; - pBtMgnt->ExtConfig.bHoldForBtOperation = false; - pBtMgnt->ExtConfig.bHoldPeriodCnt = 0; - - } - RTPRINT(FBT, BT_TRACE, - ("[BTC2H], pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage =%x pBtMgnt->ExtConfig.bHoldPeriodCnt =%x pBtMgnt->ExtConfig.bHoldForBtOperation =%x\n", - pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage, - pBtMgnt->ExtConfig.bHoldPeriodCnt, - pBtMgnt->ExtConfig.bHoldForBtOperation)); - - RTPRINT(FBT, BT_TRACE, - ("[BTC2H], btInfo =%x pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal =%x\n", - btInfo, pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal)); - if (btInfo&BT_INFO_ACL) { - RTPRINT(FBT, BT_TRACE, ("[BTC2H], BTInfo: bConnect = true btInfo =%x\n", btInfo)); - bBtLinkExist = true; - if (((btInfo&(BT_INFO_FTP|BT_INFO_A2DP|BT_INFO_HID|BT_INFO_SCO_BUSY)) != 0) || - pHalData->bt_coexist.halCoex8723.btRetryCnt > 0) { - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } else { - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } - - if (btInfo&BT_INFO_SCO || btInfo&BT_INFO_SCO_BUSY) { - if (btInfo&BT_INFO_FTP || btInfo&BT_INFO_A2DP || btInfo&BT_INFO_HID) { - switch (btInfo&0xe0) { - case BT_INFO_HID: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID\n")); - algorithm = BT_2ANT_COEX_ALGO_HID; - break; - case BT_INFO_A2DP: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP\n")); - break; - case BT_INFO_FTP: - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - break; - case (BT_INFO_HID | BT_INFO_A2DP): - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - break; - case (BT_INFO_HID | BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - break; - case (BT_INFO_A2DP | BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP; - } - break; - case (BT_INFO_HID | BT_INFO_A2DP | BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - break; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO only\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], non SCO\n")); - switch (btInfo&0xe0) { - case BT_INFO_HID: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID\n")); - algorithm = BT_2ANT_COEX_ALGO_HID; - break; - case BT_INFO_A2DP: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - break; - case BT_INFO_FTP: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - break; - case (BT_INFO_HID | BT_INFO_A2DP): - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - break; - case (BT_INFO_HID|BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - break; - case (BT_INFO_A2DP|BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP; - } - break; - case (BT_INFO_HID|BT_INFO_A2DP|BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - break; - } - - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTC2H], BTInfo: bConnect = false\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE; - } - - pBtdm8723->curAlgorithm = algorithm; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Algorithm = %d \n", pBtdm8723->curAlgorithm)); - -/* From */ - BTDM_CheckWiFiState(padapter); - if (pBtMgnt->ExtConfig.bManualControl) { - RTPRINT(FBT, BT_TRACE, ("Action Manual control, won't execute bt coexist mechanism!!\n")); - return; - } -} - -void BTDM_2AntBtCoexist8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 btInfoOriginal = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - if (BTDM_BtProfileSupport(padapter)) { - if (pBtMgnt->ExtConfig.bHoldForBtOperation) { - RTPRINT(FBT, BT_TRACE, ("Action for BT Operation adjust!!\n")); - return; - } - if (pBtMgnt->ExtConfig.bHoldPeriodCnt) { - RTPRINT(FBT, BT_TRACE, ("Hold BT inquiry/page scan setting (cnt = %d)!!\n", - pBtMgnt->ExtConfig.bHoldPeriodCnt)); - if (pBtMgnt->ExtConfig.bHoldPeriodCnt >= 11) { - pBtMgnt->ExtConfig.bHoldPeriodCnt = 0; - /* next time the coexist parameters should be reset again. */ - } else { - pBtMgnt->ExtConfig.bHoldPeriodCnt++; - } - return; - } - - if (pBtDbg->dbgCtrl) - RTPRINT(FBT, BT_TRACE, ("[Dbg control], ")); - - pBtdm8723->curAlgorithm = btdm_ActionAlgorithm(padapter); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Algorithm = %d \n", pBtdm8723->curAlgorithm)); - - if (btdm_Is2Ant8723ACommonAction(padapter)) { - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant common.\n")); - pBtdm8723->bResetTdmaAdjust = true; - } else { - if (pBtdm8723->curAlgorithm != pBtdm8723->preAlgorithm) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], preAlgorithm =%d, curAlgorithm =%d\n", - pBtdm8723->preAlgorithm, pBtdm8723->curAlgorithm)); - pBtdm8723->bResetTdmaAdjust = true; - } - switch (pBtdm8723->curAlgorithm) { - case BT_2ANT_COEX_ALGO_SCO: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = SCO.\n")); - btdm_2Ant8723ASCOAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID.\n")); - btdm_2Ant8723AHIDAction(padapter); - break; - case BT_2ANT_COEX_ALGO_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = A2DP.\n")); - btdm_2Ant8723AA2DPAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR).\n")); - btdm_2Ant8723APANEDRAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANHS: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HS mode.\n")); - btdm_2Ant8723APANHSAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN+A2DP.\n")); - btdm_2Ant8723APANEDRA2DPAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR_HID: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR)+HID.\n")); - btdm_2Ant8723APANEDRHIDAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP+PAN.\n")); - btdm_2Ant8723AHIDA2DPPANEDRAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP.\n")); - btdm_2Ant8723AHIDA2DPAction(padapter); - break; - default: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = 0.\n")); - btdm_2Ant8723AA2DPAction(padapter); - break; - } - pBtdm8723->preAlgorithm = pBtdm8723->curAlgorithm; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex] Get bt info by fw!!\n")); - /* msg shows c2h rsp for bt_info is received or not. */ - if (pHalData->bt_coexist.halCoex8723.bC2hBtInfoReqSent) - RTPRINT(FBT, BT_TRACE, ("[BTCoex] c2h for btInfo not rcvd yet!!\n")); - - btInfoOriginal = pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal; - - if (pBtMgnt->ExtConfig.bHoldForBtOperation) { - RTPRINT(FBT, BT_TRACE, ("Action for BT Operation adjust!!\n")); - return; - } - if (pBtMgnt->ExtConfig.bHoldPeriodCnt) { - RTPRINT(FBT, BT_TRACE, - ("Hold BT inquiry/page scan setting (cnt = %d)!!\n", - pBtMgnt->ExtConfig.bHoldPeriodCnt)); - if (pBtMgnt->ExtConfig.bHoldPeriodCnt >= 11) { - pBtMgnt->ExtConfig.bHoldPeriodCnt = 0; - /* next time the coexist parameters should be reset again. */ - } else { - pBtMgnt->ExtConfig.bHoldPeriodCnt++; - } - return; - } - - if (pBtDbg->dbgCtrl) - RTPRINT(FBT, BT_TRACE, ("[Dbg control], ")); - if (btdm_Is2Ant8723ACommonAction(padapter)) { - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant common.\n")); - pBtdm8723->bResetTdmaAdjust = true; - } else { - if (pBtdm8723->curAlgorithm != pBtdm8723->preAlgorithm) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], preAlgorithm =%d, curAlgorithm =%d\n", - pBtdm8723->preAlgorithm, - pBtdm8723->curAlgorithm)); - pBtdm8723->bResetTdmaAdjust = true; - } - switch (pBtdm8723->curAlgorithm) { - case BT_2ANT_COEX_ALGO_SCO: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = SCO.\n")); - btdm_2Ant8723ASCOAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID.\n")); - btdm_2Ant8723AHIDAction(padapter); - break; - case BT_2ANT_COEX_ALGO_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = A2DP.\n")); - btdm_2Ant8723AA2dp(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR).\n")); - btdm_2Ant8723APANEDRAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANHS: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HS mode.\n")); - btdm_2Ant8723APANHSAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN+A2DP.\n")); - btdm_2Ant8723APANEDRA2DPAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR_HID: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR)+HID.\n")); - btdm_2Ant8723APANEDRHIDAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP+PAN.\n")); - btdm_2Ant8723AHIDA2DPPANEDRAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP.\n")); - btdm_2Ant8723AHIDA2DPAction(padapter); - break; - default: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = 0.\n")); - btdm_2Ant8723AA2DPAction(padapter); - break; - } - pBtdm8723->preAlgorithm = pBtdm8723->curAlgorithm; - } - } -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.c ===== */ - -static u8 btCoexDbgBuf[BT_TMP_BUF_SIZE]; - -static const char *const BtProfileString[] = { - "NONE", - "A2DP", - "PAN", - "HID", - "SCO", -}; - -static const char *const BtSpecString[] = { - "1.0b", - "1.1", - "1.2", - "2.0+EDR", - "2.1+EDR", - "3.0+HS", - "4.0", -}; - -static const char *const BtLinkRoleString[] = { - "Master", - "Slave", -}; - -static u8 btdm_BtWifiAntNum(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723; - - if (Ant_x2 == pHalData->bt_coexist.BT_Ant_Num) { - if (Ant_x2 == pBtCoex->TotalAntNum) - return Ant_x2; - else - return Ant_x1; - } else { - return Ant_x1; - } - return Ant_x2; -} - -static void btdm_BtHwCountersMonitor(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u32 regHPTxRx, regLPTxRx, u4Tmp; - u32 regHPTx = 0, regHPRx = 0, regLPTx = 0, regLPRx = 0; - - regHPTxRx = REG_HIGH_PRIORITY_TXRX; - regLPTxRx = REG_LOW_PRIORITY_TXRX; - - u4Tmp = rtl8723au_read32(padapter, regHPTxRx); - regHPTx = u4Tmp & bMaskLWord; - regHPRx = (u4Tmp & bMaskHWord)>>16; - - u4Tmp = rtl8723au_read32(padapter, regLPTxRx); - regLPTx = u4Tmp & bMaskLWord; - regLPRx = (u4Tmp & bMaskHWord)>>16; - - pHalData->bt_coexist.halCoex8723.highPriorityTx = regHPTx; - pHalData->bt_coexist.halCoex8723.highPriorityRx = regHPRx; - pHalData->bt_coexist.halCoex8723.lowPriorityTx = regLPTx; - pHalData->bt_coexist.halCoex8723.lowPriorityRx = regLPRx; - - RTPRINT(FBT, BT_TRACE, ("High Priority Tx/Rx = %d / %d\n", regHPTx, regHPRx)); - RTPRINT(FBT, BT_TRACE, ("Low Priority Tx/Rx = %d / %d\n", regLPTx, regLPRx)); - - /* reset counter */ - rtl8723au_write8(padapter, 0x76e, 0xc); -} - -/* This function check if 8723 bt is disabled */ -static void btdm_BtEnableDisableCheck8723A(struct rtw_adapter *padapter) -{ - u8 btAlife = true; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - -#ifdef CHECK_BT_EXIST_FROM_REG - u8 val8; - - /* ox68[28]= 1 => BT enable; otherwise disable */ - val8 = rtl8723au_read8(padapter, 0x6B); - if (!(val8 & BIT(4))) - btAlife = false; - - if (btAlife) - pHalData->bt_coexist.bCurBtDisabled = false; - else - pHalData->bt_coexist.bCurBtDisabled = true; -#else - if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0 && - pHalData->bt_coexist.halCoex8723.highPriorityRx == 0 && - pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0 && - pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0) - btAlife = false; - if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0xeaea && - pHalData->bt_coexist.halCoex8723.highPriorityRx == 0xeaea && - pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0xeaea && - pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0xeaea) - btAlife = false; - if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0xffff && - pHalData->bt_coexist.halCoex8723.highPriorityRx == 0xffff && - pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0xffff && - pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0xffff) - btAlife = false; - if (btAlife) { - pHalData->bt_coexist.btActiveZeroCnt = 0; - pHalData->bt_coexist.bCurBtDisabled = false; - RTPRINT(FBT, BT_TRACE, ("8723A BT is enabled !!\n")); - } else { - pHalData->bt_coexist.btActiveZeroCnt++; - RTPRINT(FBT, BT_TRACE, ("8723A bt all counters = 0, %d times!!\n", - pHalData->bt_coexist.btActiveZeroCnt)); - if (pHalData->bt_coexist.btActiveZeroCnt >= 2) { - pHalData->bt_coexist.bCurBtDisabled = true; - RTPRINT(FBT, BT_TRACE, ("8723A BT is disabled !!\n")); - } - } -#endif - - if (!pHalData->bt_coexist.bCurBtDisabled) { - if (BTDM_IsWifiConnectionExist(padapter)) - BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT); - else - BTDM_SetFwChnlInfo(padapter, RT_MEDIA_DISCONNECT); - } - - if (pHalData->bt_coexist.bPreBtDisabled != - pHalData->bt_coexist.bCurBtDisabled) { - RTPRINT(FBT, BT_TRACE, ("8723A BT is from %s to %s!!\n", - (pHalData->bt_coexist.bPreBtDisabled ? "disabled":"enabled"), - (pHalData->bt_coexist.bCurBtDisabled ? "disabled":"enabled"))); - pHalData->bt_coexist.bPreBtDisabled = pHalData->bt_coexist.bCurBtDisabled; - } -} - -static void btdm_BTCoexist8723AHandler(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - - pHalData = GET_HAL_DATA(padapter); - - if (btdm_BtWifiAntNum(padapter) == Ant_x2) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 2 Ant mechanism\n")); - BTDM_2AntBtCoexist8723A(padapter); - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1 Ant mechanism\n")); - BTDM_1AntBtCoexist8723A(padapter); - } - - if (!BTDM_IsSameCoexistState(padapter)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x\n", - pHalData->bt_coexist.PreviousState, - pHalData->bt_coexist.CurrentState)); - pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState; - - RTPRINT(FBT, BT_TRACE, ("[")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT30) - RTPRINT(FBT, BT_TRACE, ("BT 3.0, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT20) - RTPRINT(FBT, BT_TRACE, ("HT20, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT40) - RTPRINT(FBT, BT_TRACE, ("HT40, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_LEGACY) - RTPRINT(FBT, BT_TRACE, ("Legacy, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_LOW) - RTPRINT(FBT, BT_TRACE, ("Rssi_Low, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_MEDIUM) - RTPRINT(FBT, BT_TRACE, ("Rssi_Mid, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_HIGH) - RTPRINT(FBT, BT_TRACE, ("Rssi_High, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_IDLE) - RTPRINT(FBT, BT_TRACE, ("Wifi_Idle, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_UPLINK) - RTPRINT(FBT, BT_TRACE, ("Wifi_Uplink, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_DOWNLINK) - RTPRINT(FBT, BT_TRACE, ("Wifi_Downlink, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE) - RTPRINT(FBT, BT_TRACE, ("BT_idle, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_HID) - RTPRINT(FBT, BT_TRACE, ("PRO_HID, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_A2DP) - RTPRINT(FBT, BT_TRACE, ("PRO_A2DP, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_PAN) - RTPRINT(FBT, BT_TRACE, ("PRO_PAN, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_SCO) - RTPRINT(FBT, BT_TRACE, ("PRO_SCO, ")); - RTPRINT(FBT, BT_TRACE, ("]\n")); - } -} - -/* extern function start with BTDM_ */ -u32 BTDM_BtTxRxCounterH(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u32 counters; - - counters = pHalData->bt_coexist.halCoex8723.highPriorityTx+ - pHalData->bt_coexist.halCoex8723.highPriorityRx; - return counters; -} - -u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u32 counters; - - counters = pHalData->bt_coexist.halCoex8723.lowPriorityTx+ - pHalData->bt_coexist.halCoex8723.lowPriorityRx; - return counters; -} - -void BTDM_SetFwChnlInfo(struct rtw_adapter *padapter, enum rt_media_status mstatus) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 H2C_Parameter[3] = {0}; - u8 chnl; - - /* opMode */ - if (RT_MEDIA_CONNECT == mstatus) - H2C_Parameter[0] = 0x1; /* 0: disconnected, 1:connected */ - - if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) { - /* channel */ - chnl = pmlmeext->cur_channel; - if (BTDM_IsHT40(padapter)) { - if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - chnl -= 2; - else if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - chnl += 2; - } - H2C_Parameter[1] = chnl; - } else { /* check if HS link is exists */ - /* channel */ - if (BT_Operation(padapter)) - H2C_Parameter[1] = pBtMgnt->BTChannel; - else - H2C_Parameter[1] = pmlmeext->cur_channel; - } - - if (BTDM_IsHT40(padapter)) - H2C_Parameter[2] = 0x30; - else - H2C_Parameter[2] = 0x20; - - FillH2CCmd(padapter, 0x19, 3, H2C_Parameter); -} - -u8 BTDM_IsWifiConnectionExist(struct rtw_adapter *padapter) -{ - u8 bRet = false; - - if (BTHCI_HsConnectionEstablished(padapter)) - bRet = true; - - if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == true) - bRet = true; - - return bRet; -} - -void BTDM_SetFw3a( - struct rtw_adapter *padapter, - u8 byte1, - u8 byte2, - u8 byte3, - u8 byte4, - u8 byte5 - ) -{ - u8 H2C_Parameter[5] = {0}; - - if (rtl8723a_BT_using_antenna_1(padapter)) { - if ((!check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) && - (get_fwstate(&padapter->mlmepriv) != WIFI_NULL_STATE)) { - /* for softap mode */ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723; - u8 BtState = pBtCoex->c2hBtInfo; - - if ((BtState != BT_INFO_STATE_NO_CONNECTION) && - (BtState != BT_INFO_STATE_CONNECT_IDLE)) { - if (byte1 & BIT(4)) { - byte1 &= ~BIT(4); - byte1 |= BIT(5); - } - - byte5 |= BIT(5); - if (byte5 & BIT(6)) - byte5 &= ~BIT(6); - } - } - } - - H2C_Parameter[0] = byte1; - H2C_Parameter[1] = byte2; - H2C_Parameter[2] = byte3; - H2C_Parameter[3] = byte4; - H2C_Parameter[4] = byte5; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x3a(5bytes) = 0x%02x%08x\n", - H2C_Parameter[0], - H2C_Parameter[1]<<24|H2C_Parameter[2]<<16|H2C_Parameter[3]<<8|H2C_Parameter[4])); - - FillH2CCmd(padapter, 0x3a, 5, H2C_Parameter); -} - -void BTDM_QueryBtInformation(struct rtw_adapter *padapter) -{ - u8 H2C_Parameter[1] = {0}; - struct hal_data_8723a *pHalData; - struct bt_coexist_8723a *pBtCoex; - - pHalData = GET_HAL_DATA(padapter); - pBtCoex = &pHalData->bt_coexist.halCoex8723; - - if (!rtl8723a_BT_enabled(padapter)) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED; - pBtCoex->bC2hBtInfoReqSent = false; - return; - } - - if (pBtCoex->c2hBtInfo == BT_INFO_STATE_DISABLED) - pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION; - - if (pBtCoex->bC2hBtInfoReqSent == true) - RTPRINT(FBT, BT_TRACE, ("[BTCoex], didn't recv previous BtInfo report!\n")); - else - pBtCoex->bC2hBtInfoReqSent = true; - - H2C_Parameter[0] |= BIT(0); /* trigger */ - -/*RTPRINT(FBT, BT_TRACE, ("[BTCoex], Query Bt information, write 0x38 = 0x%x\n", */ -/*H2C_Parameter[0])); */ - - FillH2CCmd(padapter, 0x38, 1, H2C_Parameter); -} - -void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter *padapter, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (BT_RF_RX_LPF_CORNER_SHRINK == type) { - /* Shrink RF Rx LPF corner */ - RTPRINT(FBT, BT_TRACE, ("Shrink RF Rx LPF corner!!\n")); - PHY_SetRFReg(padapter, PathA, 0x1e, bRFRegOffsetMask, 0xf0ff7); - pHalData->bt_coexist.bSWCoexistAllOff = false; - } else if (BT_RF_RX_LPF_CORNER_RESUME == type) { - /* Resume RF Rx LPF corner */ - RTPRINT(FBT, BT_TRACE, ("Resume RF Rx LPF corner!!\n")); - PHY_SetRFReg(padapter, PathA, 0x1e, bRFRegOffsetMask, pHalData->bt_coexist.BtRfRegOrigin1E); - } -} - -void -BTDM_SetSwPenaltyTxRateAdaptive( - struct rtw_adapter *padapter, - u8 raType - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 tmpU1; - - tmpU1 = rtl8723au_read8(padapter, 0x4fd); - tmpU1 |= BIT(0); - if (BT_TX_RATE_ADAPTIVE_LOW_PENALTY == raType) { - tmpU1 &= ~BIT(2); - pHalData->bt_coexist.bSWCoexistAllOff = false; - } else if (BT_TX_RATE_ADAPTIVE_NORMAL == raType) { - tmpU1 |= BIT(2); - } - - rtl8723au_write8(padapter, 0x4fd, tmpU1); -} - -void BTDM_SetFwDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[1] = {0}; - - H2C_Parameter[0] = 0; - - if (bDecBtPwr) { - H2C_Parameter[0] |= BIT(1); - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], decrease Bt Power : %s, write 0x21 = 0x%x\n", - (bDecBtPwr ? "Yes!!" : "No!!"), H2C_Parameter[0])); - - FillH2CCmd(padapter, 0x21, 1, H2C_Parameter); -} - -u8 BTDM_BtProfileSupport(struct rtw_adapter *padapter) -{ - u8 bRet = false; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pBtMgnt->bSupportProfile && - !pHalData->bt_coexist.halCoex8723.bForceFwBtInfo) - bRet = true; - - return bRet; -} - -static void BTDM_AdjustForBtOperation8723A(struct rtw_adapter *padapter) -{ - /* BTDM_2AntAdjustForBtOperation8723(padapter); */ -} - -static void BTDM_FwC2hBtRssi8723A(struct rtw_adapter *padapter, u8 *tmpBuf) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 percent, u1tmp; - - u1tmp = tmpBuf[0]; - percent = u1tmp*2+10; - - pHalData->bt_coexist.halCoex8723.btRssi = percent; -/*RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT RSSI =%d\n", percent)); */ -} - -void -rtl8723a_fw_c2h_BT_info(struct rtw_adapter *padapter, u8 *tmpBuf, u8 length) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_coexist_8723a *pBtCoex; - u8 i; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtCoex = &pHalData->bt_coexist.halCoex8723; - - pBtCoex->bC2hBtInfoReqSent = false; - - RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT info[%d]=[", length)); - - pBtCoex->btRetryCnt = 0; - for (i = 0; i < length; i++) { - switch (i) { - case 0: - pBtCoex->c2hBtInfoOriginal = tmpBuf[i]; - break; - case 1: - pBtCoex->btRetryCnt = tmpBuf[i]; - break; - case 2: - BTDM_FwC2hBtRssi8723A(padapter, &tmpBuf[i]); - break; - case 3: - pBtCoex->btInfoExt = tmpBuf[i]&BIT(0); - break; - } - - if (i == length-1) - RTPRINT(FBT, BT_TRACE, ("0x%02x]\n", tmpBuf[i])); - else - RTPRINT(FBT, BT_TRACE, ("0x%02x, ", tmpBuf[i])); - } - RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT RSSI =%d\n", pBtCoex->btRssi)); - if (pBtCoex->btInfoExt) - RTPRINT(FBT, BT_TRACE, ("[BTC2H], pBtCoex->btInfoExt =%x\n", pBtCoex->btInfoExt)); - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntFwC2hBtInfo8723A(padapter); - else - BTDM_2AntFwC2hBtInfo8723A(padapter); - - if (pBtMgnt->ExtConfig.bManualControl) { - RTPRINT(FBT, BT_TRACE, ("%s: Action Manual control!!\n", __func__)); - return; - } - - btdm_BTCoexist8723AHandler(padapter); -} - -static void BTDM_Display8723ABtCoexInfo(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 u1Tmp, u1Tmp1, u1Tmp2, i, btInfoExt, psTdmaCase = 0; - u32 u4Tmp[4]; - u8 antNum = Ant_x2; - - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n ============[BT Coexist info]============"); - DCMD_Printf(btCoexDbgBuf); - - if (!rtl8723a_BT_coexist(padapter)) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n BT not exists !!!"); - DCMD_Printf(btCoexDbgBuf); - return; - } - - antNum = btdm_BtWifiAntNum(padapter); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d/%d ", "Ant mechanism PG/Now run :", \ - ((pHalData->bt_coexist.BT_Ant_Num == Ant_x2) ? 2 : 1), ((antNum == Ant_x2) ? 2 : 1)); - DCMD_Printf(btCoexDbgBuf); - - if (pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "[Action Manual control]!!"); - DCMD_Printf(btCoexDbgBuf); - } else { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", \ - ((pBtMgnt->bSupportProfile) ? "Yes" : "No"), pBtMgnt->ExtConfig.HCIExtensionVer); - DCMD_Printf(btCoexDbgBuf); - } - - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = / %d", "Dot11 channel / BT channel", \ - pBtMgnt->BTChannel); - DCMD_Printf(btCoexDbgBuf); - - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = %d / %d / %d", "Wifi/BT/HS rssi", \ - BTDM_GetRxSS(padapter), - pHalData->bt_coexist.halCoex8723.btRssi, - pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB); - DCMD_Printf(btCoexDbgBuf); - - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = %s / %s ", "WIfi status", - ((BTDM_Legacy(padapter)) ? "Legacy" : (((BTDM_IsHT40(padapter)) ? "HT40" : "HT20"))), - ((!BTDM_IsWifiBusy(padapter)) ? "idle" : ((BTDM_IsWifiUplink(padapter)) ? "uplink" : "downlink"))); - DCMD_Printf(btCoexDbgBuf); - - if (pBtMgnt->bSupportProfile) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", - ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_SCO)) ? 1 : 0), - ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) ? 1 : 0), - ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) ? 1 : 0), - ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) ? 1 : 0)); - DCMD_Printf(btCoexDbgBuf); - - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ %s/ %s", "Bt link type/spec/role", - BtProfileString[pBtMgnt->ExtConfig.linkInfo[i].BTProfile], - BtSpecString[pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec], - BtLinkRoleString[pBtMgnt->ExtConfig.linkInfo[i].linkRole]); - DCMD_Printf(btCoexDbgBuf); - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "A2DP rate", \ - (btInfoExt & BIT(0)) ? - "Basic rate" : "EDR rate"); - DCMD_Printf(btCoexDbgBuf); - } else { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ %s", "Bt link type/spec", \ - BtProfileString[pBtMgnt->ExtConfig.linkInfo[i].BTProfile], - BtSpecString[pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec]); - DCMD_Printf(btCoexDbgBuf); - } - } - } - } - - /* Sw mechanism */ - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Sw BT Coex mechanism]============"); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "AGC Table", \ - pBtCoex->btdm2Ant.bCurAgcTableEn); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "ADC Backoff", \ - pBtCoex->btdm2Ant.bCurAdcBackOff); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Low penalty RA", \ - pBtCoex->btdm2Ant.bCurLowPenaltyRa); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "RF Rx LPF Shrink", \ - pBtCoex->btdm2Ant.bCurRfRxLpfShrink); - DCMD_Printf(btCoexDbgBuf); - } - u4Tmp[0] = PHY_QueryRFReg(padapter, PathA, 0x1e, 0xff0); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x", "RF-A, 0x1e[11:4]/original val", \ - u4Tmp[0], pHalData->bt_coexist.BtRfRegOrigin1E); - DCMD_Printf(btCoexDbgBuf); - - /* Fw mechanism */ - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Fw BT Coex mechanism]============"); - DCMD_Printf(btCoexDbgBuf); - } - if (!pBtMgnt->ExtConfig.bManualControl) { - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm1Ant.curPsTdma; - else - psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm2Ant.curPsTdma; - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %*ph case-%d", - "PS TDMA(0x3a)", 5, pHalData->bt_coexist.fw3aVal, psTdmaCase); - DCMD_Printf(btCoexDbgBuf); - - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Decrease Bt Power", \ - pBtCoex->btdm2Ant.bCurDecBtPwr); - DCMD_Printf(btCoexDbgBuf); - } - u1Tmp = rtl8723au_read8(padapter, 0x778); - u1Tmp1 = rtl8723au_read8(padapter, 0x783); - u1Tmp2 = rtl8723au_read8(padapter, 0x796); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x778/ 0x783/ 0x796", \ - u1Tmp, u1Tmp1, u1Tmp2); - DCMD_Printf(btCoexDbgBuf); - - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x / 0x%x", "Sw DacSwing Ctrl/Val", \ - pBtCoex->btdm2Ant.bCurDacSwingOn, pBtCoex->btdm2Ant.curDacSwingLvl); - DCMD_Printf(btCoexDbgBuf); - } - u4Tmp[0] = rtl8723au_read32(padapter, 0x880); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x880", \ - u4Tmp[0]); - DCMD_Printf(btCoexDbgBuf); - - /* Hw mechanism */ - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw BT Coex mechanism]============"); - DCMD_Printf(btCoexDbgBuf); - } - - u1Tmp = rtl8723au_read8(padapter, 0x40); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x40", \ - u1Tmp); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0x550); - u1Tmp = rtl8723au_read8(padapter, 0x522); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x", "0x550(bcn contrl)/0x522", \ - u4Tmp[0], u1Tmp); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0x484); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x484(rate adaptive)", \ - u4Tmp[0]); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0x50); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0xc50(dig)", \ - u4Tmp[0]); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0xda0); - u4Tmp[1] = rtl8723au_read32(padapter, 0xda4); - u4Tmp[2] = rtl8723au_read32(padapter, 0xda8); - u4Tmp[3] = rtl8723au_read32(padapter, 0xdac); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0xda0/0xda4/0xda8/0xdac(FA cnt)", \ - u4Tmp[0], u4Tmp[1], u4Tmp[2], u4Tmp[3]); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0x6c0); - u4Tmp[1] = rtl8723au_read32(padapter, 0x6c4); - u4Tmp[2] = rtl8723au_read32(padapter, 0x6c8); - u1Tmp = rtl8723au_read8(padapter, 0x6cc); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", \ - u4Tmp[0], u4Tmp[1], u4Tmp[2], u1Tmp); - DCMD_Printf(btCoexDbgBuf); - - /* u4Tmp = rtl8723au_read32(padapter, 0x770); */ - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d", "0x770(Hi pri Rx[31:16]/Tx[15:0])", \ - pHalData->bt_coexist.halCoex8723.highPriorityRx, - pHalData->bt_coexist.halCoex8723.highPriorityTx); - DCMD_Printf(btCoexDbgBuf); - /* u4Tmp = rtl8723au_read32(padapter, 0x774); */ - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d", "0x774(Lo pri Rx[31:16]/Tx[15:0])", \ - pHalData->bt_coexist.halCoex8723.lowPriorityRx, - pHalData->bt_coexist.halCoex8723.lowPriorityTx); - DCMD_Printf(btCoexDbgBuf); - - /* Tx mgnt queue hang or not, 0x41b should = 0xf, ex: 0xd ==>hang */ - u1Tmp = rtl8723au_read8(padapter, 0x41b); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x41b (hang chk == 0xf)", \ - u1Tmp); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "lastHMEBoxNum", \ - pHalData->LastHMEBoxNum); - DCMD_Printf(btCoexDbgBuf); -} - -static void -BTDM_8723ASignalCompensation(struct rtw_adapter *padapter, - u8 *rssi_wifi, u8 *rssi_bt) -{ - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntSignalCompensation(padapter, rssi_wifi, rssi_bt); -} - -static void BTDM_8723AInit(struct rtw_adapter *padapter) -{ - if (btdm_BtWifiAntNum(padapter) == Ant_x2) - BTDM_2AntParaInit(padapter); - else - BTDM_1AntParaInit(padapter); -} - -static void BTDM_HWCoexAllOff8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x2) - BTDM_2AntHwCoexAllOff8723A(padapter); -} - -static void BTDM_FWCoexAllOff8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x2) - BTDM_2AntFwCoexAllOff8723A(padapter); -} - -static void BTDM_SWCoexAllOff8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x2) - BTDM_2AntSwCoexAllOff8723A(padapter); -} - -static void -BTDM_Set8723ABtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723; - - if (antNum == 1) - pBtCoex->TotalAntNum = Ant_x1; - else if (antNum == 2) - pBtCoex->TotalAntNum = Ant_x2; -} - -void rtl8723a_BT_lps_leave(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntLpsLeave(padapter); -} - -static void BTDM_ForHalt8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntForHalt(padapter); -} - -static void BTDM_WifiScanNotify8723A(struct rtw_adapter *padapter, u8 scanType) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntWifiScanNotify(padapter, scanType); -} - -static void -BTDM_WifiAssociateNotify8723A(struct rtw_adapter *padapter, u8 action) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntWifiAssociateNotify(padapter, action); -} - -static void -BTDM_MediaStatusNotify8723A(struct rtw_adapter *padapter, - enum rt_media_status mstatus) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], MediaStatusNotify, %s\n", - mstatus?"connect":"disconnect")); - - BTDM_SetFwChnlInfo(padapter, mstatus); - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntMediaStatusNotify(padapter, mstatus); -} - -static void BTDM_ForDhcp8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntForDhcp(padapter); -} - -bool rtl8723a_BT_using_antenna_1(struct rtw_adapter *padapter) -{ - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - return true; - else - return false; -} - -static void BTDM_BTCoexist8723A(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_coexist_8723a *pBtCoex; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtCoex = &pHalData->bt_coexist.halCoex8723; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], beacon RSSI = 0x%x(%d)\n", - pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB, - pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB)); - - btdm_BtHwCountersMonitor(padapter); - btdm_BtEnableDisableCheck8723A(padapter); - - if (pBtMgnt->ExtConfig.bManualControl) { - RTPRINT(FBT, BT_TRACE, ("%s: Action Manual control!!\n", __func__)); - return; - } - - if (pBtCoex->bC2hBtInfoReqSent) { - if (!rtl8723a_BT_enabled(padapter)) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED; - } else { - if (pBtCoex->c2hBtInfo == BT_INFO_STATE_DISABLED) - pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION; - } - - btdm_BTCoexist8723AHandler(padapter); - } else if (!rtl8723a_BT_enabled(padapter)) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED; - btdm_BTCoexist8723AHandler(padapter); - } - - BTDM_QueryBtInformation(padapter); -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.c ===== */ - -/* local function start with btdm_ */ -/* extern function start with BTDM_ */ - -static void BTDM_SetAntenna(struct rtw_adapter *padapter, u8 who) -{ -} - -void -BTDM_SingleAnt( - struct rtw_adapter *padapter, - u8 bSingleAntOn, - u8 bInterruptOn, - u8 bMultiNAVOn - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[3] = {0}; - - if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1) - return; - - H2C_Parameter[2] = 0; - H2C_Parameter[1] = 0; - H2C_Parameter[0] = 0; - - if (bInterruptOn) { - H2C_Parameter[2] |= 0x02; /* BIT1 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - pHalData->bt_coexist.bInterruptOn = bInterruptOn; - - if (bSingleAntOn) { - H2C_Parameter[2] |= 0x10; /* BIT4 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - pHalData->bt_coexist.bSingleAntOn = bSingleAntOn; - - if (bMultiNAVOn) { - H2C_Parameter[2] |= 0x20; /* BIT5 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - pHalData->bt_coexist.bMultiNAVOn = bMultiNAVOn; - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], SingleAntenna =[%s:%s:%s], write 0xe = 0x%x\n", - bSingleAntOn?"ON":"OFF", bInterruptOn?"ON":"OFF", bMultiNAVOn?"ON":"OFF", - H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2])); -} - -void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - u8 stateChange = false; - u32 BT_Polling, Ratio_Act, Ratio_STA; - u32 BT_Active, BT_State; - u32 regBTActive = 0, regBTState = 0, regBTPolling = 0; - - if (!rtl8723a_BT_coexist(padapter)) - return; - if (pBtMgnt->ExtConfig.bManualControl) - return; - if (pHalData->bt_coexist.BT_CoexistType != BT_CSR_BC8) - return; - if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1) - return; - - /* The following we only consider CSR BC8 and fw version should be >= 62 */ - RTPRINT(FBT, BT_TRACE, ("[DM][BT], FirmwareVersion = 0x%x(%d)\n", - pHalData->FirmwareVersion, pHalData->FirmwareVersion)); - regBTActive = REG_BT_ACTIVE; - regBTState = REG_BT_STATE; - if (pHalData->FirmwareVersion >= FW_VER_BT_REG1) - regBTPolling = REG_BT_POLLING1; - else - regBTPolling = REG_BT_POLLING; - - BT_Active = rtl8723au_read32(padapter, regBTActive); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Active(0x%x) =%x\n", regBTActive, BT_Active)); - BT_Active = BT_Active & 0x00ffffff; - - BT_State = rtl8723au_read32(padapter, regBTState); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_State(0x%x) =%x\n", regBTState, BT_State)); - BT_State = BT_State & 0x00ffffff; - - BT_Polling = rtl8723au_read32(padapter, regBTPolling); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Polling(0x%x) =%x\n", regBTPolling, BT_Polling)); - - if (BT_Active == 0xffffffff && BT_State == 0xffffffff && BT_Polling == 0xffffffff) - return; - if (BT_Polling == 0) - return; - - Ratio_Act = BT_Active*1000/BT_Polling; - Ratio_STA = BT_State*1000/BT_Polling; - - pHalData->bt_coexist.Ratio_Tx = Ratio_Act; - pHalData->bt_coexist.Ratio_PRI = Ratio_STA; - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_Act =%d\n", Ratio_Act)); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_STA =%d\n", Ratio_STA)); - - if (Ratio_STA < 60 && Ratio_Act < 500) { /* BT PAN idle */ - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_IDLE; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK; - } else { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_IDLE; - - if (Ratio_STA) { - /* Check if BT PAN (under BT 2.1) is uplink or downlink */ - if ((Ratio_Act/Ratio_STA) < 2) { - /* BT PAN Uplink */ - pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = true; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_UPLINK; - pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = false; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK; - } else { - /* BT PAN downlink */ - pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = false; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK; - pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = true; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK; - } - } else { - /* BT PAN downlink */ - pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = false; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK; - pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = true; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK; - } - } - - /* Check BT is idle or not */ - if (pBtMgnt->ExtConfig.NumberOfHandle == 0 && - pBtMgnt->ExtConfig.NumberOfSCO == 0) { - pBtMgnt->ExtConfig.bBTBusy = false; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE; - } else { - if (Ratio_STA < 60) { - pBtMgnt->ExtConfig.bBTBusy = false; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE; - } else { - pBtMgnt->ExtConfig.bBTBusy = true; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_IDLE; - } - } - - if (pBtMgnt->ExtConfig.NumberOfHandle == 0 && - pBtMgnt->ExtConfig.NumberOfSCO == 0) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW; - pBtMgnt->ExtConfig.MIN_BT_RSSI = 0; - BTDM_SetAntenna(padapter, BTDM_ANT_BT_IDLE); - } else { - if (pBtMgnt->ExtConfig.MIN_BT_RSSI <= -5) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_RSSI_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], core stack notify bt rssi Low\n")); - } else { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], core stack notify bt rssi Normal\n")); - } - } - - if (pHalData->bt_coexist.bBTBusyTraffic != pBtMgnt->ExtConfig.bBTBusy) { - /* BT idle or BT non-idle */ - pHalData->bt_coexist.bBTBusyTraffic = pBtMgnt->ExtConfig.bBTBusy; - stateChange = true; - } - - if (stateChange) { - if (!pBtMgnt->ExtConfig.bBTBusy) - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is idle or disable\n")); - else - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is non-idle\n")); - } - if (!pBtMgnt->ExtConfig.bBTBusy) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is idle or disable\n")); - if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING|WIFI_SITE_MONITOR) == true) - BTDM_SetAntenna(padapter, BTDM_ANT_WIFI); - } -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.c ===== */ - -/* local function start with btdm_ */ - -/* Note: */ -/* In the following, FW should be done before SW mechanism. */ -/* BTDM_Balance(), BTDM_DiminishWiFi(), BT_NAV() should be done */ -/* before BTDM_AGCTable(), BTDM_BBBackOffLevel(), btdm_DacSwing(). */ - -/* extern function start with BTDM_ */ - -void -BTDM_DiminishWiFi( - struct rtw_adapter *padapter, - u8 bDACOn, - u8 bInterruptOn, - u8 DACSwingLevel, - u8 bNAVOn - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[3] = {0}; - - if (pHalData->bt_coexist.BT_Ant_Num != Ant_x2) - return; - - if ((pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_RSSI_LOW) && - (DACSwingLevel == 0x20)) { - RTPRINT(FBT, BT_TRACE, ("[BT]DiminishWiFi 0x20 original, but set 0x18 for Low RSSI!\n")); - DACSwingLevel = 0x18; - } - - H2C_Parameter[2] = 0; - H2C_Parameter[1] = DACSwingLevel; - H2C_Parameter[0] = 0; - if (bDACOn) { - H2C_Parameter[2] |= 0x01; /* BIT0 */ - if (bInterruptOn) - H2C_Parameter[2] |= 0x02; /* BIT1 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - if (bNAVOn) { - H2C_Parameter[2] |= 0x08; /* BIT3 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], bDACOn = %s, bInterruptOn = %s, write 0xe = 0x%x\n", - bDACOn?"ON":"OFF", bInterruptOn?"ON":"OFF", - H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2])); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], bNAVOn = %s\n", - bNAVOn?"ON":"OFF")); -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtCoexist.c ===== */ - -/* local function */ -static void btdm_ResetFWCoexState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->bt_coexist.CurrentState = 0; - pHalData->bt_coexist.PreviousState = 0; -} - -static void btdm_InitBtCoexistDM(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* 20100415 Joseph: Restore RF register 0x1E and 0x1F value for further usage. */ - pHalData->bt_coexist.BtRfRegOrigin1E = PHY_QueryRFReg(padapter, PathA, RF_RCK1, bRFRegOffsetMask); - pHalData->bt_coexist.BtRfRegOrigin1F = PHY_QueryRFReg(padapter, PathA, RF_RCK2, 0xf0); - - pHalData->bt_coexist.CurrentState = 0; - pHalData->bt_coexist.PreviousState = 0; - - BTDM_8723AInit(padapter); - pHalData->bt_coexist.bInitlized = true; -} - -/* */ -/* extern function */ -/* */ -void BTDM_CheckAntSelMode(struct rtw_adapter *padapter) -{ -} - -void BTDM_FwC2hBtRssi(struct rtw_adapter *padapter, u8 *tmpBuf) -{ - BTDM_FwC2hBtRssi8723A(padapter, tmpBuf); -} - -void BTDM_DisplayBtCoexInfo(struct rtw_adapter *padapter) -{ - BTDM_Display8723ABtCoexInfo(padapter); -} - -void BTDM_RejectAPAggregatedPacket(struct rtw_adapter *padapter, u8 bReject) -{ -} - -u8 BTDM_IsHT40(struct rtw_adapter *padapter) -{ - u8 isht40 = true; - enum ht_channel_width bw; - - bw = padapter->mlmeextpriv.cur_bwmode; - - if (bw == HT_CHANNEL_WIDTH_20) - isht40 = false; - else if (bw == HT_CHANNEL_WIDTH_40) - isht40 = true; - - return isht40; -} - -u8 BTDM_Legacy(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext; - u8 isLegacy = false; - - pmlmeext = &padapter->mlmeextpriv; - if ((pmlmeext->cur_wireless_mode == WIRELESS_11B) || - (pmlmeext->cur_wireless_mode == WIRELESS_11G) || - (pmlmeext->cur_wireless_mode == WIRELESS_11BG)) - isLegacy = true; - - return isLegacy; -} - -void BTDM_CheckWiFiState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct mlme_priv *pmlmepriv; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - - pHalData = GET_HAL_DATA(padapter); - pmlmepriv = &padapter->mlmepriv; - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - - if (pmlmepriv->LinkDetectInfo.bBusyTraffic) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_IDLE; - - if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic) - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_UPLINK; - else - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_UPLINK; - - if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic) - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_DOWNLINK; - else - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_DOWNLINK; - } else { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_IDLE; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_UPLINK; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_DOWNLINK; - } - - if (BTDM_Legacy(padapter)) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_LEGACY; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT20; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT40; - } else { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_LEGACY; - if (BTDM_IsHT40(padapter)) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_HT40; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT20; - } else { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_HT20; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT40; - } - } - - if (pBtMgnt->BtOperationOn) - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT30; - else - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT30; -} - -s32 BTDM_GetRxSS(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct hal_data_8723a *pHalData; - s32 UndecoratedSmoothedPWDB = 0; - - pmlmepriv = &padapter->mlmepriv; - pHalData = GET_HAL_DATA(padapter); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - UndecoratedSmoothedPWDB = GET_UNDECORATED_AVERAGE_RSSI(padapter); - } else { /* associated entry pwdb */ - UndecoratedSmoothedPWDB = pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB; - /* pHalData->BT_EntryMinUndecoratedSmoothedPWDB */ - } - RTPRINT(FBT, BT_TRACE, ("BTDM_GetRxSS() = %d\n", UndecoratedSmoothedPWDB)); - return UndecoratedSmoothedPWDB; -} - -static s32 BTDM_GetRxBeaconSS(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct hal_data_8723a *pHalData; - s32 pwdbBeacon = 0; - - pmlmepriv = &padapter->mlmepriv; - pHalData = GET_HAL_DATA(padapter); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - /* pwdbBeacon = pHalData->dmpriv.UndecoratedSmoothedBeacon; */ - pwdbBeacon = pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB; - } - RTPRINT(FBT, BT_TRACE, ("BTDM_GetRxBeaconSS() = %d\n", pwdbBeacon)); - return pwdbBeacon; -} - -/* Get beacon rssi state */ -u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - s32 pwdbBeacon = 0; - u8 bcnRssiState = 0; - - pwdbBeacon = BTDM_GetRxBeaconSS(padapter); - - if (levelNum == 2) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - - if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_LOW)) { - if (pwdbBeacon >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - bcnRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to High\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Low\n")); - } - } else { - if (pwdbBeacon < RssiThresh) { - bcnRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Low\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at High\n")); - } - } - } else if (levelNum == 3) { - if (RssiThresh > RssiThresh1) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON thresh error!!\n")); - return pHalData->bt_coexist.preRssiStateBeacon; - } - - if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_LOW)) { - if (pwdbBeacon >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - bcnRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Medium\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Low\n")); - } - } else if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_MEDIUM) || - (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_MEDIUM)) { - if (pwdbBeacon >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) { - bcnRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to High\n")); - } else if (pwdbBeacon < RssiThresh) { - bcnRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Low\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Medium\n")); - } - } else { - if (pwdbBeacon < RssiThresh1) { - bcnRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Medium\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at High\n")); - } - } - } - - pHalData->bt_coexist.preRssiStateBeacon = bcnRssiState; - - return bcnRssiState; -} - -u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - s32 UndecoratedSmoothedPWDB = 0; - u8 btRssiState = 0; - - UndecoratedSmoothedPWDB = BTDM_GetRxSS(padapter); - - if (levelNum == 2) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - - if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_LOW)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to High\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Low\n")); - } - } else { - if (UndecoratedSmoothedPWDB < RssiThresh) { - btRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Low\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at High\n")); - } - } - } else if (levelNum == 3) { - if (RssiThresh > RssiThresh1) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 thresh error!!\n")); - return pHalData->bt_coexist.preRssiState1; - } - - if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_LOW)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Medium\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Low\n")); - } - } else if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_MEDIUM) || - (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_MEDIUM)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to High\n")); - } else if (UndecoratedSmoothedPWDB < RssiThresh) { - btRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Low\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Medium\n")); - } - } else { - if (UndecoratedSmoothedPWDB < RssiThresh1) { - btRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Medium\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at High\n")); - } - } - } - - pHalData->bt_coexist.preRssiState1 = btRssiState; - - return btRssiState; -} - -u8 BTDM_CheckCoexRSSIState(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - s32 UndecoratedSmoothedPWDB = 0; - u8 btRssiState = 0; - - UndecoratedSmoothedPWDB = BTDM_GetRxSS(padapter); - - if (levelNum == 2) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - - if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_LOW)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to High\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Low\n")); - } - } else { - if (UndecoratedSmoothedPWDB < RssiThresh) { - btRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Low\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at High\n")); - } - } - } else if (levelNum == 3) { - if (RssiThresh > RssiThresh1) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI thresh error!!\n")); - return pHalData->bt_coexist.preRssiState; - } - - if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_LOW)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Medium\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Low\n")); - } - } else if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_MEDIUM) || - (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_MEDIUM)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to High\n")); - } else if (UndecoratedSmoothedPWDB < RssiThresh) { - btRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Low\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Medium\n")); - } - } else { - if (UndecoratedSmoothedPWDB < RssiThresh1) { - btRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Medium\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at High\n")); - } - } - } - - pHalData->bt_coexist.preRssiState = btRssiState; - - return btRssiState; -} - -bool rtl8723a_BT_disable_EDCA_turbo(struct rtw_adapter *padapter) -{ - struct bt_mgnt *pBtMgnt; - struct hal_data_8723a *pHalData; - u8 bBtChangeEDCA = false; - u32 EDCA_BT_BE = 0x5ea42b, cur_EDCA_reg; - bool bRet = false; - - pHalData = GET_HAL_DATA(padapter); - pBtMgnt = &pHalData->BtInfo.BtMgnt; - - if (!rtl8723a_BT_coexist(padapter)) { - bRet = false; - pHalData->bt_coexist.lastBtEdca = 0; - return bRet; - } - if (!((pBtMgnt->bSupportProfile) || - (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8))) { - bRet = false; - pHalData->bt_coexist.lastBtEdca = 0; - return bRet; - } - - if (rtl8723a_BT_using_antenna_1(padapter)) { - bRet = false; - pHalData->bt_coexist.lastBtEdca = 0; - return bRet; - } - - if (pHalData->bt_coexist.exec_cnt < 3) - pHalData->bt_coexist.exec_cnt++; - else - pHalData->bt_coexist.bEDCAInitialized = true; - - /* When BT is non idle */ - if (!(pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE)) { - RTPRINT(FBT, BT_TRACE, ("BT state non idle, set bt EDCA\n")); - - /* aggr_num = 0x0909; */ - if (pHalData->odmpriv.DM_EDCA_Table.bCurrentTurboEDCA) { - bBtChangeEDCA = true; - pHalData->odmpriv.DM_EDCA_Table.bCurrentTurboEDCA = false; - pHalData->dmpriv.prv_traffic_idx = 3; - } - cur_EDCA_reg = rtl8723au_read32(padapter, REG_EDCA_BE_PARAM); - - if (cur_EDCA_reg != EDCA_BT_BE) - bBtChangeEDCA = true; - if (bBtChangeEDCA || !pHalData->bt_coexist.bEDCAInitialized) { - rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, - EDCA_BT_BE); - pHalData->bt_coexist.lastBtEdca = EDCA_BT_BE; - } - bRet = true; - } else { - RTPRINT(FBT, BT_TRACE, ("BT state idle, set original EDCA\n")); - pHalData->bt_coexist.lastBtEdca = 0; - bRet = false; - } - return bRet; -} - -void -BTDM_Balance( - struct rtw_adapter *padapter, - u8 bBalanceOn, - u8 ms0, - u8 ms1 - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[3] = {0}; - - if (bBalanceOn) { - H2C_Parameter[2] = 1; - H2C_Parameter[1] = ms1; - H2C_Parameter[0] = ms0; - pHalData->bt_coexist.bFWCoexistAllOff = false; - } else { - H2C_Parameter[2] = 0; - H2C_Parameter[1] = 0; - H2C_Parameter[0] = 0; - } - pHalData->bt_coexist.bBalanceOn = bBalanceOn; - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], Balance =[%s:%dms:%dms], write 0xc = 0x%x\n", - bBalanceOn?"ON":"OFF", ms0, ms1, - H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2])); - - FillH2CCmd(padapter, 0xc, 3, H2C_Parameter); -} - -void BTDM_AGCTable(struct rtw_adapter *padapter, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - if (type == BT_AGCTABLE_OFF) { - RTPRINT(FBT, BT_TRACE, ("[BT]AGCTable Off!\n")); - rtl8723au_write32(padapter, 0xc78, 0x641c0001); - rtl8723au_write32(padapter, 0xc78, 0x631d0001); - rtl8723au_write32(padapter, 0xc78, 0x621e0001); - rtl8723au_write32(padapter, 0xc78, 0x611f0001); - rtl8723au_write32(padapter, 0xc78, 0x60200001); - - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x32000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x71000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xb0000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xfc000); - PHY_SetRFReg(padapter, PathA, RF_RX_G1, bRFRegOffsetMask, 0x30355); - - pHalData->bt_coexist.b8723aAgcTableOn = false; - } else if (type == BT_AGCTABLE_ON) { - RTPRINT(FBT, BT_TRACE, ("[BT]AGCTable On!\n")); - rtl8723au_write32(padapter, 0xc78, 0x4e1c0001); - rtl8723au_write32(padapter, 0xc78, 0x4d1d0001); - rtl8723au_write32(padapter, 0xc78, 0x4c1e0001); - rtl8723au_write32(padapter, 0xc78, 0x4b1f0001); - rtl8723au_write32(padapter, 0xc78, 0x4a200001); - - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xdc000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x90000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x51000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x12000); - PHY_SetRFReg(padapter, PathA, RF_RX_G1, bRFRegOffsetMask, 0x00355); - - pHalData->bt_coexist.b8723aAgcTableOn = true; - - pHalData->bt_coexist.bSWCoexistAllOff = false; - } -} - -void BTDM_BBBackOffLevel(struct rtw_adapter *padapter, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (type == BT_BB_BACKOFF_OFF) { - RTPRINT(FBT, BT_TRACE, ("[BT]BBBackOffLevel Off!\n")); - rtl8723au_write32(padapter, 0xc04, 0x3a05611); - } else if (type == BT_BB_BACKOFF_ON) { - RTPRINT(FBT, BT_TRACE, ("[BT]BBBackOffLevel On!\n")); - rtl8723au_write32(padapter, 0xc04, 0x3a07611); - pHalData->bt_coexist.bSWCoexistAllOff = false; - } -} - -void BTDM_FWCoexAllOff(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - RTPRINT(FBT, BT_TRACE, ("BTDM_FWCoexAllOff()\n")); - if (pHalData->bt_coexist.bFWCoexistAllOff) - return; - RTPRINT(FBT, BT_TRACE, ("BTDM_FWCoexAllOff(), real Do\n")); - - BTDM_FWCoexAllOff8723A(padapter); - - pHalData->bt_coexist.bFWCoexistAllOff = true; -} - -void BTDM_SWCoexAllOff(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - RTPRINT(FBT, BT_TRACE, ("BTDM_SWCoexAllOff()\n")); - if (pHalData->bt_coexist.bSWCoexistAllOff) - return; - RTPRINT(FBT, BT_TRACE, ("BTDM_SWCoexAllOff(), real Do\n")); - BTDM_SWCoexAllOff8723A(padapter); - - pHalData->bt_coexist.bSWCoexistAllOff = true; -} - -void BTDM_HWCoexAllOff(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - RTPRINT(FBT, BT_TRACE, ("BTDM_HWCoexAllOff()\n")); - if (pHalData->bt_coexist.bHWCoexistAllOff) - return; - RTPRINT(FBT, BT_TRACE, ("BTDM_HWCoexAllOff(), real Do\n")); - - BTDM_HWCoexAllOff8723A(padapter); - - pHalData->bt_coexist.bHWCoexistAllOff = true; -} - -void BTDM_CoexAllOff(struct rtw_adapter *padapter) -{ - BTDM_FWCoexAllOff(padapter); - BTDM_SWCoexAllOff(padapter); - BTDM_HWCoexAllOff(padapter); -} - -void rtl8723a_BT_disable_coexist(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv; - - if (!rtl8723a_BT_coexist(padapter)) - return; - - /* 8723 1Ant doesn't need to turn off bt coexist mechanism. */ - if (rtl8723a_BT_using_antenna_1(padapter)) - return; - - /* Before enter IPS, turn off FW BT Co-exist mechanism */ - if (ppwrctrl->reg_rfoff == rf_on) { - RTPRINT(FBT, BT_TRACE, ("[BT][DM], Before enter IPS, turn off all Coexist DM\n")); - btdm_ResetFWCoexState(padapter); - BTDM_CoexAllOff(padapter); - BTDM_SetAntenna(padapter, BTDM_ANT_BT); - } -} - -void BTDM_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt) -{ - BTDM_8723ASignalCompensation(padapter, rssi_wifi, rssi_bt); -} - -void rtl8723a_BT_do_coexist(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (!rtl8723a_BT_coexist(padapter)) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT not exists!!\n")); - return; - } - - if (!pHalData->bt_coexist.bInitlized) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_InitBtCoexistDM()\n")); - btdm_InitBtCoexistDM(padapter); - } - - RTPRINT(FBT, BT_TRACE, ("\n\n[DM][BT], BTDM start!!\n")); - - BTDM_PWDBMonitor(padapter); - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], HW type is 8723\n")); - BTDM_BTCoexist8723A(padapter); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BTDM end!!\n\n")); -} - -void BTDM_UpdateCoexState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (!BTDM_IsSameCoexistState(padapter)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x, changeBits = 0x%"i64fmt"x\n", - pHalData->bt_coexist.PreviousState, - pHalData->bt_coexist.CurrentState, - (pHalData->bt_coexist.PreviousState^pHalData->bt_coexist.CurrentState))); - pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState; - } -} - -u8 BTDM_IsSameCoexistState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState) { - return true; - } else { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], Coexist state changed!!\n")); - return false; - } -} - -void BTDM_PWDBMonitor(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(GetDefaultAdapter(padapter)); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[3] = {0}; - s32 tmpBTEntryMaxPWDB = 0, tmpBTEntryMinPWDB = 0xff; - u8 i; - - if (pBtMgnt->BtOperationOn) { - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if (pBTInfo->BtAsocEntry[i].bUsed) { - if (pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB < tmpBTEntryMinPWDB) - tmpBTEntryMinPWDB = pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB; - if (pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB > tmpBTEntryMaxPWDB) - tmpBTEntryMaxPWDB = pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB; - /* Report every BT connection (HS mode) RSSI to FW */ - H2C_Parameter[2] = (u8)(pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB & 0xFF); - H2C_Parameter[0] = (MAX_FW_SUPPORT_MACID_NUM-1-i); - RTPRINT(FDM, DM_BT30, ("RSSI report for BT[%d], H2C_Par = 0x%x\n", i, H2C_Parameter[0])); - FillH2CCmd(padapter, RSSI_SETTING_EID, 3, H2C_Parameter); - RTPRINT_ADDR(FDM, (DM_PWDB|DM_BT30), ("BT_Entry Mac :"), - pBTInfo->BtAsocEntry[i].BTRemoteMACAddr) - RTPRINT(FDM, (DM_PWDB|DM_BT30), - ("BT rx pwdb[%d] = 0x%x(%d)\n", i, - pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB, - pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB)); - } - } - if (tmpBTEntryMaxPWDB != 0) { /* If associated entry is found */ - pHalData->dmpriv.BT_EntryMaxUndecoratedSmoothedPWDB = tmpBTEntryMaxPWDB; - RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT_EntryMaxPWDB = 0x%x(%d)\n", - tmpBTEntryMaxPWDB, tmpBTEntryMaxPWDB)); - } else { - pHalData->dmpriv.BT_EntryMaxUndecoratedSmoothedPWDB = 0; - } - if (tmpBTEntryMinPWDB != 0xff) { /* If associated entry is found */ - pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB = tmpBTEntryMinPWDB; - RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT_EntryMinPWDB = 0x%x(%d)\n", - tmpBTEntryMinPWDB, tmpBTEntryMinPWDB)); - } else { - pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB = 0; - } - } -} - -u8 BTDM_IsBTBusy(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bBTBusy) - return true; - else - return false; -} - -u8 BTDM_IsWifiBusy(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */ - struct mlme_priv *pmlmepriv = &GetDefaultAdapter(padapter)->mlmepriv; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_traffic *pBtTraffic = &pBTInfo->BtTraffic; - - if (pmlmepriv->LinkDetectInfo.bBusyTraffic || - pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic || - pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic) - return true; - else - return false; -} - -u8 BTDM_IsCoexistStateChanged(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState) - return false; - else - return true; -} - -u8 BTDM_IsWifiUplink(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct bt_30info *pBTInfo; - struct bt_traffic *pBtTraffic; - - pmlmepriv = &padapter->mlmepriv; - pBTInfo = GET_BT_INFO(padapter); - pBtTraffic = &pBTInfo->BtTraffic; - - if ((pmlmepriv->LinkDetectInfo.bTxBusyTraffic) || - (pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic)) - return true; - else - return false; -} - -u8 BTDM_IsWifiDownlink(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct bt_30info *pBTInfo; - struct bt_traffic *pBtTraffic; - - pmlmepriv = &padapter->mlmepriv; - pBTInfo = GET_BT_INFO(padapter); - pBtTraffic = &pBTInfo->BtTraffic; - - if ((pmlmepriv->LinkDetectInfo.bRxBusyTraffic) || - (pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic)) - return true; - else - return false; -} - -u8 BTDM_IsBTHSMode(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */ - struct hal_data_8723a *pHalData; - struct bt_mgnt *pBtMgnt; - - pHalData = GET_HAL_DATA(padapter); - pBtMgnt = &pHalData->BtInfo.BtMgnt; - - if (pBtMgnt->BtOperationOn) - return true; - else - return false; -} - -u8 BTDM_IsBTUplink(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic) - return true; - else - return false; -} - -u8 BTDM_IsBTDownlink(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic) - return true; - else - return false; -} - -void BTDM_AdjustForBtOperation(struct rtw_adapter *padapter) -{ - RTPRINT(FBT, BT_TRACE, ("[BT][DM], BTDM_AdjustForBtOperation()\n")); - BTDM_AdjustForBtOperation8723A(padapter); -} - -void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum) -{ - BTDM_Set8723ABtCoexCurrAntNum(padapter, antNum); -} - -void BTDM_ForHalt(struct rtw_adapter *padapter) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_ForHalt8723A(padapter); - GET_HAL_DATA(padapter)->bt_coexist.bInitlized = false; -} - -void BTDM_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_WifiScanNotify8723A(padapter, scanType); -} - -void BTDM_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_WifiAssociateNotify8723A(padapter, action); -} - -void rtl8723a_BT_mediastatus_notify(struct rtw_adapter *padapter, - enum rt_media_status mstatus) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_MediaStatusNotify8723A(padapter, mstatus); -} - -void rtl8723a_BT_specialpacket_notify(struct rtw_adapter *padapter) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_ForDhcp8723A(padapter); -} - -void BTDM_ResetActionProfileState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->bt_coexist.CurrentState &= ~\ - (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP| - BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_SCO); -} - -u8 BTDM_IsActionSCO(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_SCO) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO; - bRet = true; - } - } else { - if (pBtMgnt->ExtConfig.NumberOfSCO > 0) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO; - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionHID(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo; - struct hal_data_8723a *pHalData; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID; - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - pBtMgnt->ExtConfig.NumberOfHandle == 1) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID; - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionA2DP(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_A2DP) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP; - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP) && - pBtMgnt->ExtConfig.NumberOfHandle == 1) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP; - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionPAN(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN; - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - pBtMgnt->ExtConfig.NumberOfHandle == 1) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN; - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionHIDA2DP(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_A2DP) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP); - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP); - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionHIDPAN(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_PAN) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN); - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN); - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionPANA2DP(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN_A2DP) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP); - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP); - bRet = true; - } - } - return bRet; -} - -bool rtl8723a_BT_enabled(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.bCurBtDisabled) - return false; - else - return true; -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/HalBT.c ===== */ - -/* */ -/*local function */ -/* */ - -static void halbt_InitHwConfig8723A(struct rtw_adapter *padapter) -{ -} - -/* */ -/*extern function */ -/* */ -u8 HALBT_GetPGAntNum(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - return pHalData->bt_coexist.BT_Ant_Num; -} - -void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTinfo; - struct bt_asoc_entry *pBtAssocEntry; - u16 usConfig = 0; - - pBTinfo = GET_BT_INFO(padapter); - pBtAssocEntry = &pBTinfo->BtAsocEntry[EntryNum]; - - pBtAssocEntry->HwCAMIndex = BT_HWCAM_STAR + EntryNum; - - usConfig = CAM_VALID | (CAM_AES << 2); - rtl8723a_cam_write(padapter, pBtAssocEntry->HwCAMIndex, usConfig, - pBtAssocEntry->BTRemoteMACAddr, - pBtAssocEntry->PTK + TKIP_ENC_KEY_POS); -} - -void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTinfo; - struct bt_asoc_entry *pBtAssocEntry; - - pBTinfo = GET_BT_INFO(padapter); - pBtAssocEntry = &pBTinfo->BtAsocEntry[EntryNum]; - - if (pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex != 0) { - /* ToDo : add New HALBT_RemoveKey function !! */ - if (pBtAssocEntry->HwCAMIndex >= BT_HWCAM_STAR && - pBtAssocEntry->HwCAMIndex < HALF_CAM_ENTRY) - rtl8723a_cam_empty_entry(padapter, - pBtAssocEntry->HwCAMIndex); - pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex = 0; - } -} - -void rtl8723a_BT_init_hal_vars(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - - pHalData = GET_HAL_DATA(padapter); - - pHalData->bt_coexist.BluetoothCoexist = pHalData->EEPROMBluetoothCoexist; - pHalData->bt_coexist.BT_Ant_Num = pHalData->EEPROMBluetoothAntNum; - pHalData->bt_coexist.BT_CoexistType = pHalData->EEPROMBluetoothType; - pHalData->bt_coexist.BT_Ant_isolation = pHalData->EEPROMBluetoothAntIsolation; - pHalData->bt_coexist.bt_radiosharedtype = pHalData->EEPROMBluetoothRadioShared; - - RT_TRACE(_module_hal_init_c_, _drv_info_, - "BT Coexistance = 0x%x\n", rtl8723a_BT_coexist(padapter)); - - if (rtl8723a_BT_coexist(padapter)) { - if (pHalData->bt_coexist.BT_Ant_Num == Ant_x2) { - BTDM_SetBtCoexCurrAntNum(padapter, 2); - RT_TRACE(_module_hal_init_c_, _drv_info_, - "BlueTooth BT_Ant_Num = Antx2\n"); - } else if (pHalData->bt_coexist.BT_Ant_Num == Ant_x1) { - BTDM_SetBtCoexCurrAntNum(padapter, 1); - RT_TRACE(_module_hal_init_c_, _drv_info_, - "BlueTooth BT_Ant_Num = Antx1\n"); - } - pHalData->bt_coexist.bBTBusyTraffic = false; - pHalData->bt_coexist.bBTTrafficModeSet = false; - pHalData->bt_coexist.bBTNonTrafficModeSet = false; - pHalData->bt_coexist.CurrentState = 0; - pHalData->bt_coexist.PreviousState = 0; - - RT_TRACE(_module_hal_init_c_, _drv_info_, - "bt_radiosharedType = 0x%x\n", - pHalData->bt_coexist.bt_radiosharedtype); - } -} - -bool rtl8723a_BT_coexist(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.BluetoothCoexist) - return true; - else - return false; -} - -u8 HALBT_BTChipType(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - return pHalData->bt_coexist.BT_CoexistType; -} - -void rtl8723a_BT_init_hwconfig(struct rtw_adapter *padapter) -{ - halbt_InitHwConfig8723A(padapter); - rtl8723a_BT_do_coexist(padapter); -} - -void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter *padapter) -{ -} - -/* ===== End of sync from SD7 driver HAL/HalBT.c ===== */ - -void rtl8723a_dual_antenna_detection(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct dm_odm_t *pDM_Odm; - struct sw_ant_sw *pDM_SWAT_Table; - u8 i; - - pHalData = GET_HAL_DATA(padapter); - pDM_Odm = &pHalData->odmpriv; - pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table; - - /* */ - /* RTL8723A Single and Dual antenna dynamic detection - mechanism when RF power state is on. */ - /* We should take power tracking, IQK, LCK, RCK RF read/write - operation into consideration. */ - /* 2011.12.15. */ - /* */ - if (!pHalData->bAntennaDetected) { - u8 btAntNum = BT_GetPGAntNum(padapter); - - /* Set default antenna B status */ - if (btAntNum == Ant_x2) - pDM_SWAT_Table->ANTB_ON = true; - else if (btAntNum == Ant_x1) - pDM_SWAT_Table->ANTB_ON = false; - else - pDM_SWAT_Table->ANTB_ON = true; - - if (pHalData->CustomerID != RT_CID_TOSHIBA) { - for (i = 0; i < MAX_ANTENNA_DETECTION_CNT; i++) { - if (ODM_SingleDualAntennaDetection - (&pHalData->odmpriv, ANTTESTALL) == true) - break; - } - - /* Set default antenna number for BT coexistence */ - if (btAntNum == Ant_x2) - BT_SetBtCoexCurrAntNum(padapter, - pDM_SWAT_Table-> - ANTB_ON ? 2 : 1); - } - pHalData->bAntennaDetected = true; - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c b/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c deleted file mode 100644 index 2230f4c539ec..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c +++ /dev/null @@ -1,755 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTL8723A_CMD_C_ - -#include -#include -#include -#include -#include -#include - -#define RTL92C_MAX_H2C_BOX_NUMS 4 -#define RTL92C_MAX_CMD_LEN 5 -#define MESSAGE_BOX_SIZE 4 -#define EX_MESSAGE_BOX_SIZE 2 - -static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num) -{ - u8 read_down = false; - int retry_cnts = 100; - u8 valid; - - do { - valid = rtl8723au_read8(padapter, REG_HMETFR) & BIT(msgbox_num); - if (0 == valid) - read_down = true; - } while ((!read_down) && (retry_cnts--)); - - return read_down; -} - -/***************************************** -* H2C Msg format : -*| 31 - 8 |7 | 6 - 0 | -*| h2c_msg |Ext_bit |CMD_ID | -* -******************************************/ -int FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, - u8 *pCmdBuffer) -{ - u8 bcmd_down = false; - s32 retry_cnts = 100; - u8 h2c_box_num; - u32 msgbox_addr; - u32 msgbox_ex_addr; - struct hal_data_8723a *pHalData; - u32 h2c_cmd = 0; - u16 h2c_cmd_ex = 0; - int ret = _FAIL; - - padapter = GET_PRIMARY_ADAPTER(padapter); - pHalData = GET_HAL_DATA(padapter); - - mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex); - - if (!pCmdBuffer) - goto exit; - if (CmdLen > RTL92C_MAX_CMD_LEN) - goto exit; - if (padapter->bSurpriseRemoved == true) - goto exit; - - /* pay attention to if race condition happened in H2C cmd setting. */ - do { - h2c_box_num = pHalData->LastHMEBoxNum; - - if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) { - DBG_8723A(" fw read cmd failed...\n"); - goto exit; - } - - if (CmdLen <= 3) { - memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen); - } else { - memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE); - memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer+2, (CmdLen-EX_MESSAGE_BOX_SIZE)); - *(u8 *)(&h2c_cmd) |= BIT(7); - } - - *(u8 *)(&h2c_cmd) |= ElementID; - - if (h2c_cmd & BIT(7)) { - msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE); - h2c_cmd_ex = le16_to_cpu(h2c_cmd_ex); - rtl8723au_write16(padapter, msgbox_ex_addr, h2c_cmd_ex); - } - msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * MESSAGE_BOX_SIZE); - h2c_cmd = le32_to_cpu(h2c_cmd); - rtl8723au_write32(padapter, msgbox_addr, h2c_cmd); - - bcmd_down = true; - - pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS; - - } while ((!bcmd_down) && (retry_cnts--)); - - ret = _SUCCESS; - -exit: - mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex); - return ret; -} - -int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u32 param) -{ - __le32 cmd = cpu_to_le32(param); - - FillH2CCmd(padapter, RSSI_SETTING_EID, 3, (void *)&cmd); - - return _SUCCESS; -} - -int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg) -{ - u8 buf[5]; - - memset(buf, 0, 5); - put_unaligned_le32(mask, buf); - buf[4] = arg; - - FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf); - - return _SUCCESS; -} - -/* bitmap[0:27] = tx_rate_bitmap */ -/* bitmap[28:31]= Rate Adaptive id */ -/* arg[0:4] = macid */ -/* arg[5] = Short GI */ -void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - u8 macid = arg & 0x1f; - u32 raid = bitmap & 0xf0000000; - - bitmap &= 0x0fffffff; - if (rssi_level != DM_RATR_STA_INIT) - bitmap = ODM_Get_Rate_Bitmap23a(pHalData, macid, bitmap, - rssi_level); - - bitmap |= raid; - - rtl8723a_set_raid_cmd(pAdapter, bitmap, arg); -} - -void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode) -{ - struct setpwrmode_parm H2CSetPwrMode; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - DBG_8723A("%s: Mode =%d SmartPS =%d UAPSD =%d BcnMode = 0x%02x\n", __func__, - Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable, pwrpriv->bcn_ant_mode); - - /* Forece leave RF low power mode for 1T1R to - prevent conficting setting in Fw power */ - /* saving sequence. 2010.06.07. Added by tynli. - Suggested by SD3 yschang. */ - if (Mode != PS_MODE_ACTIVE && pHalData->rf_type != RF_2T2R) - ODM_RF_Saving23a(&pHalData->odmpriv, true); - - H2CSetPwrMode.Mode = Mode; - H2CSetPwrMode.SmartPS = pwrpriv->smart_ps; - H2CSetPwrMode.AwakeInterval = 1; - H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable; - H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode; - - FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode); - -} - -static void -ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength) -{ - struct ieee80211_mgmt *mgmt; - u32 rate_len, pktlen; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - /* DBG_8723A("%s\n", __func__); */ - - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - - ether_addr_copy(mgmt->da, bc_addr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network)); - - /* A Beacon frame shouldn't have fragment bits set */ - mgmt->seq_ctrl = 0; - - /* timestamp will be inserted by hardware */ - - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.beacon.beacon_int); - - put_unaligned_le16(cur_network->capability, - &mgmt->u.beacon.capab_info); - - pframe = mgmt->u.beacon.variable; - pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable); - - if ((pmlmeinfo->state&0x03) == MSR_AP) { - /* DBG_8723A("ie len =%d\n", cur_network->IELength); */ - pktlen += cur_network->IELength; - memcpy(pframe, cur_network->IEs, pktlen); - - goto _ConstructBeacon; - } - - /* below for ad-hoc mode */ - - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - cur_network->Ssid.ssid_len, - cur_network->Ssid.ssid, &pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates); - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? - 8 : rate_len), cur_network->SupportedRates, &pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *) - &cur_network->DSConfig, &pktlen); - - if ((pmlmeinfo->state&0x03) == MSR_ADHOC) { - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2, - (unsigned char *)&ATIMWindow, &pktlen); - } - - /* todo: ERP IE */ - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - (rate_len - 8), - (cur_network->SupportedRates + 8), - &pktlen); - - /* todo:HT for adhoc */ - -_ConstructBeacon: - - if ((pktlen + TXDESC_SIZE) > 512) { - DBG_8723A("beacon frame too large\n"); - return; - } - - *pLength = pktlen; - - /* DBG_8723A("%s bcn_sz =%d\n", __func__, pktlen); */ - -} - -static void ConstructPSPoll(struct rtw_adapter *padapter, - u8 *pframe, u32 *pLength) -{ - struct ieee80211_hdr *pwlanhdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - - /* Frame control. */ - pwlanhdr->frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - /* AID. */ - pwlanhdr->duration_id = cpu_to_le16(pmlmeinfo->aid | 0xc000); - - /* BSSID. */ - memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); - - /* TA. */ - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - - *pLength = 16; -} - -static void -ConstructNullFunctionData(struct rtw_adapter *padapter, u8 *pframe, - u32 *pLength, u8 *StaAddr, u8 bQoS, u8 AC, - u8 bEosp, u8 bForcePowerSave) -{ - struct ieee80211_hdr *pwlanhdr; - u32 pktlen; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - - pwlanhdr->frame_control = 0; - pwlanhdr->seq_ctrl = 0; - - if (bForcePowerSave) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - switch (cur_network->network.ifmode) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS); - memcpy(pwlanhdr->addr1, - get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), - ETH_ALEN); - memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); - break; - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS); - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, - get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), - ETH_ALEN); - break; - case NL80211_IFTYPE_ADHOC: - default: - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, - get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); - break; - } - - if (bQoS == true) { - struct ieee80211_qos_hdr *qoshdr; - qoshdr = (struct ieee80211_qos_hdr *)pframe; - - qoshdr->frame_control |= - cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_QOS_NULLFUNC); - - qoshdr->qos_ctrl = cpu_to_le16(AC & IEEE80211_QOS_CTL_TID_MASK); - if (bEosp) - qoshdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - - pktlen = sizeof(struct ieee80211_qos_hdr); - } else { - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC); - - pktlen = sizeof(struct ieee80211_hdr_3addr); - } - - *pLength = pktlen; -} - -static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe, - u32 *pLength, u8 *StaAddr, bool bHideSSID) -{ - struct ieee80211_mgmt *mgmt; - u8 *mac, *bssid; - u32 pktlen; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - - /* DBG_8723A("%s\n", __func__); */ - - mgmt = (struct ieee80211_mgmt *)pframe; - - mac = myid(&padapter->eeprompriv); - bssid = cur_network->MacAddress; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); - - mgmt->seq_ctrl = 0; - - memcpy(mgmt->da, StaAddr, ETH_ALEN); - memcpy(mgmt->sa, mac, ETH_ALEN); - memcpy(mgmt->bssid, bssid, ETH_ALEN); - - put_unaligned_le64(cur_network->tsf, - &mgmt->u.probe_resp.timestamp); - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.probe_resp.beacon_int); - put_unaligned_le16(cur_network->capability, - &mgmt->u.probe_resp.capab_info); - - pktlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - - if (cur_network->IELength > MAX_IE_SZ) - return; - - memcpy(mgmt->u.probe_resp.variable, cur_network->IEs, - cur_network->IELength); - pktlen += (cur_network->IELength); - - *pLength = pktlen; -} - -/* */ -/* Description: Fill the reserved packets that FW will use to RSVD page. */ -/* Now we just send 4 types packet to rsvd page. */ -/* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */ -/* Input: */ -/* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */ -/* so we need to set the packet length to total lengh. */ -/* true: At the second time, we should send the first packet (default:beacon) */ -/* to Hw again and set the lengh in descriptor to the real beacon lengh. */ -/* 2009.10.15 by tynli. */ -static void SetFwRsvdPagePkt(struct rtw_adapter *padapter, bool bDLFinished) -{ - struct hal_data_8723a *pHalData; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength; - u32 NullDataLength, QosNullLength, BTQosNullLength; - u8 *ReservedPagePacket; - u8 PageNum, PageNeed, TxDescLen; - u16 BufIndex; - u32 TotalPacketLen; - struct rsvdpage_loc RsvdPageLoc; - - DBG_8723A("%s\n", __func__); - - ReservedPagePacket = kzalloc(1000, GFP_KERNEL); - if (ReservedPagePacket == NULL) { - DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __func__); - return; - } - - pHalData = GET_HAL_DATA(padapter); - pxmitpriv = &padapter->xmitpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - TxDescLen = TXDESC_SIZE; - PageNum = 0; - - /* 3 (1) beacon */ - BufIndex = TXDESC_OFFSET; - ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength); - - /* When we count the first page size, we need to reserve description size for the RSVD */ - /* packet, it will be filled in front of the packet in TXPKTBUF. */ - PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength); - /* To reserved 2 pages for beacon buffer. 2010.06.24. */ - if (PageNeed == 1) - PageNeed += 1; - PageNum += PageNeed; - pHalData->FwRsvdPageStartOffset = PageNum; - - BufIndex += PageNeed*128; - - /* 3 (2) ps-poll */ - RsvdPageLoc.LocPsPoll = PageNum; - ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false); - - PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (3) null data */ - RsvdPageLoc.LocNullData = PageNum; - ConstructNullFunctionData(padapter, &ReservedPagePacket[BufIndex], - &NullDataLength, - get_my_bssid23a(&pmlmeinfo->network), - false, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, - &ReservedPagePacket[BufIndex-TxDescLen], - NullDataLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (4) probe response */ - RsvdPageLoc.LocProbeRsp = PageNum; - ConstructProbeRsp( - padapter, - &ReservedPagePacket[BufIndex], - &ProbeRspLength, - get_my_bssid23a(&pmlmeinfo->network), - false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (5) Qos null data */ - RsvdPageLoc.LocQosNull = PageNum; - ConstructNullFunctionData( - padapter, - &ReservedPagePacket[BufIndex], - &QosNullLength, - get_my_bssid23a(&pmlmeinfo->network), - true, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (6) BT Qos null data */ - RsvdPageLoc.LocBTQosNull = PageNum; - ConstructNullFunctionData( - padapter, - &ReservedPagePacket[BufIndex], - &BTQosNullLength, - get_my_bssid23a(&pmlmeinfo->network), - true, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true); - - TotalPacketLen = BufIndex + BTQosNullLength; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->qsel = 0x10; - pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET; - memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen); - - rtl8723au_mgnt_xmit(padapter, pmgntframe); - - DBG_8723A("%s: Set RSVD page location to Fw\n", __func__); - FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc); - -exit: - kfree(ReservedPagePacket); -} - -void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus) -{ - struct joinbssrpt_parm JoinBssRptParm; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s mstatus(%x)\n", __func__, mstatus); - - if (mstatus == 1) { - bool bRecover = false; - u8 v8; - - /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */ - /* Suggested by filen. Added by tynli. */ - rtl8723au_write16(padapter, REG_BCN_PSR_RPT, - 0xC000|pmlmeinfo->aid); - /* Do not set TSF again here or vWiFi beacon DMA INT will not work. */ - /* correct_TSF23a(padapter, pmlmeext); */ - /* Hw sequende enable by dedault. 2010.06.23. by tynli. */ - /* rtl8723au_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */ - /* rtl8723au_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */ - - /* set REG_CR bit 8 */ - v8 = rtl8723au_read8(padapter, REG_CR+1); - v8 |= BIT(0); /* ENSWBCN */ - rtl8723au_write8(padapter, REG_CR+1, v8); - - /* Disable Hw protection for a time which revserd for Hw sending beacon. */ - /* Fix download reserved page packet fail that access collision with the protection time. */ - /* 2010.05.11. Added by tynli. */ -/* SetBcnCtrlReg23a(padapter, 0, BIT(3)); */ -/* SetBcnCtrlReg23a(padapter, BIT(4), 0); */ - SetBcnCtrlReg23a(padapter, BIT(4), BIT(3)); - - /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */ - if (pHalData->RegFwHwTxQCtrl & BIT(6)) - bRecover = true; - - /* To tell Hw the packet is not a real beacon frame. */ - /* U1bTmp = rtl8723au_read8(padapter, REG_FWHW_TXQ_CTRL+2); */ - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl & ~BIT(6)); - pHalData->RegFwHwTxQCtrl &= ~BIT(6); - SetFwRsvdPagePkt(padapter, 0); - - /* 2010.05.11. Added by tynli. */ - SetBcnCtrlReg23a(padapter, BIT(3), BIT(4)); - - /* To make sure that if there exists an adapter which would like to send beacon. */ - /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ - /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ - /* the beacon cannot be sent by HW. */ - /* 2010.06.23. Added by tynli. */ - if (bRecover) { - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl | BIT(6)); - pHalData->RegFwHwTxQCtrl |= BIT(6); - } - - /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */ - v8 = rtl8723au_read8(padapter, REG_CR+1); - v8 &= ~BIT(0); /* ~ENSWBCN */ - rtl8723au_write8(padapter, REG_CR+1, v8); - } - - JoinBssRptParm.OpMode = mstatus; - - FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm); - -} - -#ifdef CONFIG_8723AU_BT_COEXIST -static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - u8 fakemac[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x00}; - u32 NullDataLength, BTQosNullLength; - u8 *ReservedPagePacket; - u8 PageNum, PageNeed, TxDescLen; - u16 BufIndex; - u32 TotalPacketLen; - struct rsvdpage_loc RsvdPageLoc; - - DBG_8723A("+%s\n", __func__); - - ReservedPagePacket = kzalloc(1024, GFP_KERNEL); - if (ReservedPagePacket == NULL) { - DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __func__); - return; - } - - pHalData = GET_HAL_DATA(padapter); - pxmitpriv = &padapter->xmitpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - TxDescLen = TXDESC_SIZE; - PageNum = 0; - - /* 3 (1) beacon */ - BufIndex = TXDESC_OFFSET; - /* skip Beacon Packet */ - PageNeed = 3; - - PageNum += PageNeed; - pHalData->FwRsvdPageStartOffset = PageNum; - - BufIndex += PageNeed*128; - - /* 3 (3) null data */ - RsvdPageLoc.LocNullData = PageNum; - ConstructNullFunctionData( - padapter, - &ReservedPagePacket[BufIndex], - &NullDataLength, - fakemac, - false, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (6) BT Qos null data */ - RsvdPageLoc.LocBTQosNull = PageNum; - ConstructNullFunctionData( - padapter, - &ReservedPagePacket[BufIndex], - &BTQosNullLength, - fakemac, - true, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true); - - TotalPacketLen = BufIndex + BTQosNullLength; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->qsel = 0x10; - pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET; - memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen); - - rtl8723au_mgnt_xmit(padapter, pmgntframe); - - DBG_8723A("%s: Set RSVD page location to Fw\n", __func__); - FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc); - -exit: - kfree(ReservedPagePacket); -} - -void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - u8 bRecover = false; - - DBG_8723A("+%s\n", __func__); - - pHalData = GET_HAL_DATA(padapter); - - /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */ - if (pHalData->RegFwHwTxQCtrl & BIT(6)) - bRecover = true; - - /* To tell Hw the packet is not a real beacon frame. */ - pHalData->RegFwHwTxQCtrl &= ~BIT(6); - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl); - SetFwRsvdPagePkt_BTCoex(padapter); - - /* To make sure that if there exists an adapter which would like to send beacon. */ - /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ - /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ - /* the beacon cannot be sent by HW. */ - /* 2010.06.23. Added by tynli. */ - if (bRecover) { - pHalData->RegFwHwTxQCtrl |= BIT(6); - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl); - } -} -#endif diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_dm.c b/drivers/staging/rtl8723au/hal/rtl8723a_dm.c deleted file mode 100644 index 1e831f2d1caf..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_dm.c +++ /dev/null @@ -1,194 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -/* */ -/* Description: */ -/* */ -/* This file is for 92CE/92CU dynamic mechanism only */ -/* */ -/* */ -/* */ -#define _RTL8723A_DM_C_ - -/* */ -/* include files */ -/* */ -#include -#include - -#include -#include - -/* */ -/* Global var */ -/* */ - -static void dm_CheckPbcGPIO(struct rtw_adapter *padapter) -{ - u8 tmp1byte; - u8 bPbcPressed = false; - - if (!padapter->registrypriv.hw_wps_pbc) - return; - - tmp1byte = rtl8723au_read8(padapter, GPIO_IO_SEL); - tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT); - /* enable GPIO[2] as output mode */ - rtl8723au_write8(padapter, GPIO_IO_SEL, tmp1byte); - - tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT); - /* reset the floating voltage level */ - rtl8723au_write8(padapter, GPIO_IN, tmp1byte); - - tmp1byte = rtl8723au_read8(padapter, GPIO_IO_SEL); - tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT); - /* enable GPIO[2] as input mode */ - rtl8723au_write8(padapter, GPIO_IO_SEL, tmp1byte); - - tmp1byte = rtl8723au_read8(padapter, GPIO_IN); - - if (tmp1byte == 0xff) - return; - - if (tmp1byte&HAL_8192C_HW_GPIO_WPS_BIT) - bPbcPressed = true; - - if (bPbcPressed) { - /* Here we only set bPbcPressed to true */ - /* After trigger PBC, the variable will be set to false */ - DBG_8723A("CheckPbcGPIO - PBC is pressed\n"); - - if (padapter->pid[0] == 0) { - /* 0 is the default value and it means the application - * monitors the HW PBC doesn't privde its pid to driver. - */ - return; - } - - kill_pid(find_vpid(padapter->pid[0]), SIGUSR1, 1); - } -} - -/* Initialize GPIO setting registers */ -/* functions */ - -void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - u8 cut_ver, fab_ver; - - memset(pdmpriv, 0, sizeof(struct dm_priv)); - memset(pDM_Odm, 0, sizeof(*pDM_Odm)); - - pDM_Odm->Adapter = Adapter; - - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8723A); - - if (IS_8723A_A_CUT(pHalData->VersionID)) { - fab_ver = ODM_UMC; - cut_ver = ODM_CUT_A; - } else if (IS_8723A_B_CUT(pHalData->VersionID)) { - fab_ver = ODM_UMC; - cut_ver = ODM_CUT_B; - } else { - fab_ver = ODM_TSMC; - cut_ver = ODM_CUT_A; - } - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver); - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver); - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(pHalData->VersionID)); - - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BOARD_TYPE, pHalData->BoardType); - - if (pHalData->BoardType == BOARD_USB_High_PA) { - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_LNA, true); - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_PA, true); - } - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec); -} - -static void Update_ODM_ComInfo_8723a(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct dm_priv *pdmpriv = &pHalData->dmpriv; - int i; - pdmpriv->InitODMFlag = 0; - /* Pointer reference */ - rtl8723a_odm_support_ability_set(Adapter, DYNAMIC_ALL_FUNC_ENABLE); - - for (i = 0; i < NUM_STA; i++) - ODM_CmnInfoPtrArrayHook23a(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL); -} - -void rtl8723a_InitHalDm(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - u8 i; - - Update_ODM_ComInfo_8723a(Adapter); - ODM23a_DMInit(pDM_Odm); - /* Save REG_INIDATA_RATE_SEL value for TXDESC. */ - for (i = 0; i < 32; i++) - pdmpriv->INIDATA_RATE[i] = rtl8723au_read8(Adapter, REG_INIDATA_RATE_SEL+i) & 0x3f; -} - -void -rtl8723a_HalDmWatchDog( - struct rtw_adapter *Adapter - ) -{ - bool bFwCurrentInPSMode = false; - bool bFwPSAwake = true; - u8 bLinked = false; - u8 hw_init_completed = false; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - - hw_init_completed = Adapter->hw_init_completed; - - if (hw_init_completed == false) - goto skip_dm; - - bFwCurrentInPSMode = Adapter->pwrctrlpriv.bFwCurrentInPSMode; - bFwPSAwake = rtl8723a_get_fwlps_rf_on(Adapter); - - if (!bFwCurrentInPSMode && bFwPSAwake) { - /* Read REG_INIDATA_RATE_SEL value for TXDESC. */ - if (check_fwstate(&Adapter->mlmepriv, WIFI_STATION_STATE)) { - pdmpriv->INIDATA_RATE[0] = rtl8723au_read8(Adapter, REG_INIDATA_RATE_SEL) & 0x3f; - } else { - u8 i; - for (i = 1 ; i < (Adapter->stapriv.asoc_sta_count + 1); i++) - pdmpriv->INIDATA_RATE[i] = rtl8723au_read8(Adapter, (REG_INIDATA_RATE_SEL+i)) & 0x3f; - } - } - - /* ODM */ - if (rtw_linked_check(Adapter)) - bLinked = true; - - ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_LINK, bLinked); - ODM_DMWatchdog23a(Adapter); - -skip_dm: - - /* Check GPIO to determine current RF on/off and Pbc status. */ - /* Check Hardware Radio ON/OFF or not */ - dm_CheckPbcGPIO(Adapter); -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c deleted file mode 100644 index 1ea0af499ce9..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c +++ /dev/null @@ -1,2076 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _HAL_INIT_C_ - -#include -#include -#include - -#include -#include - -static void _FWDownloadEnable(struct rtw_adapter *padapter, bool enable) -{ - u8 tmp; - - if (enable) { - /* 8051 enable */ - tmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1); - rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1, tmp | 0x04); - - /* MCU firmware download enable. */ - tmp = rtl8723au_read8(padapter, REG_MCUFWDL); - rtl8723au_write8(padapter, REG_MCUFWDL, tmp | 0x01); - - /* 8051 reset */ - tmp = rtl8723au_read8(padapter, REG_MCUFWDL + 2); - rtl8723au_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7); - } else { - /* MCU firmware download disable. */ - tmp = rtl8723au_read8(padapter, REG_MCUFWDL); - rtl8723au_write8(padapter, REG_MCUFWDL, tmp & 0xfe); - - /* Reserved for fw extension. */ - rtl8723au_write8(padapter, REG_MCUFWDL + 1, 0x00); - } -} - -static int -_PageWrite(struct rtw_adapter *padapter, u32 page, void *buffer, u32 size) -{ - u8 value8; - u8 u8Page = (u8) (page & 0x07); - - if (size > MAX_PAGE_SIZE) - return _FAIL; - - value8 = (rtl8723au_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page; - rtl8723au_write8(padapter, REG_MCUFWDL + 2, value8); - - return rtl8723au_writeN(padapter, FW_8723A_START_ADDRESS, size, buffer); -} - -static int _WriteFW(struct rtw_adapter *padapter, void *buffer, u32 size) -{ - /* Since we need dynamic decide method of dwonload fw, so we - call this function to get chip version. */ - /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */ - int ret = _SUCCESS; - u32 pageNums, remainSize; - u32 page, offset; - u8 *bufferPtr = (u8 *) buffer; - - pageNums = size / MAX_PAGE_SIZE; - /* RT_ASSERT((pageNums <= 4), - ("Page numbers should not greater then 4 \n")); */ - remainSize = size % MAX_PAGE_SIZE; - - for (page = 0; page < pageNums; page++) { - offset = page * MAX_PAGE_SIZE; - ret = _PageWrite(padapter, page, bufferPtr + offset, - MAX_PAGE_SIZE); - - if (ret == _FAIL) - goto exit; - } - if (remainSize) { - offset = pageNums * MAX_PAGE_SIZE; - page = pageNums; - ret = _PageWrite(padapter, page, bufferPtr + offset, - remainSize); - - if (ret == _FAIL) - goto exit; - } - RT_TRACE(_module_hal_init_c_, _drv_info_, - "_WriteFW Done- for Normal chip.\n"); - -exit: - return ret; -} - -static int _FWFreeToGo(struct rtw_adapter *padapter) -{ - u32 counter = 0; - u32 value32; - - /* polling CheckSum report */ - do { - value32 = rtl8723au_read32(padapter, REG_MCUFWDL); - if (value32 & FWDL_ChkSum_rpt) - break; - } while (counter++ < POLLING_READY_TIMEOUT_COUNT); - - if (counter >= POLLING_READY_TIMEOUT_COUNT) { - RT_TRACE(_module_hal_init_c_, _drv_err_, - "%s: chksum report fail! REG_MCUFWDL:0x%08x\n", - __func__, value32); - return _FAIL; - } - RT_TRACE(_module_hal_init_c_, _drv_info_, - "%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__, - value32); - - value32 = rtl8723au_read32(padapter, REG_MCUFWDL); - value32 |= MCUFWDL_RDY; - value32 &= ~WINTINI_RDY; - rtl8723au_write32(padapter, REG_MCUFWDL, value32); - - /* polling for FW ready */ - counter = 0; - do { - value32 = rtl8723au_read32(padapter, REG_MCUFWDL); - if (value32 & WINTINI_RDY) { - RT_TRACE(_module_hal_init_c_, _drv_info_, - "%s: Polling FW ready success!! REG_MCUFWDL:0x%08x\n", - __func__, value32); - return _SUCCESS; - } - udelay(5); - } while (counter++ < POLLING_READY_TIMEOUT_COUNT); - - RT_TRACE(_module_hal_init_c_, _drv_err_, - "%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n", - __func__, value32); - return _FAIL; -} - -#define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0) - -void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 u1bTmp; - u8 Delay = 100; - - if (!(IS_FW_81xxC(padapter) && - ((pHalData->FirmwareVersion < 0x21) || - (pHalData->FirmwareVersion == 0x21 && - pHalData->FirmwareSubVersion < 0x01)))) { - /* after 88C Fw v33.1 */ - /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */ - rtl8723au_write8(padapter, REG_HMETFR + 3, 0x20); - - u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1); - while (u1bTmp & BIT(2)) { - Delay--; - if (Delay == 0) - break; - udelay(50); - u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1); - } - RT_TRACE(_module_hal_init_c_, _drv_info_, - "-%s: 8051 reset success (%d)\n", __func__, - Delay); - - if ((Delay == 0)) { - /* force firmware reset */ - u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1); - rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1, - u1bTmp & ~BIT(2)); - } - } -} - -/* */ -/* Description: */ -/* Download 8192C firmware code. */ -/* */ -/* */ -int rtl8723a_FirmwareDownload(struct rtw_adapter *padapter) -{ - int rtStatus = _SUCCESS; - u8 writeFW_retry = 0; - unsigned long fwdl_start_time; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - struct device *device = dvobj_to_dev(dvobj); - struct rt_8723a_firmware_hdr *pFwHdr = NULL; - const struct firmware *fw; - char *fw_name; - u8 *firmware_buf = NULL; - u8 *buf; - int fw_size; - static int log_version; - - RT_TRACE(_module_hal_init_c_, _drv_info_, "+%s\n", __func__); - - if (IS_8723A_A_CUT(pHalData->VersionID)) { - fw_name = "rtlwifi/rtl8723aufw_A.bin"; - RT_TRACE(_module_hal_init_c_, _drv_info_, - "rtl8723a_FirmwareDownload: R8723FwImageArray_UMC for RTL8723A A CUT\n"); - } else if (IS_8723A_B_CUT(pHalData->VersionID)) { - /* WLAN Fw. */ - if (padapter->registrypriv.wifi_spec == 1) { - fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin"; - DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for " - "RTL8723A B CUT\n"); - } else { - if (rtl8723a_BT_coexist(padapter)) { - fw_name = "rtlwifi/rtl8723aufw_B.bin"; - DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithBT " - "for RTL8723A B CUT\n"); - } else { - fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin"; - DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithout " - "BT for RTL8723A B CUT\n"); - } - } - } else { - /* We should download proper RAM Code here - to match the ROM code. */ - RT_TRACE(_module_hal_init_c_, _drv_err_, - "%s: unknown version!\n", __func__); - rtStatus = _FAIL; - goto Exit; - } - - pr_info("rtl8723au: Loading firmware %s\n", fw_name); - if (request_firmware(&fw, fw_name, device)) { - pr_err("rtl8723au: request_firmware load failed\n"); - rtStatus = _FAIL; - goto Exit; - } - if (!fw) { - pr_err("rtl8723au: Firmware %s not available\n", fw_name); - rtStatus = _FAIL; - goto Exit; - } - firmware_buf = kmemdup(fw->data, fw->size, GFP_KERNEL); - fw_size = fw->size; - release_firmware(fw); - if (!firmware_buf) { - rtStatus = _FAIL; - goto Exit; - } - buf = firmware_buf; - - /* To Check Fw header. Added by tynli. 2009.12.04. */ - pFwHdr = (struct rt_8723a_firmware_hdr *)firmware_buf; - - pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version); - pHalData->FirmwareSubVersion = pFwHdr->Subversion; - pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature); - - DBG_8723A("%s: fw_ver =%d fw_subver =%d sig = 0x%x\n", - __func__, pHalData->FirmwareVersion, - pHalData->FirmwareSubVersion, pHalData->FirmwareSignature); - - if (!log_version++) - pr_info("%sFirmware Version %d, SubVersion %d, Signature " - "0x%x\n", DRIVER_PREFIX, pHalData->FirmwareVersion, - pHalData->FirmwareSubVersion, - pHalData->FirmwareSignature); - - if (IS_FW_HEADER_EXIST(pFwHdr)) { - /* Shift 32 bytes for FW header */ - buf = buf + 32; - fw_size = fw_size - 32; - } - - /* Suggested by Filen. If 8051 is running in RAM code, driver should - inform Fw to reset by itself, */ - /* or it will cause download Fw fail. 2010.02.01. by tynli. */ - if (rtl8723au_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { - /* 8051 RAM code */ - rtl8723a_FirmwareSelfReset(padapter); - rtl8723au_write8(padapter, REG_MCUFWDL, 0x00); - } - - _FWDownloadEnable(padapter, true); - fwdl_start_time = jiffies; - while (1) { - /* reset the FWDL chksum */ - rtl8723au_write8(padapter, REG_MCUFWDL, - rtl8723au_read8(padapter, REG_MCUFWDL) | - FWDL_ChkSum_rpt); - - rtStatus = _WriteFW(padapter, buf, fw_size); - - if (rtStatus == _SUCCESS || - (jiffies_to_msecs(jiffies - fwdl_start_time) > 500 && - writeFW_retry++ >= 3)) - break; - - DBG_8723A("%s writeFW_retry:%u, time after fwdl_start_time:" - "%ums\n", __func__, writeFW_retry, - jiffies_to_msecs(jiffies - fwdl_start_time)); - } - _FWDownloadEnable(padapter, false); - if (_SUCCESS != rtStatus) { - DBG_8723A("DL Firmware failed!\n"); - goto Exit; - } - - rtStatus = _FWFreeToGo(padapter); - if (_SUCCESS != rtStatus) { - RT_TRACE(_module_hal_init_c_, _drv_err_, - "DL Firmware failed!\n"); - goto Exit; - } - RT_TRACE(_module_hal_init_c_, _drv_info_, - "Firmware is ready to run!\n"); - -Exit: - kfree(firmware_buf); - return rtStatus; -} - -void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* Init Fw LPS related. */ - padapter->pwrctrlpriv.bFwCurrentInPSMode = false; - - /* Init H2C counter. by tynli. 2009.12.09. */ - pHalData->LastHMEBoxNum = 0; -} - -/* */ -/* Efuse related code */ -/* */ -static u8 -hal_EfuseSwitchToBank(struct rtw_adapter *padapter, u8 bank) -{ - u8 bRet = false; - u32 value32 = 0; - - DBG_8723A("%s: Efuse switch bank to %d\n", __func__, bank); - value32 = rtl8723au_read32(padapter, EFUSE_TEST); - bRet = true; - switch (bank) { - case 0: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_WIFI_SEL_0); - break; - case 1: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_BT_SEL_0); - break; - case 2: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_BT_SEL_1); - break; - case 3: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_BT_SEL_2); - break; - default: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_WIFI_SEL_0); - bRet = false; - break; - } - rtl8723au_write32(padapter, EFUSE_TEST, value32); - - return bRet; -} - -static void -hal_ReadEFuse_WiFi(struct rtw_adapter *padapter, - u16 _offset, u16 _size_byte, u8 *pbuf) -{ - u8 *efuseTbl = NULL; - u16 eFuse_Addr = 0; - u8 offset, wden; - u8 efuseHeader, efuseExtHdr, efuseData; - u16 i, total, used; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* Do NOT excess total size of EFuse table. - Added by Roger, 2008.11.10. */ - if ((_offset + _size_byte) > EFUSE_MAP_LEN_8723A) { - DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n", - __func__, _offset, _size_byte); - return; - } - - efuseTbl = kmalloc(EFUSE_MAP_LEN_8723A, GFP_KERNEL); - if (!efuseTbl) - return; - /* 0xff will be efuse default value instead of 0x00. */ - memset(efuseTbl, 0xFF, EFUSE_MAP_LEN_8723A); - - /* switch bank back to bank 0 for later BT and wifi use. */ - hal_EfuseSwitchToBank(padapter, 0); - - while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) { - ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader); - if (efuseHeader == 0xFF) { - DBG_8723A("%s: data end at address =%#x\n", __func__, - eFuse_Addr); - break; - } - - /* Check PG header for section num. */ - if (EXT_HEADER(efuseHeader)) { /* extended header */ - offset = GET_HDR_OFFSET_2_0(efuseHeader); - - ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseExtHdr); - if (ALL_WORDS_DISABLED(efuseExtHdr)) - continue; - - offset |= ((efuseExtHdr & 0xF0) >> 1); - wden = efuseExtHdr & 0x0F; - } else { - offset = (efuseHeader >> 4) & 0x0f; - wden = efuseHeader & 0x0f; - } - - if (offset < EFUSE_MAX_SECTION_8723A) { - u16 addr; - /* Get word enable value from PG header */ - - addr = offset * PGPKT_DATA_SIZE; - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - /* Check word enable condition in the section */ - if (!(wden & (0x01 << i))) { - ReadEFuseByte23a(padapter, eFuse_Addr++, - &efuseData); - efuseTbl[addr] = efuseData; - - ReadEFuseByte23a(padapter, eFuse_Addr++, - &efuseData); - efuseTbl[addr + 1] = efuseData; - } - addr += 2; - } - } else { - DBG_8723A(KERN_ERR "%s: offset(%d) is illegal!!\n", - __func__, offset); - eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2; - } - } - - /* Copy from Efuse map to output pointer memory!!! */ - for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset + i]; - - /* Calculate Efuse utilization */ - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total); - used = eFuse_Addr - 1; - pHalData->EfuseUsedBytes = used; - - kfree(efuseTbl); -} - -static void -hal_ReadEFuse_BT(struct rtw_adapter *padapter, - u16 _offset, u16 _size_byte, u8 *pbuf) -{ - u8 *efuseTbl; - u8 bank; - u16 eFuse_Addr; - u8 efuseHeader, efuseExtHdr, efuseData; - u8 offset, wden; - u16 i, total, used; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* Do NOT excess total size of EFuse table. - Added by Roger, 2008.11.10. */ - if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN) { - DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n", - __func__, _offset, _size_byte); - return; - } - - efuseTbl = kmalloc(EFUSE_BT_MAP_LEN, GFP_KERNEL); - if (!efuseTbl) - return; - /* 0xff will be efuse default value instead of 0x00. */ - memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN); - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total); - - for (bank = 1; bank < EFUSE_MAX_BANK; bank++) { - if (hal_EfuseSwitchToBank(padapter, bank) == false) { - DBG_8723A("%s: hal_EfuseSwitchToBank Fail!!\n", - __func__); - goto exit; - } - - eFuse_Addr = 0; - - while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) { - ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader); - if (efuseHeader == 0xFF) - break; - - /* Check PG header for section num. */ - if (EXT_HEADER(efuseHeader)) { /* extended header */ - offset = GET_HDR_OFFSET_2_0(efuseHeader); - - ReadEFuseByte23a(padapter, eFuse_Addr++, - &efuseExtHdr); - if (ALL_WORDS_DISABLED(efuseExtHdr)) - continue; - - offset |= ((efuseExtHdr & 0xF0) >> 1); - wden = efuseExtHdr & 0x0F; - } else { - offset = (efuseHeader >> 4) & 0x0f; - wden = efuseHeader & 0x0f; - } - - if (offset < EFUSE_BT_MAX_SECTION) { - u16 addr; - - /* Get word enable value from PG header */ - - addr = offset * PGPKT_DATA_SIZE; - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - /* Check word enable condition in - the section */ - if (!(wden & (0x01 << i))) { - ReadEFuseByte23a(padapter, - eFuse_Addr++, - &efuseData); - efuseTbl[addr] = efuseData; - - ReadEFuseByte23a(padapter, - eFuse_Addr++, - &efuseData); - efuseTbl[addr + 1] = efuseData; - } - addr += 2; - } - } else { - DBG_8723A(KERN_ERR - "%s: offset(%d) is illegal!!\n", - __func__, offset); - eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2; - } - } - - if ((eFuse_Addr - 1) < total) { - DBG_8723A("%s: bank(%d) data end at %#x\n", - __func__, bank, eFuse_Addr - 1); - break; - } - } - - /* switch bank back to bank 0 for later BT and wifi use. */ - hal_EfuseSwitchToBank(padapter, 0); - - /* Copy from Efuse map to output pointer memory!!! */ - for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset + i]; - - /* */ - /* Calculate Efuse utilization. */ - /* */ - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total); - used = (EFUSE_BT_REAL_BANK_CONTENT_LEN * (bank - 1)) + eFuse_Addr - 1; - pHalData->BTEfuseUsedBytes = used; - -exit: - kfree(efuseTbl); -} - -void -rtl8723a_readefuse(struct rtw_adapter *padapter, - u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf) -{ - if (efuseType == EFUSE_WIFI) - hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf); - else - hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf); -} - -u16 rtl8723a_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter) -{ - u16 efuse_addr = 0; - u8 hoffset = 0, hworden = 0; - u8 efuse_data, word_cnts = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - efuse_addr = pHalData->EfuseUsedBytes; - - DBG_8723A("%s: start_efuse_addr = 0x%X\n", __func__, efuse_addr); - - /* switch bank back to bank 0 for later BT and wifi use. */ - hal_EfuseSwitchToBank(padapter, 0); - - while (AVAILABLE_EFUSE_ADDR(efuse_addr)) { - if (efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data) == - _FAIL) { - DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail! " - "addr = 0x%X !!\n", __func__, efuse_addr); - break; - } - - if (efuse_data == 0xFF) - break; - - if (EXT_HEADER(efuse_data)) { - hoffset = GET_HDR_OFFSET_2_0(efuse_data); - efuse_addr++; - efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data); - if (ALL_WORDS_DISABLED(efuse_data)) - continue; - - hoffset |= ((efuse_data & 0xF0) >> 1); - hworden = efuse_data & 0x0F; - } else { - hoffset = (efuse_data >> 4) & 0x0F; - hworden = efuse_data & 0x0F; - } - - word_cnts = Efuse_CalculateWordCnts23a(hworden); - efuse_addr += (word_cnts * 2) + 1; - } - - pHalData->EfuseUsedBytes = efuse_addr; - - DBG_8723A("%s: CurrentSize =%d\n", __func__, efuse_addr); - - return efuse_addr; -} - -u16 rtl8723a_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter) -{ - u16 btusedbytes; - u16 efuse_addr; - u8 bank, startBank; - u8 hoffset = 0, hworden = 0; - u8 efuse_data, word_cnts = 0; - u16 retU2 = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - btusedbytes = pHalData->BTEfuseUsedBytes; - - efuse_addr = (u16) ((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN)); - startBank = (u8) (1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN)); - - DBG_8723A("%s: start from bank =%d addr = 0x%X\n", __func__, startBank, - efuse_addr); - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2); - - for (bank = startBank; bank < EFUSE_MAX_BANK; bank++) { - if (hal_EfuseSwitchToBank(padapter, bank) == false) { - DBG_8723A(KERN_ERR "%s: switch bank(%d) Fail!!\n", - __func__, bank); - bank = EFUSE_MAX_BANK; - break; - } - - /* only when bank is switched we have to reset - the efuse_addr. */ - if (bank != startBank) - efuse_addr = 0; - - while (AVAILABLE_EFUSE_ADDR(efuse_addr)) { - if (efuse_OneByteRead23a(padapter, efuse_addr, - &efuse_data) == _FAIL) { - DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail!" - " addr = 0x%X !!\n", - __func__, efuse_addr); - bank = EFUSE_MAX_BANK; - break; - } - - if (efuse_data == 0xFF) - break; - - if (EXT_HEADER(efuse_data)) { - hoffset = GET_HDR_OFFSET_2_0(efuse_data); - efuse_addr++; - efuse_OneByteRead23a(padapter, efuse_addr, - &efuse_data); - if (ALL_WORDS_DISABLED(efuse_data)) { - efuse_addr++; - continue; - } - - hoffset |= ((efuse_data & 0xF0) >> 1); - hworden = efuse_data & 0x0F; - } else { - hoffset = (efuse_data >> 4) & 0x0F; - hworden = efuse_data & 0x0F; - } - word_cnts = Efuse_CalculateWordCnts23a(hworden); - /* read next header */ - efuse_addr += (word_cnts * 2) + 1; - } - - /* Check if we need to check next bank efuse */ - if (efuse_addr < retU2) - break; /* don't need to check next bank. */ - } - - retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr; - pHalData->BTEfuseUsedBytes = retU2; - - DBG_8723A("%s: CurrentSize =%d\n", __func__, retU2); - return retU2; -} - -void rtl8723a_read_chip_version(struct rtw_adapter *padapter) -{ - u32 value32; - struct hal_version ChipVersion; - struct hal_data_8723a *pHalData; - - pHalData = GET_HAL_DATA(padapter); - - value32 = rtl8723au_read32(padapter, REG_SYS_CFG); - ChipVersion.ICType = CHIP_8723A; - ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP); - pHalData->rf_type = RF_1T1R; - ChipVersion.VendorType = - ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC); - ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */ - - /* For regulator mode. by tynli. 2011.01.14 */ - pHalData->RegulatorMode = ((value32 & SPS_SEL) ? - RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR); - - value32 = rtl8723au_read32(padapter, REG_GPIO_OUTSTS); - /* ROM code version. */ - ChipVersion.ROMVer = (value32 & RF_RL_ID) >> 20; - - /* For multi-function consideration. Added by Roger, 2010.10.06. */ - pHalData->MultiFunc = RT_MULTI_FUNC_NONE; - value32 = rtl8723au_read32(padapter, REG_MULTI_FUNC_CTRL); - pHalData->MultiFunc |= - ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0); - pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0); - pHalData->MultiFunc |= - ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0); - pHalData->PolarityCtl = - ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : - RT_POLARITY_LOW_ACT); - pHalData->VersionID = ChipVersion; - - MSG_8723A("RF_Type is %x!!\n", pHalData->rf_type); -} - -/* */ -/* */ -/* 20100209 Joseph: */ -/* This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */ -/* We just reserve the value of the register in variable - pHalData->RegBcnCtrlVal and then operate */ -/* the value of the register via atomic operation. */ -/* This prevents from race condition when setting this register. */ -/* The value of pHalData->RegBcnCtrlVal is initialized in - HwConfigureRTL8192CE() function. */ -/* */ -void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits) -{ - u8 val8; - - val8 = rtl8723au_read8(padapter, REG_BCN_CTRL); - val8 |= SetBits; - val8 &= ~ClearBits; - - rtl8723au_write8(padapter, REG_BCN_CTRL, val8); -} - -void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter) -{ - rtl8723au_write16(padapter, REG_BCN_CTRL, 0x1010); - - /* TODO: Remove these magic number */ - rtl8723au_write16(padapter, REG_TBTT_PROHIBIT, 0x6404); /* ms */ - /* Firmware will control REG_DRVERLYINT when power saving is enable, */ - /* so don't set this register on STA mode. */ - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false) - rtl8723au_write8(padapter, REG_DRVERLYINT, - DRIVER_EARLY_INT_TIME); - /* 2ms */ - rtl8723au_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); - - /* Suggested by designer timchen. Change beacon AIFS to the - largest number beacause test chip does not contension before - sending beacon. by tynli. 2009.11.03 */ - rtl8723au_write16(padapter, REG_BCNTCFG, 0x660F); -} - -static void ResumeTxBeacon(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* 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. */ - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "+ResumeTxBeacon\n"); - - pHalData->RegFwHwTxQCtrl |= BIT(6); - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl); - rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 1, 0xff); - pHalData->RegReg542 |= BIT(0); - rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542); -} - -static void StopTxBeacon(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* 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. */ - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "+StopTxBeacon\n"); - - pHalData->RegFwHwTxQCtrl &= ~BIT(6); - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl); - rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64); - pHalData->RegReg542 &= ~BIT(0); - rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542); -} - -static void _BeaconFunctionEnable(struct rtw_adapter *padapter, u8 Enable, - u8 Linked) -{ - SetBcnCtrlReg23a(padapter, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB, - 0); - rtl8723au_write8(padapter, REG_RD_CTRL + 1, 0x6F); -} - -void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter) -{ - u32 value32; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* reset TSF, enable update TSF, correcting TSF On Beacon */ - - /* REG_BCN_INTERVAL */ - /* REG_BCNDMATIM */ - /* REG_ATIMWND */ - /* REG_TBTT_PROHIBIT */ - /* REG_DRVERLYINT */ - /* REG_BCN_MAX_ERR */ - /* REG_BCNTCFG (0x510) */ - /* REG_DUAL_TSF_RST */ - /* REG_BCN_CTRL (0x550) */ - - /* */ - /* ATIM window */ - /* */ - rtl8723au_write16(padapter, REG_ATIMWND, 2); - - /* */ - /* Beacon interval (in unit of TU). */ - /* */ - rtl8723au_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval); - - rtl8723a_InitBeaconParameters(padapter); - - rtl8723au_write8(padapter, REG_SLOT, 0x09); - - /* */ - /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */ - /* */ - value32 = rtl8723au_read32(padapter, REG_TCR); - value32 &= ~TSFRST; - rtl8723au_write32(padapter, REG_TCR, value32); - - value32 |= TSFRST; - rtl8723au_write32(padapter, REG_TCR, value32); - - /* NOTE: Fix test chip's bug (about contention windows's randomness) */ - if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE) == true) { - rtl8723au_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50); - rtl8723au_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50); - } - - _BeaconFunctionEnable(padapter, true, true); - - ResumeTxBeacon(padapter); - SetBcnCtrlReg23a(padapter, DIS_BCNQ_SUB, 0); -} - -void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter, - enum hal_odm_variable eVariable, - void *pValue1, bool bSet) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_odm_t *podmpriv = &pHalData->odmpriv; - switch (eVariable) { - case HAL_ODM_STA_INFO: - { - struct sta_info *psta = (struct sta_info *)pValue1; - - if (bSet) { - DBG_8723A("Set STA_(%d) info\n", psta->mac_id); - ODM_CmnInfoPtrArrayHook23a(podmpriv, - ODM_CMNINFO_STA_STATUS, - psta->mac_id, psta); - } else { - DBG_8723A("Clean STA_(%d) info\n", psta->mac_id); - ODM_CmnInfoPtrArrayHook23a(podmpriv, - ODM_CMNINFO_STA_STATUS, - psta->mac_id, NULL); - } - } - break; - case HAL_ODM_P2P_STATE: - ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet); - break; - case HAL_ODM_WIFI_DISPLAY_STATE: - ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet); - break; - default: - break; - } -} - -void rtl8723a_notch_filter(struct rtw_adapter *adapter, bool enable) -{ - if (enable) { - DBG_8723A("Enable notch filter\n"); - rtl8723au_write8(adapter, rOFDM0_RxDSP + 1, - rtl8723au_read8(adapter, rOFDM0_RxDSP + 1) | - BIT(1)); - } else { - DBG_8723A("Disable notch filter\n"); - rtl8723au_write8(adapter, rOFDM0_RxDSP + 1, - rtl8723au_read8(adapter, rOFDM0_RxDSP + 1) & - ~BIT(1)); - } -} - -bool c2h_id_filter_ccx_8723a(u8 id) -{ - bool ret = false; - if (id == C2H_CCX_TX_RPT) - ret = true; - - return ret; -} - -int c2h_handler_8723a(struct rtw_adapter *padapter, struct c2h_evt_hdr *c2h_evt) -{ - int ret = _SUCCESS; - u8 i = 0; - - if (c2h_evt == NULL) { - DBG_8723A("%s c2h_evt is NULL\n", __func__); - ret = _FAIL; - goto exit; - } - - switch (c2h_evt->id) { - case C2H_DBG: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "C2HCommandHandler: %s\n", c2h_evt->payload); - break; - - case C2H_CCX_TX_RPT: - handle_txrpt_ccx_8723a(padapter, c2h_evt->payload); - break; - case C2H_EXT_RA_RPT: - break; - case C2H_HW_INFO_EXCH: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "[BT], C2H_HW_INFO_EXCH\n"); - for (i = 0; i < c2h_evt->plen; i++) { - RT_TRACE(_module_hal_init_c_, _drv_info_, - "[BT], tmpBuf[%d]= 0x%x\n", i, - c2h_evt->payload[i]); - } - break; - - case C2H_C2H_H2C_TEST: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "[BT], C2H_H2C_TEST\n"); - RT_TRACE(_module_hal_init_c_, _drv_info_, - "[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ 0x%x/ 0x%x/ 0x%x\n", - c2h_evt->payload[0], - c2h_evt->payload[1], c2h_evt->payload[2], - c2h_evt->payload[3], c2h_evt->payload[4]); - break; - - case C2H_BT_INFO: - DBG_8723A("%s , Got C2H_BT_INFO \n", __func__); - rtl8723a_fw_c2h_BT_info(padapter, - c2h_evt->payload, c2h_evt->plen); - break; - - default: - ret = _FAIL; - break; - } - -exit: - return ret; -} - -void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf) -{ - struct txrpt_ccx_8723a *txrpt_ccx = buf; - struct submit_ctx *pack_tx_ops = &adapter->xmitpriv.ack_tx_ops; - - if (txrpt_ccx->int_ccx && adapter->xmitpriv.ack_tx) { - if (txrpt_ccx->pkt_ok) - rtw23a_sctx_done_err(&pack_tx_ops, - RTW_SCTX_DONE_SUCCESS); - else - rtw23a_sctx_done_err(&pack_tx_ops, - RTW_SCTX_DONE_CCX_PKT_FAIL); - } -} - -void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter) -{ - u8 val; - - val = rtl8723au_read8(padapter, REG_LEDCFG2); - /* Let 8051 take control antenna setting */ - val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */ - rtl8723au_write8(padapter, REG_LEDCFG2, val); -} - -void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter) -{ - u8 val; - - val = rtl8723au_read8(padapter, REG_LEDCFG2); - /* Let 8051 take control antenna setting */ - if (!(val & BIT(7))) { - val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */ - rtl8723au_write8(padapter, REG_LEDCFG2, val); - } -} - -void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter) -{ - u8 val; - - val = rtl8723au_read8(padapter, REG_LEDCFG2); - /* Let 8051 take control antenna setting */ - val &= ~BIT(7); /* DPDT_SEL_EN, clear 0x4C[23] */ - rtl8723au_write8(padapter, REG_LEDCFG2, val); -} - -void rtl8723a_init_default_value(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct dm_priv *pdmpriv; - u8 i; - - pHalData = GET_HAL_DATA(padapter); - pdmpriv = &pHalData->dmpriv; - - /* init default value */ - pHalData->bIQKInitialized = false; - if (!padapter->pwrctrlpriv.bkeepfwalive) - pHalData->LastHMEBoxNum = 0; - - pHalData->bIQKInitialized = false; - - /* init dm default value */ - pdmpriv->TM_Trigger = 0; /* for IQK */ -/* pdmpriv->binitialized = false; */ -/* pdmpriv->prv_traffic_idx = 3; */ -/* pdmpriv->initialize = 0; */ - - pdmpriv->ThermalValue_HP_index = 0; - for (i = 0; i < HP_THERMAL_NUM; i++) - pdmpriv->ThermalValue_HP[i] = 0; - - /* init Efuse variables */ - pHalData->EfuseUsedBytes = 0; - pHalData->BTEfuseUsedBytes = 0; -} - -u8 GetEEPROMSize8723A(struct rtw_adapter *padapter) -{ - u8 size = 0; - u32 cr; - - cr = rtl8723au_read16(padapter, REG_9346CR); - /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */ - size = (cr & BOOT_FROM_EEPROM) ? 6 : 4; - - MSG_8723A("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46"); - - return size; -} - -/* */ -/* */ -/* LLT R/W/Init function */ -/* */ -/* */ -static int _LLTWrite(struct rtw_adapter *padapter, u32 address, u32 data) -{ - int status = _SUCCESS; - s32 count = 0; - u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | - _LLT_OP(_LLT_WRITE_ACCESS); - u16 LLTReg = REG_LLT_INIT; - - rtl8723au_write32(padapter, LLTReg, value); - - /* polling */ - do { - value = rtl8723au_read32(padapter, LLTReg); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - - if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(_module_hal_init_c_, _drv_err_, - "Failed to polling write LLT done at address %d!\n", - address); - status = _FAIL; - break; - } - } while (count++); - - return status; -} - -int InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary) -{ - int status = _SUCCESS; - u32 i; - u32 txpktbuf_bndy = boundary; - u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER; - - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _LLTWrite(padapter, i, i + 1); - if (status != _SUCCESS) - return status; - } - - /* end of list */ - status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF); - if (status != _SUCCESS) - return status; - - /* Make the other pages as ring buffer */ - /* This ring buffer is used as beacon buffer if we config this - MAC as two MAC transfer. */ - /* Otherwise used as local loopback buffer. */ - for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) { - status = _LLTWrite(padapter, i, (i + 1)); - if (_SUCCESS != status) - return status; - } - - /* Let last entry point to the start entry of ring buffer */ - status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy); - - return status; -} - -static void _DisableGPIO(struct rtw_adapter *padapter) -{ -/*************************************** -j. GPIO_PIN_CTRL 0x44[31:0]= 0x000 -k.Value = GPIO_PIN_CTRL[7:0] -l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write external PIN level -m. GPIO_MUXCFG 0x42 [15:0] = 0x0780 -n. LEDCFG 0x4C[15:0] = 0x8080 -***************************************/ - u32 value32; - u32 u4bTmp; - - /* 1. Disable GPIO[7:0] */ - rtl8723au_write16(padapter, REG_GPIO_PIN_CTRL + 2, 0x0000); - value32 = rtl8723au_read32(padapter, REG_GPIO_PIN_CTRL) & 0xFFFF00FF; - u4bTmp = value32 & 0x000000FF; - value32 |= ((u4bTmp << 8) | 0x00FF0000); - rtl8723au_write32(padapter, REG_GPIO_PIN_CTRL, value32); - - /* */ - /* For RTL8723u multi-function configuration which - was autoload from Efuse offset 0x0a and 0x0b, */ - /* WLAN HW GPIO[9], GPS HW GPIO[10] and BT HW GPIO[11]. */ - /* Added by Roger, 2010.10.07. */ - /* */ - /* 2. Disable GPIO[8] and GPIO[12] */ - - /* Configure all pins as input mode. */ - rtl8723au_write16(padapter, REG_GPIO_IO_SEL_2, 0x0000); - value32 = rtl8723au_read32(padapter, REG_GPIO_PIN_CTRL_2) & 0xFFFF001F; - u4bTmp = value32 & 0x0000001F; - /* Set pin 8, 10, 11 and pin 12 to output mode. */ - value32 |= ((u4bTmp << 8) | 0x001D0000); - rtl8723au_write32(padapter, REG_GPIO_PIN_CTRL_2, value32); - - /* 3. Disable LED0 & 1 */ - rtl8723au_write16(padapter, REG_LEDCFG0, 0x8080); -} /* end of _DisableGPIO() */ - -static void _DisableRFAFEAndResetBB8192C(struct rtw_adapter *padapter) -{ -/************************************** -a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue -b. RF path 0 offset 0x00 = 0x00 disable RF -c. APSD_CTRL 0x600[7:0] = 0x40 -d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine -e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine -***************************************/ - u8 value8; - - rtl8723au_write8(padapter, REG_TXPAUSE, 0xFF); - - PHY_SetRFReg(padapter, RF_PATH_A, 0x0, bMaskByte0, 0x0); - - value8 = APSDOFF; - rtl8723au_write8(padapter, REG_APSD_CTRL, value8); /* 0x40 */ - - /* Set BB reset at first */ - value8 = FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn; - rtl8723au_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x16 */ - - /* Set global reset. */ - value8 &= ~FEN_BB_GLB_RSTn; - rtl8723au_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x14 */ - - /* 2010/08/12 MH We need to set BB/GLBAL reset to save power - for SS mode. */ -} - -static void _ResetDigitalProcedure1_92C(struct rtw_adapter *padapter, - bool bWithoutHWSM) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (IS_FW_81xxC(padapter) && (pHalData->FirmwareVersion <= 0x20)) { - /***************************** - f. MCUFWDL 0x80[7:0]= 0 reset MCU ready status - g. SYS_FUNC_EN 0x02[10]= 0 reset MCU register, (8051 reset) - h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC register, DCORE - i. SYS_FUNC_EN 0x02[10]= 1 enable MCU register, - (8051 enable) - ******************************/ - u16 valu16; - rtl8723au_write8(padapter, REG_MCUFWDL, 0); - - valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN); - /* reset MCU , 8051 */ - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, - valu16 & ~FEN_CPUEN); - - valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN) & 0x0FFF; - /* reset MAC */ - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, - valu16 | FEN_HWPDN | FEN_ELDR); - - valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN); - /* enable MCU , 8051 */ - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, - valu16 | FEN_CPUEN); - } else { - u8 retry_cnts = 0; - u8 val8; - - val8 = rtl8723au_read8(padapter, REG_MCUFWDL); - - /* 2010/08/12 MH For USB SS, we can not stop 8051 when we - are trying to enter IPS/HW&SW radio off. For - S3/S4/S5/Disable, we can stop 8051 because */ - /* we will init FW when power on again. */ - /* If we want to SS mode, we can not reset 8051. */ - if ((val8 & BIT(1)) && padapter->bFWReady) { - /* IF fw in RAM code, do reset */ - /* 2010/08/25 MH According to RD alfred's - suggestion, we need to disable other */ - /* HRCV INT to influence 8051 reset. */ - rtl8723au_write8(padapter, REG_FWIMR, 0x20); - /* 2011/02/15 MH According to Alex's - suggestion, close mask to prevent - incorrect FW write operation. */ - rtl8723au_write8(padapter, REG_FTIMR, 0x00); - rtl8723au_write8(padapter, REG_FSIMR, 0x00); - - /* 8051 reset by self */ - rtl8723au_write8(padapter, REG_HMETFR + 3, 0x20); - - while ((retry_cnts++ < 100) && - (rtl8723au_read16(padapter, REG_SYS_FUNC_EN) & - FEN_CPUEN)) { - udelay(50); /* us */ - } - - if (retry_cnts >= 100) { - /* Reset MAC and Enable 8051 */ - rtl8723au_write8(padapter, - REG_SYS_FUNC_EN + 1, 0x50); - mdelay(10); - } - } - /* Reset MAC and Enable 8051 */ - rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1, 0x54); - rtl8723au_write8(padapter, REG_MCUFWDL, 0); - } - - if (bWithoutHWSM) { - /***************************** - Without HW auto state machine - g. SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock - h. AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL - i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK - j. SYS_ISO_CTRL 0x00[7:0] = 0xF9 isolated digital to PON - ******************************/ - /* modify to 0x70A3 by Scott. */ - rtl8723au_write16(padapter, REG_SYS_CLKR, 0x70A3); - rtl8723au_write8(padapter, REG_AFE_PLL_CTRL, 0x80); - rtl8723au_write16(padapter, REG_AFE_XTAL_CTRL, 0x880F); - rtl8723au_write8(padapter, REG_SYS_ISO_CTRL, 0xF9); - } else { - /* Disable all RF/BB power */ - rtl8723au_write8(padapter, REG_RF_CTRL, 0x00); - } -} - -static void _ResetDigitalProcedure2(struct rtw_adapter *padapter) -{ -/***************************** -k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction -l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock -m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON -******************************/ - /* modify to 0x70a3 by Scott. */ - rtl8723au_write16(padapter, REG_SYS_CLKR, 0x70a3); - /* modify to 0x82 by Scott. */ - rtl8723au_write8(padapter, REG_SYS_ISO_CTRL + 1, 0x82); -} - -static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u16 value16; - u8 value8; - - if (bWithoutHWSM) { - /***************************** - n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power - o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power - r. When driver call disable, the ASIC will turn off remaining - clock automatically - ******************************/ - - rtl8723au_write8(padapter, REG_LDOA15_CTRL, 0x04); - /* rtl8723au_write8(padapter, REG_LDOV12D_CTRL, 0x54); */ - - value8 = rtl8723au_read8(padapter, REG_LDOV12D_CTRL); - value8 &= ~LDV12_EN; - rtl8723au_write8(padapter, REG_LDOV12D_CTRL, value8); - } - - /***************************** - h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode - i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend - ******************************/ - value8 = 0x23; - if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)) - value8 |= BIT(3); - - rtl8723au_write8(padapter, REG_SPS0_CTRL, value8); - - if (bWithoutHWSM) { - /* value16 |= (APDM_HOST | FSM_HSUS |/PFM_ALDN); */ - /* 2010/08/31 According to Filen description, we need to - use HW to shut down 8051 automatically. */ - /* Because suspend operation need the asistance of 8051 - to wait for 3ms. */ - value16 = APDM_HOST | AFSM_HSUS | PFM_ALDN; - } else { - value16 = APDM_HOST | AFSM_HSUS | PFM_ALDN; - } - - rtl8723au_write16(padapter, REG_APS_FSMCO, value16); /* 0x4802 */ - - rtl8723au_write8(padapter, REG_RSV_CTRL, 0x0e); -} - -/* HW Auto state machine */ -int CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU) -{ - if (padapter->bSurpriseRemoved) - return _SUCCESS; - - /* RF Off Sequence ==== */ - _DisableRFAFEAndResetBB8192C(padapter); - - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure1_92C(padapter, false); - - /* ==== Pull GPIO PIN to balance level and LED control ====== */ - _DisableGPIO(padapter); - - /* ==== Disable analog sequence === */ - _DisableAnalog(padapter, false); - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "======> Card disable finished.\n"); - - return _SUCCESS; -} - -/* without HW Auto state machine */ -int CardDisableWithoutHWSM(struct rtw_adapter *padapter) -{ - if (padapter->bSurpriseRemoved) - return _SUCCESS; - - /* RF Off Sequence ==== */ - _DisableRFAFEAndResetBB8192C(padapter); - - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure1_92C(padapter, true); - - /* ==== Pull GPIO PIN to balance level and LED control ====== */ - _DisableGPIO(padapter); - - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure2(padapter); - - /* ==== Disable analog sequence === */ - _DisableAnalog(padapter, true); - - return _SUCCESS; -} - -void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); - - if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */ - if (!pEEPROM->EepromOrEfuse) { - /* Read EFUSE real map to shadow. */ - EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI); - memcpy(PROMContent, pEEPROM->efuse_eeprom_data, - HWSET_MAX_SIZE); - } - } else { - RT_TRACE(_module_hci_hal_init_c_, _drv_notice_, - "AutoLoad Fail reported from CR9346!!\n"); - /* update to default value 0xFF */ - if (!pEEPROM->EepromOrEfuse) - EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI); - memcpy(PROMContent, pEEPROM->efuse_eeprom_data, - HWSET_MAX_SIZE); - } -} - -void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); -/* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */ - u16 EEPROMId; - - /* Checl 0x8129 again for making sure autoload status!! */ - EEPROMId = le16_to_cpu(*((__le16 *) hwinfo)); - if (EEPROMId != RTL_EEPROM_ID) { - DBG_8723A("EEPROM ID(%#x) is invalid!!\n", EEPROMId); - pEEPROM->bautoload_fail_flag = true; - } else { - pEEPROM->bautoload_fail_flag = false; - } - - RT_TRACE(_module_hal_init_c_, _drv_info_, - "EEPROM ID = 0x%04x\n", EEPROMId); -} - -static void -Hal_ReadPowerValueFromPROM_8723A(struct txpowerinfo *pwrInfo, - u8 *PROMContent, bool AutoLoadFail) -{ - u32 rfPath, eeAddr, group, rfPathMax = 1; - - memset(pwrInfo, 0, sizeof(*pwrInfo)); - - if (AutoLoadFail) { - for (group = 0; group < MAX_CHNL_GROUP; group++) { - for (rfPath = 0; rfPath < rfPathMax; rfPath++) { - pwrInfo->CCKIndex[rfPath][group] = - EEPROM_Default_TxPowerLevel; - pwrInfo->HT40_1SIndex[rfPath][group] = - EEPROM_Default_TxPowerLevel; - pwrInfo->HT40_2SIndexDiff[rfPath][group] = - EEPROM_Default_HT40_2SDiff; - pwrInfo->HT20IndexDiff[rfPath][group] = - EEPROM_Default_HT20_Diff; - pwrInfo->OFDMIndexDiff[rfPath][group] = - EEPROM_Default_LegacyHTTxPowerDiff; - pwrInfo->HT40MaxOffset[rfPath][group] = - EEPROM_Default_HT40_PwrMaxOffset; - pwrInfo->HT20MaxOffset[rfPath][group] = - EEPROM_Default_HT20_PwrMaxOffset; - } - } - pwrInfo->TSSI_A[0] = EEPROM_Default_TSSI; - return; - } - - for (rfPath = 0; rfPath < rfPathMax; rfPath++) { - for (group = 0; group < MAX_CHNL_GROUP; group++) { - eeAddr = - EEPROM_CCK_TX_PWR_INX_8723A + (rfPath * 3) + group; - - pwrInfo->CCKIndex[rfPath][group] = PROMContent[eeAddr]; - if (pwrInfo->CCKIndex[rfPath][group] > 63) - pwrInfo->CCKIndex[rfPath][group] = - EEPROM_Default_TxPowerLevel; - - eeAddr = EEPROM_HT40_1S_TX_PWR_INX_8723A + - (rfPath * 3) + group; - pwrInfo->HT40_1SIndex[rfPath][group] = - PROMContent[eeAddr]; - if (pwrInfo->HT40_1SIndex[rfPath][group] > 63) - pwrInfo->HT40_1SIndex[rfPath][group] = - EEPROM_Default_TxPowerLevel; - } - } - - for (group = 0; group < MAX_CHNL_GROUP; group++) { - for (rfPath = 0; rfPath < rfPathMax; rfPath++) { - pwrInfo->HT40_2SIndexDiff[rfPath][group] = 0; - pwrInfo->HT20IndexDiff[rfPath][group] = - (PROMContent - [EEPROM_HT20_TX_PWR_INX_DIFF_8723A + - group] >> (rfPath * 4)) & 0xF; - /* 4bit sign number to 8 bit sign number */ - if (pwrInfo->HT20IndexDiff[rfPath][group] & BIT(3)) - pwrInfo->HT20IndexDiff[rfPath][group] |= 0xF0; - - pwrInfo->OFDMIndexDiff[rfPath][group] = - (PROMContent[EEPROM_OFDM_TX_PWR_INX_DIFF_8723A + - group] >> (rfPath * 4)) & 0xF; - - pwrInfo->HT40MaxOffset[rfPath][group] = - (PROMContent[EEPROM_HT40_MAX_PWR_OFFSET_8723A + - group] >> (rfPath * 4)) & 0xF; - - pwrInfo->HT20MaxOffset[rfPath][group] = - (PROMContent[EEPROM_HT20_MAX_PWR_OFFSET_8723A + - group] >> (rfPath * 4)) & 0xF; - } - } - - pwrInfo->TSSI_A[0] = PROMContent[EEPROM_TSSI_A_8723A]; -} - -static u8 Hal_GetChnlGroup(u8 chnl) -{ - u8 group = 0; - - if (chnl < 3) /* Cjanel 1-3 */ - group = 0; - else if (chnl < 9) /* Channel 4-9 */ - group = 1; - else /* Channel 10-14 */ - group = 2; - - return group; -} - -void -Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter, - u8 *PROMContent, bool AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct txpowerinfo pwrInfo; - u8 rfPath, ch, group, rfPathMax = 1; - u8 pwr, diff; - - Hal_ReadPowerValueFromPROM_8723A(&pwrInfo, PROMContent, AutoLoadFail); - for (rfPath = 0; rfPath < rfPathMax; rfPath++) { - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - group = Hal_GetChnlGroup(ch); - - pHalData->TxPwrLevelCck[rfPath][ch] = - pwrInfo.CCKIndex[rfPath][group]; - pHalData->TxPwrLevelHT40_1S[rfPath][ch] = - pwrInfo.HT40_1SIndex[rfPath][group]; - - pHalData->TxPwrHt20Diff[rfPath][ch] = - pwrInfo.HT20IndexDiff[rfPath][group]; - pHalData->TxPwrLegacyHtDiff[rfPath][ch] = - pwrInfo.OFDMIndexDiff[rfPath][group]; - pHalData->PwrGroupHT20[rfPath][ch] = - pwrInfo.HT20MaxOffset[rfPath][group]; - pHalData->PwrGroupHT40[rfPath][ch] = - pwrInfo.HT40MaxOffset[rfPath][group]; - - pwr = pwrInfo.HT40_1SIndex[rfPath][group]; - diff = pwrInfo.HT40_2SIndexDiff[rfPath][group]; - - pHalData->TxPwrLevelHT40_2S[rfPath][ch] = - (pwr > diff) ? (pwr - diff) : 0; - } - } - for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) { - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", - rfPath, ch, - pHalData->TxPwrLevelCck[rfPath][ch], - pHalData->TxPwrLevelHT40_1S[rfPath][ch], - pHalData->TxPwrLevelHT40_2S[rfPath][ch]); - - } - } - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch, - pHalData->TxPwrHt20Diff[RF_PATH_A][ch], - pHalData->TxPwrHt20Diff[RF_PATH_A][ch]); - } - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch, - pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]); - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch, - pHalData->TxPwrHt20Diff[RF_PATH_B][ch], - pHalData->TxPwrHt20Diff[RF_PATH_B][ch]); - } - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch, - pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]); - if (!AutoLoadFail) { - struct registry_priv *registry_par = &padapter->registrypriv; - if (registry_par->regulatory_tid == 0xff) { - if (PROMContent[RF_OPTION1_8723A] == 0xff) - pHalData->EEPROMRegulatory = 0; - else - pHalData->EEPROMRegulatory = - PROMContent[RF_OPTION1_8723A] & 0x7; - } else { - pHalData->EEPROMRegulatory = - registry_par->regulatory_tid; - } - } else { - pHalData->EEPROMRegulatory = 0; - } - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory); - - if (!AutoLoadFail) - pHalData->bTXPowerDataReadFromEEPORM = true; -} - -void -Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 tempval; - u32 tmpu4; - - if (!AutoLoadFail) { - tmpu4 = rtl8723au_read32(padapter, REG_MULTI_FUNC_CTRL); - if (tmpu4 & BT_FUNC_EN) - pHalData->EEPROMBluetoothCoexist = 1; - else - pHalData->EEPROMBluetoothCoexist = 0; - pHalData->EEPROMBluetoothType = BT_RTL8723A; - - /* The following need to be checked with newer version of */ - /* eeprom spec */ - tempval = hwinfo[RF_OPTION4_8723A]; - pHalData->EEPROMBluetoothAntNum = (tempval & 0x1); - pHalData->EEPROMBluetoothAntIsolation = (tempval & 0x10) >> 4; - pHalData->EEPROMBluetoothRadioShared = (tempval & 0x20) >> 5; - } else { - pHalData->EEPROMBluetoothCoexist = 0; - pHalData->EEPROMBluetoothType = BT_RTL8723A; - pHalData->EEPROMBluetoothAntNum = Ant_x2; - pHalData->EEPROMBluetoothAntIsolation = 0; - pHalData->EEPROMBluetoothRadioShared = BT_Radio_Shared; - } - - rtl8723a_BT_init_hal_vars(padapter); -} - -void -Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (!AutoLoadFail) - pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723A]; - else - pHalData->EEPROMVersion = 1; - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "Hal_EfuseParseEEPROMVer(), EEVer = %d\n", - pHalData->EEPROMVersion); -} - -void -rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - padapter->mlmepriv.ChannelPlan = - hal_com_get_channel_plan23a(padapter, hwinfo ? - hwinfo[EEPROM_ChannelPlan_8723A]:0xFF, - padapter->registrypriv.channel_plan, - RT_CHANNEL_DOMAIN_WORLD_WIDE_13, - AutoLoadFail); - - DBG_8723A("mlmepriv.ChannelPlan = 0x%02x\n", - padapter->mlmepriv.ChannelPlan); -} - -void -Hal_EfuseParseCustomerID(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (!AutoLoadFail) { - pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723A]; - pHalData->EEPROMSubCustomerID = - hwinfo[EEPROM_SubCustomID_8723A]; - } else { - pHalData->EEPROMCustomerID = 0; - pHalData->EEPROMSubCustomerID = 0; - } - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID); - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "EEPROM SubCustomer ID: 0x%02x\n", - pHalData->EEPROMSubCustomerID); -} - -void -Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ -} - -void -Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ -} - -void -Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter, - u8 *hwinfo, u8 AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - - if (!AutoLoadFail) { - pHalData->CrystalCap = hwinfo[EEPROM_XTAL_K_8723A]; - if (pHalData->CrystalCap == 0xFF) - pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A; - } else { - pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A; - } - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "%s: CrystalCap = 0x%2x\n", __func__, - pHalData->CrystalCap); -} - -void -Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter, - u8 *PROMContent, bool AutoloadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* */ - /* ThermalMeter from EEPROM */ - /* */ - if (!AutoloadFail) - pHalData->EEPROMThermalMeter = - PROMContent[EEPROM_THERMAL_METER_8723A]; - else - pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter; - - if ((pHalData->EEPROMThermalMeter == 0xff) || AutoloadFail) { - pHalData->bAPKThermalMeterIgnore = true; - pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter; - } - - DBG_8723A("%s: ThermalMeter = 0x%x\n", __func__, - pHalData->EEPROMThermalMeter); -} - -static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc) -{ - __le16 *usPtr = (__le16 *)ptxdesc; - u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ - u32 index; - u16 checksum = 0; - - /* Clear first */ - ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); - - for (index = 0; index < count; index++) - checksum ^= le16_to_cpu(usPtr[index]); - - ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff); -} - -/* - * Description: In normal chip, we should send some packet to Hw which - * will be used by Fw in FW LPS mode. The function is to fill the Tx - * descriptor of this packets, then - */ -/* Fw can tell Hw to send these packet derectly. */ -/* Added by tynli. 2009.10.15. */ -/* */ -void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc, - u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull) -{ - struct tx_desc *ptxdesc; - - /* Clear all status */ - ptxdesc = (struct tx_desc *)pDesc; - memset(pDesc, 0, TXDESC_SIZE); - - /* offset 0 */ - /* own, bFirstSeg, bLastSeg; */ - ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - - /* 32 bytes for TX Desc */ - ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << - OFFSET_SHT) & 0x00ff0000); - - /* Buffer size + command header */ - ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff); - - /* offset 4 */ - /* Fixed queue of Mgnt queue */ - ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00); - - /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed - to error vlaue by Hw. */ - if (IsPsPoll) { - ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR); - } else { - /* Hw set sequence number */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); - /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */ - ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); - } - - if (true == IsBTQosNull) - ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */ - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8)); /* driver uses rate */ - - /* USB interface drop packet if the checksum of descriptor isn't - correct. */ - /* Using this checksum can let hardware recovery from packet bulk - out error (e.g. Cancel URC, Bulk out error.). */ - rtl8723a_cal_txdesc_chksum(ptxdesc); -} - -void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode) -{ - u8 val8; - - if (mode == MSR_INFRA || mode == MSR_NOLINK) { - StopTxBeacon(padapter); - - /* disable atim wnd */ - val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM; - SetBcnCtrlReg23a(padapter, val8, ~val8); - } else if (mode == MSR_ADHOC) { - ResumeTxBeacon(padapter); - - val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB; - SetBcnCtrlReg23a(padapter, val8, ~val8); - } else if (mode == MSR_AP) { - /* add NULL Data and BT NULL Data Packets to FW RSVD Page */ - rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter); - - ResumeTxBeacon(padapter); - - val8 = DIS_TSF_UDT | DIS_BCNQ_SUB; - SetBcnCtrlReg23a(padapter, val8, ~val8); - - /* Set RCR */ - /* rtl8723au_write32(padapter, REG_RCR, 0x70002a8e); - CBSSID_DATA must set to 0 */ - /* CBSSID_DATA must set to 0 */ - rtl8723au_write32(padapter, REG_RCR, 0x7000228e); - /* enable to rx data frame */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF); - /* enable to rx ps-poll */ - rtl8723au_write16(padapter, REG_RXFLTMAP1, 0x0400); - - /* Beacon Control related register for first time */ - /* 2ms */ - rtl8723au_write8(padapter, REG_BCNDMATIM, 0x02); - /* 5ms */ - rtl8723au_write8(padapter, REG_DRVERLYINT, 0x05); - /* 10ms for port0 */ - rtl8723au_write8(padapter, REG_ATIMWND, 0x0a); - rtl8723au_write16(padapter, REG_BCNTCFG, 0x00); - rtl8723au_write16(padapter, REG_TBTT_PROHIBIT, 0xff04); - /* +32767 (~32ms) */ - rtl8723au_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff); - - /* reset TSF */ - rtl8723au_write8(padapter, REG_DUAL_TSF_RST, BIT(0)); - - /* enable BCN Function */ - /* don't enable update TSF (due to TSF update when - beacon/probe rsp are received) */ - val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | - EN_TXBCN_RPT | DIS_BCNQ_SUB; - SetBcnCtrlReg23a(padapter, val8, ~val8); - } - - val8 = rtl8723au_read8(padapter, MSR); - val8 = (val8 & 0xC) | mode; - rtl8723au_write8(padapter, MSR, val8); -} - -void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val) -{ - u8 idx = 0; - u32 reg_macid; - - reg_macid = REG_MACID; - - for (idx = 0; idx < 6; idx++) - rtl8723au_write8(padapter, (reg_macid + idx), val[idx]); -} - -void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val) -{ - u8 idx = 0; - u32 reg_bssid; - - reg_bssid = REG_BSSID; - - for (idx = 0; idx < 6; idx++) - rtl8723au_write8(padapter, (reg_bssid + idx), val[idx]); -} - -void hw_var_set_correct_tsf(struct rtw_adapter *padapter) -{ - u64 tsf; - u32 reg_tsftr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* tsf = pmlmeext->TSFValue - ((u32)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) == MSR_ADHOC) || - ((pmlmeinfo->state & 0x03) == MSR_AP)) { - /* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */ - /* rtl8723au_write8(padapter, REG_TXPAUSE, - (rtl8723au_read8(Adapter, REG_TXPAUSE)|BIT(6))); */ - StopTxBeacon(padapter); - } - - reg_tsftr = REG_TSFTR; - - /* disable related TSF function */ - SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION); - - rtl8723au_write32(padapter, reg_tsftr, tsf); - rtl8723au_write32(padapter, reg_tsftr + 4, tsf >> 32); - - /* enable related TSF function */ - SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION, 0); - - if (((pmlmeinfo->state & 0x03) == MSR_ADHOC) || - ((pmlmeinfo->state & 0x03) == MSR_AP)) - ResumeTxBeacon(padapter); -} - -void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter) -{ - /* reject all data frames */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0); - - /* reset TSF */ - rtl8723au_write8(padapter, REG_DUAL_TSF_RST, BIT(0)); - - /* disable update TSF */ - SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0); -} - -void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type) -{ - u8 RetryLimit = 0x30; - - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (type == 0) { /* prepare to join */ - u32 v32; - - /* enable to rx data frame.Accept all data frame */ - /* rtl8723au_write32(padapter, REG_RCR, - rtl8723au_read32(padapter, REG_RCR)|RCR_ADF); */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF); - - v32 = rtl8723au_read32(padapter, REG_RCR); - v32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN; - rtl8723au_write32(padapter, REG_RCR, v32); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) - RetryLimit = - (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48; - else /* Ad-hoc Mode */ - RetryLimit = 0x7; - } else if (type == 1) { /* joinbss_event callback when join res < 0 */ - /* config RCR to receive different BSSID & not to - receive data frame during linking */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0); - } else if (type == 2) { /* sta add event callback */ - /* enable update TSF */ - SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT); - - if (check_fwstate(pmlmepriv, - WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) { - /* fixed beacon issue for 8191su........... */ - rtl8723au_write8(padapter, 0x542, 0x02); - RetryLimit = 0x7; - } - } - - rtl8723au_write16(padapter, REG_RL, - RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << - RETRY_LIMIT_LONG_SHIFT); - - switch (type) { - case 0: - /* prepare to join */ - rtl8723a_BT_wifiassociate_notify(padapter, true); - break; - case 1: - /* joinbss_event callback when join res < 0 */ - rtl8723a_BT_wifiassociate_notify(padapter, false); - break; - case 2: - /* sta add event callback */ -/* BT_WifiMediaStatusNotify(padapter, RT_MEDIA_CONNECT); */ - break; - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c deleted file mode 100644 index 06a6c3eeeb33..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c +++ /dev/null @@ -1,961 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTL8723A_PHYCFG_C_ - -#include -#include - -#include -#include - -/*---------------------------Define Local Constant---------------------------*/ -/* Channel switch:The size of command tables for switch channel*/ -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -/*---------------------------Define Local Constant---------------------------*/ - -/*------------------------Define global variable-----------------------------*/ - -/*------------------------Define local variable------------------------------*/ - -/*--------------------Define export function prototype-----------------------*/ -/* Please refer to header file */ -/*--------------------Define export function prototype-----------------------*/ - -/*----------------------------Function Body----------------------------------*/ -/* */ -/* 1. BB register R/W API */ -/* */ - -/** -* Function: phy_CalculateBitShift -* -* OverView: Get shifted position of the BitMask -* -* Input: -* u32 BitMask, -* -* Output: none -* Return: u32 Return the shift bit bit position of the mask -*/ -static u32 phy_CalculateBitShift(u32 BitMask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((BitMask>>i) & 0x1) == 1) - break; - } - - return i; -} - -/** -* Function: PHY_QueryBBReg -* -* OverView: Read "sepcific bits" from BB register -* -* Input: -* struct rtw_adapter * Adapter, -* u32 RegAddr, Target address to be readback -* u32 BitMask Target bit position in the -* target address to be readback -* Output: -* None -* Return: -* u32 Data The readback register value -* Note: -* This function is equal to "GetRegSetting" in PHY programming guide -*/ -u32 -PHY_QueryBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask) -{ - u32 ReturnValue = 0, OriginalValue, BitShift; - - OriginalValue = rtl8723au_read32(Adapter, RegAddr); - BitShift = phy_CalculateBitShift(BitMask); - ReturnValue = (OriginalValue & BitMask) >> BitShift; - return ReturnValue; -} - -/** -* Function: PHY_SetBBReg -* -* OverView: Write "Specific bits" to BB register (page 8~) -* -* Input: -* struct rtw_adapter * Adapter, -* u32 RegAddr, Target address to be modified -* u32 BitMask Target bit position in the -* target address to be modified -* u32 Data The new register value in the -* target bit position of the -* target address -* -* Output: -* None -* Return: -* None -* Note: -* This function is equal to "PutRegSetting" in PHY programming guide -*/ - -void -PHY_SetBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data) -{ - u32 OriginalValue, BitShift; - - if (BitMask != bMaskDWord) {/* if not "double word" write */ - OriginalValue = rtl8723au_read32(Adapter, RegAddr); - BitShift = phy_CalculateBitShift(BitMask); - Data = (OriginalValue & (~BitMask)) | (Data << BitShift); - } - - rtl8723au_write32(Adapter, RegAddr, Data); - - /* RTPRINT(FPHY, PHY_BBW, ("BBW MASK = 0x%lx Addr[0x%lx]= 0x%lx\n", BitMask, RegAddr, Data)); */ -} - -/* */ -/* 2. RF register R/W API */ -/* */ - -/** -* Function: phy_RFSerialRead -* -* OverView: Read regster from RF chips -* -* Input: -* struct rtw_adapter * Adapter, -* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D -* u32 Offset, The target address to be read -* -* Output: None -* Return: u32 reback value -* Note: Threre are three types of serial operations: -* 1. Software serial write -* 2. Hardware LSSI-Low Speed Serial Interface -* 3. Hardware HSSI-High speed -* serial write. Driver need to implement (1) and (2). -* This function is equal to the combination of RF_ReadReg() and -* RFLSSIRead() -*/ -static u32 -phy_RFSerialRead(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath, - u32 Offset) -{ - u32 retValue = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct bb_reg_define *pPhyReg = &pHalData->PHYRegDef[eRFPath]; - u32 NewOffset; - u32 tmplong, tmplong2; - u8 RfPiEnable = 0; - /* */ - /* Make sure RF register offset is correct */ - /* */ - Offset &= 0x3f; - - /* */ - /* Switch page for 8256 RF IC */ - /* */ - NewOffset = Offset; - - /* 2009/06/17 MH We can not execute IO for power save or - other accident mode. */ - /* if (RT_CANNOT_IO(Adapter)) */ - /* */ - /* RTPRINT(FPHY, PHY_RFR, ("phy_RFSerialRead return all one\n")); */ - /* return 0xFFFFFFFF; */ - /* */ - - /* For 92S LSSI Read RFLSSIRead */ - /* For RF A/B write 0x824/82c(does not work in the future) */ - /* We must use 0x824 for RF A and B to execute read trigger */ - tmplong = rtl8723au_read32(Adapter, rFPGA0_XA_HSSIParameter2); - if (eRFPath == RF_PATH_A) - tmplong2 = tmplong; - else - tmplong2 = rtl8723au_read32(Adapter, pPhyReg->rfHSSIPara2); - - tmplong2 = (tmplong2 & ~bLSSIReadAddress) | - (NewOffset << 23) | bLSSIReadEdge; /* T65 RF */ - - rtl8723au_write32(Adapter, rFPGA0_XA_HSSIParameter2, - tmplong & (~bLSSIReadEdge)); - udelay(10);/* PlatformStallExecution(10); */ - - rtl8723au_write32(Adapter, pPhyReg->rfHSSIPara2, tmplong2); - udelay(100);/* PlatformStallExecution(100); */ - - rtl8723au_write32(Adapter, rFPGA0_XA_HSSIParameter2, - tmplong | bLSSIReadEdge); - udelay(10);/* PlatformStallExecution(10); */ - - if (eRFPath == RF_PATH_A) - RfPiEnable = (u8)PHY_QueryBBReg(Adapter, - rFPGA0_XA_HSSIParameter1, - BIT(8)); - else if (eRFPath == RF_PATH_B) - RfPiEnable = (u8)PHY_QueryBBReg(Adapter, - rFPGA0_XB_HSSIParameter1, - BIT(8)); - - if (RfPiEnable) { - /* Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */ - retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBackPi, - bLSSIReadBackData); - /* DBG_8723A("Readback from RF-PI : 0x%x\n", retValue); */ - } else { - /* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */ - retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBack, - bLSSIReadBackData); - /* DBG_8723A("Readback from RF-SI : 0x%x\n", retValue); */ - } - /* DBG_8723A("RFR-%d Addr[0x%x]= 0x%x\n", eRFPath, pPhyReg->rfLSSIReadBack, retValue); */ - - return retValue; -} - -/** -* Function: phy_RFSerialWrite -* -* OverView: Write data to RF register (page 8~) -* -* Input: -* struct rtw_adapter * Adapter, -* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D -* u32 Offset, The target address to be read -* u32 Data The new register Data in the target -* bit position of the target to be read -* -* Output: -* None -* Return: -* None -* Note: -* Threre are three types of serial operations: -* 1. Software serial write -* 2. Hardware LSSI-Low Speed Serial Interface -* 3. Hardware HSSI-High speed -* serial write. Driver need to implement (1) and (2). -* This function is equal to the combination of RF_ReadReg() and -* RFLSSIRead() -* -* Note: For RF8256 only -* The total count of RTL8256(Zebra4) register is around 36 bit it only employs -* 4-bit RF address. RTL8256 uses "register mode control bit" -* (Reg00[12], Reg00[10]) to access register address bigger than 0xf. -* See "Appendix-4 in PHY Configuration programming guide" for more details. -* Thus, we define a sub-finction for RTL8526 register address conversion -* =========================================================== -* Register Mode: RegCTL[1] RegCTL[0] Note -* (Reg00[12]) (Reg00[10]) -* =========================================================== -* Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf) -* ------------------------------------------------------------------ -* Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf) -* ------------------------------------------------------------------ -* Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf) -* ------------------------------------------------------------------ -* -* 2008/09/02 MH Add 92S RF definition -*/ -static void -phy_RFSerialWrite(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath, - u32 Offset, u32 Data) -{ - u32 DataAndAddr = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct bb_reg_define *pPhyReg = &pHalData->PHYRegDef[eRFPath]; - u32 NewOffset; - - /* 2009/06/17 MH We can not execute IO for power save or - other accident mode. */ - /* if (RT_CANNOT_IO(Adapter)) */ - /* */ - /* RTPRINT(FPHY, PHY_RFW, ("phy_RFSerialWrite stop\n")); */ - /* return; */ - /* */ - - Offset &= 0x3f; - - /* */ - /* Shadow Update */ - /* */ - /* PHY_RFShadowWrite(Adapter, eRFPath, Offset, Data); */ - - /* */ - /* Switch page for 8256 RF IC */ - /* */ - NewOffset = Offset; - - /* */ - /* Put write addr in [5:0] and write data in [31:16] */ - /* */ - /* DataAndAddr = (Data<<16) | (NewOffset&0x3f); */ - /* T65 RF */ - DataAndAddr = ((NewOffset<<20) | (Data&0x000fffff)) & 0x0fffffff; - - /* */ - /* Write Operation */ - /* */ - rtl8723au_write32(Adapter, pPhyReg->rf3wireOffset, DataAndAddr); -} - -/** -* Function: PHY_QueryRFReg -* -* OverView: Query "Specific bits" to RF register (page 8~) -* -* Input: -* struct rtw_adapter * Adapter, -* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D -* u32 RegAddr, The target address to be read -* u32BitMask The target bit position in the target -* address to be read -* -* Output: -* None -* Return: -* u32 Readback value -* Note: -* This function is equal to "GetRFRegSetting" in PHY programming guide -*/ -u32 -PHY_QueryRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath, - u32 RegAddr, u32 BitMask) -{ - u32 Original_Value, Readback_Value, BitShift; - /* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */ - /* u8 RFWaitCounter = 0; */ - /* _irqL irqL; */ - - Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr); - - BitShift = phy_CalculateBitShift(BitMask); - Readback_Value = (Original_Value & BitMask) >> BitShift; - - return Readback_Value; -} - -/** -* Function: PHY_SetRFReg -* -* OverView: Write "Specific bits" to RF register (page 8~) -* -* Input: -* struct rtw_adapter * Adapter, -* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D -* u32 RegAddr, The target address to be modified -* u32 BitMask The target bit position in the target -* address to be modified -* u32 Data The new register Data in the target -* bit position of the target address -* -* Output: -* None -* Return: -* None -* Note: This function is equal to "PutRFRegSetting" in PHY programming guide -*/ -void -PHY_SetRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath, - u32 RegAddr, u32 BitMask, u32 Data) -{ - /* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */ - /* u8 RFWaitCounter = 0; */ - u32 Original_Value, BitShift; - - /* RF data is 12 bits only */ - if (BitMask != bRFRegOffsetMask) { - Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr); - BitShift = phy_CalculateBitShift(BitMask); - Data = (Original_Value & (~BitMask)) | (Data << BitShift); - } - - phy_RFSerialWrite(Adapter, eRFPath, RegAddr, Data); -} - -/* 3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. */ - -/*----------------------------------------------------------------------------- - * Function: PHY_MACConfig8723A - * - * Overview: Condig MAC by header file or parameter file. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 08/12/2008 MHC Create Version 0. - * - *---------------------------------------------------------------------------*/ -int PHY_MACConfig8723A(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* */ - /* Config MAC */ - /* */ - ODM_ReadAndConfig_MAC_REG_8723A(&pHalData->odmpriv); - - /* 2010.07.13 AMPDU aggregation number 9 */ - rtl8723au_write8(Adapter, REG_MAX_AGGR_NUM, 0x0A); - if (pHalData->rf_type == RF_2T2R && - BOARD_USB_DONGLE == pHalData->BoardType) - rtl8723au_write8(Adapter, 0x40, 0x04); - - return _SUCCESS; -} - -/** -* Function: phy_InitBBRFRegisterDefinition -* -* OverView: Initialize Register definition offset for Radio Path A/B/C/D -* -* Input: -* struct rtw_adapter * Adapter, -* -* Output: None -* Return: None -* Note: -* The initialization value is constant and it should never be changes -*/ -static void -phy_InitBBRFRegisterDefinition(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* RF Interface Sowrtware Control */ - /* 16 LSBs if read 32-bit from 0x870 */ - pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; - /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */ - pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; - - /* RF Interface Readback Value */ - /* 16 LSBs if read 32-bit from 0x8E0 */ - pHalData->PHYRegDef[RF_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB; - /* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */ - pHalData->PHYRegDef[RF_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB; - - /* RF Interface Output (and Enable) */ - /* 16 LSBs if read 32-bit from 0x860 */ - pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; - /* 16 LSBs if read 32-bit from 0x864 */ - pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; - - /* RF Interface (Output and) Enable */ - /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */ - pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; - /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */ - pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; - - /* Addr of LSSI. Wirte RF register by driver */ - pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; - pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter; - - /* RF parameter */ - /* BB Band Select */ - pHalData->PHYRegDef[RF_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter; - pHalData->PHYRegDef[RF_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter; - - /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ - pHalData->PHYRegDef[RF_PATH_A].rfTxGainStage = rFPGA0_TxGainStage; - pHalData->PHYRegDef[RF_PATH_B].rfTxGainStage = rFPGA0_TxGainStage; - - /* Tranceiver A~D HSSI Parameter-1 */ - /* wire control parameter1 */ - pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1; - /* wire control parameter1 */ - pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1; - - /* Tranceiver A~D HSSI Parameter-2 */ - /* wire control parameter2 */ - pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; - /* wire control parameter2 */ - pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; - - /* RF switch Control */ - pHalData->PHYRegDef[RF_PATH_A].rfSwitchControl = - rFPGA0_XAB_SwitchControl; /* TR/Ant switch control */ - pHalData->PHYRegDef[RF_PATH_B].rfSwitchControl = - rFPGA0_XAB_SwitchControl; - - /* AGC control 1 */ - pHalData->PHYRegDef[RF_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1; - pHalData->PHYRegDef[RF_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1; - - /* AGC control 2 */ - pHalData->PHYRegDef[RF_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2; - pHalData->PHYRegDef[RF_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2; - - /* RX AFE control 1 */ - pHalData->PHYRegDef[RF_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance; - pHalData->PHYRegDef[RF_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance; - - /* RX AFE control 1 */ - pHalData->PHYRegDef[RF_PATH_A].rfRxAFE = rOFDM0_XARxAFE; - pHalData->PHYRegDef[RF_PATH_B].rfRxAFE = rOFDM0_XBRxAFE; - - /* Tx AFE control 1 */ - pHalData->PHYRegDef[RF_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance; - pHalData->PHYRegDef[RF_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance; - - /* Tx AFE control 2 */ - pHalData->PHYRegDef[RF_PATH_A].rfTxAFE = rOFDM0_XATxAFE; - pHalData->PHYRegDef[RF_PATH_B].rfTxAFE = rOFDM0_XBTxAFE; - - /* Tranceiver LSSI Readback SI mode */ - pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack; - pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack; - - /* Tranceiver LSSI Readback PI mode */ - pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi = - TransceiverA_HSPI_Readback; - pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi = - TransceiverB_HSPI_Readback; -} - -/* The following is for High Power PA */ -static void -storePwrIndexDiffRateOffset(struct rtw_adapter *Adapter, u32 RegAddr, - u32 BitMask, u32 Data) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - if (RegAddr == rTxAGC_A_Rate18_06) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][0] = Data; - } - if (RegAddr == rTxAGC_A_Rate54_24) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][1] = Data; - } - if (RegAddr == rTxAGC_A_CCK1_Mcs32) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][6] = Data; - } - if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0xffffff00) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][7] = Data; - } - if (RegAddr == rTxAGC_A_Mcs03_Mcs00) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][2] = Data; - } - if (RegAddr == rTxAGC_A_Mcs07_Mcs04) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][3] = Data; - } - if (RegAddr == rTxAGC_A_Mcs11_Mcs08) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][4] = Data; - } - if (RegAddr == rTxAGC_A_Mcs15_Mcs12) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][5] = Data; - } - if (RegAddr == rTxAGC_B_Rate18_06) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][8] = Data; - } - if (RegAddr == rTxAGC_B_Rate54_24) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][9] = Data; - } - if (RegAddr == rTxAGC_B_CCK1_55_Mcs32) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][14] = Data; - } - if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0x000000ff) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][15] = Data; - } - if (RegAddr == rTxAGC_B_Mcs03_Mcs00) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][10] = Data; - } - if (RegAddr == rTxAGC_B_Mcs07_Mcs04) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][11] = Data; - } - if (RegAddr == rTxAGC_B_Mcs11_Mcs08) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][12] = Data; - } - if (RegAddr == rTxAGC_B_Mcs15_Mcs12) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][13] = Data; - pHalData->pwrGroupCnt++; - } -} - -/*----------------------------------------------------------------------------- - * Function: phy_ConfigBBWithPgHeaderFile - * - * Overview: Config PHY_REG_PG array - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/06/2008 MHC Add later!!!!!!.. Please modify for new files!!!! - * 11/10/2008 tynli Modify to mew files. - *---------------------------------------------------------------------------*/ -static int -phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter) -{ - int i; - u32 *Rtl819XPHY_REGArray_Table_PG; - u16 PHY_REGArrayPGLen; - - PHY_REGArrayPGLen = Rtl8723_PHY_REG_Array_PGLength; - Rtl819XPHY_REGArray_Table_PG = (u32 *)Rtl8723_PHY_REG_Array_PG; - - for (i = 0; i < PHY_REGArrayPGLen; i = i + 3) { - storePwrIndexDiffRateOffset(Adapter, - Rtl819XPHY_REGArray_Table_PG[i], - Rtl819XPHY_REGArray_Table_PG[i+1], - Rtl819XPHY_REGArray_Table_PG[i+2]); - } - - return _SUCCESS; -} - -static void -phy_BB8192C_Config_1T(struct rtw_adapter *Adapter) -{ - /* for path - B */ - PHY_SetBBReg(Adapter, rFPGA0_TxInfo, 0x3, 0x2); - PHY_SetBBReg(Adapter, rFPGA1_TxInfo, 0x300033, 0x200022); - - /* 20100519 Joseph: Add for 1T2R config. Suggested by Kevin, - Jenyu and Yunan. */ - PHY_SetBBReg(Adapter, rCCK0_AFESetting, bMaskByte3, 0x45); - PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, bMaskByte0, 0x23); - /* B path first AGC */ - PHY_SetBBReg(Adapter, rOFDM0_AGCParameter1, 0x30, 0x1); - - PHY_SetBBReg(Adapter, 0xe74, 0x0c000000, 0x2); - PHY_SetBBReg(Adapter, 0xe78, 0x0c000000, 0x2); - PHY_SetBBReg(Adapter, 0xe7c, 0x0c000000, 0x2); - PHY_SetBBReg(Adapter, 0xe80, 0x0c000000, 0x2); - PHY_SetBBReg(Adapter, 0xe88, 0x0c000000, 0x2); -} - -static int -phy_BB8723a_Config_ParaFile(struct rtw_adapter *Adapter) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter); - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - int rtStatus = _SUCCESS; - - /* */ - /* 1. Read PHY_REG.TXT BB INIT!! */ - /* We will separate as 88C / 92C according to chip version */ - /* */ - ODM_ReadAndConfig_PHY_REG_1T_8723A(&pHalData->odmpriv); - - /* */ - /* 20100318 Joseph: Config 2T2R to 1T2R if necessary. */ - /* */ - if (pHalData->rf_type == RF_1T2R) { - phy_BB8192C_Config_1T(Adapter); - DBG_8723A("phy_BB8723a_Config_ParaFile():Config to 1T!!\n"); - } - - /* */ - /* 2. If EEPROM or EFUSE autoload OK, We must config by - PHY_REG_PG.txt */ - /* */ - if (pEEPROM->bautoload_fail_flag == false) { - pHalData->pwrGroupCnt = 0; - - rtStatus = phy_ConfigBBWithPgHeaderFile(Adapter); - } - - if (rtStatus != _SUCCESS) - goto phy_BB8190_Config_ParaFile_Fail; - - /* */ - /* 3. BB AGC table Initialization */ - /* */ - ODM_ReadAndConfig_AGC_TAB_1T_8723A(&pHalData->odmpriv); - -phy_BB8190_Config_ParaFile_Fail: - - return rtStatus; -} - -int -PHY_BBConfig8723A(struct rtw_adapter *Adapter) -{ - int rtStatus = _SUCCESS; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 TmpU1B = 0; - u8 CrystalCap; - - phy_InitBBRFRegisterDefinition(Adapter); - - /* Suggested by Scott. tynli_test. 2010.12.30. */ - /* 1. 0x28[1] = 1 */ - TmpU1B = rtl8723au_read8(Adapter, REG_AFE_PLL_CTRL); - udelay(2); - rtl8723au_write8(Adapter, REG_AFE_PLL_CTRL, TmpU1B | BIT(1)); - udelay(2); - - /* 2. 0x29[7:0] = 0xFF */ - rtl8723au_write8(Adapter, REG_AFE_PLL_CTRL+1, 0xff); - udelay(2); - - /* 3. 0x02[1:0] = 2b'11 */ - TmpU1B = rtl8723au_read8(Adapter, REG_SYS_FUNC_EN); - rtl8723au_write8(Adapter, REG_SYS_FUNC_EN, - (TmpU1B | FEN_BB_GLB_RSTn | FEN_BBRSTB)); - - /* 4. 0x25[6] = 0 */ - TmpU1B = rtl8723au_read8(Adapter, REG_AFE_XTAL_CTRL + 1); - rtl8723au_write8(Adapter, REG_AFE_XTAL_CTRL+1, TmpU1B & ~BIT(6)); - - /* 5. 0x24[20] = 0 Advised by SD3 Alex Wang. 2011.02.09. */ - TmpU1B = rtl8723au_read8(Adapter, REG_AFE_XTAL_CTRL+2); - rtl8723au_write8(Adapter, REG_AFE_XTAL_CTRL+2, TmpU1B & ~BIT(4)); - - /* 6. 0x1f[7:0] = 0x07 */ - rtl8723au_write8(Adapter, REG_RF_CTRL, 0x07); - - /* */ - /* Config BB and AGC */ - /* */ - rtStatus = phy_BB8723a_Config_ParaFile(Adapter); - -/* only for B-cut */ - if (pHalData->EEPROMVersion >= 0x01) { - CrystalCap = pHalData->CrystalCap & 0x3F; - PHY_SetBBReg(Adapter, REG_MAC_PHY_CTRL, 0xFFF000, - (CrystalCap | (CrystalCap << 6))); - } - - rtl8723au_write32(Adapter, REG_LDOA15_CTRL, 0x01572505); - return rtStatus; -} - -/*----------------------------------------------------------------------------- - * Function: SetTxPowerLevel8723A() - * - * Overview: This function is export to "HalCommon" moudule - * We must consider RF path later!!!!!!! - * - * Input: struct rtw_adapter * Adapter - * u8 channel - * - * Output: NONE - * - * Return: NONE - * - *---------------------------------------------------------------------------*/ -void PHY_SetTxPowerLevel8723A(struct rtw_adapter *Adapter, u8 channel) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 cckpwr[2], ofdmpwr[2]; /* [0]:RF-A, [1]:RF-B */ - int i = channel - 1; - - if (pHalData->bTXPowerDataReadFromEEPORM == false) - return; - - /* 1. CCK */ - cckpwr[RF_PATH_A] = pHalData->TxPwrLevelCck[RF_PATH_A][i]; - cckpwr[RF_PATH_B] = pHalData->TxPwrLevelCck[RF_PATH_B][i]; - - /* 2. OFDM for 1S or 2S */ - if (GET_RF_TYPE(Adapter) == RF_1T2R || - GET_RF_TYPE(Adapter) == RF_1T1R) { - /* Read HT 40 OFDM TX power */ - ofdmpwr[RF_PATH_A] = pHalData->TxPwrLevelHT40_1S[RF_PATH_A][i]; - ofdmpwr[RF_PATH_B] = pHalData->TxPwrLevelHT40_1S[RF_PATH_B][i]; - } else if (GET_RF_TYPE(Adapter) == RF_2T2R) { - /* Read HT 40 OFDM TX power */ - ofdmpwr[RF_PATH_A] = pHalData->TxPwrLevelHT40_2S[RF_PATH_A][i]; - ofdmpwr[RF_PATH_B] = pHalData->TxPwrLevelHT40_2S[RF_PATH_B][i]; - } - - rtl823a_phy_rf6052setccktxpower(Adapter, &cckpwr[0]); - rtl8723a_PHY_RF6052SetOFDMTxPower(Adapter, &ofdmpwr[0], channel); -} - -/*----------------------------------------------------------------------------- - * Function: PHY_SetBWMode23aCallback8192C() - * - * Overview: Timer callback function for SetSetBWMode23a - * - * Input: PRT_TIMER pTimer - * - * Output: NONE - * - * Return: NONE - * - * Note: - * (1) We do not take j mode into consideration now - * (2) Will two workitem of "switch channel" and - * "switch channel bandwidth" run concurrently? - *---------------------------------------------------------------------------*/ -static void -_PHY_SetBWMode23a92C(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 regBwOpMode; - u8 regRRSR_RSC; - - if (Adapter->bDriverStopped) - return; - - /* 3 */ - /* 3<1>Set MAC register */ - /* 3 */ - - regBwOpMode = rtl8723au_read8(Adapter, REG_BWOPMODE); - regRRSR_RSC = rtl8723au_read8(Adapter, REG_RRSR+2); - - switch (pHalData->CurrentChannelBW) { - case HT_CHANNEL_WIDTH_20: - regBwOpMode |= BW_OPMODE_20MHZ; - rtl8723au_write8(Adapter, REG_BWOPMODE, regBwOpMode); - break; - case HT_CHANNEL_WIDTH_40: - regBwOpMode &= ~BW_OPMODE_20MHZ; - rtl8723au_write8(Adapter, REG_BWOPMODE, regBwOpMode); - regRRSR_RSC = (regRRSR_RSC & 0x90) | - (pHalData->nCur40MhzPrimeSC << 5); - rtl8723au_write8(Adapter, REG_RRSR+2, regRRSR_RSC); - break; - - default: - break; - } - - /* 3 */ - /* 3<2>Set PHY related register */ - /* 3 */ - switch (pHalData->CurrentChannelBW) { - /* 20 MHz channel*/ - case HT_CHANNEL_WIDTH_20: - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0); - PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0); - PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter2, BIT(10), 1); - - break; - - /* 40 MHz channel*/ - case HT_CHANNEL_WIDTH_40: - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1); - PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1); - - /* Set Control channel to upper or lower. These settings - are required only for 40MHz */ - PHY_SetBBReg(Adapter, rCCK0_System, bCCKSideBand, - (pHalData->nCur40MhzPrimeSC >> 1)); - PHY_SetBBReg(Adapter, rOFDM1_LSTF, 0xC00, - pHalData->nCur40MhzPrimeSC); - PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter2, BIT(10), 0); - - PHY_SetBBReg(Adapter, 0x818, BIT(26) | BIT(27), - (pHalData->nCur40MhzPrimeSC == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2:1); - break; - - default: - break; - } - /* Skip over setting of J-mode in BB register here. Default value - is "None J mode". Emily 20070315 */ - - /* Added it for 20/40 mhz switch time evaluation by guangan 070531 */ - /* NowL = PlatformEFIORead4Byte(Adapter, TSFR); */ - /* NowH = PlatformEFIORead4Byte(Adapter, TSFR+4); */ - /* EndTime = ((u64)NowH << 32) + NowL; */ - - rtl8723a_phy_rf6052set_bw(Adapter, pHalData->CurrentChannelBW); -} - - /*----------------------------------------------------------------------------- - * Function: SetBWMode23a8190Pci() - * - * Overview: This function is export to "HalCommon" moudule - * - * Input: struct rtw_adapter * Adapter - * enum ht_channel_width Bandwidth 20M or 40M - * - * Output: NONE - * - * Return: NONE - * - * Note: We do not take j mode into consideration now - *---------------------------------------------------------------------------*/ -void -PHY_SetBWMode23a8723A(struct rtw_adapter *Adapter, - enum ht_channel_width Bandwidth, unsigned char Offset) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - enum ht_channel_width tmpBW = pHalData->CurrentChannelBW; - - pHalData->CurrentChannelBW = Bandwidth; - - pHalData->nCur40MhzPrimeSC = Offset; - - if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) - _PHY_SetBWMode23a92C(Adapter); - else - pHalData->CurrentChannelBW = tmpBW; -} - -static void _PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) -{ - enum RF_RADIO_PATH eRFPath; - u32 param1, param2; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* s1. pre common command - CmdID_SetTxPowerLevel */ - PHY_SetTxPowerLevel8723A(Adapter, channel); - - /* s2. RF dependent command - CmdID_RF_WriteReg, - param1 = RF_CHNLBW, param2 = channel */ - param1 = RF_CHNLBW; - param2 = channel; - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) { - pHalData->RfRegChnlVal[eRFPath] = - (pHalData->RfRegChnlVal[eRFPath] & 0xfffffc00) | param2; - PHY_SetRFReg(Adapter, eRFPath, param1, - bRFRegOffsetMask, pHalData->RfRegChnlVal[eRFPath]); - } - - /* s3. post common command - CmdID_End, None */ -} - -void PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 tmpchannel = pHalData->CurrentChannel; - bool result = true; - - if (channel == 0) - channel = 1; - - pHalData->CurrentChannel = channel; - - if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) { - _PHY_SwChnl8723A(Adapter, channel); - - if (!result) - pHalData->CurrentChannel = tmpchannel; - } else { - pHalData->CurrentChannel = tmpchannel; - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c b/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c deleted file mode 100644 index 24c0ff3d82bc..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c +++ /dev/null @@ -1,503 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -/****************************************************************************** - * - * - * Module: rtl8192c_rf6052.c (Source C File) - * - * Note: Provide RF 6052 series relative API. - * - * Function: - * - * Export: - * - * Abbrev: - * - * History: - * Data Who Remark - * - * 09/25/2008 MHC Create initial version. - * 11/05/2008 MHC Add API for tw power setting. - * - * -******************************************************************************/ - -#define _RTL8723A_RF6052_C_ - -#include -#include - -#include -#include - -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetBandwidth() - * - * Overview: This function is called by SetBWMode23aCallback8190Pci() only - * - * Input: struct rtw_adapter * Adapter - * WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M - * - * Output: NONE - * - * Return: NONE - * - * Note: For RF type 0222D - *---------------------------------------------------------------------------*/ -void rtl8723a_phy_rf6052set_bw(struct rtw_adapter *Adapter, - enum ht_channel_width Bandwidth) /* 20M or 40M */ -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - switch (Bandwidth) { - case HT_CHANNEL_WIDTH_20: - pHalData->RfRegChnlVal[0] = - (pHalData->RfRegChnlVal[0] & 0xfffff3ff) | 0x0400; - PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, - pHalData->RfRegChnlVal[0]); - break; - case HT_CHANNEL_WIDTH_40: - pHalData->RfRegChnlVal[0] = - (pHalData->RfRegChnlVal[0] & 0xfffff3ff); - PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, - pHalData->RfRegChnlVal[0]); - break; - default: - break; - } -} - -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetCckTxPower - * - * Overview: - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/05/2008 MHC Simulate 8192series.. - * - *---------------------------------------------------------------------------*/ - -void rtl823a_phy_rf6052setccktxpower(struct rtw_adapter *Adapter, - u8 *pPowerlevel) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - u32 TxAGC[2] = {0, 0}, tmpval = 0; - u8 idx1, idx2; - u8 *ptr; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - TxAGC[RF_PATH_A] = 0x3f3f3f3f; - TxAGC[RF_PATH_B] = 0x3f3f3f3f; - - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - TxAGC[idx1] = pPowerlevel[idx1] | - (pPowerlevel[idx1] << 8) | - (pPowerlevel[idx1] << 16) | - (pPowerlevel[idx1] << 24); - /* - * 2010/10/18 MH For external PA module. We need - * to limit power index to be less than 0x20. - */ - if (TxAGC[idx1] > 0x20 && pHalData->ExternalPA) - TxAGC[idx1] = 0x20; - } - } else { -/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx - * power. It shall be determined by power training mechanism. */ -/* Currently, we cannot fully disable driver dynamic tx power - * mechanism because it is referenced by BT coexist mechanism. */ -/* In the future, two mechanism shall be separated from each other - * and maintained independently. Thanks for Lanhsin's reminder. */ - if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) { - TxAGC[RF_PATH_A] = 0x10101010; - TxAGC[RF_PATH_B] = 0x10101010; - } else if (pdmpriv->DynamicTxHighPowerLvl == - TxHighPwrLevel_Level2) { - TxAGC[RF_PATH_A] = 0x00000000; - TxAGC[RF_PATH_B] = 0x00000000; - } else { - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - TxAGC[idx1] = pPowerlevel[idx1] | - (pPowerlevel[idx1] << 8) | - (pPowerlevel[idx1] << 16) | - (pPowerlevel[idx1] << 24); - } - - if (pHalData->EEPROMRegulatory == 0) { - tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) + - (pHalData->MCSTxPowerLevelOriginalOffset[0][7]<<8); - TxAGC[RF_PATH_A] += tmpval; - - tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) + - (pHalData->MCSTxPowerLevelOriginalOffset[0][15]<<24); - TxAGC[RF_PATH_B] += tmpval; - } - } - } - - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - ptr = (u8 *)(&TxAGC[idx1]); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - - /* rf-A cck tx power */ - tmpval = TxAGC[RF_PATH_A] & 0xff; - PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval); - tmpval = TxAGC[RF_PATH_A] >> 8; - PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - - /* rf-B cck tx power */ - tmpval = TxAGC[RF_PATH_B] >> 24; - PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval); - tmpval = TxAGC[RF_PATH_B] & 0x00ffffff; - PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval); -} /* PHY_RF6052SetCckTxPower */ - -/* powerbase0 for OFDM rates */ -/* powerbase1 for HT MCS rates */ -static void getPowerBase(struct rtw_adapter *Adapter, u8 *pPowerLevel, - u8 Channel, u32 *OfdmBase, u32 *MCSBase) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u32 ofdm, mcs; - u8 Legacy_pwrdiff = 0; - s8 HT20_pwrdiff = 0; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerlevel[i] = pPowerLevel[i]; - Legacy_pwrdiff = pHalData->TxPwrLegacyHtDiff[i][Channel-1]; - ofdm = powerlevel[i] + Legacy_pwrdiff; - - ofdm = ofdm << 24 | ofdm << 16 | ofdm << 8 | ofdm; - *(OfdmBase + i) = ofdm; - } - - for (i = 0; i < 2; i++) { - /* Check HT20 to HT40 diff */ - if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { - HT20_pwrdiff = pHalData->TxPwrHt20Diff[i][Channel-1]; - powerlevel[i] += HT20_pwrdiff; - } - mcs = powerlevel[i]; - mcs = mcs << 24 | mcs << 16 | mcs << 8 | mcs; - *(MCSBase + i) = mcs; - } -} - -static void -getTxPowerWriteValByRegulatory(struct rtw_adapter *Adapter, u8 Channel, - u8 index, u32 *powerBase0, u32 *powerBase1, - u32 *pOutWriteVal) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - u8 i, chnlGroup = 0, pwr_diff_limit[4]; - u32 writeVal, customer_limit, rf; - - /* Index 0 & 1 = legacy OFDM, 2-5 = HT_MCS rate */ - for (rf = 0; rf < 2; rf++) { - switch (pHalData->EEPROMRegulatory) { - case 0: /* Realtek better performance */ - /* increase power diff defined by Realtek for - * large power */ - chnlGroup = 0; - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - case 1: /* Realtek regulatory */ - /* increase power diff defined by Realtek for - * regulatory */ - if (pHalData->pwrGroupCnt == 1) - chnlGroup = 0; - if (pHalData->pwrGroupCnt >= 3) { - if (Channel <= 3) - chnlGroup = 0; - else if (Channel >= 4 && Channel <= 9) - chnlGroup = 1; - else if (Channel > 9) - chnlGroup = 2; - - if (pHalData->CurrentChannelBW == - HT_CHANNEL_WIDTH_20) - chnlGroup++; - else - chnlGroup += 4; - } - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] + - ((index < 2) ? powerBase0[rf] : - powerBase1[rf]); - break; - case 2: /* Better regulatory */ - /* don't increase any power diff */ - writeVal = (index < 2) ? powerBase0[rf] : - powerBase1[rf]; - break; - case 3: /* Customer defined power diff. */ - chnlGroup = 0; - - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + - (rf ? 8 : 0)]&(0x7f << (i*8))) >> (i*8)); - if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40) { - if (pwr_diff_limit[i] > pHalData->PwrGroupHT40[rf][Channel-1]) - pwr_diff_limit[i] = pHalData->PwrGroupHT40[rf][Channel-1]; - } else { - if (pwr_diff_limit[i] > pHalData->PwrGroupHT20[rf][Channel-1]) - pwr_diff_limit[i] = pHalData->PwrGroupHT20[rf][Channel-1]; - } - } - customer_limit = (pwr_diff_limit[3]<<24) | (pwr_diff_limit[2]<<16) | - (pwr_diff_limit[1]<<8) | (pwr_diff_limit[0]); - writeVal = customer_limit + ((index<2)?powerBase0[rf]:powerBase1[rf]); - break; - default: - chnlGroup = 0; - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - } - -/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. - It shall be determined by power training mechanism. */ -/* Currently, we cannot fully disable driver dynamic tx power mechanism - because it is referenced by BT coexist mechanism. */ -/* In the future, two mechanism shall be separated from each other and - maintained independently. Thanks for Lanhsin's reminder. */ - - if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) - writeVal = 0x14141414; - else if (pdmpriv->DynamicTxHighPowerLvl == - TxHighPwrLevel_Level2) - writeVal = 0x00000000; - - /* 20100628 Joseph: High power mode for BT-Coexist mechanism. */ - /* This mechanism is only applied when - Driver-Highpower-Mechanism is OFF. */ - if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT1) - writeVal = writeVal - 0x06060606; - else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT2) - writeVal = writeVal; - *(pOutWriteVal + rf) = writeVal; - } -} - -static void writeOFDMPowerReg(struct rtw_adapter *Adapter, u8 index, - u32 *pValue) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u16 RegOffset_A[6] = { - rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24, - rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04, - rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12 - }; - u16 RegOffset_B[6] = { - rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24, - rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04, - rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12 - }; - u8 i, rf, pwr_val[4]; - u32 writeVal; - u16 RegOffset; - - for (rf = 0; rf < 2; rf++) { - writeVal = pValue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeVal & - (0x7f << (i * 8))) >> (i * 8)); - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeVal = pwr_val[3] << 24 | pwr_val[2] << 16 | - pwr_val[1] << 8 | pwr_val[0]; - - if (rf == 0) - RegOffset = RegOffset_A[index]; - else - RegOffset = RegOffset_B[index]; - - rtl8723au_write32(Adapter, RegOffset, writeVal); - - /* 201005115 Joseph: Set Tx Power diff for Tx power - training mechanism. */ - if (((pHalData->rf_type == RF_2T2R) && - (RegOffset == rTxAGC_A_Mcs15_Mcs12 || - RegOffset == rTxAGC_B_Mcs15_Mcs12)) || - ((pHalData->rf_type != RF_2T2R) && - (RegOffset == rTxAGC_A_Mcs07_Mcs04 || - RegOffset == rTxAGC_B_Mcs07_Mcs04))) { - writeVal = pwr_val[3]; - if (RegOffset == rTxAGC_A_Mcs15_Mcs12 || - RegOffset == rTxAGC_A_Mcs07_Mcs04) - RegOffset = 0xc90; - if (RegOffset == rTxAGC_B_Mcs15_Mcs12 || - RegOffset == rTxAGC_B_Mcs07_Mcs04) - RegOffset = 0xc98; - for (i = 0; i < 3; i++) { - if (i != 2) - writeVal = (writeVal > 8) ? - (writeVal - 8) : 0; - else - writeVal = (writeVal > 6) ? - (writeVal - 6) : 0; - rtl8723au_write8(Adapter, RegOffset + i, - (u8)writeVal); - } - } - } -} -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetOFDMTxPower - * - * Overview: For legacy and HY OFDM, we must read EEPROM TX power index for - * different channel and read original value in TX power - * register area from 0xe00. We increase offset and - * original value to be correct tx pwr. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Remark - * 11/05/2008 MHC Simulate 8192 series method. - * 01/06/2009 MHC 1. Prevent Path B tx power overflow or - * underflow dure to A/B pwr difference or - * legacy/HT pwr diff. - * 2. We concern with path B legacy/HT OFDM difference. - * 01/22/2009 MHC Support new EPRO format from SD3. - * - *---------------------------------------------------------------------------*/ -void rtl8723a_PHY_RF6052SetOFDMTxPower(struct rtw_adapter *Adapter, - u8 *pPowerLevel, u8 Channel) -{ - u32 writeVal[2], powerBase0[2], powerBase1[2]; - u8 index = 0; - - getPowerBase(Adapter, pPowerLevel, Channel, - &powerBase0[0], &powerBase1[0]); - - for (index = 0; index < 6; index++) { - getTxPowerWriteValByRegulatory(Adapter, Channel, index, - &powerBase0[0], &powerBase1[0], &writeVal[0]); - - writeOFDMPowerReg(Adapter, index, &writeVal[0]); - } -} - -static int phy_RF6052_Config_ParaFile(struct rtw_adapter *Adapter) -{ - u32 u4RegValue = 0; - u8 eRFPath; - struct bb_reg_define *pPhyReg; - int rtStatus = _SUCCESS; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* 3----------------------------------------------------------------- */ - /* 3 <2> Initialize RF */ - /* 3----------------------------------------------------------------- */ - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) { - - pPhyReg = &pHalData->PHYRegDef[eRFPath]; - - /*----Store original RFENV control type----*/ - switch (eRFPath) { - case RF_PATH_A: - u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, - bRFSI_RFENV); - break; - case RF_PATH_B: - u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, - bRFSI_RFENV << 16); - break; - } - - /*----Set RF_ENV enable----*/ - PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); - udelay(1);/* PlatformStallExecution(1); */ - - /*----Set RF_ENV output high----*/ - PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); - udelay(1);/* PlatformStallExecution(1); */ - - /* Set bit number of Address and Data for RF register */ - PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, - 0x0); /* Set 1 to 4 bits for 8255 */ - udelay(1);/* PlatformStallExecution(1); */ - - PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, - 0x0); /* Set 0 to 12 bits for 8255 */ - udelay(1);/* PlatformStallExecution(1); */ - - /*----Initialize RF fom connfiguration file----*/ - switch (eRFPath) { - case RF_PATH_A: - ODM_ReadAndConfig_RadioA_1T_8723A(&pHalData->odmpriv); - break; - case RF_PATH_B: - break; - } - - /*----Restore RFENV control type----*/ - switch (eRFPath) { - case RF_PATH_A: - PHY_SetBBReg(Adapter, pPhyReg->rfintfs, - bRFSI_RFENV, u4RegValue); - break; - case RF_PATH_B: - PHY_SetBBReg(Adapter, pPhyReg->rfintfs, - bRFSI_RFENV << 16, u4RegValue); - break; - } - - if (rtStatus != _SUCCESS) { - goto phy_RF6052_Config_ParaFile_Fail; - } - } -phy_RF6052_Config_ParaFile_Fail: - return rtStatus; -} - -int PHY_RF6052_Config8723A(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* Initialize general global value */ - /* TODO: Extend RF_PATH_C and RF_PATH_D in the future */ - if (pHalData->rf_type == RF_1T1R) - pHalData->NumTotalRFPath = 1; - else - pHalData->NumTotalRFPath = 2; - - /* Config BB and RF */ - return phy_RF6052_Config_ParaFile(Adapter); -} - -/* End of HalRf6052.c */ diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c b/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c deleted file mode 100644 index 81b5efe649fa..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTL8723A_REDESC_C_ - -#include -#include -#include - -static void process_rssi(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data; - - if (signal_stat->update_req) { - signal_stat->total_num = 0; - signal_stat->total_val = 0; - signal_stat->update_req = 0; - } - - signal_stat->total_num++; - signal_stat->total_val += pattrib->phy_info.SignalStrength; - signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num; -} - -static void process_link_qual(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib; - struct signal_stat *signal_stat; - - if (prframe == NULL || padapter == NULL) - return; - - pattrib = &prframe->attrib; - signal_stat = &padapter->recvpriv.signal_qual_data; - - if (signal_stat->update_req) { - signal_stat->total_num = 0; - signal_stat->total_val = 0; - signal_stat->update_req = 0; - } - - signal_stat->total_num++; - signal_stat->total_val += pattrib->phy_info.SignalQuality; - signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num; -} - -/* void rtl8723a_process_phy_info(struct rtw_adapter *padapter, union recv_frame *prframe) */ -void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe) -{ - struct recv_frame *precvframe = prframe; - /* Check RSSI */ - process_rssi(padapter, precvframe); - /* Check EVM */ - process_link_qual(padapter, precvframe); -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c b/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c deleted file mode 100644 index 3c46294b8788..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTL8723A_SRESET_C_ - -#include -#include -#include - -void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - unsigned long current_time; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - unsigned int diff_time; - u32 txdma_status; - - txdma_status = rtl8723au_read32(padapter, REG_TXDMA_STATUS); - if (txdma_status != 0) { - DBG_8723A("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status); - rtw_sreset_reset(padapter); - } - - current_time = jiffies; - - if (0 == pxmitpriv->free_xmitbuf_cnt || 0 == pxmitpriv->free_xmit_extbuf_cnt) { - - diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_time); - - if (diff_time > 2000) { - if (psrtpriv->last_tx_complete_time == 0) { - psrtpriv->last_tx_complete_time = current_time; - } else { - diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_complete_time); - if (diff_time > 4000) { - DBG_8723A("%s tx hang\n", __func__); - rtw_sreset_reset(padapter); - } - } - } - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_recv.c b/drivers/staging/rtl8723au/hal/rtl8723au_recv.c deleted file mode 100644 index 0fec84bcb5d9..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723au_recv.c +++ /dev/null @@ -1,267 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTL8192CU_RECV_C_ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int rtl8723au_init_recv_priv(struct rtw_adapter *padapter) -{ - struct recv_priv *precvpriv = &padapter->recvpriv; - int i, size, res = _SUCCESS; - struct recv_buf *precvbuf; - unsigned long tmpaddr; - unsigned long alignment; - struct sk_buff *pskb; - - tasklet_init(&precvpriv->recv_tasklet, - (void(*)(unsigned long))rtl8723au_recv_tasklet, - (unsigned long)padapter); - - precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!precvpriv->int_in_urb) - DBG_8723A("alloc_urb for interrupt in endpoint fail !!!!\n"); - precvpriv->int_in_buf = kzalloc(USB_INTR_CONTENT_LENGTH, GFP_KERNEL); - if (!precvpriv->int_in_buf) - DBG_8723A("alloc_mem for interrupt in endpoint fail !!!!\n"); - - size = NR_RECVBUFF * sizeof(struct recv_buf); - precvpriv->precv_buf = kzalloc(size, GFP_KERNEL); - if (!precvpriv->precv_buf) { - res = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "alloc recv_buf fail!\n"); - goto exit; - } - - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - - for (i = 0; i < NR_RECVBUFF; i++) { - INIT_LIST_HEAD(&precvbuf->list); - - precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); - if (!precvbuf->purb) - break; - - precvbuf->adapter = padapter; - - precvbuf++; - } - - skb_queue_head_init(&precvpriv->rx_skb_queue); - skb_queue_head_init(&precvpriv->free_recv_skb_queue); - - for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) { - size = MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ; - pskb = __netdev_alloc_skb(padapter->pnetdev, size, GFP_KERNEL); - - if (pskb) { - pskb->dev = padapter->pnetdev; - - tmpaddr = (unsigned long)pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); - skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment)); - - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - } - - pskb = NULL; - } - -exit: - return res; -} - -void rtl8723au_free_recv_priv(struct rtw_adapter *padapter) -{ - int i; - struct recv_buf *precvbuf; - struct recv_priv *precvpriv = &padapter->recvpriv; - - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - - for (i = 0; i < NR_RECVBUFF; i++) { - usb_free_urb(precvbuf->purb); - - if (precvbuf->pskb) - dev_kfree_skb_any(precvbuf->pskb); - - precvbuf++; - } - - kfree(precvpriv->precv_buf); - - usb_free_urb(precvpriv->int_in_urb); - kfree(precvpriv->int_in_buf); - - if (skb_queue_len(&precvpriv->rx_skb_queue)) - DBG_8723A(KERN_WARNING "rx_skb_queue not empty\n"); - - skb_queue_purge(&precvpriv->rx_skb_queue); - - if (skb_queue_len(&precvpriv->free_recv_skb_queue)) { - DBG_8723A(KERN_WARNING "free_recv_skb_queue not empty, %d\n", - skb_queue_len(&precvpriv->free_recv_skb_queue)); - } - - skb_queue_purge(&precvpriv->free_recv_skb_queue); -} - -struct recv_stat_cpu { - u32 rxdw0; - u32 rxdw1; - u32 rxdw2; - u32 rxdw3; - u32 rxdw4; - u32 rxdw5; -}; - -void update_recvframe_attrib(struct recv_frame *precvframe, - struct recv_stat *prxstat) -{ - struct rx_pkt_attrib *pattrib; - struct recv_stat_cpu report; - struct rxreport_8723a *prxreport; - - report.rxdw0 = le32_to_cpu(prxstat->rxdw0); - report.rxdw1 = le32_to_cpu(prxstat->rxdw1); - report.rxdw2 = le32_to_cpu(prxstat->rxdw2); - report.rxdw3 = le32_to_cpu(prxstat->rxdw3); - report.rxdw4 = le32_to_cpu(prxstat->rxdw4); - report.rxdw5 = le32_to_cpu(prxstat->rxdw5); - - prxreport = (struct rxreport_8723a *)&report; - - pattrib = &precvframe->attrib; - memset(pattrib, 0, sizeof(struct rx_pkt_attrib)); - - /* update rx report to recv_frame attribute */ - pattrib->pkt_len = (u16)prxreport->pktlen; - pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3); - pattrib->physt = (u8)prxreport->physt; - - pattrib->crc_err = (u8)prxreport->crc32; - pattrib->icv_err = (u8)prxreport->icverr; - - pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1); - pattrib->encrypt = (u8)prxreport->security; - - pattrib->qos = (u8)prxreport->qos; - pattrib->priority = (u8)prxreport->tid; - - pattrib->amsdu = (u8)prxreport->amsdu; - - pattrib->seq_num = (u16)prxreport->seq; - pattrib->frag_num = (u8)prxreport->frag; - pattrib->mfrag = (u8)prxreport->mf; - pattrib->mdata = (u8)prxreport->md; - - pattrib->mcs_rate = (u8)prxreport->rxmcs; - pattrib->rxht = (u8)prxreport->rxht; -} - -void update_recvframe_phyinfo(struct recv_frame *precvframe, - struct phy_stat *pphy_status) -{ - struct rtw_adapter *padapter = precvframe->adapter; - struct rx_pkt_attrib *pattrib = &precvframe->attrib; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct phy_info *pPHYInfo = &pattrib->phy_info; - struct odm_packet_info pkt_info; - u8 *sa = NULL, *da; - struct sta_priv *pstapriv; - struct sta_info *psta; - struct sk_buff *skb = precvframe->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - bool matchbssid = false; - u8 *bssid; - - matchbssid = !ieee80211_is_ctl(hdr->frame_control) && - !pattrib->icv_err && !pattrib->crc_err; - - if (matchbssid) { - switch (hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_TODS | - IEEE80211_FCTL_FROMDS)) { - case cpu_to_le16(IEEE80211_FCTL_TODS): - bssid = hdr->addr1; - break; - case cpu_to_le16(IEEE80211_FCTL_FROMDS): - bssid = hdr->addr2; - break; - case cpu_to_le16(0): - bssid = hdr->addr3; - break; - default: - bssid = NULL; - matchbssid = false; - } - - if (bssid) - matchbssid = ether_addr_equal( - get_bssid(&padapter->mlmepriv), bssid); - } - - pkt_info.bPacketMatchBSSID = matchbssid; - - da = ieee80211_get_DA(hdr); - pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && - (!memcmp(da, myid(&padapter->eeprompriv), ETH_ALEN)); - - pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && - ieee80211_is_beacon(hdr->frame_control); - - pkt_info.StationID = 0xFF; - if (pkt_info.bPacketBeacon) { - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true) - sa = padapter->mlmepriv.cur_network.network.MacAddress; - /* to do Ad-hoc */ - } else { - sa = ieee80211_get_SA(hdr); - } - - pstapriv = &padapter->stapriv; - psta = rtw_get_stainfo23a(pstapriv, sa); - if (psta) { - pkt_info.StationID = psta->mac_id; - /* printk("%s ==> StationID(%d)\n", __func__, pkt_info.StationID); */ - } - pkt_info.Rate = pattrib->mcs_rate; - - ODM_PhyStatusQuery23a(&pHalData->odmpriv, pPHYInfo, - (u8 *)pphy_status, &pkt_info); - precvframe->psta = NULL; - if (pkt_info.bPacketMatchBSSID && - (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) { - if (psta) { - precvframe->psta = psta; - rtl8723a_process_phy_info(padapter, precvframe); - } - } else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) { - if (check_fwstate(&padapter->mlmepriv, - WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == - true) { - if (psta) - precvframe->psta = psta; - } - rtl8723a_process_phy_info(padapter, precvframe); - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c deleted file mode 100644 index 14746dd8db78..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c +++ /dev/null @@ -1,520 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RTL8192C_XMIT_C_ -#include -#include -#include -#include -#include -/* include */ -#include - -static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz) -{ - int blnSetTxDescOffset; - struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); - - if (pdvobj->ishighspeed) { - if (((sz + TXDESC_SIZE) % 512) == 0) - blnSetTxDescOffset = 1; - else - blnSetTxDescOffset = 0; - } else { - if (((sz + TXDESC_SIZE) % 64) == 0) - blnSetTxDescOffset = 1; - else - blnSetTxDescOffset = 0; - } - return blnSetTxDescOffset; -} - -static void rtl8192cu_cal_txdesc_chksum(struct tx_desc *ptxdesc) -{ - __le16 *usPtr = (__le16 *)ptxdesc; - u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ - u32 index; - u16 checksum = 0; - - /* Clear first */ - ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); - - for (index = 0 ; index < count ; index++) - checksum = checksum ^ le16_to_cpu(*(usPtr + index)); - - ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff&checksum); -} - -static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc) -{ - if ((pattrib->encrypt > 0) && !pattrib->bswenc) { - switch (pattrib->encrypt) { - /* SEC_TYPE */ - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000); - break; - case WLAN_CIPHER_SUITE_TKIP: - /* ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000); */ - ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000); - break; - case WLAN_CIPHER_SUITE_CCMP: - ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000); - break; - case 0: - default: - break; - } - } -} - -static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw) -{ - /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */ - - switch (pattrib->vcs_mode) { - case RTS_CTS: - *pdw |= cpu_to_le32(BIT(12)); - break; - case CTS_TO_SELF: - *pdw |= cpu_to_le32(BIT(11)); - break; - case NONE_VCS: - default: - break; - } - - if (pattrib->vcs_mode) { - *pdw |= cpu_to_le32(BIT(13)); - - /* Set RTS BW */ - if (pattrib->ht_en) { - *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0; - - if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - *pdw |= cpu_to_le32((0x01<<28)&0x30000000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - *pdw |= cpu_to_le32((0x02<<28)&0x30000000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - *pdw |= 0; - else - *pdw |= cpu_to_le32((0x03<<28)&0x30000000); - } - } -} - -static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw) -{ - if (pattrib->ht_en) { - *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0; - - if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - *pdw |= cpu_to_le32((0x01<<20)&0x003f0000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - *pdw |= cpu_to_le32((0x02<<20)&0x003f0000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - *pdw |= 0; - else - *pdw |= cpu_to_le32((0x03<<20)&0x003f0000); - } -} - -static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz) -{ - int pull = 0; - uint qsel; - struct rtw_adapter *padapter = pxmitframe->padapter; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct tx_desc *ptxdesc = (struct tx_desc *)pmem; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (urb_zero_packet_chk(padapter, sz) == 0) { - ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ); - pull = 1; - pxmitframe->pkt_offset--; - } - - memset(ptxdesc, 0, sizeof(struct tx_desc)); - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f); - - qsel = (uint)(pattrib->qsel & 0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); - - ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000); - - fill_txdesc_sectype(pattrib, ptxdesc); - - if (pattrib->ampdu_en) - ptxdesc->txdw1 |= cpu_to_le32(BIT(5));/* AGG EN */ - else - ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */ - - /* offset 8 */ - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 , offset 20 */ - if (pattrib->qos_en) - ptxdesc->txdw4 |= cpu_to_le32(BIT(6));/* QoS */ - - if ((pattrib->ether_type != 0x888e) && - (pattrib->ether_type != 0x0806) && - (pattrib->dhcp_pkt != 1)) { - /* Non EAP & ARP & DHCP type data packet */ - - fill_txdesc_vcs(pattrib, &ptxdesc->txdw4); - fill_txdesc_phy(pattrib, &ptxdesc->txdw4); - - ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate = 24M */ - ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* */ - - /* use REG_INIDATA_RATE_SEL value */ - ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]); - } else { - /* EAP data packet and ARP packet. */ - /* Use the 1M data rate to send the EAP/ARP packet. */ - /* This will maybe make the handshake smooth. */ - - ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */ - - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) - ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */ - - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } - } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f); - - qsel = (uint)(pattrib->qsel&0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel<txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000); - - /* offset 8 */ - /* CCX-TXRPT ack for xmit mgmt frames. */ - if (pxmitframe->ack_report) - ptxdesc->txdw2 |= cpu_to_le32(BIT(19)); - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - /* offset 20 */ - ptxdesc->txdw5 |= cpu_to_le32(BIT(17));/* retry limit enable */ - ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */ - - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { - DBG_8723A("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); - } else { - DBG_8723A("pxmitframe->frame_tag = %d\n", - pxmitframe->frame_tag); - - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);/* CAM_ID(MAC_ID) */ - - ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);/* raid */ - - /* offset 8 */ - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - /* offset 20 */ - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } - - /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */ - /* mgnt frame should be controlled by Hw because Fw will also send null data */ - /* which we cannot control when Fw LPS enable. */ - /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */ - /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */ - /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */ - if (!pattrib->qos_en) { - /* Hw set sequence number */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); - /* set bit3 to 1. */ - ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); - } - - /* offset 0 */ - ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff); - ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<txdw0 |= cpu_to_le32(BIT(24)); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "offset0-txdesc = 0x%x\n", ptxdesc->txdw0); - - /* offset 4 */ - /* pkt_offset, unit:8 bytes padding */ - if (pxmitframe->pkt_offset > 0) - ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000); - - rtl8192cu_cal_txdesc_chksum(ptxdesc); - return pull; -} - -static int rtw_dump_xframe(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int ret = _SUCCESS; - int inner_ret = _SUCCESS; - int t, sz, w_sz, pull = 0; - u8 *mem_addr; - u32 ff_hwaddr; - struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (pxmitframe->frame_tag == DATA_FRAMETAG && - pxmitframe->attrib.ether_type != ETH_P_ARP && - pxmitframe->attrib.ether_type != ETH_P_PAE && - pxmitframe->attrib.dhcp_pkt != 1) - rtw_issue_addbareq_cmd23a(padapter, pxmitframe); - - mem_addr = pxmitframe->buf_addr; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "rtw_dump_xframe()\n"); - - for (t = 0; t < pattrib->nr_frags; t++) { - if (inner_ret != _SUCCESS && ret == _SUCCESS) - ret = _FAIL; - - if (t != (pattrib->nr_frags - 1)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "pattrib->nr_frags =%d\n", pattrib->nr_frags); - - sz = pxmitpriv->frag_len; - sz = sz - 4 - pattrib->icv_len; - } else { - /* no frag */ - sz = pattrib->last_txcmdsz; - } - - pull = update_txdesc(pxmitframe, mem_addr, sz); - - if (pull) { - mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */ - - pxmitframe->buf_addr = mem_addr; - - w_sz = sz + TXDESC_SIZE; - } else { - w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ; - } - - ff_hwaddr = rtw_get_ff_hwaddr23a(pxmitframe); - inner_ret = rtl8723au_write_port(padapter, ff_hwaddr, - w_sz, pxmitbuf); - rtw_count_tx_stats23a(padapter, pxmitframe, sz); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_write_port, w_sz =%d\n", w_sz); - - mem_addr += w_sz; - - mem_addr = PTR_ALIGN(mem_addr, 4); - } - - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - if (ret != _SUCCESS) - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN); - - return ret; -} - -bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter, - struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf) -{ - struct hw_xmit *phwxmits; - struct xmit_frame *pxmitframe; - int hwentry; - int res = _SUCCESS, xcnt = 0; - - phwxmits = pxmitpriv->hwxmits; - hwentry = pxmitpriv->hwxmit_entry; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "xmitframe_complete()\n"); - - if (pxmitbuf == NULL) { - pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv); - if (!pxmitbuf) - return false; - } - pxmitframe = rtw_dequeue_xframe23a(pxmitpriv, phwxmits, hwentry); - - if (pxmitframe) { - pxmitframe->pxmitbuf = pxmitbuf; - - pxmitframe->buf_addr = pxmitbuf->pbuf; - - pxmitbuf->priv_data = pxmitframe; - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - if (pxmitframe->attrib.priority <= 15)/* TID0~15 */ - res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe); - - rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */ - } - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "xmitframe_complete(): rtw_dump_xframe\n"); - - if (res == _SUCCESS) { - rtw_dump_xframe(padapter, pxmitframe); - } else { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - } - xcnt++; - } else { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - return false; - } - return true; -} - -static int xmitframe_direct(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int res; - - res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe); - if (res == _SUCCESS) - rtw_dump_xframe(padapter, pxmitframe); - return res; -} - -/* - * Return - * true dump packet directly - * false enqueue packet - */ -bool rtl8723au_hal_xmit(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int res; - struct xmit_buf *pxmitbuf = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pattrib->qsel = pattrib->priority; - spin_lock_bh(&pxmitpriv->lock); - -#ifdef CONFIG_8723AU_AP_MODE - if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_unlock_bh(&pxmitpriv->lock); - - if (pattrib->psta) - psta = pattrib->psta; - else - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - - if (psta) { - if (psta->sleepq_len > (NR_XMITFRAME>>3)) - wakeup_sta_to_xmit23a(padapter, psta); - } - - return false; - } -#endif - - if (rtw_txframes_sta_ac_pending23a(padapter, pattrib) > 0) - goto enqueue; - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) - goto enqueue; - - pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv); - if (pxmitbuf == NULL) - goto enqueue; - - spin_unlock_bh(&pxmitpriv->lock); - - pxmitframe->pxmitbuf = pxmitbuf; - pxmitframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pxmitframe; - - if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - } - return true; - -enqueue: - res = rtw_xmitframe_enqueue23a(padapter, pxmitframe); - spin_unlock_bh(&pxmitpriv->lock); - - if (res != _SUCCESS) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "pre_xmitframe: enqueue xmitframe fail\n"); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - /* Trick, make the statistics correct */ - pxmitpriv->tx_pkts--; - pxmitpriv->tx_drop++; - return true; - } - return false; -} - -int rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - return rtw_dump_xframe(padapter, pmgntframe); -} - -int rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int err; - - err = rtw_xmitframe_enqueue23a(padapter, pxmitframe); - if (err != _SUCCESS) { - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - /* Trick, make the statistics correct */ - pxmitpriv->tx_pkts--; - pxmitpriv->tx_drop++; - } else { - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - } - return err; -} diff --git a/drivers/staging/rtl8723au/hal/usb_halinit.c b/drivers/staging/rtl8723au/hal/usb_halinit.c deleted file mode 100644 index fa47aebf8b98..000000000000 --- a/drivers/staging/rtl8723au/hal/usb_halinit.c +++ /dev/null @@ -1,1269 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _HCI_HAL_INIT_C_ - -#include -#include -#include - -#include -#include -#include -#include - -#include - -static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter, - enum rt_rf_power_state eRFPowerState); - -static void -_ConfigChipOutEP(struct rtw_adapter *pAdapter, u8 NumOutPipe) -{ - u8 value8; - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - - pHalData->OutEpQueueSel = 0; - pHalData->OutEpNumber = 0; - - /* Normal and High queue */ - value8 = rtl8723au_read8(pAdapter, (REG_NORMAL_SIE_EP + 1)); - - if (value8 & USB_NORMAL_SIE_EP_MASK) { - pHalData->OutEpQueueSel |= TX_SELE_HQ; - pHalData->OutEpNumber++; - } - - if ((value8 >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) { - pHalData->OutEpQueueSel |= TX_SELE_NQ; - pHalData->OutEpNumber++; - } - - /* Low queue */ - value8 = rtl8723au_read8(pAdapter, (REG_NORMAL_SIE_EP + 2)); - if (value8 & USB_NORMAL_SIE_EP_MASK) { - pHalData->OutEpQueueSel |= TX_SELE_LQ; - pHalData->OutEpNumber++; - } - - /* TODO: Error recovery for this case */ - /* RT_ASSERT((NumOutPipe == pHalData->OutEpNumber), - ("Out EP number isn't match! %d(Descriptor) != %d (SIE reg)\n", - (u32)NumOutPipe, (u32)pHalData->OutEpNumber)); */ -} - -bool rtl8723au_chip_configure(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - u8 NumInPipe = pdvobjpriv->RtNumInPipes; - u8 NumOutPipe = pdvobjpriv->RtNumOutPipes; - - _ConfigChipOutEP(padapter, NumOutPipe); - - /* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */ - if (pHalData->OutEpNumber == 1) { - if (NumInPipe != 1) - return false; - } - - return Hal_MappingOutPipe23a(padapter, NumOutPipe); -} - -static int _InitPowerOn(struct rtw_adapter *padapter) -{ - u16 value16; - u8 value8; - - /* RSV_CTRL 0x1C[7:0] = 0x00 - unlock ISO/CLK/Power control register */ - rtl8723au_write8(padapter, REG_RSV_CTRL, 0x0); - - /* HW Power on sequence */ - if (!HalPwrSeqCmdParsing23a(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_USB_MSK, rtl8723AU_card_enable_flow)) - return _FAIL; - - /* 0x04[19] = 1, suggest by Jackie 2011.05.09, reset 8051 */ - value8 = rtl8723au_read8(padapter, REG_APS_FSMCO+2); - rtl8723au_write8(padapter, REG_APS_FSMCO + 2, value8 | BIT(3)); - - /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ - /* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. - Added by tynli. 2011.08.31. */ - value16 = rtl8723au_read16(padapter, REG_CR); - value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN | - PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN | - ENSEC | CALTMR_EN); - rtl8723au_write16(padapter, REG_CR, value16); - - /* for Efuse PG, suggest by Jackie 2011.11.23 */ - PHY_SetBBReg(padapter, REG_EFUSE_CTRL, BIT(28)|BIT(29)|BIT(30), 0x06); - - return _SUCCESS; -} - -/* Shall USB interface init this? */ -static void _InitInterrupt(struct rtw_adapter *Adapter) -{ - u32 value32; - - /* HISR - turn all on */ - value32 = 0xFFFFFFFF; - rtl8723au_write32(Adapter, REG_HISR, value32); - - /* HIMR - turn all on */ - rtl8723au_write32(Adapter, REG_HIMR, value32); -} - -static void _InitQueueReservedPage(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u32 numHQ = 0; - u32 numLQ = 0; - u32 numNQ = 0; - u32 numPubQ; - u32 value32; - u8 value8; - bool bWiFiConfig = pregistrypriv->wifi_spec; - - /* RT_ASSERT((outEPNum>= 2), ("for WMM , number of out-ep " - "must more than or equal to 2!\n")); */ - - numPubQ = bWiFiConfig ? WMM_NORMAL_PAGE_NUM_PUBQ : NORMAL_PAGE_NUM_PUBQ; - - if (pHalData->OutEpQueueSel & TX_SELE_HQ) { - numHQ = bWiFiConfig ? - WMM_NORMAL_PAGE_NUM_HPQ : NORMAL_PAGE_NUM_HPQ; - } - - if (pHalData->OutEpQueueSel & TX_SELE_LQ) { - numLQ = bWiFiConfig ? - WMM_NORMAL_PAGE_NUM_LPQ : NORMAL_PAGE_NUM_LPQ; - } - /* NOTE: This step shall be proceed before - writting REG_RQPN. */ - if (pHalData->OutEpQueueSel & TX_SELE_NQ) { - numNQ = bWiFiConfig ? - WMM_NORMAL_PAGE_NUM_NPQ : NORMAL_PAGE_NUM_NPQ; - } - value8 = (u8)_NPQ(numNQ); - rtl8723au_write8(Adapter, REG_RQPN_NPQ, value8); - - /* TX DMA */ - value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN; - rtl8723au_write32(Adapter, REG_RQPN, value32); -} - -static void _InitTxBufferBoundary(struct rtw_adapter *Adapter) -{ - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - - u8 txpktbuf_bndy; - - if (!pregistrypriv->wifi_spec) - txpktbuf_bndy = TX_PAGE_BOUNDARY; - else /* for WMM */ - txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY; - - rtl8723au_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl8723au_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - rtl8723au_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); - rtl8723au_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy); - rtl8723au_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy); -} - -static void _InitPageBoundary(struct rtw_adapter *Adapter) -{ - /* RX Page Boundary */ - /* srand(static_cast(time(NULL))); */ - u16 rxff_bndy = 0x27FF;/* rand() % 1) ? 0x27FF : 0x23FF; */ - - rtl8723au_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); - - /* TODO: ?? shall we set tx boundary? */ -} - -static void -_InitNormalChipRegPriority(struct rtw_adapter *Adapter, u16 beQ, u16 bkQ, - u16 viQ, u16 voQ, u16 mgtQ, u16 hiQ) -{ - u16 value16 = rtl8723au_read16(Adapter, REG_TRXDMA_CTRL) & 0x7; - - value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) | - _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) | - _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ); - - rtl8723au_write16(Adapter, REG_TRXDMA_CTRL, value16); -} - -static void _InitNormalChipOneOutEpPriority(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u16 value = 0; - - switch (pHalData->OutEpQueueSel) { - case TX_SELE_HQ: - value = QUEUE_HIGH; - break; - case TX_SELE_LQ: - value = QUEUE_LOW; - break; - case TX_SELE_NQ: - value = QUEUE_NORMAL; - break; - default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ - break; - } - - _InitNormalChipRegPriority(Adapter, value, value, value, - value, value, value); -} - -static void _InitNormalChipTwoOutEpPriority(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; - u16 valueHi = 0; - u16 valueLow = 0; - - switch (pHalData->OutEpQueueSel) { - case (TX_SELE_HQ | TX_SELE_LQ): - valueHi = QUEUE_HIGH; - valueLow = QUEUE_LOW; - break; - case (TX_SELE_NQ | TX_SELE_LQ): - valueHi = QUEUE_NORMAL; - valueLow = QUEUE_LOW; - break; - case (TX_SELE_HQ | TX_SELE_NQ): - valueHi = QUEUE_HIGH; - valueLow = QUEUE_NORMAL; - break; - default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ - break; - } - - if (!pregistrypriv->wifi_spec) { - beQ = valueLow; - bkQ = valueLow; - viQ = valueHi; - voQ = valueHi; - mgtQ = valueHi; - hiQ = valueHi; - } else {/* for WMM , CONFIG_OUT_EP_WIFI_MODE */ - beQ = valueLow; - bkQ = valueHi; - viQ = valueHi; - voQ = valueLow; - mgtQ = valueHi; - hiQ = valueHi; - } - - _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ); -} - -static void _InitNormalChipThreeOutEpPriority(struct rtw_adapter *Adapter) -{ - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; - - if (!pregistrypriv->wifi_spec) {/* typical setting */ - beQ = QUEUE_LOW; - bkQ = QUEUE_LOW; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; - } else {/* for WMM */ - beQ = QUEUE_LOW; - bkQ = QUEUE_NORMAL; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; - } - _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ); -} - -static void _InitQueuePriority(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - switch (pHalData->OutEpNumber) { - case 1: - _InitNormalChipOneOutEpPriority(Adapter); - break; - case 2: - _InitNormalChipTwoOutEpPriority(Adapter); - break; - case 3: - _InitNormalChipThreeOutEpPriority(Adapter); - break; - default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ - break; - } -} - -static void _InitTransferPageSize(struct rtw_adapter *Adapter) -{ - /* Tx page size is always 128. */ - - u8 value8; - value8 = _PSRX(PBP_128) | _PSTX(PBP_128); - rtl8723au_write8(Adapter, REG_PBP, value8); -} - -static void _InitDriverInfoSize(struct rtw_adapter *Adapter, u8 drvInfoSize) -{ - rtl8723au_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize); -} - -static void _InitWMACSetting(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* don't turn on AAP, it will allow all packets to driver */ - pHalData->ReceiveConfig = RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA | - RCR_CBSSID_BCN | RCR_APP_ICV | RCR_AMF | - RCR_HTC_LOC_CTRL | RCR_APP_MIC | - RCR_APP_PHYSTS; - - /* some REG_RCR will be modified later by - phy_ConfigMACWithHeaderFile() */ - rtl8723au_write32(Adapter, REG_RCR, pHalData->ReceiveConfig); - - /* Accept all multicast address */ - rtl8723au_write32(Adapter, REG_MAR, 0xFFFFFFFF); - rtl8723au_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF); - - /* Accept all data frames */ - /* value16 = 0xFFFF; */ - /* rtl8723au_write16(Adapter, REG_RXFLTMAP2, value16); */ - - /* 2010.09.08 hpfan */ - /* Since ADF is removed from RCR, ps-poll will not be indicate - to driver, */ - /* RxFilterMap should mask ps-poll to guarantee AP mode can - rx ps-poll. */ - /* value16 = 0x400; */ - /* rtl8723au_write16(Adapter, REG_RXFLTMAP1, value16); */ - - /* Accept all management frames */ - /* value16 = 0xFFFF; */ - /* rtl8723au_write16(Adapter, REG_RXFLTMAP0, value16); */ - - /* enable RX_SHIFT bits */ - /* rtl8723au_write8(Adapter, REG_TRXDMA_CTRL, rtl8723au_read8(Adapter, - REG_TRXDMA_CTRL)|BIT(1)); */ -} - -static void _InitAdaptiveCtrl(struct rtw_adapter *Adapter) -{ - u16 value16; - u32 value32; - - /* Response Rate Set */ - value32 = rtl8723au_read32(Adapter, REG_RRSR); - value32 &= ~RATE_BITMAP_ALL; - value32 |= RATE_RRSR_CCK_ONLY_1M; - rtl8723au_write32(Adapter, REG_RRSR, value32); - - /* CF-END Threshold */ - /* m_spIoBase->rtl8723au_write8(REG_CFEND_TH, 0x1); */ - - /* SIFS (used in NAV) */ - value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10); - rtl8723au_write16(Adapter, REG_SPEC_SIFS, value16); - - /* Retry Limit */ - value16 = _LRL(0x30) | _SRL(0x30); - rtl8723au_write16(Adapter, REG_RL, value16); -} - -static void _InitRateFallback(struct rtw_adapter *Adapter) -{ - /* Set Data Auto Rate Fallback Retry Count register. */ - rtl8723au_write32(Adapter, REG_DARFRC, 0x00000000); - rtl8723au_write32(Adapter, REG_DARFRC+4, 0x10080404); - rtl8723au_write32(Adapter, REG_RARFRC, 0x04030201); - rtl8723au_write32(Adapter, REG_RARFRC+4, 0x08070605); -} - -static void _InitEDCA(struct rtw_adapter *Adapter) -{ - /* Set Spec SIFS (used in NAV) */ - rtl8723au_write16(Adapter, REG_SPEC_SIFS, 0x100a); - rtl8723au_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a); - - /* Set SIFS for CCK */ - rtl8723au_write16(Adapter, REG_SIFS_CTX, 0x100a); - - /* Set SIFS for OFDM */ - rtl8723au_write16(Adapter, REG_SIFS_TRX, 0x100a); - - /* TXOP */ - rtl8723au_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B); - rtl8723au_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F); - rtl8723au_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324); - rtl8723au_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226); -} - -static void _InitRDGSetting(struct rtw_adapter *Adapter) -{ - rtl8723au_write8(Adapter, REG_RD_CTRL, 0xFF); - rtl8723au_write16(Adapter, REG_RD_NAV_NXT, 0x200); - rtl8723au_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05); -} - -static void _InitRetryFunction(struct rtw_adapter *Adapter) -{ - u8 value8; - - value8 = rtl8723au_read8(Adapter, REG_FWHW_TXQ_CTRL); - value8 |= EN_AMPDU_RTY_NEW; - rtl8723au_write8(Adapter, REG_FWHW_TXQ_CTRL, value8); - - /* Set ACK timeout */ - rtl8723au_write8(Adapter, REG_ACKTO, 0x40); -} - -static void _InitRFType(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - pHalData->rf_type = RF_1T1R; -} - -/* Set CCK and OFDM Block "ON" */ -static void _BBTurnOnBlock(struct rtw_adapter *Adapter) -{ - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1); - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1); -} - -#define MgntActSet_RF_State(...) -static void _RfPowerSave(struct rtw_adapter *padapter) -{ -} - -enum { - Antenna_Lfet = 1, - Antenna_Right = 2, -}; - -enum rt_rf_power_state RfOnOffDetect23a(struct rtw_adapter *pAdapter) -{ - /* struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); */ - u8 val8; - enum rt_rf_power_state rfpowerstate = rf_off; - - rtl8723au_write8(pAdapter, REG_MAC_PINMUX_CFG, - rtl8723au_read8(pAdapter, - REG_MAC_PINMUX_CFG) & ~BIT(3)); - val8 = rtl8723au_read8(pAdapter, REG_GPIO_IO_SEL); - DBG_8723A("GPIO_IN =%02x\n", val8); - rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off; - - return rfpowerstate; -} - -int rtl8723au_hal_init(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u8 val8 = 0; - u32 boundary; - int status = _SUCCESS; - bool mac_on; - - unsigned long init_start_time = jiffies; - - Adapter->hw_init_completed = false; - - if (Adapter->pwrctrlpriv.bkeepfwalive) { - phy_SsPwrSwitch92CU(Adapter, rf_on); - - if (pHalData->bIQKInitialized) { - rtl8723a_phy_iq_calibrate(Adapter, true); - } else { - rtl8723a_phy_iq_calibrate(Adapter, false); - pHalData->bIQKInitialized = true; - } - rtl8723a_odm_check_tx_power_tracking(Adapter); - rtl8723a_phy_lc_calibrate(Adapter); - - goto exit; - } - - /* Check if MAC has already power on. by tynli. 2011.05.27. */ - val8 = rtl8723au_read8(Adapter, REG_CR); - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "%s: REG_CR 0x100 = 0x%02x\n", __func__, val8); - /* Fix 92DU-VC S3 hang with the reason is that secondary mac is not - initialized. */ - /* 0x100 value of first mac is 0xEA while 0x100 value of secondary - is 0x00 */ - if (val8 == 0xEA) { - mac_on = false; - } else { - mac_on = true; - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "%s: MAC has already power on\n", __func__); - } - - status = _InitPowerOn(Adapter); - if (status == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "Failed to init power on!\n"); - goto exit; - } - - if (!pregistrypriv->wifi_spec) { - boundary = TX_PAGE_BOUNDARY; - } else { - /* for WMM */ - boundary = WMM_NORMAL_TX_PAGE_BOUNDARY; - } - - if (!mac_on) { - status = InitLLTTable23a(Adapter, boundary); - if (status == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "Failed to init LLT table\n"); - goto exit; - } - } - - if (pHalData->bRDGEnable) - _InitRDGSetting(Adapter); - - status = rtl8723a_FirmwareDownload(Adapter); - if (status != _SUCCESS) { - Adapter->bFWReady = false; - DBG_8723A("fw download fail!\n"); - goto exit; - } else { - Adapter->bFWReady = true; - DBG_8723A("fw download ok!\n"); - } - - rtl8723a_InitializeFirmwareVars(Adapter); - - if (pwrctrlpriv->reg_rfoff == true) { - pwrctrlpriv->rf_pwrstate = rf_off; - } - - /* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */ - /* HW GPIO pin. Before PHY_RFConfig8192C. */ - /* HalDetectPwrDownMode(Adapter); */ - /* 2010/08/26 MH If Efuse does not support sective suspend then disable the function. */ - /* HalDetectSelectiveSuspendMode(Adapter); */ - - /* Set RF type for BB/RF configuration */ - _InitRFType(Adapter);/* _ReadRFType() */ - - /* Save target channel */ - /* Current Channel will be updated again later. */ - pHalData->CurrentChannel = 6;/* default set to 6 */ - - status = PHY_MACConfig8723A(Adapter); - if (status == _FAIL) { - DBG_8723A("PHY_MACConfig8723A fault !!\n"); - goto exit; - } - - /* */ - /* d. Initialize BB related configurations. */ - /* */ - status = PHY_BBConfig8723A(Adapter); - if (status == _FAIL) { - DBG_8723A("PHY_BBConfig8723A fault !!\n"); - goto exit; - } - - /* Add for tx power by rate fine tune. We need to call the function after BB config. */ - /* Because the tx power by rate table is inited in BB config. */ - - status = PHY_RF6052_Config8723A(Adapter); - if (status == _FAIL) { - DBG_8723A("PHY_RF6052_Config8723A failed!!\n"); - goto exit; - } - - /* reducing 80M spur */ - rtl8723au_write32(Adapter, REG_AFE_XTAL_CTRL, 0x0381808d); - rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff83); - rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff82); - rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff83); - - /* RFSW Control */ - /* 0x804[14]= 0 */ - rtl8723au_write32(Adapter, rFPGA0_TxInfo, 0x00000003); - /* 0x870[6:5]= b'11 */ - rtl8723au_write32(Adapter, rFPGA0_XAB_RFInterfaceSW, 0x07000760); - /* 0x860[6:5]= b'00 */ - rtl8723au_write32(Adapter, rFPGA0_XA_RFInterfaceOE, 0x66F60210); - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "%s: 0x870 = value 0x%x\n", __func__, - rtl8723au_read32(Adapter, 0x870)); - - /* */ - /* Joseph Note: Keep RfRegChnlVal for later use. */ - /* */ - pHalData->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, RF_PATH_A, - RF_CHNLBW, bRFRegOffsetMask); - pHalData->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, RF_PATH_B, - RF_CHNLBW, bRFRegOffsetMask); - - if (!mac_on) { - _InitQueueReservedPage(Adapter); - _InitTxBufferBoundary(Adapter); - } - _InitQueuePriority(Adapter); - _InitPageBoundary(Adapter); - _InitTransferPageSize(Adapter); - - /* Get Rx PHY status in order to report RSSI and others. */ - _InitDriverInfoSize(Adapter, DRVINFO_SZ); - - _InitInterrupt(Adapter); - hw_var_set_macaddr(Adapter, Adapter->eeprompriv.mac_addr); - rtl8723a_set_media_status(Adapter, MSR_INFRA); - _InitWMACSetting(Adapter); - _InitAdaptiveCtrl(Adapter); - _InitEDCA(Adapter); - _InitRateFallback(Adapter); - _InitRetryFunction(Adapter); - rtl8723a_InitBeaconParameters(Adapter); - - _BBTurnOnBlock(Adapter); - /* NicIFSetMacAddress(padapter, padapter->PermanentAddress); */ - - rtl8723a_cam_invalidate_all(Adapter); - - /* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */ - PHY_SetTxPowerLevel8723A(Adapter, pHalData->CurrentChannel); - - rtl8723a_InitAntenna_Selection(Adapter); - - /* HW SEQ CTRL */ - /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */ - rtl8723au_write8(Adapter, REG_HWSEQ_CTRL, 0xFF); - - /* */ - /* Disable BAR, suggested by Scott */ - /* 2010.04.09 add by hpfan */ - /* */ - rtl8723au_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff); - - if (pregistrypriv->wifi_spec) - rtl8723au_write16(Adapter, REG_FAST_EDCA_CTRL, 0); - - /* Move by Neo for USB SS from above setp */ - _RfPowerSave(Adapter); - - /* 2010/08/26 MH Merge from 8192CE. */ - /* sherry masked that it has been done in _RfPowerSave */ - /* 20110927 */ - /* recovery for 8192cu and 9723Au 20111017 */ - if (pwrctrlpriv->rf_pwrstate == rf_on) { - if (pHalData->bIQKInitialized) { - rtl8723a_phy_iq_calibrate(Adapter, true); - } else { - rtl8723a_phy_iq_calibrate(Adapter, false); - pHalData->bIQKInitialized = true; - } - - rtl8723a_odm_check_tx_power_tracking(Adapter); - - rtl8723a_phy_lc_calibrate(Adapter); - - rtl8723a_dual_antenna_detection(Adapter); - } - - /* fixed USB interface interference issue */ - rtl8723au_write8(Adapter, 0xfe40, 0xe0); - rtl8723au_write8(Adapter, 0xfe41, 0x8d); - rtl8723au_write8(Adapter, 0xfe42, 0x80); - rtl8723au_write32(Adapter, 0x20c, 0xfd0320); - /* Solve too many protocol error on USB bus */ - if (!IS_81xxC_VENDOR_UMC_A_CUT(pHalData->VersionID)) { - /* 0xE6 = 0x94 */ - rtl8723au_write8(Adapter, 0xFE40, 0xE6); - rtl8723au_write8(Adapter, 0xFE41, 0x94); - rtl8723au_write8(Adapter, 0xFE42, 0x80); - - /* 0xE0 = 0x19 */ - rtl8723au_write8(Adapter, 0xFE40, 0xE0); - rtl8723au_write8(Adapter, 0xFE41, 0x19); - rtl8723au_write8(Adapter, 0xFE42, 0x80); - - /* 0xE5 = 0x91 */ - rtl8723au_write8(Adapter, 0xFE40, 0xE5); - rtl8723au_write8(Adapter, 0xFE41, 0x91); - rtl8723au_write8(Adapter, 0xFE42, 0x80); - - /* 0xE2 = 0x81 */ - rtl8723au_write8(Adapter, 0xFE40, 0xE2); - rtl8723au_write8(Adapter, 0xFE41, 0x81); - rtl8723au_write8(Adapter, 0xFE42, 0x80); - - } - -/* _InitPABias(Adapter); */ - - /* Init BT hw config. */ - rtl8723a_BT_init_hwconfig(Adapter); - - rtl8723a_InitHalDm(Adapter); - - val8 = DIV_ROUND_UP(WiFiNavUpperUs, HAL_8723A_NAV_UPPER_UNIT); - rtl8723au_write8(Adapter, REG_NAV_UPPER, val8); - - /* 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, but we need to fin root cause. */ - if (((rtl8723au_read32(Adapter, rFPGA0_RFMOD) & 0xFF000000) != - 0x83000000)) { - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(24), 1); - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "%s: IQK fail recover\n", __func__); - } - - /* ack for xmit mgmt frames. */ - rtl8723au_write32(Adapter, REG_FWHW_TXQ_CTRL, - rtl8723au_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12)); - -exit: - if (status == _SUCCESS) { - Adapter->hw_init_completed = true; - - if (Adapter->registrypriv.notch_filter == 1) - rtl8723a_notch_filter(Adapter, 1); - } - - DBG_8723A("%s in %dms\n", __func__, - jiffies_to_msecs(jiffies - init_start_time)); - return status; -} - -static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter, - enum rt_rf_power_state eRFPowerState) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 sps0; - - sps0 = rtl8723au_read8(Adapter, REG_SPS0_CTRL); - - switch (eRFPowerState) { - case rf_on: - /* 1. Enable MAC Clock. Can not be enabled now. */ - /* WriteXBYTE(REG_SYS_CLKR+1, - ReadXBYTE(REG_SYS_CLKR+1) | BIT(3)); */ - - /* 2. Force PWM, Enable SPS18_LDO_Marco_Block */ - rtl8723au_write8(Adapter, REG_SPS0_CTRL, - sps0 | BIT(0) | BIT(3)); - - /* 3. restore BB, AFE control register. */ - /* RF */ - if (pHalData->rf_type == RF_2T2R) - PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, - 0x380038, 1); - else - PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, - 0x38, 1); - PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 1); - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(1), 0); - - /* AFE */ - if (pHalData->rf_type == RF_2T2R) - rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x63DB25A0); - else if (pHalData->rf_type == RF_1T1R) - rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x631B25A0); - - /* 4. issue 3-wire command that RF set to Rx idle - mode. This is used to re-write the RX idle mode. */ - /* We can only prvide a usual value instead and then - HW will modify the value by itself. */ - PHY_SetRFReg(Adapter, RF_PATH_A, RF_AC, - bRFRegOffsetMask, 0x32D95); - if (pHalData->rf_type == RF_2T2R) { - PHY_SetRFReg(Adapter, RF_PATH_B, RF_AC, - bRFRegOffsetMask, 0x32D95); - } - break; - case rf_sleep: - case rf_off: - if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)) - sps0 &= ~BIT(0); - else - sps0 &= ~(BIT(0) | BIT(3)); - - RT_TRACE(_module_hal_init_c_, _drv_err_, "SS LVL1\n"); - /* Disable RF and BB only for SelectSuspend. */ - - /* 1. Set BB/RF to shutdown. */ - /* (1) Reg878[5:3]= 0 RF rx_code for - preamble power saving */ - /* (2)Reg878[21:19]= 0 Turn off RF-B */ - /* (3) RegC04[7:4]= 0 Turn off all paths - for packet detection */ - /* (4) Reg800[1] = 1 enable preamble power saving */ - Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF0] = - rtl8723au_read32(Adapter, rFPGA0_XAB_RFParameter); - Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF1] = - rtl8723au_read32(Adapter, rOFDM0_TRxPathEnable); - Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF2] = - rtl8723au_read32(Adapter, rFPGA0_RFMOD); - if (pHalData->rf_type == RF_2T2R) - PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, - 0x380038, 0); - else if (pHalData->rf_type == RF_1T1R) - PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, 0x38, 0); - PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 0); - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(1), 1); - - /* 2 .AFE control register to power down. bit[30:22] */ - Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_AFE0] = - rtl8723au_read32(Adapter, rRx_Wait_CCA); - if (pHalData->rf_type == RF_2T2R) - rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x00DB25A0); - else if (pHalData->rf_type == RF_1T1R) - rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x001B25A0); - - /* 3. issue 3-wire command that RF set to power down.*/ - PHY_SetRFReg(Adapter, RF_PATH_A, RF_AC, bRFRegOffsetMask, 0); - if (pHalData->rf_type == RF_2T2R) - PHY_SetRFReg(Adapter, RF_PATH_B, RF_AC, - bRFRegOffsetMask, 0); - - /* 4. Force PFM , disable SPS18_LDO_Marco_Block */ - rtl8723au_write8(Adapter, REG_SPS0_CTRL, sps0); - break; - default: - break; - } -} - -static void CardDisableRTL8723U(struct rtw_adapter *Adapter) -{ - u8 u1bTmp; - - DBG_8723A("CardDisableRTL8723U\n"); - /* USB-MF Card Disable Flow */ - /* 1. Run LPS WL RFOFF flow */ - HalPwrSeqCmdParsing23a(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_USB_MSK, rtl8723AU_enter_lps_flow); - - /* 2. 0x1F[7:0] = 0 turn off RF */ - rtl8723au_write8(Adapter, REG_RF_CTRL, 0x00); - - /* ==== Reset digital sequence ====== */ - if ((rtl8723au_read8(Adapter, REG_MCUFWDL) & BIT(7)) && - Adapter->bFWReady) /* 8051 RAM code */ - rtl8723a_FirmwareSelfReset(Adapter); - - /* Reset MCU. Suggested by Filen. 2011.01.26. by tynli. */ - u1bTmp = rtl8723au_read8(Adapter, REG_SYS_FUNC_EN+1); - rtl8723au_write8(Adapter, REG_SYS_FUNC_EN+1, u1bTmp & ~BIT(2)); - - /* g. MCUFWDL 0x80[1:0]= 0 reset MCU ready status */ - rtl8723au_write8(Adapter, REG_MCUFWDL, 0x00); - - /* ==== Reset digital sequence end ====== */ - /* Card disable power action flow */ - HalPwrSeqCmdParsing23a(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_USB_MSK, - rtl8723AU_card_disable_flow); - - /* Reset MCU IO Wrapper, added by Roger, 2011.08.30. */ - u1bTmp = rtl8723au_read8(Adapter, REG_RSV_CTRL + 1); - rtl8723au_write8(Adapter, REG_RSV_CTRL+1, u1bTmp & ~BIT(0)); - u1bTmp = rtl8723au_read8(Adapter, REG_RSV_CTRL + 1); - rtl8723au_write8(Adapter, REG_RSV_CTRL+1, u1bTmp | BIT(0)); - - /* 7. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */ - rtl8723au_write8(Adapter, REG_RSV_CTRL, 0x0e); -} - -int rtl8723au_hal_deinit(struct rtw_adapter *padapter) -{ - DBG_8723A("==> %s\n", __func__); - -#ifdef CONFIG_8723AU_BT_COEXIST - BT_HaltProcess(padapter); -#endif - /* 2011/02/18 To Fix RU LNA power leakage problem. We need to - execute below below in Adapter init and halt sequence. - According to EEchou's opinion, we can enable the ability for all */ - /* IC. Accord to johnny's opinion, only RU need the support. */ - CardDisableRTL8723U(padapter); - - padapter->hw_init_completed = false; - - return _SUCCESS; -} - -int rtl8723au_inirp_init(struct rtw_adapter *Adapter) -{ - u8 i; - struct recv_buf *precvbuf; - int status; - struct recv_priv *precvpriv = &Adapter->recvpriv; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - status = _SUCCESS; - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "===> usb_inirp_init\n"); - - /* issue Rx irp to receive data */ - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - for (i = 0; i < NR_RECVBUFF; i++) { - if (rtl8723au_read_port(Adapter, 0, precvbuf) == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "usb_rx_init: usb_read_port error\n"); - status = _FAIL; - goto exit; - } - precvbuf++; - } - if (rtl8723au_read_interrupt(Adapter) == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "%s: usb_read_interrupt error\n", __func__); - status = _FAIL; - } - pHalData->IntrMask[0] = rtl8723au_read32(Adapter, REG_USB_HIMR); - MSG_8723A("pHalData->IntrMask = 0x%04x\n", pHalData->IntrMask[0]); - pHalData->IntrMask[0] |= UHIMR_C2HCMD|UHIMR_CPWM; - rtl8723au_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]); -exit: - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "<=== usb_inirp_init\n"); - return status; -} - -int rtl8723au_inirp_deinit(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "===> usb_rx_deinit\n"); - rtl8723au_read_port_cancel(Adapter); - pHalData->IntrMask[0] = rtl8723au_read32(Adapter, REG_USB_HIMR); - MSG_8723A("%s pHalData->IntrMask = 0x%04x\n", __func__, - pHalData->IntrMask[0]); - pHalData->IntrMask[0] = 0x0; - rtl8723au_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]); - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "<=== usb_rx_deinit\n"); - return _SUCCESS; -} - -static void _ReadBoardType(struct rtw_adapter *Adapter, u8 *PROMContent, - bool AutoloadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 boardType = BOARD_USB_DONGLE; - - if (AutoloadFail) { - if (IS_8723_SERIES(pHalData->VersionID)) - pHalData->rf_type = RF_1T1R; - else - pHalData->rf_type = RF_2T2R; - pHalData->BoardType = boardType; - return; - } - - boardType = PROMContent[EEPROM_NORMAL_BoardType]; - boardType &= BOARD_TYPE_NORMAL_MASK;/* bit[7:5] */ - boardType >>= 5; - - pHalData->BoardType = boardType; - MSG_8723A("_ReadBoardType(%x)\n", pHalData->BoardType); - - if (boardType == BOARD_USB_High_PA) - pHalData->ExternalPA = 1; -} - -static void Hal_EfuseParseMACAddr_8723AU(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - u16 i; - u8 sMacAddr[ETH_ALEN] = {0x00, 0xE0, 0x4C, 0x87, 0x23, 0x00}; - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); - - if (AutoLoadFail) { - for (i = 0; i < 6; i++) - pEEPROM->mac_addr[i] = sMacAddr[i]; - } else { - /* Read Permanent MAC address */ - memcpy(pEEPROM->mac_addr, &hwinfo[EEPROM_MAC_ADDR_8723AU], - ETH_ALEN); - } - - RT_TRACE(_module_hci_hal_init_c_, _drv_notice_, - "Hal_EfuseParseMACAddr_8723AU: Permanent Address =%pM\n", - pEEPROM->mac_addr); -} - -static void readAdapterInfo(struct rtw_adapter *padapter) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); - /* struct hal_data_8723a * pHalData = GET_HAL_DATA(padapter); */ - u8 hwinfo[HWSET_MAX_SIZE]; - - Hal_InitPGData(padapter, hwinfo); - Hal_EfuseParseIDCode(padapter, hwinfo); - Hal_EfuseParseEEPROMVer(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParseMACAddr_8723AU(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParsetxpowerinfo_8723A(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - _ReadBoardType(padapter, hwinfo, pEEPROM->bautoload_fail_flag); - Hal_EfuseParseBTCoexistInfo_8723A(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - - rtl8723a_EfuseParseChnlPlan(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParseThermalMeter_8723A(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); -/* _ReadRFSetting(Adapter, PROMContent, pEEPROM->bautoload_fail_flag); */ -/* _ReadPSSetting(Adapter, PROMContent, pEEPROM->bautoload_fail_flag); */ - Hal_EfuseParseAntennaDiversity(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - - Hal_EfuseParseEEPROMVer(padapter, hwinfo, pEEPROM->bautoload_fail_flag); - Hal_EfuseParseCustomerID(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParseRateIndicationOption(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParseXtal_8723A(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - - /* hal_CustomizedBehavior_8723U(Adapter); */ - -/* Adapter->bDongle = (PROMContent[EEPROM_EASY_REPLACEMENT] == 1)? 0: 1; */ - DBG_8723A("%s(): REPLACEMENT = %x\n", __func__, padapter->bDongle); -} - -static void _ReadPROMContent(struct rtw_adapter *Adapter) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter); - u8 eeValue; - - eeValue = rtl8723au_read8(Adapter, REG_9346CR); - /* To check system boot selection. */ - pEEPROM->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false; - pEEPROM->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true; - - DBG_8723A("Boot from %s, Autoload %s !\n", - (pEEPROM->EepromOrEfuse ? "EEPROM" : "EFUSE"), - (pEEPROM->bautoload_fail_flag ? "Fail" : "OK")); - - readAdapterInfo(Adapter); -} - -/* */ -/* Description: */ -/* We should set Efuse cell selection to WiFi cell in default. */ -/* */ -/* Assumption: */ -/* PASSIVE_LEVEL */ -/* */ -/* Added by Roger, 2010.11.23. */ -/* */ -static void hal_EfuseCellSel(struct rtw_adapter *Adapter) -{ - u32 value32; - - value32 = rtl8723au_read32(Adapter, EFUSE_TEST); - value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0); - rtl8723au_write32(Adapter, EFUSE_TEST, value32); -} - -void rtl8723a_read_adapter_info(struct rtw_adapter *Adapter) -{ - unsigned long start = jiffies; - - /* Read EEPROM size before call any EEPROM function */ - Adapter->EepromAddressSize = GetEEPROMSize8723A(Adapter); - - MSG_8723A("====> _ReadAdapterInfo8723AU\n"); - - hal_EfuseCellSel(Adapter); - - _ReadPROMContent(Adapter); - - MSG_8723A("<==== _ReadAdapterInfo8723AU in %d ms\n", - jiffies_to_msecs(jiffies - start)); -} - -/* */ -/* Description: */ -/* Query setting of specified variable. */ -/* */ -int GetHalDefVar8192CUsb(struct rtw_adapter *Adapter, - enum hal_def_variable eVariable, void *pValue) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - int bResult = _SUCCESS; - - switch (eVariable) { - case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB: - *((int *)pValue) = pHalData->dmpriv.UndecoratedSmoothedPWDB; - break; - case HAL_DEF_IS_SUPPORT_ANT_DIV: - break; - case HAL_DEF_CURRENT_ANTENNA: - break; - case HAL_DEF_DRVINFO_SZ: - *((u32 *)pValue) = DRVINFO_SZ; - break; - case HAL_DEF_MAX_RECVBUF_SZ: - *((u32 *)pValue) = MAX_RECVBUF_SZ; - break; - case HAL_DEF_RX_PACKET_OFFSET: - *((u32 *)pValue) = RXDESC_SIZE + DRVINFO_SZ; - break; - case HAL_DEF_DBG_DUMP_RXPKT: - *((u8 *)pValue) = pHalData->bDumpRxPkt; - break; - case HAL_DEF_DBG_DM_FUNC: - *((u32 *)pValue) = pHalData->odmpriv.SupportAbility; - break; - case HW_VAR_MAX_RX_AMPDU_FACTOR: - *((u32 *)pValue) = IEEE80211_HT_MAX_AMPDU_64K; - break; - case HW_DEF_ODM_DBG_FLAG: - { - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - printk("pDM_Odm->DebugComponents = 0x%llx\n", - pDM_Odm->DebugComponents); - } - break; - default: - bResult = _FAIL; - break; - } - - return bResult; -} - -void rtl8723a_update_ramask(struct rtw_adapter *padapter, - u32 mac_id, u8 rssi_level) -{ - struct sta_info *psta; - struct FW_Sta_Info *fw_sta; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - u8 init_rate, networkType, raid, arg; - u32 mask, rate_bitmap; - u8 shortGIrate = false; - int supportRateNum; - - if (mac_id >= NUM_STA) /* CAM_SIZE */ - return; - - psta = pmlmeinfo->FW_sta_info[mac_id].psta; - if (psta == NULL) - return; - - switch (mac_id) { - case 0:/* for infra mode */ - supportRateNum = - rtw_get_rateset_len23a(cur_network->SupportedRates); - networkType = judge_network_type23a(padapter, - cur_network->SupportedRates, - supportRateNum) & 0xf; - /* pmlmeext->cur_wireless_mode = networkType; */ - raid = networktype_to_raid23a(networkType); - - mask = update_supported_rate23a(cur_network->SupportedRates, - supportRateNum); - mask |= (pmlmeinfo->HT_enable) ? - update_MSC_rate23a(&pmlmeinfo->ht_cap) : 0; - - if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap)) - shortGIrate = true; - break; - - case 1:/* for broadcast/multicast */ - fw_sta = &pmlmeinfo->FW_sta_info[mac_id]; - supportRateNum = rtw_get_rateset_len23a(fw_sta->SupportedRates); - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - networkType = WIRELESS_11B; - else - networkType = WIRELESS_11G; - raid = networktype_to_raid23a(networkType); - - mask = update_basic_rate23a(cur_network->SupportedRates, - supportRateNum); - break; - - default: /* for each sta in IBSS */ - fw_sta = &pmlmeinfo->FW_sta_info[mac_id]; - supportRateNum = rtw_get_rateset_len23a(fw_sta->SupportedRates); - networkType = judge_network_type23a(padapter, - fw_sta->SupportedRates, - supportRateNum) & 0xf; - /* pmlmeext->cur_wireless_mode = networkType; */ - raid = networktype_to_raid23a(networkType); - - mask = update_supported_rate23a(cur_network->SupportedRates, - supportRateNum); - - /* todo: support HT in IBSS */ - break; - } - - /* mask &= 0x0fffffff; */ - rate_bitmap = ODM_Get_Rate_Bitmap23a(pHalData, mac_id, mask, - rssi_level); - DBG_8723A("%s => mac_id:%d, networkType:0x%02x, " - "mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n", - __func__, mac_id, networkType, mask, rssi_level, rate_bitmap); - - mask &= rate_bitmap; - mask |= ((raid << 28) & 0xf0000000); - - init_rate = get_highest_rate_idx23a(mask) & 0x3f; - - arg = mac_id & 0x1f;/* MACID */ - arg |= BIT(7); - - if (shortGIrate == true) - arg |= BIT(5); - - DBG_8723A("update raid entry, mask = 0x%x, arg = 0x%x\n", mask, arg); - - rtl8723a_set_raid_cmd(padapter, mask, arg); - - /* set ra_id */ - psta->raid = raid; - psta->init_rate = init_rate; - - /* set correct initial date rate for each mac_id */ - pdmpriv->INIDATA_RATE[mac_id] = init_rate; -} diff --git a/drivers/staging/rtl8723au/hal/usb_ops_linux.c b/drivers/staging/rtl8723au/hal/usb_ops_linux.c deleted file mode 100644 index 5c81ff48252e..000000000000 --- a/drivers/staging/rtl8723au/hal/usb_ops_linux.c +++ /dev/null @@ -1,690 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _HCI_OPS_OS_C_ - -#include -#include -#include -#include -#include -#include -#include - -u8 rtl8723au_read8(struct rtw_adapter *padapter, u16 addr) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int len; - u8 data; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ, - addr, 0, &pdvobjpriv->usb_buf.val8, sizeof(data), - RTW_USB_CONTROL_MSG_TIMEOUT); - - data = pdvobjpriv->usb_buf.val8; - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - - return data; -} - -u16 rtl8723au_read16(struct rtw_adapter *padapter, u16 addr) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int len; - u16 data; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ, - addr, 0, &pdvobjpriv->usb_buf.val16, sizeof(data), - RTW_USB_CONTROL_MSG_TIMEOUT); - - data = le16_to_cpu(pdvobjpriv->usb_buf.val16); - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - - return data; -} - -u32 rtl8723au_read32(struct rtw_adapter *padapter, u16 addr) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int len; - u32 data; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ, - addr, 0, &pdvobjpriv->usb_buf.val32, sizeof(data), - RTW_USB_CONTROL_MSG_TIMEOUT); - - data = le32_to_cpu(pdvobjpriv->usb_buf.val32); - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - - return data; -} - -int rtl8723au_write8(struct rtw_adapter *padapter, u16 addr, u8 val) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int ret; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - pdvobjpriv->usb_buf.val8 = val; - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, - addr, 0, &pdvobjpriv->usb_buf.val8, sizeof(val), - RTW_USB_CONTROL_MSG_TIMEOUT); - - if (ret != sizeof(val)) - ret = _FAIL; - else - ret = _SUCCESS; - - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - return ret; -} - -int rtl8723au_write16(struct rtw_adapter *padapter, u16 addr, u16 val) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int ret; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - pdvobjpriv->usb_buf.val16 = cpu_to_le16(val); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, - addr, 0, &pdvobjpriv->usb_buf.val16, sizeof(val), - RTW_USB_CONTROL_MSG_TIMEOUT); - - if (ret != sizeof(val)) - ret = _FAIL; - else - ret = _SUCCESS; - - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - return ret; -} - -int rtl8723au_write32(struct rtw_adapter *padapter, u16 addr, u32 val) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int ret; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - pdvobjpriv->usb_buf.val32 = cpu_to_le32(val); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, - addr, 0, &pdvobjpriv->usb_buf.val32, sizeof(val), - RTW_USB_CONTROL_MSG_TIMEOUT); - - if (ret != sizeof(val)) - ret = _FAIL; - else - ret = _SUCCESS; - - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - return ret; -} - -int rtl8723au_writeN(struct rtw_adapter *padapter, u16 addr, u16 len, u8 *buf) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int ret; - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, - addr, 0, buf, len, RTW_USB_CONTROL_MSG_TIMEOUT); - - if (ret != len) - return _FAIL; - return _SUCCESS; -} - -/* - * Description: - * Recognize the interrupt content by reading the interrupt - * register or content and masking interrupt mask (IMR) - * if it is our NIC's interrupt. After recognizing, we may clear - * the all interrupts (ISR). - * Arguments: - * [in] Adapter - - * The adapter context. - * [in] pContent - - * Under PCI interface, this field is ignord. - * Under USB interface, the content is the interrupt - * content pointer. - * Under SDIO interface, this is the interrupt type which - * is Local interrupt or system interrupt. - * [in] ContentLen - - * The length in byte of pContent. - * Return: - * If any interrupt matches the mask (IMR), return true, and - * return false otherwise. - */ -static bool -InterruptRecognized8723AU(struct rtw_adapter *Adapter, void *pContent, - u32 ContentLen) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 *buffer = (u8 *)pContent; - struct reportpwrstate_parm report; - - memcpy(&pHalData->IntArray[0], &buffer[USB_INTR_CONTENT_HISR_OFFSET], - 4); - pHalData->IntArray[0] &= pHalData->IntrMask[0]; - - /* For HISR extension. Added by tynli. 2009.10.07. */ - memcpy(&pHalData->IntArray[1], - &buffer[USB_INTR_CONTENT_HISRE_OFFSET], 4); - pHalData->IntArray[1] &= pHalData->IntrMask[1]; - - /* We sholud remove this function later because DDK suggest - * not to executing too many operations in MPISR */ - - memcpy(&report.state, &buffer[USB_INTR_CPWM_OFFSET], 1); - - return (pHalData->IntArray[0] & pHalData->IntrMask[0]) != 0 || - (pHalData->IntArray[1] & pHalData->IntrMask[1]) != 0; -} - -static void usb_read_interrupt_complete(struct urb *purb) -{ - int err; - struct rtw_adapter *padapter = (struct rtw_adapter *)purb->context; - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped || - padapter->bReadPortCancel) { - DBG_8723A("%s() RX Warning! bDriverStopped(%d) OR " - "bSurpriseRemoved(%d) bReadPortCancel(%d)\n", - __func__, padapter->bDriverStopped, - padapter->bSurpriseRemoved, - padapter->bReadPortCancel); - return; - } - - if (purb->status == 0) { - struct c2h_evt_hdr *c2h_evt; - - c2h_evt = (struct c2h_evt_hdr *)purb->transfer_buffer; - - if (purb->actual_length > USB_INTR_CONTENT_LENGTH) { - DBG_8723A("usb_read_interrupt_complete: purb->actual_" - "length > USB_INTR_CONTENT_LENGTH\n"); - goto urb_submit; - } - - InterruptRecognized8723AU(padapter, purb->transfer_buffer, - purb->actual_length); - - if (c2h_evt_exist(c2h_evt)) { - if (c2h_id_filter_ccx_8723a(c2h_evt->id)) { - /* Handle CCX report here */ - handle_txrpt_ccx_8723a(padapter, (void *) - c2h_evt->payload); - schedule_work(&padapter->evtpriv.irq_wk); - } else { - struct evt_work *c2w; - int res; - - c2w = kmalloc(sizeof(struct evt_work), - GFP_ATOMIC); - - if (!c2w) - goto urb_submit; - - c2w->adapter = padapter; - INIT_WORK(&c2w->work, rtw_evt_work); - memcpy(c2w->u.buf, purb->transfer_buffer, 16); - - res = queue_work(padapter->evtpriv.wq, - &c2w->work); - - if (!res) { - printk(KERN_ERR "%s: Call to " - "queue_work() failed\n", - __func__); - kfree(c2w); - goto urb_submit; - } - } - } - -urb_submit: - err = usb_submit_urb(purb, GFP_ATOMIC); - if (err && (err != -EPERM)) { - DBG_8723A("cannot submit interrupt in-token(err = " - "0x%08x), urb_status = %d\n", - err, purb->status); - } - } else { - DBG_8723A("###=> usb_read_interrupt_complete => urb " - "status(%d)\n", purb->status); - - switch (purb->status) { - case -EINVAL: - case -EPIPE: - case -ENODEV: - case -ESHUTDOWN: - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bSurpriseRemoved =true\n"); - /* Fall Through here */ - case -ENOENT: - padapter->bDriverStopped = true; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bDriverStopped =true\n"); - break; - case -EPROTO: - break; - case -EINPROGRESS: - DBG_8723A("ERROR: URB IS IN PROGRESS!\n"); - break; - default: - break; - } - } -} - -int rtl8723au_read_interrupt(struct rtw_adapter *adapter) -{ - int err; - unsigned int pipe; - int ret = _SUCCESS; - struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter); - struct recv_priv *precvpriv = &adapter->recvpriv; - struct usb_device *pusbd = pdvobj->pusbdev; - - /* translate DMA FIFO addr to pipehandle */ - pipe = usb_rcvintpipe(pusbd, pdvobj->RtInPipe[1]); - - usb_fill_int_urb(precvpriv->int_in_urb, pusbd, pipe, - precvpriv->int_in_buf, USB_INTR_CONTENT_LENGTH, - usb_read_interrupt_complete, adapter, 1); - - err = usb_submit_urb(precvpriv->int_in_urb, GFP_ATOMIC); - if (err && (err != -EPERM)) { - DBG_8723A("cannot submit interrupt in-token(err = 0x%08x)," - "urb_status = %d\n", err, - precvpriv->int_in_urb->status); - ret = _FAIL; - } - - return ret; -} - -static int recvbuf2recvframe(struct rtw_adapter *padapter, struct sk_buff *pskb) -{ - u8 *pbuf; - u8 shift_sz = 0; - u16 pkt_cnt; - u32 pkt_offset, skb_len, alloc_sz; - int transfer_len; - struct recv_stat *prxstat; - struct phy_stat *pphy_info; - struct sk_buff *pkt_copy; - struct recv_frame *precvframe; - struct rx_pkt_attrib *pattrib; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct rtw_queue *pfree_recv_queue = &precvpriv->free_recv_queue; - - transfer_len = (int)pskb->len; - pbuf = pskb->data; - - prxstat = (struct recv_stat *)pbuf; - pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff; - - do { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvbuf2recvframe: rxdesc = offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n", - prxstat->rxdw0, prxstat->rxdw1, - prxstat->rxdw2, prxstat->rxdw4); - - prxstat = (struct recv_stat *)pbuf; - - precvframe = rtw_alloc_recvframe23a(pfree_recv_queue); - if (!precvframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvbuf2recvframe: precvframe == NULL\n"); - DBG_8723A("%s()-%d: rtw_alloc_recvframe23a() failed! RX " - "Drop!\n", __func__, __LINE__); - goto _exit_recvbuf2recvframe; - } - - INIT_LIST_HEAD(&precvframe->list); - - update_recvframe_attrib(precvframe, prxstat); - - pattrib = &precvframe->attrib; - - if (pattrib->crc_err) { - DBG_8723A("%s()-%d: RX Warning! rx CRC ERROR !!\n", - __func__, __LINE__); - rtw_free_recvframe23a(precvframe); - goto _exit_recvbuf2recvframe; - } - - pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + - pattrib->shift_sz + pattrib->pkt_len; - - if (pattrib->pkt_len <= 0 || pkt_offset > transfer_len) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvbuf2recvframe: pkt_len<= 0\n"); - DBG_8723A("%s()-%d: RX Warning!\n", - __func__, __LINE__); - rtw_free_recvframe23a(precvframe); - goto _exit_recvbuf2recvframe; - } - - /* Modified by Albert 20101213 */ - /* For 8 bytes IP header alignment. */ - /* Qos data, wireless lan header length is 26 */ - if (pattrib->qos) - shift_sz = 6; - else - shift_sz = 0; - - skb_len = pattrib->pkt_len; - - /* for first fragment packet, driver need allocate - * 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. - * modify alloc_sz for recvive crc error packet - * by thomas 2011-06-02 */ - if (pattrib->mfrag == 1 && pattrib->frag_num == 0) { - /* alloc_sz = 1664; 1664 is 128 alignment. */ - if (skb_len <= 1650) - alloc_sz = 1664; - else - alloc_sz = skb_len + 14; - } else { - alloc_sz = skb_len; - /* 6 is for IP header 8 bytes alignment in QoS packet case. */ - /* 8 is for skb->data 4 bytes alignment. */ - alloc_sz += 14; - } - - pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz); - if (pkt_copy) { - pkt_copy->dev = padapter->pnetdev; - precvframe->pkt = pkt_copy; - /* force pkt_copy->data at 8-byte alignment address */ - skb_reserve(pkt_copy, 8 - - ((unsigned long)(pkt_copy->data) & 7)); - /*force ip_hdr at 8-byte alignment address - according to shift_sz. */ - skb_reserve(pkt_copy, shift_sz); - memcpy(pkt_copy->data, pbuf + pattrib->shift_sz + - pattrib->drvinfo_sz + RXDESC_SIZE, skb_len); - skb_put(pkt_copy, skb_len); - } else { - if (pattrib->mfrag == 1 && pattrib->frag_num == 0) { - DBG_8723A("recvbuf2recvframe: alloc_skb fail, " - "drop frag frame \n"); - rtw_free_recvframe23a(precvframe); - goto _exit_recvbuf2recvframe; - } - - precvframe->pkt = skb_clone(pskb, GFP_ATOMIC); - if (!precvframe->pkt) { - DBG_8723A("recvbuf2recvframe: skb_clone " - "fail\n"); - rtw_free_recvframe23a(precvframe); - goto _exit_recvbuf2recvframe; - } - } - - if (pattrib->physt) { - pphy_info = (struct phy_stat *)(pbuf + RXDESC_OFFSET); - update_recvframe_phyinfo(precvframe, pphy_info); - } - - if (rtw_recv_entry23a(precvframe) != _SUCCESS) - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvbuf2recvframe: rtw_recv_entry23a(precvframe) != _SUCCESS\n"); - - pkt_cnt--; - transfer_len -= pkt_offset; - pbuf += pkt_offset; - precvframe = NULL; - pkt_copy = NULL; - - if (transfer_len > 0 && pkt_cnt == 0) - pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff; - - } while (transfer_len > 0 && pkt_cnt > 0); - -_exit_recvbuf2recvframe: - - return _SUCCESS; -} - -void rtl8723au_recv_tasklet(void *priv) -{ - struct sk_buff *pskb; - struct rtw_adapter *padapter = (struct rtw_adapter *)priv; - struct recv_priv *precvpriv = &padapter->recvpriv; - - while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) { - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { - DBG_8723A("recv_tasklet => bDriverStopped or " - "bSurpriseRemoved \n"); - dev_kfree_skb_any(pskb); - break; - } - - recvbuf2recvframe(padapter, pskb); - skb_reset_tail_pointer(pskb); - - pskb->len = 0; - - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - } -} - -static void usb_read_port_complete(struct urb *purb) -{ - struct recv_buf *precvbuf = (struct recv_buf *)purb->context; - struct rtw_adapter *padapter = (struct rtw_adapter *)precvbuf->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete!!!\n"); - - precvpriv->rx_pending_cnt--; - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped || - padapter->bReadPortCancel) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved); - - DBG_8723A("%s()-%d: RX Warning! bDriverStopped(%d) OR " - "bSurpriseRemoved(%d) bReadPortCancel(%d)\n", - __func__, __LINE__, padapter->bDriverStopped, - padapter->bSurpriseRemoved, padapter->bReadPortCancel); - return; - } - - if (purb->status == 0) { - if (purb->actual_length > MAX_RECVBUF_SZ || - purb->actual_length < RXDESC_SIZE) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n"); - rtl8723au_read_port(padapter, 0, precvbuf); - DBG_8723A("%s()-%d: RX Warning!\n", - __func__, __LINE__); - } else { - rtw_reset_continual_urb_error( - adapter_to_dvobj(padapter)); - - skb_put(precvbuf->pskb, purb->actual_length); - skb_queue_tail(&precvpriv->rx_skb_queue, - precvbuf->pskb); - - if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1) - tasklet_schedule(&precvpriv->recv_tasklet); - - precvbuf->pskb = NULL; - rtl8723au_read_port(padapter, 0, precvbuf); - } - } else { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete : purb->status(%d) != 0\n", - purb->status); - skb_put(precvbuf->pskb, purb->actual_length); - precvbuf->pskb = NULL; - - DBG_8723A("###=> usb_read_port_complete => urb status(%d)\n", - purb->status); - - if (rtw_inc_and_chk_continual_urb_error( - adapter_to_dvobj(padapter))) { - padapter->bSurpriseRemoved = true; - } - - switch (purb->status) { - case -EINVAL: - case -EPIPE: - case -ENODEV: - case -ESHUTDOWN: - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bSurpriseRemoved = true\n"); - /* Intentional fall through here */ - case -ENOENT: - padapter->bDriverStopped = true; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bDriverStopped = true\n"); - break; - case -EPROTO: - case -EOVERFLOW: - rtl8723au_read_port(padapter, 0, precvbuf); - break; - case -EINPROGRESS: - DBG_8723A("ERROR: URB IS IN PROGRESS!\n"); - break; - default: - break; - } - } -} - -int rtl8723au_read_port(struct rtw_adapter *adapter, u32 cnt, - struct recv_buf *precvbuf) -{ - struct urb *purb; - struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter); - struct recv_priv *precvpriv = &adapter->recvpriv; - struct usb_device *pusbd = pdvobj->pusbdev; - int err; - unsigned int pipe; - unsigned long tmpaddr; - unsigned long alignment; - int ret = _SUCCESS; - - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port:(padapter->bDriverStopped ||padapter->bSurpriseRemoved)!!!\n"); - return _FAIL; - } - - if (!precvbuf) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port:precvbuf == NULL\n"); - return _FAIL; - } - - if (!precvbuf->pskb) - precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); - - /* re-assign for linux based on skb */ - if (!precvbuf->pskb) { - precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); - if (precvbuf->pskb == NULL) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "init_recvbuf(): alloc_skb fail!\n"); - return _FAIL; - } - - tmpaddr = (unsigned long)precvbuf->pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); - skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); - } - - precvpriv->rx_pending_cnt++; - - purb = precvbuf->purb; - - /* translate DMA FIFO addr to pipehandle */ - pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]); - - usb_fill_bulk_urb(purb, pusbd, pipe, precvbuf->pskb->data, - MAX_RECVBUF_SZ, usb_read_port_complete, - precvbuf);/* context is precvbuf */ - - err = usb_submit_urb(purb, GFP_ATOMIC); - if ((err) && (err != -EPERM)) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "cannot submit rx in-token(err = 0x%.8x), URB_STATUS = 0x%.8x\n", - err, purb->status); - DBG_8723A("cannot submit rx in-token(err = 0x%08x), urb_status " - "= %d\n", err, purb->status); - ret = _FAIL; - } - return ret; -} - -void rtl8723au_xmit_tasklet(void *priv) -{ - int ret; - struct rtw_adapter *padapter = (struct rtw_adapter *)priv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY)) - return; - - while (1) { - if (padapter->bDriverStopped || padapter->bSurpriseRemoved || - padapter->bWritePortCancel) { - DBG_8723A("xmit_tasklet => bDriverStopped or " - "bSurpriseRemoved or bWritePortCancel\n"); - break; - } - - ret = rtl8723au_xmitframe_complete(padapter, pxmitpriv, NULL); - - if (!ret) - break; - } -} - -void rtl8723au_set_hw_type(struct rtw_adapter *padapter) -{ - padapter->chip_type = RTL8723A; - padapter->HardwareType = HARDWARE_TYPE_RTL8723AU; - DBG_8723A("CHIP TYPE: RTL8723A\n"); -} diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h deleted file mode 100644 index bcf36579f43a..000000000000 --- a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h +++ /dev/null @@ -1,162 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - * - ******************************************************************************/ -#ifndef __INC_HAL8723PHYCFG_H__ -#define __INC_HAL8723PHYCFG_H__ - -/*------------------------------Define structure----------------------------*/ -enum RF_RADIO_PATH { - RF_PATH_A = 0, /* Radio Path A */ - RF_PATH_B = 1, /* Radio Path B */ - RF_PATH_MAX /* Max RF number 90 support */ -}; - -#define CHANNEL_MAX_NUMBER 14 /* 14 is the max channel number */ - -enum WIRELESS_MODE { - WIRELESS_MODE_UNKNOWN = 0x00, - WIRELESS_MODE_A = BIT(2), - WIRELESS_MODE_B = BIT(0), - WIRELESS_MODE_G = BIT(1), - WIRELESS_MODE_AUTO = BIT(5), - WIRELESS_MODE_N_24G = BIT(3), - WIRELESS_MODE_N_5G = BIT(4), - WIRELESS_MODE_AC = BIT(6) -}; - -struct bb_reg_define { - u32 rfintfs; /* set software control: */ - /* 0x870~0x877[8 bytes] */ - u32 rfintfi; /* readback data: */ - /* 0x8e0~0x8e7[8 bytes] */ - u32 rfintfo; /* output data: */ - /* 0x860~0x86f [16 bytes] */ - u32 rfintfe; /* output enable: */ - /* 0x860~0x86f [16 bytes] */ - u32 rf3wireOffset; /* LSSI data: */ - /* 0x840~0x84f [16 bytes] */ - u32 rfLSSI_Select; /* BB Band Select: */ - /* 0x878~0x87f [8 bytes] */ - u32 rfTxGainStage; /* Tx gain stage: */ - /* 0x80c~0x80f [4 bytes] */ - u32 rfHSSIPara1; /* wire parameter control1 : */ - /* 0x820~0x823, 0x828~0x82b, 0x830~0x833, 0x838~0x83b [16 bytes] */ - u32 rfHSSIPara2; /* wire parameter control2 : */ - /* 0x824~0x827, 0x82c~0x82f, 0x834~0x837, 0x83c~0x83f [16 bytes] */ - u32 rfSwitchControl; /* Tx Rx antenna control : */ - /* 0x858~0x85f [16 bytes] */ - u32 rfAGCControl1; /* AGC parameter control1 : */ - /* 0xc50~0xc53, 0xc58~0xc5b, 0xc60~0xc63, 0xc68~0xc6b [16 bytes] */ - u32 rfAGCControl2; /* AGC parameter control2 : */ - /* 0xc54~0xc57, 0xc5c~0xc5f, 0xc64~0xc67, 0xc6c~0xc6f [16 bytes] */ - u32 rfRxIQImbalance; /* OFDM Rx IQ imbalance matrix : */ - /* 0xc14~0xc17, 0xc1c~0xc1f, 0xc24~0xc27, 0xc2c~0xc2f [16 bytes] */ - u32 rfRxAFE; /* Rx IQ DC ofset and Rx digital filter, Rx DC notch filter : */ - /* 0xc10~0xc13, 0xc18~0xc1b, 0xc20~0xc23, 0xc28~0xc2b [16 bytes] */ - u32 rfTxIQImbalance; /* OFDM Tx IQ imbalance matrix */ - /* 0xc80~0xc83, 0xc88~0xc8b, 0xc90~0xc93, 0xc98~0xc9b [16 bytes] */ - u32 rfTxAFE; /* Tx IQ DC Offset and Tx DFIR type */ - /* 0xc84~0xc87, 0xc8c~0xc8f, 0xc94~0xc97, 0xc9c~0xc9f [16 bytes] */ - u32 rfLSSIReadBack; /* LSSI RF readback data SI mode */ - /* 0x8a0~0x8af [16 bytes] */ - u32 rfLSSIReadBackPi; /* LSSI RF readback data PI mode 0x8b8-8bc for Path A and B */ -}; - -struct r_antenna_sel_ofdm { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 OFDM_TXSC:2; - u32 Reserved:2; -}; - -struct r_antenna_sel_cck { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - -/*------------------------------Define structure----------------------------*/ - - -/*------------------------Export global variable----------------------------*/ -/*------------------------Export global variable----------------------------*/ - - -/*------------------------Export Macro Definition---------------------------*/ -/*------------------------Export Macro Definition---------------------------*/ - - -/*--------------------------Exported Function prototype---------------------*/ -/* */ -/* BB and RF register read/write */ -/* */ -u32 PHY_QueryBBReg(struct rtw_adapter *Adapter, u32 RegAddr, - u32 BitMask); -void PHY_SetBBReg(struct rtw_adapter *Adapter, u32 RegAddr, - u32 BitMask, u32 Data); -u32 PHY_QueryRFReg(struct rtw_adapter *Adapter, - enum RF_RADIO_PATH eRFPath, u32 RegAddr, - u32 BitMask); -void PHY_SetRFReg(struct rtw_adapter *Adapter, - enum RF_RADIO_PATH eRFPath, u32 RegAddr, - u32 BitMask, u32 Data); - -/* */ -/* BB TX Power R/W */ -/* */ -void PHY_SetTxPowerLevel8723A(struct rtw_adapter *Adapter, u8 channel); - -/* */ -/* Switch bandwidth for 8723A */ -/* */ -void PHY_SetBWMode23a8723A(struct rtw_adapter *pAdapter, - enum ht_channel_width ChnlWidth, - unsigned char Offset); - -/* */ -/* channel switch related funciton */ -/* */ -void PHY_SwChnl8723A(struct rtw_adapter *pAdapter, u8 channel); - /* Call after initialization */ -void ChkFwCmdIoDone(struct rtw_adapter *Adapter); - -/* */ -/* Modify the value of the hw register when beacon interval be changed. */ -/* */ -void -rtl8192c_PHY_SetBeaconHwReg(struct rtw_adapter *Adapter, u16 BeaconInterval); - - -void PHY_SwitchEphyParameter(struct rtw_adapter *Adapter); - -void PHY_EnableHostClkReq(struct rtw_adapter *Adapter); - -bool -SetAntennaConfig92C(struct rtw_adapter *Adapter, u8 DefaultAnt); - -/*--------------------------Exported Function prototype---------------------*/ - -#define PHY_SetMacReg PHY_SetBBReg - -/* MAC/BB/RF HAL config */ -int PHY_BBConfig8723A(struct rtw_adapter *Adapter); -s32 PHY_MACConfig8723A(struct rtw_adapter *padapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyReg.h b/drivers/staging/rtl8723au/include/Hal8723APhyReg.h deleted file mode 100644 index 759928f78d6d..000000000000 --- a/drivers/staging/rtl8723au/include/Hal8723APhyReg.h +++ /dev/null @@ -1,1078 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - * - ******************************************************************************/ -#ifndef __INC_HAL8723APHYREG_H__ -#define __INC_HAL8723APHYREG_H__ - -/* 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 read/write command address. */ -#define RF_BB_CMD_DATA 0x02c4 /* RF/BB read/write command 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 -#define rFPGA0_XB_HSSIParameter2 0x82c -#define rTxAGC_B_Rate18_06 0x830 -#define rTxAGC_B_Rate54_24 0x834 -#define rTxAGC_B_CCK1_55_Mcs32 0x838 -#define rTxAGC_B_Mcs03_Mcs00 0x83c - -#define rTxAGC_B_Mcs07_Mcs04 0x848 -#define rTxAGC_B_Mcs11_Mcs08 0x84c - -#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 - -#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */ -#define rFPGA0_XB_RFInterfaceOE 0x864 - -#define rTxAGC_B_Mcs15_Mcs12 0x868 -#define rTxAGC_B_CCK11_A_CCK2_11 0x86c - -#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Control */ -#define rFPGA0_XCD_RFInterfaceSW 0x874 - -#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */ -#define rFPGA0_XCD_RFParameter 0x87c - -#define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting RF-R/W protection for parameter4?? */ -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 /* Useless now */ -#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 */ -#define TransceiverA_HSPI_Readback 0x8b8 /* Transceiver A HSPI Readback */ -#define TransceiverB_HSPI_Readback 0x8bc /* Transceiver B HSPI Readback */ -#define rFPGA0_XAB_RFInterfaceRB 0x8e0 /* Useless now RF Interface Readback Value */ -#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */ - -/* 4. Page9(0x900) */ -#define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC RF BW Setting?? */ - -#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. These settings are required only for 40MHz */ -#define rCCK0_System 0xa00 - -#define rCCK0_AFESetting 0xa04 /* Disable init gain now Select RX path by RSSI */ -#define rCCK0_CCA 0xa08 /* Disable init gain now Init gain */ - -#define rCCK0_RxAGC1 0xa0c /* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. Not the same as 90 series */ -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ - -#define rCCK0_RxHP 0xa14 - -#define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel estimation threshold */ -#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 0xa30-a4f channel report */ -#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 - -#define rOFDM0_XARxAFE 0xc10 /* RxIQ DC offset, Rx digital filter, DC notch filter */ -#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imblance 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) */ -#define rTxAGC_A_Rate18_06 0xe00 -#define rTxAGC_A_Rate54_24 0xe04 -#define rTxAGC_A_CCK1_Mcs32 0xe08 -#define rTxAGC_A_Mcs03_Mcs00 0xe10 -#define rTxAGC_A_Mcs07_Mcs04 0xe14 -#define rTxAGC_A_Mcs11_Mcs08 0xe18 -#define rTxAGC_A_Mcs15_Mcs12 0xe1c - -#define rFPGA0_IQK 0xe28 -#define rTx_IQK_Tone_A 0xe30 -#define rRx_IQK_Tone_A 0xe34 -#define rTx_IQK_PI_A 0xe38 -#define rRx_IQK_PI_A 0xe3c - -#define rTx_IQK 0xe40 -#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 -#define rRx_Wait_CCA 0xe70 -#define rTx_CCK_RFON 0xe74 -#define rTx_CCK_BBON 0xe78 -#define rTx_OFDM_RFON 0xe7c -#define rTx_OFDM_BBON 0xe80 -#define rTx_To_Rx 0xe84 -#define rTx_To_Tx 0xe88 -#define rRx_CCK 0xe8c - -#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 -#define rRx_Wait_RIFS 0xed4 -#define rRx_TO_Rx 0xed8 -#define rStandby 0xedc -#define rSleep 0xee0 -#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 */ - -#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_BS_PA_APSET_G1_G4 0x03 -#define RF_BS_PA_APSET_G5_G8 0x04 -#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_MODE_AG 0x18 -#define rRfChannel 0x18 /* RF channel and BW switch */ -#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 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 */ - -/* 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 /* chane 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 - -#define b3WireDataLength 0x800 /* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */ -#define b3WireAddressLength 0x400 - -#define b3WireRFPowerDown 0x1 /* Useless now */ -/* define bHWSISelect 0x8 */ -#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 - -#define bADClkPhase 0x4000000 /* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */ - -#define b80MClkDelay 0x18000000 /* Useless */ -#define bAFEWatchDogEnable 0x20000000 - -#define bXtalCap01 0xc0000000 /* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */ -#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 also 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 switch */ - -#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 bCCKRxAGCFormat 0x4000 remove to HSSI register 0x824 */ -#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 /* the threshold for high power */ -#define bRSSI_Gen 0x7f000000 /* the 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 bRxMF_Hold 0x3800 */ -#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 bRxPath1 0x01 */ -/* define bRxPath2 0x02 */ -/* define bRxPath3 0x04 */ -/* define bRxPath4 0x08 */ -/* define bTxPath1 0x10 */ -/* define bTxPath2 0x20 */ -#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 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 max debug item in each debug page */ -/* define bMaxItem_FPGA_PHY0 0x9 */ -/* define bMaxItem_FPGA_PHY1 0x3 */ -/* define bMaxItem_PHY_11B 0x16 */ -/* define bMaxItem_OFDM_PHY0 0x29 */ -/* define bMaxItem_OFDM_PHY1 0x0 */ - -#define bPMACControl 0x0 /* Useless */ -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define PathA 0x0 /* Useless */ -#define PathB 0x1 -#define PathC 0x2 -#define PathD 0x3 - -/* PageB(0xB00) */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rPdp_AntA_8 0xb08 -#define rPdp_AntA_C 0xb0c -#define rPdp_AntA_18 0xb18 -#define rPdp_AntA_1C 0xb1c -#define rPdp_AntA_20 0xb20 -#define rPdp_AntA_24 0xb24 - -#define rConfig_Pmpd_AntA 0xb28 -#define rConfig_ram64x16 0xb2c - -#define rBndA 0xb30 -#define rHssiPar 0xb34 - -#define rConfig_AntA 0xb68 -#define rConfig_AntB 0xb6c - -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rPdp_AntB_8 0xb78 -#define rPdp_AntB_C 0xb7c -#define rPdp_AntB_10 0xb80 -#define rPdp_AntB_14 0xb84 -#define rPdp_AntB_18 0xb88 -#define rPdp_AntB_1C 0xb8c -#define rPdp_AntB_20 0xb90 -#define rPdp_AntB_24 0xb94 - -#define rConfig_Pmpd_AntB 0xb98 - -#define rBndB 0xba0 - -#define rAPK 0xbd8 -#define rPm_Rx0_AntA 0xbdc -#define rPm_Rx1_AntA 0xbe0 -#define rPm_Rx2_AntA 0xbe4 -#define rPm_Rx3_AntA 0xbe8 -#define rPm_Rx0_AntB 0xbec -#define rPm_Rx1_AntB 0xbf0 -#define rPm_Rx2_AntB 0xbf4 -#define rPm_Rx3_AntB 0xbf8 - -#endif diff --git a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h deleted file mode 100644 index 3771d6bb5774..000000000000 --- a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef __HAL8723PWRSEQ_H__ -#define __HAL8723PWRSEQ_H__ -/* - Check document WM-20110607-Paul-RTL8723A_Power_Architecture-R02.vsd - There are 6 HW Power States: - 0: POFF--Power Off - 1: PDN--Power Down - 2: CARDEMU--Card Emulation - 3: ACT--Active Mode - 4: LPS--Low Power State - 5: SUS--Suspend - - The transision from different states are defined below - TRANS_CARDEMU_TO_ACT - TRANS_ACT_TO_CARDEMU - TRANS_CARDEMU_TO_SUS - TRANS_SUS_TO_CARDEMU - TRANS_CARDEMU_TO_PDN - TRANS_ACT_TO_LPS - TRANS_LPS_TO_ACT - - TRANS_END -*/ -#include "HalPwrSeqCmd.h" -#include "rtl8723a_spec.h" - -#define RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS 15 -#define RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS 15 -#define RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS 15 -#define RTL8723A_TRANS_SUS_TO_CARDEMU_STEPS 15 -#define RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS 15 -#define RTL8723A_TRANS_PDN_TO_CARDEMU_STEPS 15 -#define RTL8723A_TRANS_ACT_TO_LPS_STEPS 15 -#define RTL8723A_TRANS_LPS_TO_ACT_STEPS 15 -#define RTL8723A_TRANS_END_STEPS 1 - - -/* format - * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here - */ -#define RTL8723A_TRANS_CARDEMU_TO_ACT \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \ - {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \ - {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS},/*Delay 1ms*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), 0}, /*0x00[5] = 1b'0 release analog Ips to digital , 1:isolation*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), 0},/* disable SW LPS 0x04[10]= 0*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},/* wait till 0x04[17] = 1 power ready*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},/* release WLON reset 0x04[16]= 1*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* disable HWPDN 0x04[15]= 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0},/* disable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},/* polling until return 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0},/**/ \ - {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 1},/*0x4C[23] = 0x4E[7] = 1, switch DPDT_SEL_P output from WL BB */\ - -#define RTL8723A_TRANS_ACT_TO_CARDEMU \ - {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/ \ - {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/*0x4C[23] = 0x4E[7] = 0, switch DPDT_SEL_P output from register 0x65[2] */\ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, /*0x04[9] = 1 turn off MAC by HW state machine*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, /*0x00[5] = 1b'1 analog Ips to digital , 1:isolation*/ \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \ - - -#define RTL8723A_TRANS_CARDEMU_TO_SUS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ - -#define RTL8723A_TRANS_SUS_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ - -#define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ - -#define RTL8723A_TRANS_CARDDIS_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ - -#define RTL8723A_TRANS_CARDEMU_TO_PDN \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/\ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/ - -#define RTL8723A_TRANS_PDN_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/ - -#define RTL8723A_TRANS_ACT_TO_LPS \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},/*Tx Pause*/ \ - {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ - {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ - {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ - {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/*CCK and OFDM are disabled, and clock are gated*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*Whole BB is reset*/ \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03},/*Reset MAC TRX*/ \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/ \ - {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)},/*Respond TxOK to scheduler*/ - -#define RTL8723A_TRANS_LPS_TO_ACT \ - {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*. 0x08[4] = 0 switch TSF to 40M*/\ - {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, /*Polling 0x109[7]= 0 TSF in 40M*/\ - {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, /*. 0x29[7:6] = 2b'00 enable BB clock*/\ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, /*. 0x101[1] = 1*/\ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)}, /*. 0x02[1:0] = 2b'11 enable BB macro*/\ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/ - -#define RTL8723A_TRANS_END \ - {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, 0, PWR_CMD_END, 0, 0}, - - -extern struct wlan_pwr_cfg rtl8723AU_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS]; - -#endif diff --git a/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h b/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h deleted file mode 100644 index c834b3a738d7..000000000000 --- a/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __INC_HAL8723U_FW_IMG_H -#define __INC_HAL8723U_FW_IMG_H - -/*Created on 2013/01/14, 15:51*/ - -/* FW v16 enable usb interrupt */ -#define Rtl8723UImgArrayLength 22172 -extern u8 Rtl8723UFwImgArray[Rtl8723UImgArrayLength]; -#define Rtl8723UBTImgArrayLength 1 -extern u8 Rtl8723UFwBTImgArray[Rtl8723UBTImgArrayLength]; - -#define Rtl8723UUMCBCutImgArrayWithBTLength 24118 -#define Rtl8723UUMCBCutImgArrayWithoutBTLength 19200 - -extern u8 Rtl8723UFwUMCBCutImgArrayWithBT[Rtl8723UUMCBCutImgArrayWithBTLength]; -extern u8 Rtl8723UFwUMCBCutImgArrayWithoutBT[Rtl8723UUMCBCutImgArrayWithoutBTLength]; - -#define Rtl8723SUMCBCutMPImgArrayLength 24174 -extern const u8 Rtl8723SFwUMCBCutMPImgArray[Rtl8723SUMCBCutMPImgArrayLength]; - -#define Rtl8723EBTImgArrayLength 15276 -extern u8 Rtl8723EFwBTImgArray[Rtl8723EBTImgArrayLength]; - -#define Rtl8723UPHY_REG_Array_PGLength 336 -extern u32 Rtl8723UPHY_REG_Array_PG[Rtl8723UPHY_REG_Array_PGLength]; -#define Rtl8723UMACPHY_Array_PGLength 1 -extern u32 Rtl8723UMACPHY_Array_PG[Rtl8723UMACPHY_Array_PGLength]; - -#endif /* ifndef __INC_HAL8723U_FW_IMG_H */ diff --git a/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h b/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h deleted file mode 100644 index d7651f7a665b..000000000000 --- a/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - * - ******************************************************************************/ -#ifndef __RTL8723A_ODM_H__ -#define __RTL8723A_ODM_H__ -/* */ - -#define RSSI_CCK 0 -#define RSSI_OFDM 1 -#define RSSI_DEFAULT 2 - -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 - - -/* */ -/* structure and define */ -/* */ - - - - -/*------------------------Export global variable----------------------------*/ -/*------------------------Export global variable----------------------------*/ -/*------------------------Export Marco Definition---------------------------*/ -/* define DM_MultiSTA_InitGainChangeNotify(Event) {DM_DigTable.CurMultiSTAConnectState = Event;} */ - - -/* */ -/* function prototype */ -/* */ - -/* */ -/* IQ calibrate */ -/* */ -void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery); - -/* */ -/* LC calibrate */ -/* */ -void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter); - -/* */ -/* AP calibrate */ -/* */ -void rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta); - -void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h deleted file mode 100644 index 127609404652..000000000000 --- a/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. 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 for -* more details. -* -* -******************************************************************************/ - -#ifndef __INC_BB_8723A_HW_IMG_H -#define __INC_BB_8723A_HW_IMG_H - -/****************************************************************************** -* AGC_TAB_1T.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm); - -/****************************************************************************** -* PHY_REG_1T.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm); - -/****************************************************************************** -* PHY_REG_MP.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h deleted file mode 100644 index 7ee363b99b49..000000000000 --- a/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2012 Realtek Corporation. 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 for -* more details. -* -* -******************************************************************************/ - -#ifndef __INC_FW_8723A_HW_IMG_H -#define __INC_FW_8723A_HW_IMG_H - - -/****************************************************************************** -* rtl8723fw_B.TXT -******************************************************************************/ - -void ODM_ReadFirmware_8723A_rtl8723fw_B(struct dm_odm_t *pDM_Odm, - u8 *pFirmware, u32 *pFirmwareSize); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h deleted file mode 100644 index 201be1f87292..000000000000 --- a/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. 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 for -* more details. -* -* -******************************************************************************/ - -#ifndef __INC_MAC_8723A_HW_IMG_H -#define __INC_MAC_8723A_HW_IMG_H - -/****************************************************************************** -* MAC_REG.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h deleted file mode 100644 index c9af1c375339..000000000000 --- a/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. 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 for -* more details. -* -******************************************************************************/ - -#ifndef __INC_RF_8723A_HW_IMG_H -#define __INC_RF_8723A_HW_IMG_H - -/****************************************************************************** -* RadioA_1T.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *pDM_Odm); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h b/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h deleted file mode 100644 index 12e03a36f2d3..000000000000 --- a/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h +++ /dev/null @@ -1,130 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - * - ******************************************************************************/ -#ifndef __HALPWRSEQCMD_H__ -#define __HALPWRSEQCMD_H__ - -#include - -/*---------------------------------------------*/ -/*---------------------------------------------*/ -#define PWR_CMD_READ 0x00 - /* offset: the read register offset */ - /* msk: the mask of the read value */ - /* value: N/A, left by 0 */ - /* note: dirver shall implement this function by read & msk */ - -#define PWR_CMD_WRITE 0x01 - /* offset: the read register offset */ - /* msk: the mask of the write bits */ - /* value: write value */ - /* note: driver shall implement this cmd by read & msk after write */ - -#define PWR_CMD_POLLING 0x02 - /* offset: the read register offset */ - /* msk: the mask of the polled value */ - /* value: the value to be polled, masked by the msd field. */ - /* note: driver shall implement this cmd by */ - /* do{ */ - /* if( (Read(offset) & msk) == (value & msk) ) */ - /* break; */ - /* } while(not timeout); */ - -#define PWR_CMD_DELAY 0x03 - /* offset: the value to delay */ - /* msk: N/A */ - /* value: the unit of delay, 0: us, 1: ms */ - -#define PWR_CMD_END 0x04 - /* offset: N/A */ - /* msk: N/A */ - /* value: N/A */ - -/*---------------------------------------------*/ -/* 3 The value of base: 4 bits */ -/*---------------------------------------------*/ - /* define the base address of each block */ -#define PWR_BASEADDR_MAC 0x00 -#define PWR_BASEADDR_USB 0x01 -#define PWR_BASEADDR_PCIE 0x02 -#define PWR_BASEADDR_SDIO 0x03 - -/*---------------------------------------------*/ -/* 3 The value of interface_msk: 4 bits */ -/*---------------------------------------------*/ -#define PWR_INTF_SDIO_MSK BIT(0) -#define PWR_INTF_USB_MSK BIT(1) -#define PWR_INTF_PCI_MSK BIT(2) -#define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) - -/*---------------------------------------------*/ -/* 3 The value of fab_msk: 4 bits */ -/*---------------------------------------------*/ -#define PWR_FAB_TSMC_MSK BIT(0) -#define PWR_FAB_UMC_MSK BIT(1) -#define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) - -/*---------------------------------------------*/ -/* 3 The value of cut_msk: 8 bits */ -/*---------------------------------------------*/ -#define PWR_CUT_TESTCHIP_MSK BIT(0) -#define PWR_CUT_A_MSK BIT(1) -#define PWR_CUT_B_MSK BIT(2) -#define PWR_CUT_C_MSK BIT(3) -#define PWR_CUT_D_MSK BIT(4) -#define PWR_CUT_E_MSK BIT(5) -#define PWR_CUT_F_MSK BIT(6) -#define PWR_CUT_G_MSK BIT(7) -#define PWR_CUT_ALL_MSK 0xFF - - -enum pwrseq_delay_unit { - PWRSEQ_DELAY_US, - PWRSEQ_DELAY_MS, -}; - -struct wlan_pwr_cfg { - u16 offset; - u8 cut_msk; - u8 fab_msk:4; - u8 interface_msk:4; - u8 base:4; - u8 cmd:4; - u8 msk; - u8 value; -}; - - -#define GET_PWR_CFG_OFFSET(__PWR_CMD) __PWR_CMD.offset -#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) __PWR_CMD.cut_msk -#define GET_PWR_CFG_FAB_MASK(__PWR_CMD) __PWR_CMD.fab_msk -#define GET_PWR_CFG_INTF_MASK(__PWR_CMD) __PWR_CMD.interface_msk -#define GET_PWR_CFG_BASE(__PWR_CMD) __PWR_CMD.base -#define GET_PWR_CFG_CMD(__PWR_CMD) __PWR_CMD.cmd -#define GET_PWR_CFG_MASK(__PWR_CMD) __PWR_CMD.msk -#define GET_PWR_CFG_VALUE(__PWR_CMD) __PWR_CMD.value - - -/* */ -/* Prototype of protected function. */ -/* */ -u8 HalPwrSeqCmdParsing23a( - struct rtw_adapter *padapter, - u8 CutVersion, - u8 FabVersion, - u8 InterfaceType, - struct wlan_pwr_cfg PwrCfgCmd[]); - -#endif diff --git a/drivers/staging/rtl8723au/include/HalVerDef.h b/drivers/staging/rtl8723au/include/HalVerDef.h deleted file mode 100644 index 2a0e4ea7afad..000000000000 --- a/drivers/staging/rtl8723au/include/HalVerDef.h +++ /dev/null @@ -1,114 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __HAL_VERSION_DEF_H__ -#define __HAL_VERSION_DEF_H__ - -enum hal_ic_type { - CHIP_8192S = 0, - CHIP_8188C = 1, - CHIP_8192C = 2, - CHIP_8192D = 3, - CHIP_8723A = 4, - CHIP_8188E = 5, - CHIP_8881A = 6, - CHIP_8812A = 7, - CHIP_8821A = 8, - CHIP_8723B = 9, - CHIP_8192E = 10, -}; - -enum hal_chip_type { - TEST_CHIP = 0, - NORMAL_CHIP = 1, - FPGA = 2, -}; - -enum hal_cut_version { - A_CUT_VERSION = 0, - B_CUT_VERSION = 1, - C_CUT_VERSION = 2, - D_CUT_VERSION = 3, - E_CUT_VERSION = 4, - F_CUT_VERSION = 5, - G_CUT_VERSION = 6, -}; - -/* HAL_Manufacturer */ -enum hal_vendor { - CHIP_VENDOR_TSMC = 0, - CHIP_VENDOR_UMC = 1, -}; - -struct hal_version { - enum hal_ic_type ICType; - enum hal_chip_type ChipType; - enum hal_cut_version CUTVersion; - enum hal_vendor VendorType; - u8 ROMVer; -}; - -/* Get element */ -#define GET_CVID_IC_TYPE(version) ((version).ICType) -#define GET_CVID_CHIP_TYPE(version) ((version).ChipType) -#define GET_CVID_MANUFACTUER(version) ((version).VendorType) -#define GET_CVID_CUT_VERSION(version) ((version).CUTVersion) -#define GET_CVID_ROM_VERSION(version) (((version).ROMVer) & ROM_VERSION_MASK) - -/* Common Macro. -- */ - -#define IS_81XXC(version) \ - (((GET_CVID_IC_TYPE(version) == CHIP_8192C) || \ - (GET_CVID_IC_TYPE(version) == CHIP_8188C)) ? true : false) -#define IS_8723_SERIES(version) \ - ((GET_CVID_IC_TYPE(version) == CHIP_8723A) ? true : false) - -#define IS_TEST_CHIP(version) \ - ((GET_CVID_CHIP_TYPE(version) == TEST_CHIP) ? true : false) -#define IS_NORMAL_CHIP(version) \ - ((GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) ? true : false) - -#define IS_A_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == A_CUT_VERSION) ? true : false) -#define IS_B_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true : false) -#define IS_C_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == C_CUT_VERSION) ? true : false) -#define IS_D_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == D_CUT_VERSION) ? true : false) -#define IS_E_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == E_CUT_VERSION) ? true : false) - -#define IS_CHIP_VENDOR_TSMC(version) \ - ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_TSMC) ? true : false) -#define IS_CHIP_VENDOR_UMC(version) \ - ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false) - -/* Chip version Macro. -- */ - -#define IS_81xxC_VENDOR_UMC_A_CUT(version) \ - (IS_81XXC(version)?(IS_CHIP_VENDOR_UMC(version) ? \ - (IS_A_CUT(version) ? true : false) : false) : false) -#define IS_81xxC_VENDOR_UMC_B_CUT(version) \ - (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \ - (IS_B_CUT(version) ? true : false) : false): false) -#define IS_81xxC_VENDOR_UMC_C_CUT(version) \ - (IS_81XXC(version)?(IS_CHIP_VENDOR_UMC(version) ? \ - (IS_C_CUT(version) ? true : false) : false) : false) -#define IS_8723A_A_CUT(version) \ - ((IS_8723_SERIES(version)) ? (IS_A_CUT(version) ? true : false) : false) -#define IS_8723A_B_CUT(version) \ - ((IS_8723_SERIES(version)) ? (IS_B_CUT(version) ? true : false) : false) - -#endif diff --git a/drivers/staging/rtl8723au/include/drv_types.h b/drivers/staging/rtl8723au/include/drv_types.h deleted file mode 100644 index e83463aeb9b1..000000000000 --- a/drivers/staging/rtl8723au/include/drv_types.h +++ /dev/null @@ -1,274 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -/*----------------------------------------------------------------------------- - - For type defines and data structure defines - -------------------------------------------------------------------------------*/ - - -#ifndef __DRV_TYPES_H__ -#define __DRV_TYPES_H__ - -#include -#include - - -enum _NIC_VERSION { - RTL8711_NIC, - RTL8712_NIC, - RTL8713_NIC, - RTL8716_NIC - -}; - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ioctl_cfg80211.h" - -struct registry_priv { - u8 chip_version; - u8 rfintfs; - struct cfg80211_ssid ssid; - u8 channel;/* ad-hoc support requirement */ - u8 wireless_mode;/* A, B, G, auto */ - u8 scan_mode;/* active, passive */ - u8 preamble;/* long, short, auto */ - u8 vrtl_carrier_sense;/* Enable, Disable, Auto */ - u8 vcs_type;/* RTS/CTS, CTS-to-self */ - u16 rts_thresh; - u16 frag_thresh; - u8 adhoc_tx_pwr; - u8 soft_ap; - u8 power_mgnt; - u8 ips_mode; - u8 smart_ps; - u8 long_retry_lmt; - u8 short_retry_lmt; - u16 busy_thresh; - u8 ack_policy; - u8 software_encrypt; - u8 software_decrypt; - u8 acm_method; - /* UAPSD */ - u8 wmm_enable; - u8 uapsd_enable; - - struct wlan_bssid_ex dev_network; - - u8 ht_enable; - u8 cbw40_enable; - u8 ampdu_enable;/* for tx */ - u8 rx_stbc; - u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */ - u8 lowrate_two_xmit; - - u8 rf_config; - u8 low_power; - - u8 wifi_spec;/* !turbo_mode */ - - u8 channel_plan; -#ifdef CONFIG_8723AU_BT_COEXIST - u8 btcoex; - u8 bt_iso; - u8 bt_sco; - u8 bt_ampdu; -#endif - bool bAcceptAddbaReq; - - u8 antdiv_cfg; - u8 antdiv_type; - - u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */ - u8 hwpwrp_detect;/* 0:disable,1:enable */ - - u8 hw_wps_pbc;/* 0:disable,1:enable */ - - u8 max_roaming_times; /* max number driver will try to roaming */ - - u8 enable80211d; - - u8 ifname[16]; - u8 if2name[16]; - - u8 notch_filter; - - u8 regulatory_tid; -}; - - -#define MAX_CONTINUAL_URB_ERR 4 - -#define GET_PRIMARY_ADAPTER(padapter) \ - (((struct rtw_adapter *)padapter)->dvobj->if1) - -enum _IFACE_ID { - IFACE_ID0, /* maping to PRIMARY_ADAPTER */ - IFACE_ID1, /* maping to SECONDARY_ADAPTER */ - IFACE_ID2, - IFACE_ID3, - IFACE_ID_MAX, -}; - -struct dvobj_priv { - struct rtw_adapter *if1; /* PRIMARY_ADAPTER */ - struct rtw_adapter *if2; /* SECONDARY_ADAPTER */ - - /* for local/global synchronization */ - struct mutex hw_init_mutex; - struct mutex h2c_fwcmd_mutex; - struct mutex setch_mutex; - struct mutex setbw_mutex; - - unsigned char oper_channel; /* saved chan info when set chan bw */ - unsigned char oper_bwmode; - unsigned char oper_ch_offset;/* PRIME_CHNL_OFFSET */ - - struct rtw_adapter *padapters[IFACE_ID_MAX]; - u8 iface_nums; /* total number of ifaces used runtime */ - - /* For 92D, DMDP have 2 interface. */ - u8 InterfaceNumber; - u8 NumInterfaces; - - /* In /Out Pipe information */ - int RtInPipe[2]; - int RtOutPipe[3]; - u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */ - -/*-------- below is for USB INTERFACE --------*/ - - u8 nr_endpoint; - u8 ishighspeed; - u8 RtNumInPipes; - u8 RtNumOutPipes; - int ep_num[5]; /* endpoint number */ - - struct mutex usb_vendor_req_mutex; - - union { - __le32 val32; - __le16 val16; - u8 val8; - } usb_buf; - - struct usb_interface *pusbintf; - struct usb_device *pusbdev; - atomic_t continual_urb_error; - -/*-------- below is for PCIE INTERFACE --------*/ - -}; - -static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj) -{ - /* todo: get interface type from dvobj and the return the dev accordingly */ - return &dvobj->pusbintf->dev; -} - -enum _IFACE_TYPE { - IFACE_PORT0, /* mapping to port0 for C/D series chips */ - IFACE_PORT1, /* mapping to port1 for C/D series chip */ - MAX_IFACE_PORT, -}; - -enum _ADAPTER_TYPE { - PRIMARY_ADAPTER, - SECONDARY_ADAPTER, - MAX_ADAPTER, -}; - -struct rtw_adapter { - int pid[3];/* process id from UI, 0:wps, 1:hostapd, 2:dhcpcd */ - int bDongle;/* build-in module or external dongle */ - u16 chip_type; - u16 HardwareType; - - struct dvobj_priv *dvobj; - struct mlme_priv mlmepriv; - struct mlme_ext_priv mlmeextpriv; - struct cmd_priv cmdpriv; - struct evt_priv evtpriv; - struct xmit_priv xmitpriv; - struct recv_priv recvpriv; - struct sta_priv stapriv; - struct security_priv securitypriv; - struct registry_priv registrypriv; - struct pwrctrl_priv pwrctrlpriv; - struct eeprom_priv eeprompriv; - - u32 setband; - - void *HalData; - - s32 bDriverStopped; - s32 bSurpriseRemoved; - s32 bCardDisableWOHSM; - - u32 IsrContent; - u32 ImrContent; - - u8 EepromAddressSize; - u8 hw_init_completed; - u8 bDriverIsGoingToUnload; - u8 init_adpt_in_progress; - u8 bHaltInProgress; - - struct net_device *pnetdev; - - /* used by rtw_rereg_nd_name related function */ - int bup; - struct net_device_stats stats; - - struct wireless_dev *rtw_wdev; - int net_closed; - - u8 bFWReady; - u8 bReadPortCancel; - u8 bWritePortCancel; - - /* extend to support multi interface */ - /* IFACE_ID0 is equals to PRIMARY_ADAPTER */ - /* IFACE_ID1 is equals to SECONDARY_ADAPTER */ - u8 iface_id; -}; - -#define adapter_to_dvobj(adapter) (adapter->dvobj) - -static inline u8 *myid(struct eeprom_priv *peepriv) -{ - return peepriv->mac_addr; -} - -#endif /* __DRV_TYPES_H__ */ diff --git a/drivers/staging/rtl8723au/include/hal_com.h b/drivers/staging/rtl8723au/include/hal_com.h deleted file mode 100644 index 9c50320b2100..000000000000 --- a/drivers/staging/rtl8723au/include/hal_com.h +++ /dev/null @@ -1,182 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __HAL_COMMON_H__ -#define __HAL_COMMON_H__ - -/* */ -/* Rate Definition */ -/* */ -/* CCK */ -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -/* OFDM */ -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -/* MCS 1 Spatial Stream */ -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -/* MCS 2 Spatial Stream */ -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -/* CCK */ -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -/* OFDM */ -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) - -/*------------------------------ Tx Desc definition Macro ------------------------*/ -/* pragma mark -- Tx Desc related definition. -- */ -/* */ -/* */ -/* Rate */ -/* */ -/* CCK Rates, TxHT = 0 */ -#define DESC_RATE1M 0x00 -#define DESC_RATE2M 0x01 -#define DESC_RATE5_5M 0x02 -#define DESC_RATE11M 0x03 - -/* OFDM Rates, TxHT = 0 */ -#define DESC_RATE6M 0x04 -#define DESC_RATE9M 0x05 -#define DESC_RATE12M 0x06 -#define DESC_RATE18M 0x07 -#define DESC_RATE24M 0x08 -#define DESC_RATE36M 0x09 -#define DESC_RATE48M 0x0a -#define DESC_RATE54M 0x0b - -/* MCS Rates, TxHT = 1 */ -#define DESC_RATEMCS0 0x0c -#define DESC_RATEMCS1 0x0d -#define DESC_RATEMCS2 0x0e -#define DESC_RATEMCS3 0x0f -#define DESC_RATEMCS4 0x10 -#define DESC_RATEMCS5 0x11 -#define DESC_RATEMCS6 0x12 -#define DESC_RATEMCS7 0x13 -#define DESC_RATEMCS8 0x14 -#define DESC_RATEMCS9 0x15 -#define DESC_RATEMCS10 0x16 -#define DESC_RATEMCS11 0x17 -#define DESC_RATEMCS12 0x18 -#define DESC_RATEMCS13 0x19 -#define DESC_RATEMCS14 0x1a -#define DESC_RATEMCS15 0x1b -#define DESC_RATEMCS15_SG 0x1c -#define DESC_RATEMCS32 0x20 - -#define REG_P2P_CTWIN 0x0572 /* 1 Byte long (in unit of TU) */ -#define REG_NOA_DESC_SEL 0x05CF -#define REG_NOA_DESC_DURATION 0x05E0 -#define REG_NOA_DESC_INTERVAL 0x05E4 -#define REG_NOA_DESC_START 0x05E8 -#define REG_NOA_DESC_COUNT 0x05EC - -#include "HalVerDef.h" - - -u8 /* return the final channel plan decision */ -hal_com_get_channel_plan23a( - struct rtw_adapter *padapter, - u8 hw_channel_plan, /* channel plan from HW (efuse/eeprom) */ - u8 sw_channel_plan, /* channel plan from SW (registry/module param) */ - u8 def_channel_plan, /* channel plan used when the former two is invalid */ - bool AutoLoadFail - ); - -u8 MRateToHwRate23a(u8 rate); - -void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS); - -bool -Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe); - -void c2h_evt_clear23a(struct rtw_adapter *adapter); -s32 c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf); - -void rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet); -void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet); -void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl); -void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status); -void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status); -void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val); -void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val); -void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag); -void rtl8723a_on_rcr_am(struct rtw_adapter *padapter); -void rtl8723a_off_rcr_am(struct rtw_adapter *padapter); -void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime); -void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble); -void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec); -void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex); -void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter); -void rtl8723a_cam_write(struct rtw_adapter *padapter, - u8 entry, u16 ctrl, const u8 *mac, const u8 *key); -void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter); -void rtl8723a_set_apfm_on_mac(struct rtw_adapter *padapter, u8 val); -void rtl8723a_bcn_valid(struct rtw_adapter *padapter); -bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter); -void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval); -void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter, - u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2); -void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo); -void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi); -void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be); -void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk); -void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val); -void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain); - -void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val); -void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter); -void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter); -void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val); -void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val); - -void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val); -u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter); -bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter); -bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter); - -#endif /* __HAL_COMMON_H__ */ diff --git a/drivers/staging/rtl8723au/include/hal_intf.h b/drivers/staging/rtl8723au/include/hal_intf.h deleted file mode 100644 index b924d47fcfbc..000000000000 --- a/drivers/staging/rtl8723au/include/hal_intf.h +++ /dev/null @@ -1,115 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __HAL_INTF_H__ -#define __HAL_INTF_H__ - -#include -#include - -enum _CHIP_TYPE { - NULL_CHIP_TYPE, - RTL8712_8188S_8191S_8192S, - RTL8188C_8192C, - RTL8192D, - RTL8723A, - RTL8188E, - MAX_CHIP_TYPE -}; - -enum hal_def_variable { - HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, - HAL_DEF_IS_SUPPORT_ANT_DIV, - HAL_DEF_CURRENT_ANTENNA, - HAL_DEF_DRVINFO_SZ, - HAL_DEF_MAX_RECVBUF_SZ, - HAL_DEF_RX_PACKET_OFFSET, - HAL_DEF_DBG_DUMP_RXPKT,/* for dbg */ - HAL_DEF_DBG_DM_FUNC,/* for dbg */ - HAL_DEF_RA_DECISION_RATE, - HAL_DEF_RA_SGI, - HAL_DEF_PT_PWR_STATUS, - HW_VAR_MAX_RX_AMPDU_FACTOR, - HW_DEF_RA_INFO_DUMP, - HAL_DEF_DBG_DUMP_TXPKT, - HW_DEF_FA_CNT_DUMP, - HW_DEF_ODM_DBG_FLAG, -}; - -enum hal_odm_variable { - HAL_ODM_STA_INFO, - HAL_ODM_P2P_STATE, - HAL_ODM_WIFI_DISPLAY_STATE, -}; - -enum rt_eeprom_type { - EEPROM_93C46, - EEPROM_93C56, - EEPROM_BOOT_EFUSE, -}; - - - -#define RF_CHANGE_BY_INIT 0 -#define RF_CHANGE_BY_IPS BIT(28) -#define RF_CHANGE_BY_PS BIT(29) -#define RF_CHANGE_BY_HW BIT(30) -#define RF_CHANGE_BY_SW BIT(31) - -enum hardware_type { - HARDWARE_TYPE_RTL8180, - HARDWARE_TYPE_RTL8185, - HARDWARE_TYPE_RTL8187, - HARDWARE_TYPE_RTL8188, - HARDWARE_TYPE_RTL8190P, - HARDWARE_TYPE_RTL8192E, - HARDWARE_TYPE_RTL819xU, - HARDWARE_TYPE_RTL8192SE, - HARDWARE_TYPE_RTL8192SU, - HARDWARE_TYPE_RTL8192CE, - HARDWARE_TYPE_RTL8192CU, - HARDWARE_TYPE_RTL8192DE, - HARDWARE_TYPE_RTL8192DU, - HARDWARE_TYPE_RTL8723AE, - HARDWARE_TYPE_RTL8723AU, - HARDWARE_TYPE_RTL8723AS, - HARDWARE_TYPE_RTL8188EE, - HARDWARE_TYPE_RTL8188EU, - HARDWARE_TYPE_RTL8188ES, - HARDWARE_TYPE_MAX, -}; - -#define GET_EEPROM_EFUSE_PRIV(adapter) (&adapter->eeprompriv) - -void rtw_hal_def_value_init23a(struct rtw_adapter *padapter); -int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal); - -int rtl8723au_hal_init(struct rtw_adapter *padapter); -int rtl8723au_hal_deinit(struct rtw_adapter *padapter); -void rtw_hal_stop(struct rtw_adapter *padapter); - -void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level); -void rtw_hal_clone_data(struct rtw_adapter *dst_padapter, struct rtw_adapter *src_padapter); - -void hw_var_set_correct_tsf(struct rtw_adapter *padapter); -void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter); -void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode); -void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val); -void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val); -void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type); - -int GetHalDefVar8192CUsb(struct rtw_adapter *Adapter, - enum hal_def_variable eVariable, void *pValue); - -#endif /* __HAL_INTF_H__ */ diff --git a/drivers/staging/rtl8723au/include/ieee80211.h b/drivers/staging/rtl8723au/include/ieee80211.h deleted file mode 100644 index 634102e1bda6..000000000000 --- a/drivers/staging/rtl8723au/include/ieee80211.h +++ /dev/null @@ -1,341 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __IEEE80211_H -#define __IEEE80211_H - -#include -#include -#include "linux/ieee80211.h" -#include "wifi.h" - -#include - -#if (WIRELESS_EXT < 22) -#error "Obsolete pre 2007 wireless extensions are not supported" -#endif - - -#ifdef CONFIG_8723AU_AP_MODE - -/* STA flags */ -#define WLAN_STA_AUTH BIT(0) -#define WLAN_STA_ASSOC BIT(1) -#define WLAN_STA_PS BIT(2) -#define WLAN_STA_TIM BIT(3) -#define WLAN_STA_PERM BIT(4) -#define WLAN_STA_AUTHORIZED BIT(5) -#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */ -#define WLAN_STA_SHORT_PREAMBLE BIT(7) -#define WLAN_STA_PREAUTH BIT(8) -#define WLAN_STA_WME BIT(9) -#define WLAN_STA_MFP BIT(10) -#define WLAN_STA_HT BIT(11) -#define WLAN_STA_WPS BIT(12) -#define WLAN_STA_MAYBE_WPS BIT(13) -#define WLAN_STA_NONERP BIT(31) - -#endif - -#define WPA_CIPHER_NONE BIT(0) -#define WPA_CIPHER_WEP40 BIT(1) -#define WPA_CIPHER_WEP104 BIT(2) -#define WPA_CIPHER_TKIP BIT(3) -#define WPA_CIPHER_CCMP BIT(4) - - - -#define WPA_SELECTOR_LEN 4 -extern u8 RTW_WPA_OUI23A_TYPE[] ; -extern u16 RTW_WPA_VERSION23A ; -extern u8 WPA_AUTH_KEY_MGMT_NONE23A[]; -extern u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[]; -extern u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[]; -extern u8 WPA_CIPHER_SUITE_NONE23A[]; -extern u8 WPA_CIPHER_SUITE_WEP4023A[]; -extern u8 WPA_CIPHER_SUITE_TKIP23A[]; -extern u8 WPA_CIPHER_SUITE_WRAP23A[]; -extern u8 WPA_CIPHER_SUITE_CCMP23A[]; -extern u8 WPA_CIPHER_SUITE_WEP10423A[]; - - -#define RSN_HEADER_LEN 4 -#define RSN_SELECTOR_LEN 4 - -extern u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[]; -extern u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[]; -extern u8 RSN_CIPHER_SUITE_NONE23A[]; -extern u8 RSN_CIPHER_SUITE_WEP4023A[]; -extern u8 RSN_CIPHER_SUITE_TKIP23A[]; -extern u8 RSN_CIPHER_SUITE_WRAP23A[]; -extern u8 RSN_CIPHER_SUITE_CCMP23A[]; -extern u8 RSN_CIPHER_SUITE_WEP10423A[]; - -enum ratr_table_mode { - RATR_INX_WIRELESS_NGB = 0, /* BGN 40 Mhz 2SS 1SS */ - RATR_INX_WIRELESS_NG = 1, /* GN or N */ - RATR_INX_WIRELESS_NB = 2, /* BGN 20 Mhz 2SS 1SS or BN */ - RATR_INX_WIRELESS_N = 3, - RATR_INX_WIRELESS_GB = 4, - RATR_INX_WIRELESS_G = 5, - RATR_INX_WIRELESS_B = 6, - RATR_INX_WIRELESS_MC = 7, - RATR_INX_WIRELESS_AC_N = 8, -}; - -enum NETWORK_TYPE -{ - WIRELESS_INVALID = 0, - /* Sub-Element */ - /* tx: cck only , rx: cck only, hw: cck */ - WIRELESS_11B = BIT(0), - /* tx: ofdm only, rx: ofdm & cck, hw: cck & ofdm */ - WIRELESS_11G = BIT(1), - /* tx: ofdm only, rx: ofdm only, hw: ofdm only */ - WIRELESS_11A = BIT(2), - /* tx: MCS only, rx: MCS & cck, hw: MCS & cck */ - WIRELESS_11_24N = BIT(3), - /* tx: MCS only, rx: MCS & ofdm, hw: ofdm only */ - WIRELESS_11_5N = BIT(4), - /* WIRELESS_AUTO = BIT(5), */ - WIRELESS_AC = BIT(6), - - /* Combination */ - /* tx: cck & ofdm, rx: cck & ofdm & MCS, hw: cck & ofdm */ - WIRELESS_11BG = WIRELESS_11B|WIRELESS_11G, - /* tx: ofdm & MCS, rx: ofdm & cck & MCS, hw: cck & ofdm */ - WIRELESS_11G_24N = WIRELESS_11G | WIRELESS_11_24N, - /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */ - WIRELESS_11A_5N = WIRELESS_11A | WIRELESS_11_5N, - /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */ - WIRELESS_11BG_24N = WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N, - /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */ - WIRELESS_11AGN = WIRELESS_11A | WIRELESS_11G | WIRELESS_11_24N | - WIRELESS_11_5N, - WIRELESS_11ABGN = WIRELESS_11A | WIRELESS_11B | WIRELESS_11G | - WIRELESS_11_24N | WIRELESS_11_5N, -}; - -#define SUPPORTED_24G_NETTYPE_MSK (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N) -#define SUPPORTED_5G_NETTYPE_MSK (WIRELESS_11A | WIRELESS_11_5N) - -#define IsSupported24G(NetType) (NetType & SUPPORTED_24G_NETTYPE_MSK ? true : false) -#define IsSupported5G(NetType) (NetType & SUPPORTED_5G_NETTYPE_MSK ? true : false) - -#define IsEnableHWCCK(NetType) IsSupported24G(NetType) -#define IsEnableHWOFDM(NetType) (NetType & (WIRELESS_11G|WIRELESS_11_24N|SUPPORTED_5G_NETTYPE_MSK) ? true : false) - -#define IsSupportedRxCCK(NetType) IsEnableHWCCK(NetType) -#define IsSupportedRxOFDM(NetType) IsEnableHWOFDM(NetType) -#define IsSupportedRxMCS(NetType) IsEnableHWOFDM(NetType) - -#define IsSupportedTxCCK(NetType) (NetType & (WIRELESS_11B) ? true : false) -#define IsSupportedTxOFDM(NetType) (NetType & (WIRELESS_11G|WIRELESS_11A) ? true : false) -#define IsSupportedTxMCS(NetType) (NetType & (WIRELESS_11_24N|WIRELESS_11_5N) ? true : false) - - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -/* QoS,QOS */ -#define NORMAL_ACK 0 -#define NO_ACK 1 -#define NON_EXPLICIT_ACK 2 -#define BLOCK_ACK 3 - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct ieee80211_snap_hdr { - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ -} __attribute__ ((packed)); - - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define WLAN_REASON_JOIN_WRONG_CHANNEL 65534 -#define WLAN_REASON_EXPIRATION_CHK 65535 - -#define IEEE80211_CCK_RATE_LEN 4 -#define IEEE80211_NUM_OFDM_RATESLEN 8 - - -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_LEN 8 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) -#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) -#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) -#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) -#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) -#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) -#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) -#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) -#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) -#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) -#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) -#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ - IEEE80211_CCK_RATE_2MB_MASK) -#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ - IEEE80211_CCK_RATE_5MB_MASK | \ - IEEE80211_CCK_RATE_11MB_MASK) - -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 -#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ - IEEE80211_OFDM_RATE_12MB_MASK | \ - IEEE80211_OFDM_RATE_24MB_MASK) -#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ - IEEE80211_OFDM_RATE_9MB_MASK | \ - IEEE80211_OFDM_RATE_18MB_MASK | \ - IEEE80211_OFDM_RATE_36MB_MASK | \ - IEEE80211_OFDM_RATE_48MB_MASK | \ - IEEE80211_OFDM_RATE_54MB_MASK) -#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ - IEEE80211_CCK_DEFAULT_RATES_MASK) - -#define IEEE80211_NUM_OFDM_RATES 8 -#define IEEE80211_NUM_CCK_RATES 4 -#define IEEE80211_OFDM_SHIFT_MASK_A 4 - -#define WEP_KEYS 4 - - -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... */ -#define MAX_RATES_LENGTH 12 -#define MAX_RATES_EX_LENGTH 16 -#define MAX_CHANNEL_NUMBER 161 -#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ - -#define MAX_WPA_IE_LEN 256 -#define MAX_WPS_IE_LEN 256 -#define MAX_P2P_IE_LEN 256 -#define MAX_WFD_IE_LEN 128 - -/* -join_res: --1: authentication fail --2: association fail -> 0: TID -*/ - -#define MAXTID 16 - -#define WME_OUI_TYPE 2 -#define WME_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -#define WME_OUI_SUBTYPE_PARAMETER_ELEMENT 1 -#define WME_OUI_SUBTYPE_TSPEC_ELEMENT 2 -#define WME_VERSION 1 - - -#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ - -#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ - -/* Represent channel details, subset of ieee80211_channel */ -struct rtw_ieee80211_channel { - /* enum nl80211_band band; */ - /* u16 center_freq; */ - u16 hw_value; - u32 flags; - /* int max_antenna_gain; */ - /* int max_power; */ - /* int max_reg_power; */ - /* bool beacon_found; */ - /* u32 orig_flags; */ - /* int orig_mag; */ - /* int orig_mpwr; */ -}; - -#define CHAN_FMT \ - /*"band:%d, "*/ \ - /*"center_freq:%u, "*/ \ - "hw_value:%u, " \ - "flags:0x%08x" \ - /*"max_antenna_gain:%d\n"*/ \ - /*"max_power:%d\n"*/ \ - /*"max_reg_power:%d\n"*/ \ - /*"beacon_found:%u\n"*/ \ - /*"orig_flags:0x%08x\n"*/ \ - /*"orig_mag:%d\n"*/ \ - /*"orig_mpwr:%d\n"*/ - -#define CHAN_ARG(channel) \ - /*(channel)->band*/ \ - /*, (channel)->center_freq*/ \ - (channel)->hw_value \ - , (channel)->flags \ - /*, (channel)->max_antenna_gain*/ \ - /*, (channel)->max_power*/ \ - /*, (channel)->max_reg_power*/ \ - /*, (channel)->beacon_found*/ \ - /*, (channel)->orig_flags*/ \ - /*, (channel)->orig_mag*/ \ - /*, (channel)->orig_mpwr*/ \ - -u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen); - -u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset); -u8 *rtw_set_ie23a_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt); -u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset); - -u8 *rtw_get_ie23a(u8*pbuf, int index, int *len, int limit); -u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen); -int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len); - -void rtw_set_supported_rate23a(u8 *SupportedRates, uint mode); - -int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x); -int rtw_parse_wpa2_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x); - -const u8 *rtw_get_wps_attr23a(const u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr); -const u8 *rtw_get_wps_attr_content23a(const u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content); - -uint rtw_get_rateset_len23a(u8 *rateset); - -struct registry_priv; -int rtw_generate_ie23a(struct registry_priv *pregistrypriv); - - -int rtw_get_bit_value_from_ieee_value23a(u8 val); - -int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel); - -void rtw_get_bcn_info23a(struct wlan_network *pnetwork); - -u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, - struct ieee80211_mcs_info *mcs); - -#endif /* IEEE80211_H */ diff --git a/drivers/staging/rtl8723au/include/ioctl_cfg80211.h b/drivers/staging/rtl8723au/include/ioctl_cfg80211.h deleted file mode 100644 index 3a4ead54f948..000000000000 --- a/drivers/staging/rtl8723au/include/ioctl_cfg80211.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __IOCTL_CFG80211_H__ -#define __IOCTL_CFG80211_H__ - -struct rtw_wdev_priv { - struct wireless_dev *rtw_wdev; - - struct rtw_adapter *padapter; - - struct cfg80211_scan_request *scan_request; - spinlock_t scan_req_lock; - - struct net_device *pmon_ndev;/* for monitor interface */ - char ifname_mon[IFNAMSIZ + 1]; /* name for monitor interface */ - - u8 p2p_enabled; - - bool power_mgmt; -}; - -#define wdev_to_priv(w) ((struct rtw_wdev_priv *)(wdev_priv(w))) - -#define wiphy_to_adapter(x) \ - (struct rtw_adapter *)(((struct rtw_wdev_priv *) \ - wiphy_priv(x))->padapter) - -#define wiphy_to_wdev(x) \ - (struct wireless_dev *)(((struct rtw_wdev_priv *) \ - wiphy_priv(x))->rtw_wdev) - -int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev); -void rtw_wdev_free(struct wireless_dev *wdev); -void rtw_wdev_unregister(struct wireless_dev *wdev); - -void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter); - -void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter); - -void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter); -void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter); -void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv, - bool aborted); - -#ifdef CONFIG_8723AU_AP_MODE -void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter, - u8 *pmgmt_frame, uint frame_len); -void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter, - unsigned char *da, unsigned short reason); -#endif /* CONFIG_8723AU_AP_MODE */ - -bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter); - -#endif /* __IOCTL_CFG80211_H__ */ diff --git a/drivers/staging/rtl8723au/include/mlme_osdep.h b/drivers/staging/rtl8723au/include/mlme_osdep.h deleted file mode 100644 index 4bb5525b7a68..000000000000 --- a/drivers/staging/rtl8723au/include/mlme_osdep.h +++ /dev/null @@ -1,24 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __MLME_OSDEP_H_ -#define __MLME_OSDEP_H_ - -#include -#include - -void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter); -void rtw_reset_securitypriv23a(struct rtw_adapter *adapter); - -#endif /* _MLME_OSDEP_H_ */ diff --git a/drivers/staging/rtl8723au/include/odm.h b/drivers/staging/rtl8723au/include/odm.h deleted file mode 100644 index 24f2f28c473f..000000000000 --- a/drivers/staging/rtl8723au/include/odm.h +++ /dev/null @@ -1,860 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - - -#ifndef __HALDMOUTSRC_H__ -#define __HALDMOUTSRC_H__ - -/* */ -/* Definition */ -/* */ -/* */ -/* 2011/09/22 MH Define all team supprt ability. */ -/* */ - -/* */ -/* 2011/09/22 MH Define for all teams. Please Define the constan in your precomp header. */ -/* */ -/* define DM_ODM_SUPPORT_AP 0 */ -/* define DM_ODM_SUPPORT_ADSL 0 */ -/* define DM_ODM_SUPPORT_CE 0 */ -/* define DM_ODM_SUPPORT_MP 1 */ - -#define TP_MODE 0 -#define RSSI_MODE 1 -#define TRAFFIC_LOW 0 -#define TRAFFIC_HIGH 1 - - -/* */ -/* 3 Tx Power Tracking */ -/* 3============================================================ */ -#define DPK_DELTA_MAPPING_NUM 13 -#define index_mapping_HP_NUM 15 - - -/* */ -/* 3 PSD Handler */ -/* 3============================================================ */ - -#define AFH_PSD 1 /* 0:normal PSD scan, 1: only do 20 pts PSD */ -#define MODE_40M 0 /* 0:20M, 1:40M */ -#define PSD_TH2 3 -#define PSD_CHMIN 20 /* Minimum channel number for BT AFH */ -#define SIR_STEP_SIZE 3 -#define Smooth_Size_1 5 -#define Smooth_TH_1 3 -#define Smooth_Size_2 10 -#define Smooth_TH_2 4 -#define Smooth_Size_3 20 -#define Smooth_TH_3 4 -#define Smooth_Step_Size 5 -#define Adaptive_SIR 1 -#define PSD_RESCAN 4 -#define PSD_SCAN_INTERVAL 700 /* ms */ - -/* 8723A High Power IGI Setting */ -#define DM_DIG_HIGH_PWR_IGI_LOWER_BOUND 0x22 -#define DM_DIG_Gmode_HIGH_PWR_IGI_LOWER_BOUND 0x28 -#define DM_DIG_HIGH_PWR_THRESHOLD 0x3a - -/* LPS define */ -#define DM_DIG_FA_TH0_LPS 4 /* 4 in lps */ -#define DM_DIG_FA_TH1_LPS 15 /* 15 lps */ -#define DM_DIG_FA_TH2_LPS 30 /* 30 lps */ -#define RSSI_OFFSET_DIG 0x05; - -/* ANT Test */ -#define ANTTESTALL 0x00 /* Ant A or B will be Testing */ -#define ANTTESTA 0x01 /* Ant A will be Testing */ -#define ANTTESTB 0x02 /* Ant B will be testing */ - - -/* */ -/* structure and define */ -/* */ - -struct dig_t { - u8 Dig_Enable_Flag; - u8 Dig_Ext_Port_Stage; - - int RssiLowThresh; - int RssiHighThresh; - - u32 FALowThresh; - u32 FAHighThresh; - - u8 CurSTAConnectState; - u8 PreSTAConnectState; - u8 CurMultiSTAConnectState; - - u8 PreIGValue; - u8 CurIGValue; - u8 BackupIGValue; - - s8 BackoffVal; - s8 BackoffVal_range_max; - s8 BackoffVal_range_min; - u8 rx_gain_range_max; - u8 rx_gain_range_min; - u8 Rssi_val_min; - - u8 PreCCK_CCAThres; - u8 CurCCK_CCAThres; - u8 PreCCKPDState; - u8 CurCCKPDState; - - u8 LargeFAHit; - u8 ForbiddenIGI; - u32 Recover_cnt; - - u8 DIG_Dynamic_MIN_0; - u8 DIG_Dynamic_MIN_1; - bool bMediaConnect_0; - bool bMediaConnect_1; - - u32 RSSI_max; -}; - -struct dynamic_pwr_sav { - u8 PreCCAState; - u8 CurCCAState; - - u8 PreRFState; - u8 CurRFState; - - int Rssi_val_min; - - u8 initialize; - u32 Reg874, RegC70, Reg85C, RegA74; -}; - -struct false_alarm_stats { - u32 Cnt_Parity_Fail; - u32 Cnt_Rate_Illegal; - u32 Cnt_Crc8_fail; - u32 Cnt_Mcs_fail; - u32 Cnt_Ofdm_fail; - u32 Cnt_Cck_fail; - u32 Cnt_all; - u32 Cnt_Fast_Fsync; - u32 Cnt_SB_Search_fail; - u32 Cnt_OFDM_CCA; - u32 Cnt_CCK_CCA; - u32 Cnt_CCA_all; - u32 Cnt_BW_USC; /* Gary */ - u32 Cnt_BW_LSC; /* Gary */ -}; - -#define ASSOCIATE_ENTRY_NUM 32 /* Max size of AsocEntry[]. */ -#define ODM_ASSOCIATE_ENTRY_NUM ASSOCIATE_ENTRY_NUM - -/* This indicates two different the steps. */ -/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */ -/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK */ -/* with original RSSI to determine if it is necessary to switch antenna. */ -#define SWAW_STEP_PEAK 0 -#define SWAW_STEP_DETERMINE 1 - -#define TP_MODE 0 -#define RSSI_MODE 1 -#define TRAFFIC_LOW 0 -#define TRAFFIC_HIGH 1 - -struct sw_ant_sw { - u8 try_flag; - s32 PreRSSI; - u8 CurAntenna; - u8 PreAntenna; - u8 RSSI_Trying; - u8 TestMode; - u8 bTriggerAntennaSwitch; - u8 SelectAntennaMap; - u8 RSSI_target; - - /* Before link Antenna Switch check */ - u8 SWAS_NoLink_State; - u32 SWAS_NoLink_BK_Reg860; - bool ANTA_ON; /* To indicate Ant A is or not */ - bool ANTB_ON; /* To indicate Ant B is on or not */ - - s32 RSSI_sum_A; - s32 RSSI_sum_B; - s32 RSSI_cnt_A; - s32 RSSI_cnt_B; - - u64 lastTxOkCnt; - u64 lastRxOkCnt; - u64 TXByteCnt_A; - u64 TXByteCnt_B; - u64 RXByteCnt_A; - u64 RXByteCnt_B; - u8 TrafficLoad; -}; - -struct edca_turbo { - bool bCurrentTurboEDCA; - u32 prv_traffic_idx; /* edca turbo */ -}; - -struct odm_rate_adapt { - u8 Type; /* DM_Type_ByFW/DM_Type_ByDriver */ - u8 HighRSSIThresh; /* if RSSI > HighRSSIThresh => RATRState is DM_RATR_STA_HIGH */ - u8 LowRSSIThresh; /* if RSSI <= LowRSSIThresh => RATRState is DM_RATR_STA_LOW */ - u8 RATRState; /* Current RSSI level, DM_RATR_STA_HIGH/DM_RATR_STA_MIDDLE/DM_RATR_STA_LOW */ - u32 LastRATR; /* RATR Register Content */ -}; - -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM_MAX 10 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 - -#define AVG_THERMAL_NUM 8 -#define IQK_Matrix_REG_NUM 8 -#define IQK_Matrix_Settings_NUM 1+24+21 - -#define DM_Type_ByFW 0 -#define DM_Type_ByDriver 1 - -/* Declare for common info */ - -struct odm_phy_dbg_info { - /* ODM Write,debug info */ - s8 RxSNRdB[RF_PATH_MAX]; - u64 NumQryPhyStatus; - u64 NumQryPhyStatusCCK; - u64 NumQryPhyStatusOFDM; - /* Others */ - s32 RxEVM[RF_PATH_MAX]; - -}; - -struct odm_packet_info { - u8 Rate; - u8 StationID; - bool bPacketMatchBSSID; - bool bPacketToSelf; - bool bPacketBeacon; -}; - - -enum { - /* BB Team */ - ODM_DIG = 0x00000001, - ODM_HIGH_POWER = 0x00000002, - ODM_CCK_CCA_TH = 0x00000004, - ODM_FA_STATISTICS = 0x00000008, - ODM_RAMASK = 0x00000010, - ODM_RSSI_MONITOR = 0x00000020, - ODM_SW_ANTDIV = 0x00000040, - ODM_HW_ANTDIV = 0x00000080, - ODM_BB_PWRSV = 0x00000100, - ODM_2TPATHDIV = 0x00000200, - ODM_1TPATHDIV = 0x00000400, - ODM_PSD2AFH = 0x00000800 -}; - -/* */ -/* 2011/10/20 MH Define Common info enum for all team. */ -/* */ - -enum odm_cmninfo { - /* Fixed value: */ - /* */ - - ODM_CMNINFO_MP_TEST_CHIP = 2, - ODM_CMNINFO_IC_TYPE, /* enum odm_ic_type_def */ - ODM_CMNINFO_CUT_VER, /* enum odm_cut_version */ - ODM_CMNINFO_FAB_VER, /* enum odm_fab_version */ - ODM_CMNINFO_BOARD_TYPE, /* enum odm_board_type */ - ODM_CMNINFO_EXT_LNA, /* true */ - ODM_CMNINFO_EXT_PA, - ODM_CMNINFO_EXT_TRSW, - ODM_CMNINFO_BINHCT_TEST, - ODM_CMNINFO_BWIFI_TEST, - ODM_CMNINFO_SMART_CONCURRENT, - - - /* */ - /* Dynamic value: */ - /* */ - ODM_CMNINFO_MP_MODE, - - ODM_CMNINFO_WIFI_DIRECT, - ODM_CMNINFO_WIFI_DISPLAY, - ODM_CMNINFO_LINK, - ODM_CMNINFO_RSSI_MIN, - ODM_CMNINFO_DBG_COMP, /* u64 */ - ODM_CMNINFO_DBG_LEVEL, /* u32 */ - ODM_CMNINFO_RA_THRESHOLD_HIGH, /* u8 */ - ODM_CMNINFO_RA_THRESHOLD_LOW, /* u8 */ - ODM_CMNINFO_RF_ANTENNA_TYPE, /* u8 */ - ODM_CMNINFO_BT_DISABLED, - ODM_CMNINFO_BT_OPERATION, - ODM_CMNINFO_BT_DIG, - ODM_CMNINFO_BT_BUSY, /* Check Bt is using or not */ - ODM_CMNINFO_BT_DISABLE_EDCA, - - /* */ - /* Dynamic ptr array hook itms. */ - /* */ - ODM_CMNINFO_STA_STATUS, - ODM_CMNINFO_PHY_STATUS, - ODM_CMNINFO_MAC_STATUS, - - ODM_CMNINFO_MAX, -}; - -/* Define ODM support ability. ODM_CMNINFO_ABILITY */ -enum { - /* BB ODM section BIT 0-15 */ - ODM_BB_ANT_DIV = BIT(6), -}; - -/* ODM_CMNINFO_INTERFACE */ -enum odm_interface_def { - ODM_ITRF_PCIE = 0x1, - ODM_ITRF_USB = 0x2, - ODM_ITRF_SDIO = 0x4, - ODM_ITRF_ALL = 0x7, -}; - -/* ODM_CMNINFO_IC_TYPE */ -enum odm_ic_type_def { - ODM_RTL8192S = BIT(0), - ODM_RTL8192C = BIT(1), - ODM_RTL8192D = BIT(2), - ODM_RTL8723A = BIT(3), - ODM_RTL8188E = BIT(4), - ODM_RTL8812 = BIT(5), - ODM_RTL8821 = BIT(6), -}; - -/* ODM_CMNINFO_CUT_VER */ -enum odm_cut_version { - ODM_CUT_A = 1, - ODM_CUT_B = 2, - ODM_CUT_C = 3, - ODM_CUT_D = 4, - ODM_CUT_E = 5, - ODM_CUT_F = 6, - ODM_CUT_TEST = 7, -}; - -/* ODM_CMNINFO_FAB_VER */ -enum odm_fab_version { - ODM_TSMC = 0, - ODM_UMC = 1, -}; - -/* For example 1T2R (A+AB = BIT0|BIT4|BIT5) */ -enum rf_path_def { - ODM_RF_TX_A = BIT(0), - ODM_RF_TX_B = BIT(1), - ODM_RF_TX_C = BIT(2), - ODM_RF_TX_D = BIT(3), - ODM_RF_RX_A = BIT(4), - ODM_RF_RX_B = BIT(5), - ODM_RF_RX_C = BIT(6), - ODM_RF_RX_D = BIT(7), -}; - -/* ODM Dynamic common info value definition */ - -enum odm_mac_phy_mode { - ODM_SMSP = 0, - ODM_DMSP = 1, - ODM_DMDP = 2, -}; - - -enum odm_bt_coexist { - ODM_BT_BUSY = 1, - ODM_BT_ON = 2, - ODM_BT_OFF = 3, - ODM_BT_NONE = 4, -}; - -/* ODM_CMNINFO_OP_MODE */ -enum odm_operation_mode { - ODM_NO_LINK = BIT(0), - ODM_LINK = BIT(1), - ODM_SCAN = BIT(2), - ODM_POWERSAVE = BIT(3), - ODM_AP_MODE = BIT(4), - ODM_CLIENT_MODE = BIT(5), - ODM_AD_HOC = BIT(6), - ODM_WIFI_DIRECT = BIT(7), - ODM_WIFI_DISPLAY = BIT(8), -}; - -/* ODM_CMNINFO_WM_MODE */ -enum odm_wireless_mode { - ODM_WM_UNKNOW = 0x0, - ODM_WM_B = BIT(0), - ODM_WM_G = BIT(1), - ODM_WM_A = BIT(2), - ODM_WM_N24G = BIT(3), - ODM_WM_N5G = BIT(4), - ODM_WM_AUTO = BIT(5), - ODM_WM_AC = BIT(6), -}; - -/* ODM_CMNINFO_BAND */ -enum odm_band_type { - ODM_BAND_2_4G = BIT(0), - ODM_BAND_5G = BIT(1), - -}; - -/* ODM_CMNINFO_SEC_CHNL_OFFSET */ -enum odm_sec_chnl_offset { - ODM_DONT_CARE = 0, - ODM_BELOW = 1, - ODM_ABOVE = 2 -}; - -/* ODM_CMNINFO_CHNL */ - -/* ODM_CMNINFO_BOARD_TYPE */ -enum odm_board_type { - ODM_BOARD_NORMAL = 0, - ODM_BOARD_HIGHPWR = 1, - ODM_BOARD_MINICARD = 2, - ODM_BOARD_SLIM = 3, - ODM_BOARD_COMBO = 4, - -}; - -/* ODM_CMNINFO_ONE_PATH_CCA */ -enum odm_cca_path { - ODM_CCA_2R = 0, - ODM_CCA_1R_A = 1, - ODM_CCA_1R_B = 2, -}; - -struct iqk_matrix_regs_set { - bool bIQKDone; - s32 Value[1][IQK_Matrix_REG_NUM]; -}; - -struct odm_rf_cal_t { - /* for tx power tracking */ - - u32 RegA24; /* for TempCCK */ - s32 RegE94; - s32 RegE9C; - s32 RegEB4; - s32 RegEBC; - - /* u8 bTXPowerTracking; */ - u8 TXPowercount; - bool bTXPowerTrackingInit; - bool bTXPowerTracking; - u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking as default */ - u8 TM_Trigger; - u8 InternalPA5G[2]; /* pathA / pathB */ - - u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */ - u8 ThermalValue; - u8 ThermalValue_LCK; - u8 ThermalValue_IQK; - u8 ThermalValue_DPK; - u8 ThermalValue_AVG[AVG_THERMAL_NUM]; - u8 ThermalValue_AVG_index; - u8 ThermalValue_RxGain; - u8 ThermalValue_Crystal; - u8 ThermalValue_DPKstore; - u8 ThermalValue_DPKtrack; - bool TxPowerTrackingInProgress; - bool bDPKenable; - - bool bReloadtxpowerindex; - u8 bRfPiEnable; - u32 TXPowerTrackingCallbackCnt; /* cosa add for debug */ - - u8 bCCKinCH14; - u8 CCK_index; - u8 OFDM_index[2]; - bool bDoneTxpower; - - u8 ThermalValue_HP[HP_THERMAL_NUM]; - u8 ThermalValue_HP_index; - struct iqk_matrix_regs_set IQKMatrixRegSetting[IQK_Matrix_Settings_NUM]; - - u8 Delta_IQK; - u8 Delta_LCK; - - /* for IQK */ - u32 RegC04; - u32 Reg874; - u32 RegC08; - u32 RegB68; - u32 RegB6C; - u32 Reg870; - u32 Reg860; - u32 Reg864; - - bool bIQKInitialized; - bool bLCKInProgress; - bool bAntennaDetected; - u32 ADDA_backup[IQK_ADDA_REG_NUM]; - u32 IQK_MAC_backup[IQK_MAC_REG_NUM]; - u32 IQK_BB_backup_recover[9]; - u32 IQK_BB_backup[IQK_BB_REG_NUM]; - - /* for APK */ - u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */ - u8 bAPKdone; - u8 bAPKThermalMeterIgnore; - u8 bDPdone; - u8 bDPPathAOK; - u8 bDPPathBOK; -}; - -enum ant_dif_type { - NO_ANTDIV = 0xFF, - CG_TRX_HW_ANTDIV = 0x01, - CGCS_RX_HW_ANTDIV = 0x02, - FIXED_HW_ANTDIV = 0x03, - CG_TRX_SMART_ANTDIV = 0x04, - CGCS_RX_SW_ANTDIV = 0x05, -}; - -/* 2011/09/22 MH Copy from SD4 defined structure. We use to support PHY DM integration. */ -struct dm_odm_t { - /* */ - /* Add for different team use temporarily */ - /* */ - struct rtw_adapter *Adapter; /* For CE/NIC team */ - - u64 DebugComponents; - u32 DebugLevel; - -/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */ - bool bCckHighPower; - u8 RFPathRxEnable; /* ODM_CMNINFO_RFPATH_ENABLE */ -/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */ - -/* 1 COMMON INFORMATION */ - - /* Init Value */ -/* HOOK BEFORE REG INIT----------- */ - /* ODM Support Ability DIG/RATR/TX_PWR_TRACK/ ¡K¡K = 1/2/3/¡K */ - u32 SupportAbility; - /* ODM composite or independent. Bit oriented/ 92C+92D+ .... or any other type = 1/2/3/... */ - u32 SupportICType; - /* Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */ - u8 CutVersion; - /* Fab Version TSMC/UMC = 0/1 */ - u8 FabVersion; - /* Board Type Normal/HighPower/MiniCard/SLIM/Combo/... = 0/1/2/3/4/... */ - u8 BoardType; - /* with external LNA NO/Yes = 0/1 */ - u8 ExtLNA; - /* with external PA NO/Yes = 0/1 */ - u8 ExtPA; - /* with external TRSW NO/Yes = 0/1 */ - u8 ExtTRSW; - bool bInHctTest; - bool bWIFITest; - - bool bDualMacSmartConcurrent; - u32 BK_SupportAbility; -/* HOOK BEFORE REG INIT----------- */ - - /* */ - /* Dynamic Value */ - /* */ -/* POINTER REFERENCE----------- */ - - u8 u8_temp; - bool bool_temp; - struct rtw_adapter *PADAPTER_temp; - -/* POINTER REFERENCE----------- */ - /* */ -/* CALL BY VALUE------------- */ - bool bWIFI_Direct; - bool bWIFI_Display; - bool bLinked; - u8 RSSI_Min; - u8 InterfaceIndex; /* Add for 92D dual MAC: 0--Mac0 1--Mac1 */ - bool bIsMPChip; - bool bOneEntryOnly; - /* Common info for BTDM */ - bool bBtDisabled; /* BT is disabled */ - bool bBtHsOperation; /* BT HS mode is under progress */ - u8 btHsDigVal; /* use BT rssi to decide the DIG value */ - bool bBtDisableEdcaTurbo; /* Under some condition, don't enable the EDCA Turbo */ - bool bBtBusy; /* BT is busy. */ -/* CALL BY VALUE------------- */ - - /* 2 Define STA info. */ - /* _ODM_STA_INFO */ - /* 2012/01/12 MH For MP, we need to reduce one array pointer for default port.?? */ - struct sta_info * pODM_StaInfo[ODM_ASSOCIATE_ENTRY_NUM]; - - /* Latest packet phy info (ODM write) */ - struct odm_phy_dbg_info PhyDbgInfo; - /* PHY_INFO_88E PhyInfo; */ - - /* Latest packet phy info (ODM write) */ - /* MAC_INFO_88E MacInfo; */ - - /* Different Team independt structure?? */ - - /* */ - /* TX_RTP_CMN TX_retrpo; */ - /* TX_RTP_88E TX_retrpo; */ - /* TX_RTP_8195 TX_retrpo; */ - - /* */ - /* ODM Structure */ - /* */ - struct dig_t DM_DigTable; - struct dynamic_pwr_sav DM_PSTable; - struct false_alarm_stats FalseAlmCnt; - struct false_alarm_stats FlaseAlmCntBuddyAdapter; - struct sw_ant_sw DM_SWAT_Table; - - struct edca_turbo DM_EDCA_Table; - u32 WMMEDCA_BE; - /* Copy from SD4 structure */ - /* */ - /* ================================================== */ - /* */ - - /* PSD */ - u8 RSSI_BT; /* come from BT */ - struct odm_rate_adapt RateAdaptive; - - - struct odm_rf_cal_t RFCalibrateInfo; -}; /* DM_Dynamic_Mechanism_Structure */ - -enum odm_rf_content { - odm_radioa_txt = 0x1000, - odm_radiob_txt = 0x1001, - odm_radioc_txt = 0x1002, - odm_radiod_txt = 0x1003 -}; - -/* Status code */ -enum rt_status { - RT_STATUS_SUCCESS, - RT_STATUS_FAILURE, - RT_STATUS_PENDING, - RT_STATUS_RESOURCE, - RT_STATUS_INVALID_CONTEXT, - RT_STATUS_INVALID_PARAMETER, - RT_STATUS_NOT_SUPPORT, - RT_STATUS_OS_API_FAILED, -}; - -/* include "odm_function.h" */ - -/* 3=========================================================== */ -/* 3 DIG */ -/* 3=========================================================== */ - -enum dm_dig_op { - DIG_TYPE_THRESH_HIGH = 0, - DIG_TYPE_THRESH_LOW = 1, - DIG_TYPE_BACKOFF = 2, - DIG_TYPE_RX_GAIN_MIN = 3, - DIG_TYPE_RX_GAIN_MAX = 4, - DIG_TYPE_ENABLE = 5, - DIG_TYPE_DISABLE = 6, - DIG_OP_TYPE_MAX -}; - -#define DM_DIG_THRESH_HIGH 40 -#define DM_DIG_THRESH_LOW 35 - -#define DM_SCAN_RSSI_TH 0x14 /* scan return issue for LC */ - - -#define DM_FALSEALARM_THRESH_LOW 400 -#define DM_FALSEALARM_THRESH_HIGH 1000 - -#define DM_DIG_MAX_NIC 0x4e -#define DM_DIG_MIN_NIC 0x1e - -#define DM_DIG_MAX_AP 0x32 -#define DM_DIG_MIN_AP 0x20 - -#define DM_DIG_MAX_NIC_HP 0x46 -#define DM_DIG_MIN_NIC_HP 0x2e - -#define DM_DIG_MAX_AP_HP 0x42 -#define DM_DIG_MIN_AP_HP 0x30 - -/* vivi 92c&92d has different definition, 20110504 */ -/* this is for 92c */ -#define DM_DIG_FA_TH0 0x200 -#define DM_DIG_FA_TH1 0x300 -#define DM_DIG_FA_TH2 0x400 -/* this is for 92d */ -#define DM_DIG_FA_TH0_92D 0x100 -#define DM_DIG_FA_TH1_92D 0x400 -#define DM_DIG_FA_TH2_92D 0x600 - -#define DM_DIG_BACKOFF_MAX 12 -#define DM_DIG_BACKOFF_MIN -4 -#define DM_DIG_BACKOFF_DEFAULT 10 - -/* 3=========================================================== */ -/* 3 AGC RX High Power Mode */ -/* 3=========================================================== */ -#define LNA_Low_Gain_1 0x64 -#define LNA_Low_Gain_2 0x5A -#define LNA_Low_Gain_3 0x58 - -#define FA_RXHP_TH1 5000 -#define FA_RXHP_TH2 1500 -#define FA_RXHP_TH3 800 -#define FA_RXHP_TH4 600 -#define FA_RXHP_TH5 500 - -/* 3=========================================================== */ -/* 3 EDCA */ -/* 3=========================================================== */ - -/* 3=========================================================== */ -/* 3 Dynamic Tx Power */ -/* 3=========================================================== */ -/* Dynamic Tx Power Control Threshold */ -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 -#define TX_POWER_NEAR_FIELD_THRESH_AP 0x3F - -#define TxHighPwrLevel_Normal 0 -#define TxHighPwrLevel_Level1 1 -#define TxHighPwrLevel_Level2 2 -#define TxHighPwrLevel_BT1 3 -#define TxHighPwrLevel_BT2 4 -#define TxHighPwrLevel_15 5 -#define TxHighPwrLevel_35 6 -#define TxHighPwrLevel_50 7 -#define TxHighPwrLevel_70 8 -#define TxHighPwrLevel_100 9 - -/* 3=========================================================== */ -/* 3 Rate Adaptive */ -/* 3=========================================================== */ -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -/* 3=========================================================== */ -/* 3 BB Power Save */ -/* 3=========================================================== */ - - -enum dm_1r_cca { - CCA_1R =0, - CCA_2R = 1, - CCA_MAX = 2, -}; - -enum dm_rf_def { - RF_Save =0, - RF_Normal = 1, - RF_MAX = 2, -}; - -/* 3=========================================================== */ -/* 3 Antenna Diversity */ -/* 3=========================================================== */ -enum dm_swas { - Antenna_A = 1, - Antenna_B = 2, - Antenna_MAX = 3, -}; - -/* Maximal number of antenna detection mechanism needs to perform, added by Roger, 2011.12.28. */ -#define MAX_ANTENNA_DETECTION_CNT 10 - -/* */ -/* Extern Global Variables. */ -/* */ -#define OFDM_TABLE_SIZE_92C 37 -#define OFDM_TABLE_SIZE_92D 43 -#define CCK_TABLE_SIZE 33 - -extern u32 OFDMSwingTable23A[OFDM_TABLE_SIZE_92D]; -extern u8 CCKSwingTable_Ch1_Ch1323A[CCK_TABLE_SIZE][8]; -extern u8 CCKSwingTable_Ch1423A [CCK_TABLE_SIZE][8]; - - - -/* 20100514 Joseph: Add definition for antenna switching test after link. */ -/* This indicates two different the steps. */ -/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */ -/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK */ -/* with original RSSI to determine if it is necessary to switch antenna. */ -#define SWAW_STEP_PEAK 0 -#define SWAW_STEP_DETERMINE 1 - -struct hal_data_8723a; - -void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm, u8 CurrentIGI); -void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8 CurCCK_CCAThres); - -void ODM_SetAntenna(struct dm_odm_t *pDM_Odm, u8 Antenna); - - -#define dm_RF_Saving ODM_RF_Saving23a -void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal); - -#define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck23a -void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm); - -bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate, - u8 *pRATRState); - - -u32 ConvertTo_dB23a(u32 Value); - -u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, u8 initial_gain_psd); - -void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm); - -u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid, u32 ra_mask, u8 rssi_level); - - -void ODM23a_DMInit(struct dm_odm_t *pDM_Odm); - -void ODM_DMWatchdog23a(struct rtw_adapter *adapter); - -void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, u32 Value); - -void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, u16 Index, void *pValue); - -void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value); - -void ODM_ResetIQKResult(struct dm_odm_t *pDM_Odm); - -void ODM_AntselStatistics_88C(struct dm_odm_t *pDM_Odm, u8 MacId, u32 PWDBAll, bool isCCKrate); - -void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm); - -bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode); - -#endif diff --git a/drivers/staging/rtl8723au/include/odm_HWConfig.h b/drivers/staging/rtl8723au/include/odm_HWConfig.h deleted file mode 100644 index c748d5fb47fa..000000000000 --- a/drivers/staging/rtl8723au/include/odm_HWConfig.h +++ /dev/null @@ -1,153 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - - -#ifndef __HALHWOUTSRC_H__ -#define __HALHWOUTSRC_H__ - -#include - -/* */ -/* Definition */ -/* */ -/* */ -/* */ -/* CCK Rates, TxHT = 0 */ -#define DESC92C_RATE1M 0x00 -#define DESC92C_RATE2M 0x01 -#define DESC92C_RATE5_5M 0x02 -#define DESC92C_RATE11M 0x03 - -/* OFDM Rates, TxHT = 0 */ -#define DESC92C_RATE6M 0x04 -#define DESC92C_RATE9M 0x05 -#define DESC92C_RATE12M 0x06 -#define DESC92C_RATE18M 0x07 -#define DESC92C_RATE24M 0x08 -#define DESC92C_RATE36M 0x09 -#define DESC92C_RATE48M 0x0a -#define DESC92C_RATE54M 0x0b - -/* MCS Rates, TxHT = 1 */ -#define DESC92C_RATEMCS0 0x0c -#define DESC92C_RATEMCS1 0x0d -#define DESC92C_RATEMCS2 0x0e -#define DESC92C_RATEMCS3 0x0f -#define DESC92C_RATEMCS4 0x10 -#define DESC92C_RATEMCS5 0x11 -#define DESC92C_RATEMCS6 0x12 -#define DESC92C_RATEMCS7 0x13 -#define DESC92C_RATEMCS8 0x14 -#define DESC92C_RATEMCS9 0x15 -#define DESC92C_RATEMCS10 0x16 -#define DESC92C_RATEMCS11 0x17 -#define DESC92C_RATEMCS12 0x18 -#define DESC92C_RATEMCS13 0x19 -#define DESC92C_RATEMCS14 0x1a -#define DESC92C_RATEMCS15 0x1b -#define DESC92C_RATEMCS15_SG 0x1c -#define DESC92C_RATEMCS32 0x20 - - -/* */ -/* structure and define */ -/* */ - -struct phy_rx_agc_info { - #ifdef __LITTLE_ENDIAN - u8 gain:7, trsw:1; - #else - u8 trsw:1, gain:7; - #endif -}; - -struct phy_status_rpt { - struct phy_rx_agc_info path_agc[RF_PATH_MAX]; - u8 ch_corr[RF_PATH_MAX]; - u8 cck_sig_qual_ofdm_pwdb_all; - u8 cck_agc_rpt_ofdm_cfosho_a; - u8 cck_rpt_b_ofdm_cfosho_b; - u8 rsvd_1;/* ch_corr_msb; */ - u8 noise_power_db_msb; - u8 path_cfotail[RF_PATH_MAX]; - u8 pcts_mask[RF_PATH_MAX]; - s8 stream_rxevm[RF_PATH_MAX]; - u8 path_rxsnr[RF_PATH_MAX]; - u8 noise_power_db_lsb; - u8 rsvd_2[3]; - u8 stream_csi[RF_PATH_MAX]; - u8 stream_target_csi[RF_PATH_MAX]; - s8 sig_evm; - u8 rsvd_3; - -#ifdef __LITTLE_ENDIAN - u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ - u8 sgi_en:1; - u8 rxsc:2; - u8 idle_long:1; - u8 r_ant_train_en:1; - u8 ant_sel_b:1; - u8 ant_sel:1; -#else /* _BIG_ENDIAN_ */ - u8 ant_sel:1; - u8 ant_sel_b:1; - u8 r_ant_train_en:1; - u8 idle_long:1; - u8 rxsc:2; - u8 sgi_en:1; - u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ -#endif -}; - - -struct phy_status_rpt_8195 { - struct phy_rx_agc_info path_agc[2]; - u8 ch_num[2]; - u8 cck_sig_qual_ofdm_pwdb_all; - u8 cck_agc_rpt_ofdm_cfosho_a; - u8 cck_bb_pwr_ofdm_cfosho_b; - u8 cck_rx_path; /* CCK_RX_PATH [3:0] (with regA07[3:0] definition) */ - u8 rsvd_1; - u8 path_cfotail[2]; - u8 pcts_mask[2]; - s8 stream_rxevm[2]; - u8 path_rxsnr[2]; - u8 rsvd_2[2]; - u8 stream_snr[2]; - u8 stream_csi[2]; - u8 rsvd_3[2]; - s8 sig_evm; - u8 rsvd_4; -#ifdef __LITTLE_ENDIAN - u8 antidx_anta:3; - u8 antidx_antb:3; - u8 rsvd_5:2; -#else /* _BIG_ENDIAN_ */ - u8 rsvd_5:2; - u8 antidx_antb:3; - u8 antidx_anta:3; -#endif -}; - - -void -ODM_PhyStatusQuery23a( - struct dm_odm_t *pDM_Odm, - struct phy_info *pPhyInfo, - u8 * pPhyStatus, - struct odm_packet_info *pPktinfo - ); - -#endif diff --git a/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h b/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h deleted file mode 100644 index f2a54d829ed5..000000000000 --- a/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h +++ /dev/null @@ -1,27 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __INC_ODM_REGCONFIG_H_8723A -#define __INC_ODM_REGCONFIG_H_8723A - -void odm_ConfigRFReg_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data, - enum RF_RADIO_PATH RF_PATH, u32 RegAddr); - -void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u8 Data); - -void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data); - -void odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data); - -#endif /* end of SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/odm_RegDefine11N.h b/drivers/staging/rtl8723au/include/odm_RegDefine11N.h deleted file mode 100644 index 27782154f502..000000000000 --- a/drivers/staging/rtl8723au/include/odm_RegDefine11N.h +++ /dev/null @@ -1,165 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#ifndef __ODM_REGDEFINE11N_H__ -#define __ODM_REGDEFINE11N_H__ - - -/* 2 RF REG LIST */ -#define ODM_REG_RF_MODE_11N 0x00 -#define ODM_REG_RF_0B_11N 0x0B -#define ODM_REG_CHNBW_11N 0x18 -#define ODM_REG_T_METER_11N 0x24 -#define ODM_REG_RF_25_11N 0x25 -#define ODM_REG_RF_26_11N 0x26 -#define ODM_REG_RF_27_11N 0x27 -#define ODM_REG_RF_2B_11N 0x2B -#define ODM_REG_RF_2C_11N 0x2C -#define ODM_REG_RXRF_A3_11N 0x3C -#define ODM_REG_T_METER_92D_11N 0x42 -#define ODM_REG_T_METER_88E_11N 0x42 - - - -/* 2 BB REG LIST */ -/* PAGE 8 */ -#define ODM_REG_BB_CTRL_11N 0x800 -#define ODM_REG_RF_PIN_11N 0x804 -#define ODM_REG_PSD_CTRL_11N 0x808 -#define ODM_REG_TX_ANT_CTRL_11N 0x80C -#define ODM_REG_BB_PWR_SAV5_11N 0x818 -#define ODM_REG_CCK_RPT_FORMAT_11N 0x824 -#define ODM_REG_RX_DEFUALT_A_11N 0x858 -#define ODM_REG_RX_DEFUALT_B_11N 0x85A -#define ODM_REG_BB_PWR_SAV3_11N 0x85C -#define ODM_REG_ANTSEL_CTRL_11N 0x860 -#define ODM_REG_RX_ANT_CTRL_11N 0x864 -#define ODM_REG_PIN_CTRL_11N 0x870 -#define ODM_REG_BB_PWR_SAV1_11N 0x874 -#define ODM_REG_ANTSEL_PATH_11N 0x878 -#define ODM_REG_BB_3WIRE_11N 0x88C -#define ODM_REG_SC_CNT_11N 0x8C4 -#define ODM_REG_PSD_DATA_11N 0x8B4 -/* PAGE 9 */ -#define ODM_REG_ANT_MAPPING1_11N 0x914 -#define ODM_REG_ANT_MAPPING2_11N 0x918 -/* PAGE A */ -#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00 -#define ODM_REG_CCK_CCA_11N 0xA0A -#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C -#define ODM_REG_CCK_ANTDIV_PARA3_11N 0xA10 -#define ODM_REG_CCK_ANTDIV_PARA4_11N 0xA14 -#define ODM_REG_CCK_FILTER_PARA1_11N 0xA22 -#define ODM_REG_CCK_FILTER_PARA2_11N 0xA23 -#define ODM_REG_CCK_FILTER_PARA3_11N 0xA24 -#define ODM_REG_CCK_FILTER_PARA4_11N 0xA25 -#define ODM_REG_CCK_FILTER_PARA5_11N 0xA26 -#define ODM_REG_CCK_FILTER_PARA6_11N 0xA27 -#define ODM_REG_CCK_FILTER_PARA7_11N 0xA28 -#define ODM_REG_CCK_FILTER_PARA8_11N 0xA29 -#define ODM_REG_CCK_FA_RST_11N 0xA2C -#define ODM_REG_CCK_FA_MSB_11N 0xA58 -#define ODM_REG_CCK_FA_LSB_11N 0xA5C -#define ODM_REG_CCK_CCA_CNT_11N 0xA60 -#define ODM_REG_BB_PWR_SAV4_11N 0xA74 -/* PAGE B */ -#define ODM_REG_LNA_SWITCH_11N 0xB2C -#define ODM_REG_PATH_SWITCH_11N 0xB30 -#define ODM_REG_RSSI_CTRL_11N 0xB38 -#define ODM_REG_CONFIG_ANTA_11N 0xB68 -#define ODM_REG_RSSI_BT_11N 0xB9C -/* PAGE C */ -#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00 -#define ODM_REG_RX_PATH_11N 0xC04 -#define ODM_REG_TRMUX_11N 0xC08 -#define ODM_REG_OFDM_FA_RSTC_11N 0xC0C -#define ODM_REG_RXIQI_MATRIX_11N 0xC14 -#define ODM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C -#define ODM_REG_IGI_A_11N 0xC50 -#define ODM_REG_ANTDIV_PARA2_11N 0xC54 -#define ODM_REG_IGI_B_11N 0xC58 -#define ODM_REG_ANTDIV_PARA3_11N 0xC5C -#define ODM_REG_BB_PWR_SAV2_11N 0xC70 -#define ODM_REG_RX_OFF_11N 0xC7C -#define ODM_REG_TXIQK_MATRIXA_11N 0xC80 -#define ODM_REG_TXIQK_MATRIXB_11N 0xC88 -#define ODM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 -#define ODM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C -#define ODM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 -#define ODM_REG_ANTDIV_PARA1_11N 0xCA4 -#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0 -/* PAGE D */ -#define ODM_REG_OFDM_FA_RSTD_11N 0xD00 -#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0 -#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4 -#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8 -/* PAGE E */ -#define ODM_REG_TXAGC_A_6_18_11N 0xE00 -#define ODM_REG_TXAGC_A_24_54_11N 0xE04 -#define ODM_REG_TXAGC_A_1_MCS32_11N 0xE08 -#define ODM_REG_TXAGC_A_MCS0_3_11N 0xE10 -#define ODM_REG_TXAGC_A_MCS4_7_11N 0xE14 -#define ODM_REG_TXAGC_A_MCS8_11_11N 0xE18 -#define ODM_REG_TXAGC_A_MCS12_15_11N 0xE1C -#define ODM_REG_FPGA0_IQK_11N 0xE28 -#define ODM_REG_TXIQK_TONE_A_11N 0xE30 -#define ODM_REG_RXIQK_TONE_A_11N 0xE34 -#define ODM_REG_TXIQK_PI_A_11N 0xE38 -#define ODM_REG_RXIQK_PI_A_11N 0xE3C -#define ODM_REG_TXIQK_11N 0xE40 -#define ODM_REG_RXIQK_11N 0xE44 -#define ODM_REG_IQK_AGC_PTS_11N 0xE48 -#define ODM_REG_IQK_AGC_RSP_11N 0xE4C -#define ODM_REG_BLUETOOTH_11N 0xE6C -#define ODM_REG_RX_WAIT_CCA_11N 0xE70 -#define ODM_REG_TX_CCK_RFON_11N 0xE74 -#define ODM_REG_TX_CCK_BBON_11N 0xE78 -#define ODM_REG_OFDM_RFON_11N 0xE7C -#define ODM_REG_OFDM_BBON_11N 0xE80 -#define ODM_REG_TX2RX_11N 0xE84 -#define ODM_REG_TX2TX_11N 0xE88 -#define ODM_REG_RX_CCK_11N 0xE8C -#define ODM_REG_RX_OFDM_11N 0xED0 -#define ODM_REG_RX_WAIT_RIFS_11N 0xED4 -#define ODM_REG_RX2RX_11N 0xED8 -#define ODM_REG_STANDBY_11N 0xEDC -#define ODM_REG_SLEEP_11N 0xEE0 -#define ODM_REG_PMPD_ANAEN_11N 0xEEC - - - - - - - -/* 2 MAC REG LIST */ -#define ODM_REG_BB_RST_11N 0x02 -#define ODM_REG_ANTSEL_PIN_11N 0x4C -#define ODM_REG_EARLY_MODE_11N 0x4D0 -#define ODM_REG_RSSI_MONITOR_11N 0x4FE -#define ODM_REG_EDCA_VO_11N 0x500 -#define ODM_REG_EDCA_VI_11N 0x504 -#define ODM_REG_EDCA_BE_11N 0x508 -#define ODM_REG_EDCA_BK_11N 0x50C -#define ODM_REG_TXPAUSE_11N 0x522 -#define ODM_REG_RESP_TX_11N 0x6D8 -#define ODM_REG_ANT_TRAIN_PARA1_11N 0x7b0 -#define ODM_REG_ANT_TRAIN_PARA2_11N 0x7b4 - - -/* DIG Related */ -#define ODM_BIT_IGI_11N 0x0000007F - -#endif diff --git a/drivers/staging/rtl8723au/include/odm_debug.h b/drivers/staging/rtl8723au/include/odm_debug.h deleted file mode 100644 index c4b375a6f409..000000000000 --- a/drivers/staging/rtl8723au/include/odm_debug.h +++ /dev/null @@ -1,117 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - - -#ifndef __ODM_DBG_H__ -#define __ODM_DBG_H__ - - -/* */ -/* Define the debug levels */ -/* */ -/* 1. DBG_TRACE and DBG_LOUD are used for normal cases. */ -/* So that, they can help SW engineer to develop or trace states changed */ -/* and also help HW enginner to trace every operation to and from HW, */ -/* e.g IO, Tx, Rx. */ -/* */ -/* 2. DBG_WARNNING and DBG_SERIOUS are used for unusual or error cases, */ -/* which help us to debug SW or HW. */ -/* */ -/* */ -/* */ -/* Never used in a call to ODM_RT_TRACE()! */ -/* */ -#define ODM_DBG_OFF 1 - -/* */ -/* Fatal bug. */ -/* For example, Tx/Rx/IO locked up, OS hangs, memory access violation, */ -/* resource allocation failed, unexpected HW behavior, HW BUG and so on. */ -/* */ -#define ODM_DBG_SERIOUS 2 - -/* */ -/* Abnormal, rare, or unexpeted cases. */ -/* For example, IRP/Packet/OID canceled, device suprisely unremoved and so on. */ -/* */ -#define ODM_DBG_WARNING 3 - -/* */ -/* Normal case with useful information about current SW or HW state. */ -/* For example, Tx/Rx descriptor to fill, Tx/Rx descriptor completed status, */ -/* SW protocol state change, dynamic mechanism state change and so on. */ -/* */ -#define ODM_DBG_LOUD 4 - -/* */ -/* Normal case with detail execution flow or information. */ -/* */ -#define ODM_DBG_TRACE 5 - -/* */ -/* Define the tracing components */ -/* */ -/* */ -/* BB Functions */ -#define ODM_COMP_DIG BIT(0) -#define ODM_COMP_RA_MASK BIT(1) -#define ODM_COMP_DYNAMIC_TXPWR BIT(2) -#define ODM_COMP_FA_CNT BIT(3) -#define ODM_COMP_RSSI_MONITOR BIT(4) -#define ODM_COMP_CCK_PD BIT(5) -#define ODM_COMP_ANT_DIV BIT(6) -#define ODM_COMP_PWR_SAVE BIT(7) -#define ODM_COMP_PWR_TRAIN BIT(8) -#define ODM_COMP_RATE_ADAPTIVE BIT(9) -#define ODM_COMP_PATH_DIV BIT(10) -#define ODM_COMP_PSD BIT(11) -#define ODM_COMP_DYNAMIC_PRICCA BIT(12) -#define ODM_COMP_RXHP BIT(13) -/* MAC Functions */ -#define ODM_COMP_EDCA_TURBO BIT(16) -#define ODM_COMP_EARLY_MODE BIT(17) -/* RF Functions */ -#define ODM_COMP_TX_PWR_TRACK BIT(24) -#define ODM_COMP_RX_GAIN_TRACK BIT(25) -#define ODM_COMP_CALIBRATION BIT(26) -/* Common Functions */ -#define ODM_COMP_COMMON BIT(30) -#define ODM_COMP_INIT BIT(31) - -/*------------------------Export Macro Definition---------------------------*/ - #define RT_PRINTK(fmt, args...) printk("%s(): " fmt, __func__, ## args); - -#ifndef ASSERT - #define ASSERT(expr) -#endif - -#define ODM_RT_TRACE(pDM_Odm, comp, level, fmt) \ - if(((comp) & pDM_Odm->DebugComponents) && (level <= pDM_Odm->DebugLevel)) \ - { \ - printk("[ODM-8723A] "); \ - RT_PRINTK fmt; \ - } - -#define ODM_RT_ASSERT(pDM_Odm, expr, fmt) \ - if(!(expr)) { \ - printk("Assertion failed! %s at ......\n", #expr); \ - printk(" ......%s,%s,line=%d\n", __FILE__, __func__, __LINE__);\ - RT_PRINTK fmt; \ - ASSERT(false); \ - } - -void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm); - -#endif /* __ODM_DBG_H__ */ diff --git a/drivers/staging/rtl8723au/include/odm_interface.h b/drivers/staging/rtl8723au/include/odm_interface.h deleted file mode 100644 index 1d3bf03b59ea..000000000000 --- a/drivers/staging/rtl8723au/include/odm_interface.h +++ /dev/null @@ -1,62 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - - -#ifndef __ODM_INTERFACE_H__ -#define __ODM_INTERFACE_H__ - - -/* _cat: implemented by Token-Pasting Operator. */ - -/*=================================== - -#define ODM_REG_DIG_11N 0xC50 -#define ODM_REG_DIG_11AC 0xDDD - -ODM_REG(DIG,_pDM_Odm) -=====================================*/ - -#define _reg_11N(_name) ODM_REG_##_name##_11N -#define _reg_11AC(_name) ODM_REG_##_name##_11AC -#define _bit_11N(_name) ODM_BIT_##_name##_11N -#define _bit_11AC(_name) ODM_BIT_##_name##_11AC - -#define _cat(_name, _func) \ - ( \ - _func##_11N(_name) \ - ) - -/* _name: name of register or bit. */ -/* Example: "ODM_REG(R_A_AGC_CORE1, pDM_Odm)" */ -/* gets "ODM_R_A_AGC_CORE1" or "ODM_R_A_AGC_CORE1_8192C", depends on SupportICType. */ -#define ODM_REG(_name, _pDM_Odm) _cat(_name, _reg) -#define ODM_BIT(_name, _pDM_Odm) _cat(_name, _bit) - -/* */ -/* 2012/02/17 MH For non-MP compile pass only. Linux does not support workitem. */ -/* Suggest HW team to use thread instead of workitem. Windows also support the feature. */ -/* */ -typedef void (*RT_WORKITEM_CALL_BACK)(struct work_struct *pContext); - -/* */ -/* =========== EXtern Function Prototype */ -/* */ - -void ODM_SetRFReg(struct dm_odm_t *pDM_Odm, enum RF_RADIO_PATH eRFPath, - u32 RegAddr, u32 BitMask, u32 Data); -u32 ODM_GetRFReg(struct dm_odm_t *pDM_Odm, enum RF_RADIO_PATH eRFPath, - u32 RegAddr, u32 BitMask); - -#endif /* __ODM_INTERFACE_H__ */ diff --git a/drivers/staging/rtl8723au/include/odm_precomp.h b/drivers/staging/rtl8723au/include/odm_precomp.h deleted file mode 100644 index fb793c8ba7f8..000000000000 --- a/drivers/staging/rtl8723au/include/odm_precomp.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#ifndef __ODM_PRECOMP_H__ -#define __ODM_PRECOMP_H__ - -/* 2 Config Flags and Structs - defined by each ODM Type */ - -#include -#include -#include - - -/* 2 Hardware Parameter Files */ -#include "Hal8723UHWImg_CE.h" - - -/* 2 OutSrc Header Files */ - -#include "odm.h" -#include "odm_HWConfig.h" -#include "odm_debug.h" -#include "odm_RegDefine11N.h" - -#include "HalDMOutSrc8723A.h" /* for IQK,LCK,Power-tracking */ -#include "rtl8723a_hal.h" - -#include "odm_interface.h" -#include "odm_reg.h" - -#include "HalHWImg8723A_MAC.h" -#include "HalHWImg8723A_RF.h" -#include "HalHWImg8723A_BB.h" -#include "HalHWImg8723A_FW.h" -#include "odm_RegConfig8723A.h" - -#endif /* __ODM_PRECOMP_H__ */ diff --git a/drivers/staging/rtl8723au/include/odm_reg.h b/drivers/staging/rtl8723au/include/odm_reg.h deleted file mode 100644 index c18433120fe8..000000000000 --- a/drivers/staging/rtl8723au/include/odm_reg.h +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -/* */ -/* File Name: odm_reg.h */ -/* */ -/* Description: */ -/* */ -/* This file is for general register definition. */ -/* */ -/* */ -/* */ -#ifndef __HAL_ODM_REG_H__ -#define __HAL_ODM_REG_H__ - -/* */ -/* Register Definition */ -/* */ - -/* MAC REG */ -#define ODM_BB_RESET 0x002 -#define ODM_DUMMY 0x4fe -#define ODM_EDCA_VO_PARAM 0x500 -#define ODM_EDCA_VI_PARAM 0x504 -#define ODM_EDCA_BE_PARAM 0x508 -#define ODM_EDCA_BK_PARAM 0x50C -#define ODM_TXPAUSE 0x522 - -/* BB REG */ -#define ODM_FPGA_PHY0_PAGE8 0x800 -#define ODM_PSD_SETTING 0x808 -#define ODM_AFE_SETTING 0x818 -#define ODM_TXAGC_B_6_18 0x830 -#define ODM_TXAGC_B_24_54 0x834 -#define ODM_TXAGC_B_MCS32_5 0x838 -#define ODM_TXAGC_B_MCS0_MCS3 0x83c -#define ODM_TXAGC_B_MCS4_MCS7 0x848 -#define ODM_TXAGC_B_MCS8_MCS11 0x84c -#define ODM_ANALOG_REGISTER 0x85c -#define ODM_RF_INTERFACE_OUTPUT 0x860 -#define ODM_TXAGC_B_MCS12_MCS15 0x868 -#define ODM_TXAGC_B_11_A_2_11 0x86c -#define ODM_AD_DA_LSB_MASK 0x874 -#define ODM_ENABLE_3_WIRE 0x88c -#define ODM_PSD_REPORT 0x8b4 -#define ODM_R_ANT_SELECT 0x90c -#define ODM_CCK_ANT_SELECT 0xa07 -#define ODM_CCK_PD_THRESH 0xa0a -#define ODM_CCK_RF_REG1 0xa11 -#define ODM_CCK_MATCH_FILTER 0xa20 -#define ODM_CCK_RAKE_MAC 0xa2e -#define ODM_CCK_CNT_RESET 0xa2d -#define ODM_CCK_TX_DIVERSITY 0xa2f -#define ODM_CCK_FA_CNT_MSB 0xa5b -#define ODM_CCK_FA_CNT_LSB 0xa5c -#define ODM_CCK_NEW_FUNCTION 0xa75 -#define ODM_OFDM_PHY0_PAGE_C 0xc00 -#define ODM_OFDM_RX_ANT 0xc04 -#define ODM_R_A_RXIQI 0xc14 -#define ODM_R_A_AGC_CORE1 0xc50 -#define ODM_R_A_AGC_CORE2 0xc54 -#define ODM_R_B_AGC_CORE1 0xc58 -#define ODM_R_AGC_PAR 0xc70 -#define ODM_R_HTSTF_AGC_PAR 0xc7c -#define ODM_TX_PWR_TRAINING_A 0xc90 -#define ODM_TX_PWR_TRAINING_B 0xc98 -#define ODM_OFDM_FA_CNT1 0xcf0 -#define ODM_OFDM_PHY0_PAGE_D 0xd00 -#define ODM_OFDM_FA_CNT2 0xda0 -#define ODM_OFDM_FA_CNT3 0xda4 -#define ODM_OFDM_FA_CNT4 0xda8 -#define ODM_TXAGC_A_6_18 0xe00 -#define ODM_TXAGC_A_24_54 0xe04 -#define ODM_TXAGC_A_1_MCS32 0xe08 -#define ODM_TXAGC_A_MCS0_MCS3 0xe10 -#define ODM_TXAGC_A_MCS4_MCS7 0xe14 -#define ODM_TXAGC_A_MCS8_MCS11 0xe18 -#define ODM_TXAGC_A_MCS12_MCS15 0xe1c - -/* RF REG */ -#define ODM_GAIN_SETTING 0x00 -#define ODM_CHANNEL 0x18 - -/* Ant Detect Reg */ -#define ODM_DPDT 0x300 - -/* PSD Init */ -#define ODM_PSDREG 0x808 - -/* 92D Path Div */ -#define PATHDIV_REG 0xB30 -#define PATHDIV_TRI 0xBA0 - -/* */ -/* Bitmap Definition */ -/* */ - -#define BIT_FA_RESET BIT(0) - -#endif diff --git a/drivers/staging/rtl8723au/include/osdep_intf.h b/drivers/staging/rtl8723au/include/osdep_intf.h deleted file mode 100644 index a157eb2e78df..000000000000 --- a/drivers/staging/rtl8723au/include/osdep_intf.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#ifndef __OSDEP_INTF_H_ -#define __OSDEP_INTF_H_ - -#include -#include - -int rtw_init_drv_sw23a(struct rtw_adapter *padapter); -int rtw_free_drv_sw23a(struct rtw_adapter *padapter); -int rtw_reset_drv_sw23a(struct rtw_adapter *padapter); - -void rtw_cancel_all_timer23a(struct rtw_adapter *padapter); - -int rtw_init_netdev23a_name23a(struct net_device *pnetdev, const char *ifname); -struct net_device *rtw_init_netdev23a(struct rtw_adapter *padapter); - -u16 rtw_recv_select_queue23a(struct sk_buff *skb); - -void rtw_ips_dev_unload23a(struct rtw_adapter *padapter); - -int rtw_ips_pwr_up23a(struct rtw_adapter *padapter); -void rtw_ips_pwr_down23a(struct rtw_adapter *padapter); - -int rtw_drv_register_netdev(struct rtw_adapter *padapter); -void rtw_ndev_destructor(struct net_device *ndev); - -int rtl8723au_inirp_init(struct rtw_adapter *Adapter); -int rtl8723au_inirp_deinit(struct rtw_adapter *Adapter); -void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter); - -#endif /* _OSDEP_INTF_H_ */ diff --git a/drivers/staging/rtl8723au/include/osdep_service.h b/drivers/staging/rtl8723au/include/osdep_service.h deleted file mode 100644 index 98250b12e9f2..000000000000 --- a/drivers/staging/rtl8723au/include/osdep_service.h +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __OSDEP_SERVICE_H_ -#define __OSDEP_SERVICE_H_ - -#define _FAIL 0 -#define _SUCCESS 1 -#define RTW_RX_HANDLED 2 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for struct tasklet_struct */ -#include - -#include -#include - -struct rtw_queue { - struct list_head queue; - spinlock_t lock; -}; - -static inline struct list_head *get_list_head(struct rtw_queue *queue) -{ - return &queue->queue; -} - -static inline int rtw_netif_queue_stopped(struct net_device *pnetdev) -{ - return (netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 1)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 2)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3))); -} - -static inline u32 CHKBIT(u32 x) -{ - WARN_ON(x >= 32); - if (x >= 32) - return 0; - return BIT(x); -} - -extern unsigned char MCS_rate_2R23A[16]; - -extern unsigned char MCS_rate_2R23A[16]; -extern unsigned char MCS_rate_1R23A[16]; - -void _rtw_init_queue23a(struct rtw_queue *pqueue); - -/* Macros for handling unaligned memory accesses */ - -#define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ - ((u32) (a)[2])) - -#endif diff --git a/drivers/staging/rtl8723au/include/recv_osdep.h b/drivers/staging/rtl8723au/include/recv_osdep.h deleted file mode 100644 index c2d3f1bd5948..000000000000 --- a/drivers/staging/rtl8723au/include/recv_osdep.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RECV_OSDEP_H_ -#define __RECV_OSDEP_H_ - -#include -#include - -int _rtw_init_recv_priv23a(struct recv_priv *precvpriv, struct rtw_adapter *padapter); -void _rtw_free_recv_priv23a (struct recv_priv *precvpriv); - -int rtw_recv_entry23a(struct recv_frame *precv_frame); -int rtw_recv_indicatepkt23a(struct rtw_adapter *adapter, struct recv_frame *precv_frame); - -void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup); - -int rtw_init_recv_priv(struct recv_priv *precvpriv, struct rtw_adapter *padapter); -void rtw_free_recv_priv (struct recv_priv *precvpriv); - -int rtw_os_recv_resource_init(struct recv_priv *precvpriv, struct rtw_adapter *padapter); - -void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h b/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h deleted file mode 100644 index 7add5dfe015f..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h +++ /dev/null @@ -1,1627 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_BT_COEXIST_H__ -#define __RTL8723A_BT_COEXIST_H__ - -#include -#include "odm_precomp.h" - - -/* HEADER/PlatformDef.h */ -enum rt_media_status { - RT_MEDIA_DISCONNECT = 0, - RT_MEDIA_CONNECT = 1 -}; - -/* ===== Below this line is sync from SD7 driver COMMON/BT.h ===== */ - -#define BT_TMP_BUF_SIZE 100 - -void BT_SignalCompensation(struct rtw_adapter *padapter, - u8 *rssi_wifi, u8 *rssi_bt); -void BT_HaltProcess(struct rtw_adapter *padapter); -void BT_LpsLeave(struct rtw_adapter *padapter); - - -#define BT_HsConnectionEstablished(Adapter) false -/* ===== End of sync from SD7 driver COMMON/BT.h ===== */ - -/* HEADER/SecurityType.h */ -#define TKIP_ENC_KEY_POS 32 /* KEK_LEN+KEK_LEN) */ -#define MAXRSNIELEN 256 - -/* COMMON/Protocol802_11.h */ -/* */ -/* 802.11 Management frame Status Code field */ -/* */ -struct octet_string { - u8 *Octet; - u16 Length; -}; - - -/* AES_CCMP specific */ -enum { - AESCCMP_BLK_SIZE = 16, /* # octets in an AES block */ - AESCCMP_MAX_PACKET = 4*512, /* largest packet size */ - AESCCMP_N_RESERVED = 0, /* reserved nonce octet value */ - AESCCMP_A_DATA = 0x40, /* the Adata bit in the flags */ - AESCCMP_M_SHIFT = 3, /* how much to shift the 3-bit M field */ - AESCCMP_L_SHIFT = 0, /* how much to shift the 3-bit L field */ - AESCCMP_L_SIZE = 2, /* size of the l(m) length field (in octets) */ - AESCCMP_OFFSET_SC = 22, - AESCCMP_OFFSET_DURATION = 4, - AESCCMP_OFFSET_A2 = 10, - AESCCMP_OFFSET_A4 = 24, - AESCCMP_QC_TID_MASK = 0x0f, - AESCCMP_BLK_SIZE_TOTAL = 16*16, /* Added by Annie for CKIP AES MIC BSOD, 2006-08-17. */ - /* 16*8 < 4*60 Resove to 16*16 */ -}; - -/* Key Length */ -#define PMK_LEN 32 -#define PTK_LEN_TKIP 64 -#define GTK_LEN 32 -#define KEY_NONCE_LEN 32 - - -/* COMMON/Dot11d.h */ -struct chnl_txpower_triple { - u8 FirstChnl; - u8 NumChnls; - s8 MaxTxPowerInDbm; -}; - - -/* ===== Below this line is sync from SD7 driver COMMON/bt_hci.h ===== */ -/* The following is for BT 3.0 + HS HCI COMMAND ERRORS CODES */ - -#define Max80211PALPDUSize 1492 -#define Max80211AMPASSOCLen 672 -#define MinGUserPrio 4 -#define MaxGUserPrio 7 -#define BEUserPrio0 0 -#define BEUserPrio1 3 -#define Max80211BeaconPeriod 2000 -#define ShortRangeModePowerMax 4 - -#define BT_Default_Chnl 10 -#define ACLDataHeaderLen 4 - -#define BTTotalDataBlockNum 0x100 -#define BTLocalBufNum 0x200 -#define BTMaxDataBlockLen 0x800 -#define BTTOTALBANDWIDTH 0x7530 -#define BTMAXBANDGUBANDWIDTH 0x4e20 -#define TmpLocalBufSize 0x100 -#define BTSynDataPacketLength 0xff -/* */ - -#define BTMaxAuthCount 5 -#define BTMaxAsocCount 5 - -#define MAX_LOGICAL_LINK_NUM 2 /* temporarily define */ -#define MAX_BT_ASOC_ENTRY_NUM 2 /* temporarily define */ - -#define INVALID_PL_HANDLE 0xff -#define INVALID_ENTRY_NUM 0xff -/* */ - -#define CAM_BT_START_INDEX (HALF_CAM_ENTRY - 4) /* MAX_BT_ASOC_ENTRY_NUM : 4 !!! */ -#define BT_HWCAM_STAR CAM_BT_START_INDEX /* We used HALF_CAM_ENTRY ~ HALF_CAM_ENTRY -MAX_BT_ASOC_ENTRY_NUM */ - -enum hci_status { - HCI_STATUS_SUCCESS = 0x00, /* Success */ - HCI_STATUS_UNKNOW_HCI_CMD = 0x01, /* Unknown HCI Command */ - HCI_STATUS_UNKNOW_CONNECT_ID = 0X02, /* Unknown Connection Identifier */ - HCI_STATUS_HW_FAIL = 0X03, /* Hardware Failure */ - HCI_STATUS_PAGE_TIMEOUT = 0X04, /* Page Timeout */ - HCI_STATUS_AUTH_FAIL = 0X05, /* Authentication Failure */ - HCI_STATUS_PIN_OR_KEY_MISSING = 0X06, /* PIN or Key Missing */ - HCI_STATUS_MEM_CAP_EXCEED = 0X07, /* Memory Capacity Exceeded */ - HCI_STATUS_CONNECT_TIMEOUT = 0X08, /* Connection Timeout */ - HCI_STATUS_CONNECT_LIMIT = 0X09, /* Connection Limit Exceeded */ - HCI_STATUS_SYN_CONNECT_LIMIT = 0X0a, /* Synchronous Connection Limit To A Device Exceeded */ - HCI_STATUS_ACL_CONNECT_EXISTS = 0X0b, /* ACL Connection Already Exists */ - HCI_STATUS_CMD_DISALLOW = 0X0c, /* Command Disallowed */ - HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE = 0X0d, /* Connection Rejected due to Limited Resources */ - HCI_STATUS_CONNECT_RJT_SEC_REASON = 0X0e, /* Connection Rejected Due To Security Reasons */ - HCI_STATUS_CONNECT_RJT_UNACCEPT_BD_ADDR = 0X0f, /* Connection Rejected due to Unacceptable BD_ADDR */ - HCI_STATUS_CONNECT_ACCEPT_TIMEOUT = 0X10, /* Connection Accept Timeout Exceeded */ - HCI_STATUS_UNSUPPORT_FEATURE_PARA_VALUE = 0X11, /* Unsupported Feature or Parameter Value */ - HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE = 0X12, /* Invalid HCI Command Parameters */ - HCI_STATUS_REMOTE_USER_TERMINATE_CONNECT = 0X13, /* Remote User Terminated Connection */ - HCI_STATUS_REMOTE_DEV_TERMINATE_LOW_RESOURCE = 0X14, /* Remote Device Terminated Connection due to Low Resources */ - HCI_STATUS_REMOTE_DEV_TERMINATE_CONNECT_POWER_OFF = 0X15, /* Remote Device Terminated Connection due to Power Off */ - HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST = 0X16, /* Connection Terminated By Local Host */ - HCI_STATUS_REPEATE_ATTEMPT = 0X17, /* Repeated Attempts */ - HCI_STATUS_PAIR_NOT_ALLOW = 0X18, /* Pairing Not Allowed */ - HCI_STATUS_UNKNOW_LMP_PDU = 0X19, /* Unknown LMP PDU */ - HCI_STATUS_UNSUPPORT_REMOTE_LMP_FEATURE = 0X1a, /* Unsupported Remote Feature / Unsupported LMP Feature */ - HCI_STATUS_SOC_OFFSET_REJECT = 0X1b, /* SCO Offset Rejected */ - HCI_STATUS_SOC_INTERVAL_REJECT = 0X1c, /* SCO Interval Rejected */ - HCI_STATUS_SOC_AIR_MODE_REJECT = 0X1d,/* SCO Air Mode Rejected */ - HCI_STATUS_INVALID_LMP_PARA = 0X1e, /* Invalid LMP Parameters */ - HCI_STATUS_UNSPECIFIC_ERROR = 0X1f, /* Unspecified Error */ - HCI_STATUS_UNSUPPORT_LMP_PARA_VALUE = 0X20, /* Unsupported LMP Parameter Value */ - HCI_STATUS_ROLE_CHANGE_NOT_ALLOW = 0X21, /* Role Change Not Allowed */ - HCI_STATUS_LMP_RESPONSE_TIMEOUT = 0X22, /* LMP Response Timeout */ - HCI_STATUS_LMP_ERROR_TRANSACTION_COLLISION = 0X23, /* LMP Error Transaction Collision */ - HCI_STATUS_LMP_PDU_NOT_ALLOW = 0X24, /* LMP PDU Not Allowed */ - HCI_STATUS_ENCRYPTION_MODE_NOT_ALLOW = 0X25, /* Encryption Mode Not Acceptable */ - HCI_STATUS_LINK_KEY_CAN_NOT_CHANGE = 0X26, /* Link Key Can Not be Changed */ - HCI_STATUS_REQUEST_QOS_NOT_SUPPORT = 0X27, /* Requested QoS Not Supported */ - HCI_STATUS_INSTANT_PASSED = 0X28, /* Instant Passed */ - HCI_STATUS_PAIRING_UNIT_KEY_NOT_SUPPORT = 0X29, /* Pairing With Unit Key Not Supported */ - HCI_STATUS_DIFFERENT_TRANSACTION_COLLISION = 0X2a, /* Different Transaction Collision */ - HCI_STATUS_RESERVE_1 = 0X2b, /* Reserved */ - HCI_STATUS_QOS_UNACCEPT_PARA = 0X2c, /* QoS Unacceptable Parameter */ - HCI_STATUS_QOS_REJECT = 0X2d, /* QoS Rejected */ - HCI_STATUS_CHNL_CLASSIFICATION_NOT_SUPPORT = 0X2e, /* Channel Classification Not Supported */ - HCI_STATUS_INSUFFICIENT_SECURITY = 0X2f, /* Insufficient Security */ - HCI_STATUS_PARA_OUT_OF_RANGE = 0x30, /* Parameter Out Of Mandatory Range */ - HCI_STATUS_RESERVE_2 = 0X31, /* Reserved */ - HCI_STATUS_ROLE_SWITCH_PENDING = 0X32, /* Role Switch Pending */ - HCI_STATUS_RESERVE_3 = 0X33, /* Reserved */ - HCI_STATUS_RESERVE_SOLT_VIOLATION = 0X34, /* Reserved Slot Violation */ - HCI_STATUS_ROLE_SWITCH_FAIL = 0X35, /* Role Switch Failed */ - HCI_STATUS_EXTEND_INQUIRY_RSP_TOO_LARGE = 0X36, /* Extended Inquiry Response Too Large */ - HCI_STATUS_SEC_SIMPLE_PAIRING_NOT_SUPPORT = 0X37, /* Secure Simple Pairing Not Supported By Host. */ - HCI_STATUS_HOST_BUSY_PAIRING = 0X38, /* Host Busy - Pairing */ - HCI_STATUS_CONNECT_REJ_NOT_SUIT_CHNL_FOUND = 0X39, /* Connection Rejected due to No Suitable Channel Found */ - HCI_STATUS_CONTROLLER_BUSY = 0X3a /* CONTROLLER BUSY */ -}; - -/* */ -/* The following is for BT 3.0 + HS HCI COMMAND */ -/* */ - -/* bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ -/* | OCF | OGF | */ -/* */ - -/* OGF 0x01 */ -#define LINK_CONTROL_COMMANDS 0x01 -enum link_control_commands { - HCI_INQUIRY = 0x0001, - HCI_INQUIRY_CANCEL = 0x0002, - HCI_PERIODIC_INQUIRY_MODE = 0x0003, - HCI_EXIT_PERIODIC_INQUIRY_MODE = 0x0004, - HCI_CREATE_CONNECTION = 0x0005, - HCI_DISCONNECT = 0x0006, - HCI_CREATE_CONNECTION_CANCEL = 0x0008, - HCI_ACCEPT_CONNECTIONREQUEST = 0x0009, - HCI_REJECT_CONNECTION_REQUEST = 0x000a, - HCI_LINK_KEY_REQUEST_REPLY = 0x000b, - HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY = 0x000c, - HCI_PIN_CODE_REQUEST_REPLY = 0x000d, - HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY = 0x000e, - HCI_CHANGE_CONNECTION_PACKET_TYPE = 0x000f, - HCI_AUTHENTICATION_REQUESTED = 0x0011, - HCI_SET_CONNECTION_ENCRYPTION = 0x0013, - HCI_CHANGE_CONNECTION_LINK_KEY = 0x0015, - HCI_MASTER_LINK_KEY = 0x0017, - HCI_REMOTE_NAME_REQUEST = 0x0019, - HCI_REMOTE_NAME_REQUEST_CANCEL = 0x001a, - HCI_READ_REMOTE_SUPPORTED_FEATURES = 0x001b, - HCI_READ_REMOTE_EXTENDED_FEATURES = 0x001c, - HCI_READ_REMOTE_VERSION_INFORMATION = 0x001d, - HCI_READ_CLOCK_OFFSET = 0x001f, - HCI_READ_LMP_HANDLE = 0x0020, - HCI_SETUP_SYNCHRONOUS_CONNECTION = 0x0028, - HCI_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST = 0x0029, - HCI_REJECT_SYNCHRONOUS_CONNECTION_REQUEST = 0x002a, - HCI_IO_CAPABILITY_REQUEST_REPLY = 0x002b, - HCI_USER_CONFIRMATION_REQUEST_REPLY = 0x002c, - HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY = 0x002d, - HCI_USER_PASSKEY_REQUEST_REPLY = 0x002e, - HCI_USER_PASSKEY_REQUESTNEGATIVE_REPLY = 0x002f, - HCI_REMOTE_OOB_DATA_REQUEST_REPLY = 0x0030, - HCI_REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY = 0x0033, - HCI_IO_CAPABILITY_REQUEST_NEGATIVE_REPLY = 0x0034, - HCI_CREATE_PHYSICAL_LINK = 0x0035, - HCI_ACCEPT_PHYSICAL_LINK = 0x0036, - HCI_DISCONNECT_PHYSICAL_LINK = 0x0037, - HCI_CREATE_LOGICAL_LINK = 0x0038, - HCI_ACCEPT_LOGICAL_LINK = 0x0039, - HCI_DISCONNECT_LOGICAL_LINK = 0x003a, - HCI_LOGICAL_LINK_CANCEL = 0x003b, - HCI_FLOW_SPEC_MODIFY = 0x003c -}; - -/* OGF 0x02 */ -#define HOLD_MODE_COMMAND 0x02 -enum hold_mode_command { - HCI_HOLD_MODE = 0x0001, - HCI_SNIFF_MODE = 0x0002, - HCI_EXIT_SNIFF_MODE = 0x0003, - HCI_PARK_STATE = 0x0005, - HCI_EXIT_PARK_STATE = 0x0006, - HCI_QOS_SETUP = 0x0007, - HCI_ROLE_DISCOVERY = 0x0009, - HCI_SWITCH_ROLE = 0x000b, - HCI_READ_LINK_POLICY_SETTINGS = 0x000c, - HCI_WRITE_LINK_POLICY_SETTINGS = 0x000d, - HCI_READ_DEFAULT_LINK_POLICY_SETTINGS = 0x000e, - HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS = 0x000f, - HCI_FLOW_SPECIFICATION = 0x0010, - HCI_SNIFF_SUBRATING = 0x0011 -}; - -/* OGF 0x03 */ -#define OGF_SET_EVENT_MASK_COMMAND 0x03 -enum set_event_mask_command { - HCI_SET_EVENT_MASK = 0x0001, - HCI_RESET = 0x0003, - HCI_SET_EVENT_FILTER = 0x0005, - HCI_FLUSH = 0x0008, - HCI_READ_PIN_TYPE = 0x0009, - HCI_WRITE_PIN_TYPE = 0x000a, - HCI_CREATE_NEW_UNIT_KEY = 0x000b, - HCI_READ_STORED_LINK_KEY = 0x000d, - HCI_WRITE_STORED_LINK_KEY = 0x0011, - HCI_DELETE_STORED_LINK_KEY = 0x0012, - HCI_WRITE_LOCAL_NAME = 0x0013, - HCI_READ_LOCAL_NAME = 0x0014, - HCI_READ_CONNECTION_ACCEPT_TIMEOUT = 0x0015, - HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT = 0x0016, - HCI_READ_PAGE_TIMEOUT = 0x0017, - HCI_WRITE_PAGE_TIMEOUT = 0x0018, - HCI_READ_SCAN_ENABLE = 0x0019, - HCI_WRITE_SCAN_ENABLE = 0x001a, - HCI_READ_PAGE_SCAN_ACTIVITY = 0x001b, - HCI_WRITE_PAGE_SCAN_ACTIVITY = 0x001c, - HCI_READ_INQUIRY_SCAN_ACTIVITY = 0x001d, - HCI_WRITE_INQUIRY_SCAN_ACTIVITY = 0x001e, - HCI_READ_AUTHENTICATION_ENABLE = 0x001f, - HCI_WRITE_AUTHENTICATION_ENABLE = 0x0020, - HCI_READ_CLASS_OF_DEVICE = 0x0023, - HCI_WRITE_CLASS_OF_DEVICE = 0x0024, - HCI_READ_VOICE_SETTING = 0x0025, - HCI_WRITE_VOICE_SETTING = 0x0026, - HCI_READ_AUTOMATIC_FLUSH_TIMEOUT = 0x0027, - HCI_WRITE_AUTOMATIC_FLUSH_TIMEOUT = 0x0028, - HCI_READ_NUM_BROADCAST_RETRANSMISSIONS = 0x0029, - HCI_WRITE_NUM_BROADCAST_RETRANSMISSIONS = 0x002a, - HCI_READ_HOLD_MODE_ACTIVITY = 0x002b, - HCI_WRITE_HOLD_MODE_ACTIVITY = 0x002c, - HCI_READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 0x002e, - HCI_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 0x002f, - HCI_SET_CONTROLLER_TO_HOST_FLOW_CONTROL = 0x0031, - HCI_HOST_BUFFER_SIZE = 0x0033, - HCI_HOST_NUMBER_OF_COMPLETED_PACKETS = 0x0035, - HCI_READ_LINK_SUPERVISION_TIMEOUT = 0x0036, - HCI_WRITE_LINK_SUPERVISION_TIMEOUT = 0x0037, - HCI_READ_NUMBER_OF_SUPPORTED_IAC = 0x0038, - HCI_READ_CURRENT_IAC_LAP = 0x0039, - HCI_WRITE_CURRENT_IAC_LAP = 0x003a, - HCI_READ_PAGE_SCAN_MODE = 0x003d, - HCI_WRITE_PAGE_SCAN_MODE = 0x003e, - HCI_SET_AFH_HOST_CHANNEL_CLASSIFICATION = 0x003f, - HCI_READ_INQUIRY_SCAN_TYPE = 0x0042, - HCI_WRITE_INQUIRY_SCAN_TYPE = 0x0043, - HCI_READ_INQUIRY_MODE = 0x0044, - HCI_WRITE_INQUIRY_MODE = 0x0045, - HCI_READ_PAGE_SCAN_TYPE = 0x0046, - HCI_WRITE_PAGE_SCAN_TYPE = 0x0047, - HCI_READ_AFH_CHANNEL_ASSESSMENT_MODE = 0x0048, - HCI_WRITE_AFH_CHANNEL_ASSESSMENT_MODE = 0x0049, - HCI_READ_EXTENDED_INQUIRY_RESPONSE = 0x0051, - HCI_WRITE_EXTENDED_INQUIRY_RESPONSE = 0x0052, - HCI_REFRESH_ENCRYPTION_KEY = 0x0053, - HCI_READ_SIMPLE_PAIRING_MODE = 0x0055, - HCI_WRITE_SIMPLE_PAIRING_MODE = 0x0056, - HCI_READ_LOCAL_OOB_DATA = 0x0057, - HCI_READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL = 0x0058, - HCI_WRITE_INQUIRY_TRANSMIT_POWER_LEVEL = 0x0059, - HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING = 0x005a, - HCI_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING = 0x005b, - HCI_ENHANCED_FLUSH = 0x005f, - HCI_SEND_KEYPRESS_NOTIFICATION = 0x0060, - HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0061, - HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0062, - HCI_SET_EVENT_MASK_PAGE_2 = 0x0063, - HCI_READ_LOCATION_DATA = 0x0064, - HCI_WRITE_LOCATION_DATA = 0x0065, - HCI_READ_FLOW_CONTROL_MODE = 0x0066, - HCI_WRITE_FLOW_CONTROL_MODE = 0x0067, - HCI_READ_ENHANCE_TRANSMIT_POWER_LEVEL = 0x0068, - HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT = 0x0069, - HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT = 0x006a, - HCI_SHORT_RANGE_MODE = 0x006b -}; - -/* OGF 0x04 */ -#define OGF_INFORMATIONAL_PARAMETERS 0x04 -enum informational_params { - HCI_READ_LOCAL_VERSION_INFORMATION = 0x0001, - HCI_READ_LOCAL_SUPPORTED_COMMANDS = 0x0002, - HCI_READ_LOCAL_SUPPORTED_FEATURES = 0x0003, - HCI_READ_LOCAL_EXTENDED_FEATURES = 0x0004, - HCI_READ_BUFFER_SIZE = 0x0005, - HCI_READ_BD_ADDR = 0x0009, - HCI_READ_DATA_BLOCK_SIZE = 0x000a -}; - -/* OGF 0x05 */ -#define OGF_STATUS_PARAMETERS 0x05 -enum status_params { - HCI_READ_FAILED_CONTACT_COUNTER = 0x0001, - HCI_RESET_FAILED_CONTACT_COUNTER = 0x0002, - HCI_READ_LINK_QUALITY = 0x0003, - HCI_READ_RSSI = 0x0005, - HCI_READ_AFH_CHANNEL_MAP = 0x0006, - HCI_READ_CLOCK = 0x0007, - HCI_READ_ENCRYPTION_KEY_SIZE = 0x0008, - HCI_READ_LOCAL_AMP_INFO = 0x0009, - HCI_READ_LOCAL_AMP_ASSOC = 0x000a, - HCI_WRITE_REMOTE_AMP_ASSOC = 0x000b -}; - -/* OGF 0x06 */ -#define OGF_TESTING_COMMANDS 0x06 -enum testing_commands { - HCI_READ_LOOPBACK_MODE = 0x0001, - HCI_WRITE_LOOPBACK_MODE = 0x0002, - HCI_ENABLE_DEVICE_UNDER_TEST_MODE = 0x0003, - HCI_WRITE_SIMPLE_PAIRING_DEBUG_MODE = 0x0004, - HCI_ENABLE_AMP_RECEIVER_REPORTS = 0x0007, - HCI_AMP_TEST_END = 0x0008, - HCI_AMP_TEST_COMMAND = 0x0009 -}; - -/* OGF 0x3f */ -#define OGF_EXTENSION 0X3f -enum hci_extension_commands { - HCI_SET_ACL_LINK_DATA_FLOW_MODE = 0x0010, - HCI_SET_ACL_LINK_STATUS = 0x0020, - HCI_SET_SCO_LINK_STATUS = 0x0030, - HCI_SET_RSSI_VALUE = 0x0040, - HCI_SET_CURRENT_BLUETOOTH_STATUS = 0x0041, - - /* The following is for RTK8723 */ - HCI_EXTENSION_VERSION_NOTIFY = 0x0100, - HCI_LINK_STATUS_NOTIFY = 0x0101, - HCI_BT_OPERATION_NOTIFY = 0x0102, - HCI_ENABLE_WIFI_SCAN_NOTIFY = 0x0103, - - - /* The following is for IVT */ - HCI_WIFI_CURRENT_CHANNEL = 0x0300, - HCI_WIFI_CURRENT_BANDWIDTH = 0x0301, - HCI_WIFI_CONNECTION_STATUS = 0x0302, -}; - -enum bt_spec { - BT_SPEC_1_0_b = 0x00, - BT_SPEC_1_1 = 0x01, - BT_SPEC_1_2 = 0x02, - BT_SPEC_2_0_EDR = 0x03, - BT_SPEC_2_1_EDR = 0x04, - BT_SPEC_3_0_HS = 0x05, - BT_SPEC_4_0 = 0x06 -}; - -/* The following is for BT 3.0 + HS EVENTS */ -enum hci_event { - HCI_EVENT_INQUIRY_COMPLETE = 0x01, - HCI_EVENT_INQUIRY_RESULT = 0x02, - HCI_EVENT_CONNECTION_COMPLETE = 0x03, - HCI_EVENT_CONNECTION_REQUEST = 0x04, - HCI_EVENT_DISCONNECTION_COMPLETE = 0x05, - HCI_EVENT_AUTHENTICATION_COMPLETE = 0x06, - HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE = 0x07, - HCI_EVENT_ENCRYPTION_CHANGE = 0x08, - HCI_EVENT_CHANGE_LINK_KEY_COMPLETE = 0x09, - HCI_EVENT_MASTER_LINK_KEY_COMPLETE = 0x0a, - HCI_EVENT_READ_REMOTE_SUPPORT_FEATURES_COMPLETE = 0x0b, - HCI_EVENT_READ_REMOTE_VER_INFO_COMPLETE = 0x0c, - HCI_EVENT_QOS_SETUP_COMPLETE = 0x0d, - HCI_EVENT_COMMAND_COMPLETE = 0x0e, - HCI_EVENT_COMMAND_STATUS = 0x0f, - HCI_EVENT_HARDWARE_ERROR = 0x10, - HCI_EVENT_FLUSH_OCCRUED = 0x11, - HCI_EVENT_ROLE_CHANGE = 0x12, - HCI_EVENT_NUMBER_OF_COMPLETE_PACKETS = 0x13, - HCI_EVENT_MODE_CHANGE = 0x14, - HCI_EVENT_RETURN_LINK_KEYS = 0x15, - HCI_EVENT_PIN_CODE_REQUEST = 0x16, - HCI_EVENT_LINK_KEY_REQUEST = 0x17, - HCI_EVENT_LINK_KEY_NOTIFICATION = 0x18, - HCI_EVENT_LOOPBACK_COMMAND = 0x19, - HCI_EVENT_DATA_BUFFER_OVERFLOW = 0x1a, - HCI_EVENT_MAX_SLOTS_CHANGE = 0x1b, - HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE = 0x1c, - HCI_EVENT_CONNECT_PACKET_TYPE_CHANGE = 0x1d, - HCI_EVENT_QOS_VIOLATION = 0x1e, - HCI_EVENT_PAGE_SCAN_REPETITION_MODE_CHANGE = 0x20, - HCI_EVENT_FLOW_SEPC_COMPLETE = 0x21, - HCI_EVENT_INQUIRY_RESULT_WITH_RSSI = 0x22, - HCI_EVENT_READ_REMOTE_EXT_FEATURES_COMPLETE = 0x23, - HCI_EVENT_SYNC_CONNECT_COMPLETE = 0x2c, - HCI_EVENT_SYNC_CONNECT_CHANGE = 0x2d, - HCI_EVENT_SNIFFER_SUBRATING = 0x2e, - HCI_EVENT_EXTENTED_INQUIRY_RESULT = 0x2f, - HCI_EVENT_ENCRYPTION_KEY_REFLASH_COMPLETE = 0x30, - HCI_EVENT_IO_CAPIBILITY_COMPLETE = 0x31, - HCI_EVENT_IO_CAPIBILITY_RESPONSE = 0x32, - HCI_EVENT_USER_CONFIRMTION_REQUEST = 0x33, - HCI_EVENT_USER_PASSKEY_REQUEST = 0x34, - HCI_EVENT_REMOTE_OOB_DATA_REQUEST = 0x35, - HCI_EVENT_SIMPLE_PAIRING_COMPLETE = 0x36, - HCI_EVENT_LINK_SUPERVISION_TIMEOUT_CHANGE = 0x38, - HCI_EVENT_ENHANCED_FLUSH_COMPLETE = 0x39, - HCI_EVENT_USER_PASSKEY_NOTIFICATION = 0x3b, - HCI_EVENT_KEYPRESS_NOTIFICATION = 0x3c, - HCI_EVENT_REMOTE_HOST_SUPPORT_FEATURES_NOTIFICATION = 0x3d, - HCI_EVENT_PHY_LINK_COMPLETE = 0x40, - HCI_EVENT_CHANNEL_SELECT = 0x41, - HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE = 0x42, - HCI_EVENT_PHY_LINK_LOSS_EARLY_WARNING = 0x43, - HCI_EVENT_PHY_LINK_RECOVER = 0x44, - HCI_EVENT_LOGICAL_LINK_COMPLETE = 0x45, - HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE = 0x46, - HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE = 0x47, - HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS = 0x48, - HCI_EVENT_AMP_START_TEST = 0x49, - HCI_EVENT_AMP_TEST_END = 0x4a, - HCI_EVENT_AMP_RECEIVER_REPORT = 0x4b, - HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE = 0x4c, - HCI_EVENT_AMP_STATUS_CHANGE = 0x4d, - HCI_EVENT_EXTENSION_RTK = 0xfe, - HCI_EVENT_EXTENSION_MOTO = 0xff, -}; - -enum hci_extension_event_moto { - HCI_EVENT_GET_BT_RSSI = 0x01, -}; - -enum hci_extension_event { - HCI_EVENT_EXT_WIFI_SCAN_NOTIFY = 0x01, -}; - -enum hci_event_mask_page_2 { - EMP2_HCI_EVENT_PHY_LINK_COMPLETE = 0x0000000000000001, - EMP2_HCI_EVENT_CHANNEL_SELECT = 0x0000000000000002, - EMP2_HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE = 0x0000000000000004, - EMP2_HCI_EVENT_PHY_LINK_LOSS_EARLY_WARNING = 0x0000000000000008, - EMP2_HCI_EVENT_PHY_LINK_RECOVER = 0x0000000000000010, - EMP2_HCI_EVENT_LOGICAL_LINK_COMPLETE = 0x0000000000000020, - EMP2_HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE = 0x0000000000000040, - EMP2_HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE = 0x0000000000000080, - EMP2_HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS = 0x0000000000000100, - EMP2_HCI_EVENT_AMP_START_TEST = 0x0000000000000200, - EMP2_HCI_EVENT_AMP_TEST_END = 0x0000000000000400, - EMP2_HCI_EVENT_AMP_RECEIVER_REPORT = 0x0000000000000800, - EMP2_HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE = 0x0000000000001000, - EMP2_HCI_EVENT_AMP_STATUS_CHANGE = 0x0000000000002000, -}; - -enum hci_state_machine { - HCI_STATE_STARTING = 0x01, - HCI_STATE_CONNECTING = 0x02, - HCI_STATE_AUTHENTICATING = 0x04, - HCI_STATE_CONNECTED = 0x08, - HCI_STATE_DISCONNECTING = 0x10, - HCI_STATE_DISCONNECTED = 0x20 -}; - -enum amp_assoc_structure_type { - AMP_MAC_ADDR = 0x01, - AMP_PREFERRED_CHANNEL_LIST = 0x02, - AMP_CONNECTED_CHANNEL = 0x03, - AMP_80211_PAL_CAP_LIST = 0x04, - AMP_80211_PAL_VISION = 0x05, - AMP_RESERVED_FOR_TESTING = 0x33 -}; - -enum amp_btap_type { - AMP_BTAP_NONE, - AMP_BTAP_CREATOR, - AMP_BTAP_JOINER -}; - -enum hci_state_with_cmd { - STATE_CMD_CREATE_PHY_LINK, - STATE_CMD_ACCEPT_PHY_LINK, - STATE_CMD_DISCONNECT_PHY_LINK, - STATE_CMD_CONNECT_ACCEPT_TIMEOUT, - STATE_CMD_MAC_START_COMPLETE, - STATE_CMD_MAC_START_FAILED, - STATE_CMD_MAC_CONNECT_COMPLETE, - STATE_CMD_MAC_CONNECT_FAILED, - STATE_CMD_MAC_DISCONNECT_INDICATE, - STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, - STATE_CMD_4WAY_FAILED, - STATE_CMD_4WAY_SUCCESSED, - STATE_CMD_ENTER_STATE, - STATE_CMD_NO_SUCH_CMD, -}; - -enum hci_service_type { - SERVICE_NO_TRAFFIC, - SERVICE_BEST_EFFORT, - SERVICE_GUARANTEE -}; - -enum hci_traffic_mode { - TRAFFIC_MODE_BEST_EFFORT = 0x00, - TRAFFIC_MODE_GUARANTEED_LATENCY = 0x01, - TRAFFIC_MODE_GUARANTEED_BANDWIDTH = 0x02, - TRAFFIC_MODE_GUARANTEED_LATENCY_AND_BANDWIDTH = 0x03 -}; - -#define HCIOPCODE(_OCF, _OGF) (_OGF<<10|_OCF) -#define HCIOPCODELOW(_OCF, _OGF) (u8)(HCIOPCODE(_OCF, _OGF)&0x00ff) -#define HCIOPCODEHIGHT(_OCF, _OGF) (u8)(HCIOPCODE(_OCF, _OGF)>>8) - -#define TWOBYTE_HIGHTBYTE(_DATA) (u8)(_DATA>>8) -#define TWOBYTE_LOWBYTE(_DATA) (u8)(_DATA) - -enum amp_status { - AMP_STATUS_AVA_PHY_PWR_DWN = 0x0, - AMP_STATUS_BT_USE_ONLY = 0x1, - AMP_STATUS_NO_CAPACITY_FOR_BT = 0x2, - AMP_STATUS_LOW_CAPACITY_FOR_BT = 0x3, - AMP_STATUS_MEDIUM_CAPACITY_FOR_BT = 0x4, - AMP_STATUS_HIGH_CAPACITY_FOR_BT = 0x5, - AMP_STATUS_FULL_CAPACITY_FOR_BT = 0x6 -}; - -enum bt_wpa_msg_type { - Type_BT_4way1st = 0, - Type_BT_4way2nd = 1, - Type_BT_4way3rd = 2, - Type_BT_4way4th = 3, - Type_BT_unknow = 4 -}; - -enum bt_connect_type { - BT_CONNECT_AUTH_REQ = 0x00, - BT_CONNECT_AUTH_RSP = 0x01, - BT_CONNECT_ASOC_REQ = 0x02, - BT_CONNECT_ASOC_RSP = 0x03, - BT_DISCONNECT = 0x04 -}; - -enum bt_ll_service_type { - BT_LL_BE = 0x01, - BT_LL_GU = 0x02 -}; - -enum bt_ll_flowspec { - BT_TX_BE_FS, /* TX best effort flowspec */ - BT_RX_BE_FS, /* RX best effort flowspec */ - BT_TX_GU_FS, /* TX guaranteed latency flowspec */ - BT_RX_GU_FS, /* RX guaranteed latency flowspec */ - BT_TX_BE_AGG_FS, /* TX aggregated best effort flowspec */ - BT_RX_BE_AGG_FS, /* RX aggregated best effort flowspec */ - BT_TX_GU_BW_FS, /* TX guaranteed bandwidth flowspec */ - BT_RX_GU_BW_FS, /* RX guaranteed bandwidth flowspec */ - BT_TX_GU_LARGE_FS, /* TX guaranteed latency flowspec, for testing only */ - BT_RX_GU_LARGE_FS, /* RX guaranteed latency flowspec, for testing only */ -}; - -enum bt_traffic_mode { - BT_MOTOR_EXT_BE = 0x00, /* Best Effort. Default. for HCRP, PAN, SDP, RFCOMM-based profiles like FTP, OPP, SPP, DUN, etc. */ - BT_MOTOR_EXT_GUL = 0x01, /* Guaranteed Latency. This type of traffic is used e.g. for HID and AVRCP. */ - BT_MOTOR_EXT_GUB = 0X02, /* Guaranteed Bandwidth. */ - BT_MOTOR_EXT_GULB = 0X03 /* Guaranteed Latency and Bandwidth. for A2DP and VDP. */ -}; - -enum bt_traffic_mode_profile { - BT_PROFILE_NONE, - BT_PROFILE_A2DP, - BT_PROFILE_PAN, - BT_PROFILE_HID, - BT_PROFILE_SCO -}; - -enum bt_link_role { - BT_LINK_MASTER = 0, - BT_LINK_SLAVE = 1 -}; - -enum bt_state_wpa_auth { - STATE_WPA_AUTH_UNINITIALIZED, - STATE_WPA_AUTH_WAIT_PACKET_1, /* Join */ - STATE_WPA_AUTH_WAIT_PACKET_2, /* Creat */ - STATE_WPA_AUTH_WAIT_PACKET_3, - STATE_WPA_AUTH_WAIT_PACKET_4, - STATE_WPA_AUTH_SUCCESSED -}; - -#define BT_WPA_AUTH_TIMEOUT_PERIOD 1000 -#define BTMaxWPAAuthReTransmitCoun 5 - -#define MAX_AMP_ASSOC_FRAG_LEN 248 -#define TOTAL_ALLOCIATE_ASSOC_LEN 1000 - -struct hci_flow_spec { - u8 Identifier; - u8 ServiceType; - u16 MaximumSDUSize; - u32 SDUInterArrivalTime; - u32 AccessLatency; - u32 FlushTimeout; -}; - -struct hci_log_link_cmd_data { - u8 BtPhyLinkhandle; - u16 BtLogLinkhandle; - u8 BtTxFlowSpecID; - struct hci_flow_spec Tx_Flow_Spec; - struct hci_flow_spec Rx_Flow_Spec; - u32 TxPacketCount; - u32 BestEffortFlushTimeout; - - u8 bLLCompleteEventIsSet; - - u8 bLLCancelCMDIsSetandComplete; -}; - -struct hci_phy_link_cmd_data { - /* Physical_Link_Handle */ - u8 BtPhyLinkhandle; - - u16 LinkSuperversionTimeout; - - /* u16 SuperTimeOutCnt; */ - - /* Dedicated_AMP_Key_Length */ - u8 BtAMPKeyLen; - /* Dedicated_AMP_Key_Type */ - u8 BtAMPKeyType; - /* Dedicated_AMP_Key */ - u8 BtAMPKey[PMK_LEN]; -}; - -struct amp_assoc_structure { - /* TYPE ID */ - u8 TypeID; - /* Length */ - u16 Length; - /* Value */ - u8 Data[1]; -}; - -struct amp_pref_chnl_regulatory { - u8 reXId; - u8 regulatoryClass; - u8 coverageClass; -}; - -struct amp_assoc_cmd_data { - /* Physical_Link_Handle */ - u8 BtPhyLinkhandle; - /* Length_So_Far */ - u16 LenSoFar; - - u16 MaxRemoteASSOCLen; - /* AMP_ASSOC_Remaining_Length */ - u16 AMPAssocRemLen; - /* AMP_ASSOC_fragment */ - void *AMPAssocfragment; -}; - -struct hci_link_info { - u16 ConnectHandle; - u8 IncomingTrafficMode; - u8 OutgoingTrafficMode; - u8 BTProfile; - u8 BTCoreSpec; - s8 BT_RSSI; - u8 TrafficProfile; - u8 linkRole; -}; - -struct hci_ext_config { - struct hci_link_info linkInfo[MAX_BT_ASOC_ENTRY_NUM]; - u8 btOperationCode; - u16 CurrentConnectHandle; - u8 CurrentIncomingTrafficMode; - u8 CurrentOutgoingTrafficMode; - s8 MIN_BT_RSSI; - u8 NumberOfHandle; - u8 NumberOfSCO; - u8 CurrentBTStatus; - u16 HCIExtensionVer; - - /* Bt coexist related */ - u8 btProfileCase; - u8 btProfileAction; - u8 bManualControl; - u8 bBTBusy; - u8 bBTA2DPBusy; - u8 bEnableWifiScanNotify; - - u8 bHoldForBtOperation; - u32 bHoldPeriodCnt; -}; - -struct hci_acl_packet_data { - u16 ACLDataPacketLen; - u8 SyncDataPacketLen; - u16 TotalNumACLDataPackets; - u16 TotalSyncNumDataPackets; -}; - -struct hci_phy_link_bss_info { - u16 bdCap; /* capability information */ -}; - -struct packet_irp_hcicmd_data { - u16 OCF:10; - u16 OGF:6; - u8 Length; - u8 Data[20]; -}; - -struct bt_asoc_entry { - u8 bUsed; - u8 mAssoc; - u8 b4waySuccess; - u8 Bssid[6]; - struct hci_phy_link_cmd_data PhyLinkCmdData; - - struct hci_log_link_cmd_data LogLinkCmdData[MAX_LOGICAL_LINK_NUM]; - - struct hci_acl_packet_data ACLPacketsData; - - struct amp_assoc_cmd_data AmpAsocCmdData; - struct octet_string BTSsid; - u8 BTSsidBuf[33]; - - enum hci_status PhyLinkDisconnectReason; - - u8 bSendSupervisionPacket; - /* u8 CurrentSuervisionPacketSendNum; */ - /* u8 LastSuervisionPacketSendNum; */ - u32 NoRxPktCnt; - /* Is Creator or Joiner */ - enum amp_btap_type AMPRole; - - /* BT current state */ - u8 BtCurrentState; - /* BT next state */ - u8 BtNextState; - - u8 bNeedPhysLinkCompleteEvent; - - enum hci_status PhysLinkCompleteStatus; - - u8 BTRemoteMACAddr[6]; - - u32 BTCapability; - - u8 SyncDataPacketLen; - - u16 TotalSyncNumDataPackets; - u16 TotalNumACLDataPackets; - - u8 ShortRangeMode; - - u8 PTK[PTK_LEN_TKIP]; - u8 GTK[GTK_LEN]; - u8 ANonce[KEY_NONCE_LEN]; - u8 SNonce[KEY_NONCE_LEN]; - u64 KeyReplayCounter; - u8 WPAAuthReplayCount; - u8 AESKeyBuf[AESCCMP_BLK_SIZE_TOTAL]; - u8 PMK[PMK_LEN]; - enum bt_state_wpa_auth BTWPAAuthState; - s32 UndecoratedSmoothedPWDB; - - /* Add for HW security !! */ - u8 HwCAMIndex; /* Cam index */ - u8 bPeerQosSta; - - u32 rxSuvpPktCnt; -}; - -struct bt_traffic_statistics { - u8 bTxBusyTraffic; - u8 bRxBusyTraffic; - u8 bIdle; - u32 TxPktCntInPeriod; - u32 RxPktCntInPeriod; - u64 TxPktLenInPeriod; - u64 RxPktLenInPeriod; -}; - -struct bt_mgnt { - u8 bBTConnectInProgress; - u8 bLogLinkInProgress; - u8 bPhyLinkInProgress; - u8 bPhyLinkInProgressStartLL; - u8 BtCurrentPhyLinkhandle; - u16 BtCurrentLogLinkhandle; - u8 CurrentConnectEntryNum; - u8 DisconnectEntryNum; - u8 CurrentBTConnectionCnt; - enum bt_connect_type BTCurrentConnectType; - enum bt_connect_type BTReceiveConnectPkt; - u8 BTAuthCount; - u8 BTAsocCount; - u8 bStartSendSupervisionPkt; - u8 BtOperationOn; - u8 BTNeedAMPStatusChg; - u8 JoinerNeedSendAuth; - struct hci_phy_link_bss_info bssDesc; - struct hci_ext_config ExtConfig; - u8 bNeedNotifyAMPNoCap; - u8 bCreateSpportQos; - u8 bSupportProfile; - u8 BTChannel; - u8 CheckChnlIsSuit; - u8 bBtScan; - u8 btLogoTest; -}; - -struct bt_hci_dgb_info { - u32 hciCmdCnt; - u32 hciCmdCntUnknown; - u32 hciCmdCntCreatePhyLink; - u32 hciCmdCntAcceptPhyLink; - u32 hciCmdCntDisconnectPhyLink; - u32 hciCmdPhyLinkStatus; - u32 hciCmdCntCreateLogLink; - u32 hciCmdCntAcceptLogLink; - u32 hciCmdCntDisconnectLogLink; - u32 hciCmdCntReadLocalAmpAssoc; - u32 hciCmdCntWriteRemoteAmpAssoc; - u32 hciCmdCntSetAclLinkStatus; - u32 hciCmdCntSetScoLinkStatus; - u32 hciCmdCntExtensionVersionNotify; - u32 hciCmdCntLinkStatusNotify; -}; - -struct bt_irp_dgb_info { - u32 irpMJCreate; - /* Io Control */ - u32 irpIoControl; - u32 irpIoCtrlHciCmd; - u32 irpIoCtrlHciEvent; - u32 irpIoCtrlHciTxData; - u32 irpIoCtrlHciRxData; - u32 irpIoCtrlUnknown; - - u32 irpIoCtrlHciTxData1s; -}; - -struct bt_packet_dgb_info { - u32 btPktTxProbReq; - u32 btPktRxProbReq; - u32 btPktRxProbReqFail; - u32 btPktTxProbRsp; - u32 btPktRxProbRsp; - u32 btPktTxAuth; - u32 btPktRxAuth; - u32 btPktRxAuthButDrop; - u32 btPktTxAssocReq; - u32 btPktRxAssocReq; - u32 btPktRxAssocReqButDrop; - u32 btPktTxAssocRsp; - u32 btPktRxAssocRsp; - u32 btPktTxDisassoc; - u32 btPktRxDisassoc; - u32 btPktRxDeauth; - u32 btPktTx4way1st; - u32 btPktRx4way1st; - u32 btPktTx4way2nd; - u32 btPktRx4way2nd; - u32 btPktTx4way3rd; - u32 btPktRx4way3rd; - u32 btPktTx4way4th; - u32 btPktRx4way4th; - u32 btPktTxLinkSuperReq; - u32 btPktRxLinkSuperReq; - u32 btPktTxLinkSuperRsp; - u32 btPktRxLinkSuperRsp; - u32 btPktTxData; - u32 btPktRxData; -}; - -struct bt_dgb { - u8 dbgCtrl; - u32 dbgProfile; - struct bt_hci_dgb_info dbgHciInfo; - struct bt_irp_dgb_info dbgIrpInfo; - struct bt_packet_dgb_info dbgBtPkt; -}; - -struct bt_hci_info { - /* 802.11 Pal version specifier */ - u8 BTPalVersion; - u16 BTPalCompanyID; - u16 BTPalsubversion; - - /* Connected channel list */ - u16 BTConnectChnlListLen; - u8 BTConnectChnllist[64]; - - /* Fail contact counter */ - u16 FailContactCount; - - /* Event mask */ - u64 BTEventMask; - u64 BTEventMaskPage2; - - /* timeout var */ - u16 ConnAcceptTimeout; - u16 LogicalAcceptTimeout; - u16 PageTimeout; - - u8 LocationDomainAware; - u16 LocationDomain; - u8 LocationDomainOptions; - u8 LocationOptions; - - u8 FlowControlMode; - - /* Preferred channel list */ - u16 BtPreChnlListLen; - u8 BTPreChnllist[64]; - - u16 enFlush_LLH; /* enhanced flush handle */ - u16 FLTO_LLH; /* enhanced flush handle */ - - /* */ - /* Test command only. */ - u8 bInTestMode; - u8 bTestIsEnd; - u8 bTestNeedReport; - u8 TestScenario; - u8 TestReportInterval; - u8 TestCtrType; - u32 TestEventType; - u16 TestNumOfFrame; - u16 TestNumOfErrFrame; - u16 TestNumOfBits; - u16 TestNumOfErrBits; - /* */ -}; - -struct bt_traffic { - /* Add for check replay data */ - u8 LastRxUniFragNum; - u16 LastRxUniSeqNum; - - /* s32 EntryMaxUndecoratedSmoothedPWDB; */ - /* s32 EntryMinUndecoratedSmoothedPWDB; */ - - struct bt_traffic_statistics Bt30TrafficStatistics; -}; - -#define RT_WORK_ITEM struct work_struct - -struct bt_security { - /* WPA auth state - * May need to remove to BTSecInfo ... - * enum bt_state_wpa_auth BTWPAAuthState; - */ - struct octet_string RSNIE; - u8 RSNIEBuf[MAXRSNIELEN]; - u8 bRegNoEncrypt; - u8 bUsedHwEncrypt; -}; - -struct bt_30info { - struct rtw_adapter *padapter; - struct bt_asoc_entry BtAsocEntry[MAX_BT_ASOC_ENTRY_NUM]; - struct bt_mgnt BtMgnt; - struct bt_dgb BtDbg; - struct bt_hci_info BtHciInfo; - struct bt_traffic BtTraffic; - struct bt_security BtSec; - RT_WORK_ITEM HCICmdWorkItem; - struct timer_list BTHCICmdTimer; - RT_WORK_ITEM BTPsDisableWorkItem; - RT_WORK_ITEM BTConnectWorkItem; - struct timer_list BTHCIDiscardAclDataTimer; - struct timer_list BTHCIJoinTimeoutTimer; - struct timer_list BTTestSendPacketTimer; - struct timer_list BTDisconnectPhyLinkTimer; - struct timer_list BTBeaconTimer; - u8 BTBeaconTmrOn; - - struct timer_list BTPsDisableTimer; - - void * pBtChnlList; -}; - -struct packet_irp_acl_data { - u16 Handle:12; - u16 PB_Flag:2; - u16 BC_Flag:2; - u16 Length; - u8 Data[1]; -}; - -struct packet_irp_hcievent_data { - u8 EventCode; - u8 Length; - u8 Data[20]; -}; - -struct common_triple { - u8 byte_1st; - u8 byte_2nd; - u8 byte_3rd; -}; - -#define COUNTRY_STR_LEN 3 /* country string len = 3 */ - -#define LOCAL_PMK 0 - -enum hci_wifi_connect_status { - HCI_WIFI_NOT_CONNECTED = 0x0, - HCI_WIFI_CONNECTED = 0x1, - HCI_WIFI_CONNECT_IN_PROGRESS = 0x2, -}; - -enum hci_ext_bp_operation { - HCI_BT_OP_NONE = 0x0, - HCI_BT_OP_INQUIRY_START = 0x1, - HCI_BT_OP_INQUIRY_FINISH = 0x2, - HCI_BT_OP_PAGING_START = 0x3, - HCI_BT_OP_PAGING_SUCCESS = 0x4, - HCI_BT_OP_PAGING_UNSUCCESS = 0x5, - HCI_BT_OP_PAIRING_START = 0x6, - HCI_BT_OP_PAIRING_FINISH = 0x7, - HCI_BT_OP_BT_DEV_ENABLE = 0x8, - HCI_BT_OP_BT_DEV_DISABLE = 0x9, - HCI_BT_OP_MAX -}; - -#define BTHCI_SM_WITH_INFO(_Adapter, _StateToEnter, _StateCmd, _EntryNum) \ -{ \ - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state change] caused by ""%s"", line =%d\n", __func__, __LINE__)); \ - BTHCI_StateMachine(_Adapter, _StateToEnter, _StateCmd, _EntryNum);\ -} - -void BTHCI_EventParse(struct rtw_adapter *padapter, void *pEvntData, - u32 dataLen); -#define BT_EventParse BTHCI_EventParse -u8 BTHCI_HsConnectionEstablished(struct rtw_adapter *padapter); -void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter *padapter); -void BTHCI_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType); -void BTHCI_StateMachine(struct rtw_adapter *padapter, u8 StateToEnter, - enum hci_state_with_cmd StateCmd, u8 EntryNum); -void BTHCI_DisconnectPeer(struct rtw_adapter *padapter, u8 EntryNum); -void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter *padapter); -void BTHCI_EventAMPStatusChange(struct rtw_adapter *padapter, u8 AMP_Status); -void BTHCI_DisconnectAll(struct rtw_adapter *padapter); -enum hci_status BTHCI_HandleHCICMD(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd); - -/* ===== End of sync from SD7 driver COMMON/bt_hci.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.h ===== */ -#define GET_BT_INFO(padapter) (&GET_HAL_DATA(padapter)->BtInfo) - -#define BTC_FOR_SCAN_START 1 -#define BTC_FOR_SCAN_FINISH 0 - -#define BT_TXRX_CNT_THRES_1 1200 -#define BT_TXRX_CNT_THRES_2 1400 -#define BT_TXRX_CNT_THRES_3 3000 -#define BT_TXRX_CNT_LEVEL_0 0 /* < 1200 */ -#define BT_TXRX_CNT_LEVEL_1 1 /* >= 1200 && < 1400 */ -#define BT_TXRX_CNT_LEVEL_2 2 /* >= 1400 */ -#define BT_TXRX_CNT_LEVEL_3 3 /* >= 3000 */ - -enum bt_state_1ant { - BT_INFO_STATE_DISABLED = 0, - BT_INFO_STATE_NO_CONNECTION = 1, - BT_INFO_STATE_CONNECT_IDLE = 2, - BT_INFO_STATE_INQ_OR_PAG = 3, - BT_INFO_STATE_ACL_ONLY_BUSY = 4, - BT_INFO_STATE_SCO_ONLY_BUSY = 5, - BT_INFO_STATE_ACL_SCO_BUSY = 6, - BT_INFO_STATE_ACL_INQ_OR_PAG = 7, - BT_INFO_STATE_MAX = 8 -}; - -struct btdm_8723a_1ant { - u8 prePsTdma; - u8 curPsTdma; - u8 psTdmaDuAdjType; - u8 bPrePsTdmaOn; - u8 bCurPsTdmaOn; - u8 preWifiPara; - u8 curWifiPara; - u8 preCoexWifiCon; - u8 curCoexWifiCon; - u8 wifiRssiThresh; - - u32 psTdmaMonitorCnt; - u32 psTdmaGlobalCnt; - - /* DurationAdjust For SCO */ - u32 psTdmaMonitorCntForSCO; - u8 psTdmaDuAdjTypeForSCO; - u8 RSSI_WiFi_Last; - u8 RSSI_BT_Last; - - u8 bWiFiHalt; - u8 bRAChanged; -}; - -void BTDM_1AntSignalCompensation(struct rtw_adapter *padapter, - u8 *rssi_wifi, u8 *rssi_bt); -void BTDM_1AntForDhcp(struct rtw_adapter *padapter); -void BTDM_1AntBtCoexist8723A(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.h ===== */ -enum bt_2ant_bt_status { - BT_2ANT_BT_STATUS_IDLE = 0x0, - BT_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1, - BT_2ANT_BT_STATUS_NON_IDLE = 0x2, - BT_2ANT_BT_STATUS_MAX -}; - -enum bt_2ant_coex_algo { - BT_2ANT_COEX_ALGO_UNDEFINED = 0x0, - BT_2ANT_COEX_ALGO_SCO = 0x1, - BT_2ANT_COEX_ALGO_HID = 0x2, - BT_2ANT_COEX_ALGO_A2DP = 0x3, - BT_2ANT_COEX_ALGO_PANEDR = 0x4, - BT_2ANT_COEX_ALGO_PANHS = 0x5, - BT_2ANT_COEX_ALGO_PANEDR_A2DP = 0x6, - BT_2ANT_COEX_ALGO_PANEDR_HID = 0x7, - BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x8, - BT_2ANT_COEX_ALGO_HID_A2DP = 0x9, - BT_2ANT_COEX_ALGO_HID_A2DP_PANHS = 0xA, - BT_2ANT_COEX_ALGO_MAX = 0xB, -}; - -struct btdm_8723a_2ant { - u8 bPreDecBtPwr; - u8 bCurDecBtPwr; - - u8 preWlanActHi; - u8 curWlanActHi; - u8 preWlanActLo; - u8 curWlanActLo; - - u8 preFwDacSwingLvl; - u8 curFwDacSwingLvl; - - u8 bPreRfRxLpfShrink; - u8 bCurRfRxLpfShrink; - - u8 bPreLowPenaltyRa; - u8 bCurLowPenaltyRa; - - u8 preBtRetryIndex; - u8 curBtRetryIndex; - - u8 bPreDacSwingOn; - u32 preDacSwingLvl; - u8 bCurDacSwingOn; - u32 curDacSwingLvl; - - u8 bPreAdcBackOff; - u8 bCurAdcBackOff; - - u8 bPreAgcTableEn; - u8 bCurAgcTableEn; - - u32 preVal0x6c0; - u32 curVal0x6c0; - u32 preVal0x6c8; - u32 curVal0x6c8; - u8 preVal0x6cc; - u8 curVal0x6cc; - - u8 bCurIgnoreWlanAct; - u8 bPreIgnoreWlanAct; - - u8 prePsTdma; - u8 curPsTdma; - u8 psTdmaDuAdjType; - u8 bPrePsTdmaOn; - u8 bCurPsTdmaOn; - - u8 preAlgorithm; - u8 curAlgorithm; - u8 bResetTdmaAdjust; - - u8 btStatus; -}; - -void BTDM_2AntBtCoexist8723A(struct rtw_adapter *padapter); -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */ - -#define BT_Q_PKT_OFF 0 -#define BT_Q_PKT_ON 1 - -#define BT_TX_PWR_OFF 0 -#define BT_TX_PWR_ON 1 - -/* TDMA mode definition */ -#define TDMA_2ANT 0 -#define TDMA_1ANT 1 -#define TDMA_NAV_OFF 0 -#define TDMA_NAV_ON 1 -#define TDMA_DAC_SWING_OFF 0 -#define TDMA_DAC_SWING_ON 1 - -#define BT_RSSI_LEVEL_H 0 -#define BT_RSSI_LEVEL_M 1 -#define BT_RSSI_LEVEL_L 2 - -/* PTA mode related definition */ -#define BT_PTA_MODE_OFF 0 -#define BT_PTA_MODE_ON 1 - -/* Penalty Tx Rate Adaptive */ -#define BT_TX_RATE_ADAPTIVE_NORMAL 0 -#define BT_TX_RATE_ADAPTIVE_LOW_PENALTY 1 - -/* RF Corner */ -#define BT_RF_RX_LPF_CORNER_RESUME 0 -#define BT_RF_RX_LPF_CORNER_SHRINK 1 - -#define BT_INFO_ACL BIT(0) -#define BT_INFO_SCO BIT(1) -#define BT_INFO_INQ_PAG BIT(2) -#define BT_INFO_ACL_BUSY BIT(3) -#define BT_INFO_SCO_BUSY BIT(4) -#define BT_INFO_HID BIT(5) -#define BT_INFO_A2DP BIT(6) -#define BT_INFO_FTP BIT(7) - - - -struct bt_coexist_8723a { - u32 highPriorityTx; - u32 highPriorityRx; - u32 lowPriorityTx; - u32 lowPriorityRx; - u8 btRssi; - u8 TotalAntNum; - u8 bC2hBtInfoSupport; - u8 c2hBtInfo; - u8 c2hBtInfoOriginal; - u8 prec2hBtInfo; /* for 1Ant */ - u8 bC2hBtInquiryPage; - unsigned long btInqPageStartTime; /* for 2Ant */ - u8 c2hBtProfile; /* for 1Ant */ - u8 btRetryCnt; - u8 btInfoExt; - u8 bC2hBtInfoReqSent; - u8 bForceFwBtInfo; - u8 bForceA2dpSink; - struct btdm_8723a_2ant btdm2Ant; - struct btdm_8723a_1ant btdm1Ant; -}; - -void BTDM_SetFwChnlInfo(struct rtw_adapter *padapter, - enum rt_media_status mstatus); -u8 BTDM_IsWifiConnectionExist(struct rtw_adapter *padapter); -void BTDM_SetFw3a(struct rtw_adapter *padapter, u8 byte1, u8 byte2, u8 byte3, - u8 byte4, u8 byte5); -void BTDM_QueryBtInformation(struct rtw_adapter *padapter); -void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter *padapter, u8 type); -void BTDM_SetSwPenaltyTxRateAdaptive(struct rtw_adapter *padapter, u8 raType); -void BTDM_SetFwDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr); -u8 BTDM_BtProfileSupport(struct rtw_adapter *padapter); -void BTDM_LpsLeave(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.h ===== */ - -enum BT_A2DP_INDEX{ - BT_A2DP_INDEX0 = 0, /* 32, 12; the most critical for BT */ - BT_A2DP_INDEX1, /* 12, 24 */ - BT_A2DP_INDEX2, /* 0, 0 */ - BT_A2DP_INDEX_MAX -}; - -#define BT_A2DP_STATE_NOT_ENTERED 0 -#define BT_A2DP_STATE_DETECTING 1 -#define BT_A2DP_STATE_DETECTED 2 - -#define BTDM_ANT_BT_IDLE 0 -#define BTDM_ANT_WIFI 1 -#define BTDM_ANT_BT 2 - - -void BTDM_SingleAnt(struct rtw_adapter *padapter, u8 bSingleAntOn, - u8 bInterruptOn, u8 bMultiNAVOn); -void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.h ===== */ - -/* */ -/* For old core stack before v251 */ -/* */ -#define BT_RSSI_STATE_NORMAL_POWER BIT(0) -#define BT_RSSI_STATE_AMDPU_OFF BIT(1) -#define BT_RSSI_STATE_SPECIAL_LOW BIT(2) -#define BT_RSSI_STATE_BG_EDCA_LOW BIT(3) -#define BT_RSSI_STATE_TXPOWER_LOW BIT(4) - -#define BT_DACSWING_OFF 0 -#define BT_DACSWING_M4 1 -#define BT_DACSWING_M7 2 -#define BT_DACSWING_M10 3 - -void BTDM_DiminishWiFi(struct rtw_adapter *Adapter, u8 bDACOn, u8 bInterruptOn, - u8 DACSwingLevel, u8 bNAVOn); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.h ===== */ - -/* HEADER/TypeDef.h */ -#define MAX_FW_SUPPORT_MACID_NUM 64 - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtCoexist.h ===== */ - -#define FW_VER_BT_REG 62 -#define FW_VER_BT_REG1 74 -#define REG_BT_ACTIVE 0x444 -#define REG_BT_STATE 0x448 -#define REG_BT_POLLING1 0x44c -#define REG_BT_POLLING 0x700 - -#define REG_BT_ACTIVE_OLD 0x488 -#define REG_BT_STATE_OLD 0x48c -#define REG_BT_POLLING_OLD 0x490 - -/* The reg define is for 8723 */ -#define REG_HIGH_PRIORITY_TXRX 0x770 -#define REG_LOW_PRIORITY_TXRX 0x774 - -#define BT_FW_COEX_THRESH_TOL 6 -#define BT_FW_COEX_THRESH_20 20 -#define BT_FW_COEX_THRESH_23 23 -#define BT_FW_COEX_THRESH_25 25 -#define BT_FW_COEX_THRESH_30 30 -#define BT_FW_COEX_THRESH_35 35 -#define BT_FW_COEX_THRESH_40 40 -#define BT_FW_COEX_THRESH_45 45 -#define BT_FW_COEX_THRESH_47 47 -#define BT_FW_COEX_THRESH_50 50 -#define BT_FW_COEX_THRESH_55 55 -#define BT_FW_COEX_THRESH_65 65 - -#define BT_COEX_STATE_BT30 BIT(0) -#define BT_COEX_STATE_WIFI_HT20 BIT(1) -#define BT_COEX_STATE_WIFI_HT40 BIT(2) -#define BT_COEX_STATE_WIFI_LEGACY BIT(3) - -#define BT_COEX_STATE_WIFI_RSSI_LOW BIT(4) -#define BT_COEX_STATE_WIFI_RSSI_MEDIUM BIT(5) -#define BT_COEX_STATE_WIFI_RSSI_HIGH BIT(6) -#define BT_COEX_STATE_DEC_BT_POWER BIT(7) - -#define BT_COEX_STATE_WIFI_IDLE BIT(8) -#define BT_COEX_STATE_WIFI_UPLINK BIT(9) -#define BT_COEX_STATE_WIFI_DOWNLINK BIT(10) - -#define BT_COEX_STATE_BT_INQ_PAGE BIT(11) -#define BT_COEX_STATE_BT_IDLE BIT(12) -#define BT_COEX_STATE_BT_UPLINK BIT(13) -#define BT_COEX_STATE_BT_DOWNLINK BIT(14) -/* */ -/* Todo: Remove these definitions */ -#define BT_COEX_STATE_BT_PAN_IDLE BIT(15) -#define BT_COEX_STATE_BT_PAN_UPLINK BIT(16) -#define BT_COEX_STATE_BT_PAN_DOWNLINK BIT(17) -#define BT_COEX_STATE_BT_A2DP_IDLE BIT(18) -/* */ -#define BT_COEX_STATE_BT_RSSI_LOW BIT(19) - -#define BT_COEX_STATE_PROFILE_HID BIT(20) -#define BT_COEX_STATE_PROFILE_A2DP BIT(21) -#define BT_COEX_STATE_PROFILE_PAN BIT(22) -#define BT_COEX_STATE_PROFILE_SCO BIT(23) - -#define BT_COEX_STATE_WIFI_RSSI_1_LOW BIT(24) -#define BT_COEX_STATE_WIFI_RSSI_1_MEDIUM BIT(25) -#define BT_COEX_STATE_WIFI_RSSI_1_HIGH BIT(26) - -#define BT_COEX_STATE_WIFI_RSSI_BEACON_LOW BIT(27) -#define BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM BIT(28) -#define BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH BIT(29) - - -#define BT_COEX_STATE_BTINFO_COMMON BIT(30) -#define BT_COEX_STATE_BTINFO_B_HID_SCOESCO BIT(31) -#define BT_COEX_STATE_BTINFO_B_FTP_A2DP BIT(32) - -#define BT_COEX_STATE_BT_CNT_LEVEL_0 BIT(33) -#define BT_COEX_STATE_BT_CNT_LEVEL_1 BIT(34) -#define BT_COEX_STATE_BT_CNT_LEVEL_2 BIT(35) -#define BT_COEX_STATE_BT_CNT_LEVEL_3 BIT(36) - -#define BT_RSSI_STATE_HIGH 0 -#define BT_RSSI_STATE_MEDIUM 1 -#define BT_RSSI_STATE_LOW 2 -#define BT_RSSI_STATE_STAY_HIGH 3 -#define BT_RSSI_STATE_STAY_MEDIUM 4 -#define BT_RSSI_STATE_STAY_LOW 5 - -#define BT_AGCTABLE_OFF 0 -#define BT_AGCTABLE_ON 1 - -#define BT_BB_BACKOFF_OFF 0 -#define BT_BB_BACKOFF_ON 1 - -#define BT_FW_NAV_OFF 0 -#define BT_FW_NAV_ON 1 - -#define BT_COEX_MECH_NONE 0 -#define BT_COEX_MECH_SCO 1 -#define BT_COEX_MECH_HID 2 -#define BT_COEX_MECH_A2DP 3 -#define BT_COEX_MECH_PAN 4 -#define BT_COEX_MECH_HID_A2DP 5 -#define BT_COEX_MECH_HID_PAN 6 -#define BT_COEX_MECH_PAN_A2DP 7 -#define BT_COEX_MECH_HID_SCO_ESCO 8 -#define BT_COEX_MECH_FTP_A2DP 9 -#define BT_COEX_MECH_COMMON 10 -#define BT_COEX_MECH_MAX 11 -/* BT Dbg Ctrl */ -#define BT_DBG_PROFILE_NONE 0 -#define BT_DBG_PROFILE_SCO 1 -#define BT_DBG_PROFILE_HID 2 -#define BT_DBG_PROFILE_A2DP 3 -#define BT_DBG_PROFILE_PAN 4 -#define BT_DBG_PROFILE_HID_A2DP 5 -#define BT_DBG_PROFILE_HID_PAN 6 -#define BT_DBG_PROFILE_PAN_A2DP 7 -#define BT_DBG_PROFILE_MAX 9 - -struct bt_coexist_str { - u8 BluetoothCoexist; - u8 BT_Ant_Num; - u8 BT_CoexistType; - u8 BT_Ant_isolation; /* 0:good, 1:bad */ - u8 bt_radiosharedtype; - u32 Ratio_Tx; - u32 Ratio_PRI; - u8 bInitlized; - u32 BtRfRegOrigin1E; - u32 BtRfRegOrigin1F; - u8 bBTBusyTraffic; - u8 bBTTrafficModeSet; - u8 bBTNonTrafficModeSet; - struct bt_traffic_statistics BT21TrafficStatistics; - u64 CurrentState; - u64 PreviousState; - u8 preRssiState; - u8 preRssiState1; - u8 preRssiStateBeacon; - u8 bFWCoexistAllOff; - u8 bSWCoexistAllOff; - u8 bHWCoexistAllOff; - u8 bBalanceOn; - u8 bSingleAntOn; - u8 bInterruptOn; - u8 bMultiNAVOn; - u8 PreWLANActH; - u8 PreWLANActL; - u8 WLANActH; - u8 WLANActL; - u8 A2DPState; - u8 AntennaState; - u32 lastBtEdca; - u16 last_aggr_num; - u8 bEDCAInitialized; - u8 exec_cnt; - u8 b8723aAgcTableOn; - u8 b92DAgcTableOn; - struct bt_coexist_8723a halCoex8723; - u8 btActiveZeroCnt; - u8 bCurBtDisabled; - u8 bPreBtDisabled; - u8 bNeedToRoamForBtDisableEnable; - u8 fw3aVal[5]; -}; - -void BTDM_CheckAntSelMode(struct rtw_adapter *padapter); -void BTDM_FwC2hBtRssi(struct rtw_adapter *padapter, u8 *tmpBuf); -#define BT_FwC2hBtRssi BTDM_FwC2hBtRssi -void BTDM_DisplayBtCoexInfo(struct rtw_adapter *padapter); -#define BT_DisplayBtCoexInfo BTDM_DisplayBtCoexInfo -void BTDM_RejectAPAggregatedPacket(struct rtw_adapter *padapter, u8 bReject); -u8 BTDM_IsHT40(struct rtw_adapter *padapter); -u8 BTDM_Legacy(struct rtw_adapter *padapter); -void BTDM_CheckWiFiState(struct rtw_adapter *padapter); -s32 BTDM_GetRxSS(struct rtw_adapter *padapter); -u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1); -u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1); -u8 BTDM_CheckCoexRSSIState(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1); -void BTDM_Balance(struct rtw_adapter *padapter, u8 bBalanceOn, u8 ms0, u8 ms1); -void BTDM_AGCTable(struct rtw_adapter *padapter, u8 type); -void BTDM_BBBackOffLevel(struct rtw_adapter *padapter, u8 type); -void BTDM_FWCoexAllOff(struct rtw_adapter *padapter); -void BTDM_SWCoexAllOff(struct rtw_adapter *padapter); -void BTDM_HWCoexAllOff(struct rtw_adapter *padapter); -void BTDM_CoexAllOff(struct rtw_adapter *padapter); -void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter *padapter); -void BTDM_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, - u8 *rssi_bt); -void BTDM_UpdateCoexState(struct rtw_adapter *padapter); -u8 BTDM_IsSameCoexistState(struct rtw_adapter *padapter); -void BTDM_PWDBMonitor(struct rtw_adapter *padapter); -u8 BTDM_IsBTBusy(struct rtw_adapter *padapter); -#define BT_IsBtBusy BTDM_IsBTBusy -u8 BTDM_IsWifiBusy(struct rtw_adapter *padapter); -u8 BTDM_IsCoexistStateChanged(struct rtw_adapter *padapter); -u8 BTDM_IsWifiUplink(struct rtw_adapter *padapter); -u8 BTDM_IsWifiDownlink(struct rtw_adapter *padapter); -u8 BTDM_IsBTHSMode(struct rtw_adapter *padapter); -u8 BTDM_IsBTUplink(struct rtw_adapter *padapter); -u8 BTDM_IsBTDownlink(struct rtw_adapter *padapter); -void BTDM_AdjustForBtOperation(struct rtw_adapter *padapter); -void BTDM_ForHalt(struct rtw_adapter *padapter); -void BTDM_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType); -void BTDM_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action); -void BTDM_MediaStatusNotify(struct rtw_adapter *padapter, - enum rt_media_status mstatus); -void BTDM_ForDhcp(struct rtw_adapter *padapter); -void BTDM_ResetActionProfileState(struct rtw_adapter *padapter); -void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum); -#define BT_SetBtCoexCurrAntNum BTDM_SetBtCoexCurrAntNum -u8 BTDM_IsActionSCO(struct rtw_adapter *padapter); -u8 BTDM_IsActionHID(struct rtw_adapter *padapter); -u8 BTDM_IsActionA2DP(struct rtw_adapter *padapter); -u8 BTDM_IsActionPAN(struct rtw_adapter *padapter); -u8 BTDM_IsActionHIDA2DP(struct rtw_adapter *padapter); -u8 BTDM_IsActionHIDPAN(struct rtw_adapter *padapter); -u8 BTDM_IsActionPANA2DP(struct rtw_adapter *padapter); -u32 BTDM_BtTxRxCounterH(struct rtw_adapter *padapter); -u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/HalBT.h ===== */ - -#define RTS_CTS_NO_LEN_LIMIT 0 - -u8 HALBT_GetPGAntNum(struct rtw_adapter *padapter); -#define BT_GetPGAntNum HALBT_GetPGAntNum -void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum); -void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum); -u8 HALBT_IsBTExist(struct rtw_adapter *padapter); -#define BT_IsBtExist HALBT_IsBTExist -u8 HALBT_BTChipType(struct rtw_adapter *padapter); -void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/HalBT.c ===== */ - -#define _bt_dbg_off_ 0 -#define _bt_dbg_on_ 1 - -extern u32 BTCoexDbgLevel; - - - -#endif /* __RTL8723A_BT_COEXIST_H__ */ diff --git a/drivers/staging/rtl8723au/include/rtl8723a_bt_intf.h b/drivers/staging/rtl8723au/include/rtl8723a_bt_intf.h deleted file mode 100644 index 4733559970e5..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_bt_intf.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * Copyright(c) 2014, Jes Sorensen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_BT_INTF_H__ -#define __RTL8723A_BT_INTF_H__ - -#include - -#ifdef CONFIG_8723AU_BT_COEXIST -enum rt_media_status; -bool rtl8723a_BT_using_antenna_1(struct rtw_adapter *padapter); -bool rtl8723a_BT_enabled(struct rtw_adapter *padapter); -bool rtl8723a_BT_coexist(struct rtw_adapter *padapter); -void rtl8723a_BT_do_coexist(struct rtw_adapter *padapter); -void rtl8723a_BT_wifiscan_notify(struct rtw_adapter *padapter, u8 scanType); -void rtl8723a_BT_mediastatus_notify(struct rtw_adapter *padapter, - enum rt_media_status mstatus); -void rtl8723a_BT_specialpacket_notify(struct rtw_adapter *padapter); -void rtl8723a_BT_lps_leave(struct rtw_adapter *padapter); -void rtl8723a_BT_disable_coexist(struct rtw_adapter *padapter); -bool rtl8723a_BT_disable_EDCA_turbo(struct rtw_adapter *padapter); -void rtl8723a_dual_antenna_detection(struct rtw_adapter *padapter); -void rtl8723a_BT_init_hwconfig(struct rtw_adapter *padapter); -void rtl8723a_BT_wifiassociate_notify(struct rtw_adapter *padapter, u8 action); -void rtl8723a_BT_init_hal_vars(struct rtw_adapter *padapter); -void rtl8723a_fw_c2h_BT_info(struct rtw_adapter *padapter, u8 *tmpBuf, u8 length); -#else -static inline bool rtl8723a_BT_using_antenna_1(struct rtw_adapter *padapter) -{ - return false; -} -static inline bool rtl8723a_BT_enabled(struct rtw_adapter *padapter) -{ - return false; -} -static inline bool rtl8723a_BT_coexist(struct rtw_adapter *padapter) -{ - return false; -} -#define rtl8723a_BT_do_coexist(padapter) do {} while(0) -#define rtl8723a_BT_wifiscan_notify(padapter, scanType) do {} while(0) -#define rtl8723a_BT_mediastatus_notify(padapter, mstatus) do {} while(0) -#define rtl8723a_BT_specialpacket_notify(padapter) do {} while(0) -#define rtl8723a_BT_lps_leave(padapter) do {} while(0) -#define rtl8723a_BT_disable_coexist(padapter) do {} while(0) -static inline bool rtl8723a_BT_disable_EDCA_turbo(struct rtw_adapter *padapter) -{ - return false; -} -#define rtl8723a_dual_antenna_detection(padapter) do {} while(0) -#define rtl8723a_BT_init_hwconfig(padapter) do {} while(0) -#define rtl8723a_BT_wifiassociate_notify(padapter, action) do {} while(0) -#define rtl8723a_BT_init_hal_vars(padapter) do {} while(0) -#define rtl8723a_fw_c2h_BT_info(padapter, tmpBuf, length) do {} while(0) -#endif - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_cmd.h b/drivers/staging/rtl8723au/include/rtl8723a_cmd.h deleted file mode 100644 index f95535a915ab..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_cmd.h +++ /dev/null @@ -1,158 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_CMD_H__ -#define __RTL8723A_CMD_H__ - - -#define H2C_BT_FW_PATCH_LEN 3 -#define H2C_BT_PWR_FORCE_LEN 3 - -enum cmd_msg_element_id -{ - NONE_CMDMSG_EID, - AP_OFFLOAD_EID = 0, - SET_PWRMODE_EID = 1, - JOINBSS_RPT_EID = 2, - RSVD_PAGE_EID = 3, - RSSI_4_EID = 4, - RSSI_SETTING_EID = 5, - MACID_CONFIG_EID = 6, - MACID_PS_MODE_EID = 7, - P2P_PS_OFFLOAD_EID = 8, - SELECTIVE_SUSPEND_ROF_CMD = 9, - BT_QUEUE_PKT_EID = 17, - BT_ANT_TDMA_EID = 20, - BT_2ANT_HID_EID = 21, - P2P_PS_CTW_CMD_EID = 32, - FORCE_BT_TX_PWR_EID = 33, - SET_TDMA_WLAN_ACT_TIME_EID = 34, - SET_BT_TX_RETRY_INDEX_EID = 35, - HID_PROFILE_ENABLE_EID = 36, - BT_IGNORE_WLAN_ACT_EID = 37, - BT_PTA_MANAGER_UPDATE_ENABLE_EID = 38, - DAC_SWING_VALUE_EID = 41, - TRADITIONAL_TDMA_EN_EID = 51, - H2C_BT_FW_PATCH = 54, - B_TYPE_TDMA_EID = 58, - SCAN_EN_EID = 59, - LOWPWR_LPS_EID = 71, - H2C_RESET_TSF = 75, - MAX_CMDMSG_EID -}; - -struct cmd_msg_parm { - u8 eid; /* element id */ - u8 sz; /* sz */ - u8 buf[6]; -}; - -struct setpwrmode_parm { - u8 Mode; - u8 SmartPS; - u8 AwakeInterval; /* unit: beacon interval */ - u8 bAllQueueUAPSD; - -#define SETPM_LOWRXBCN BIT(0) -#define SETPM_AUTOANTSWITCH BIT(1) -#define SETPM_PSALLOWBTHIGHPRI BIT(2) - u8 BcnAntMode; -} __packed; - -struct H2C_SS_RFOFF_PARAM{ - u8 ROFOn; /* 1: on, 0:off */ - u16 gpio_period; /* unit: 1024 us */ -}__attribute__ ((packed)); - - -struct joinbssrpt_parm { - u8 OpMode; /* enum rt_media_status */ -}; - -struct rsvdpage_loc { - u8 LocProbeRsp; - u8 LocPsPoll; - u8 LocNullData; - u8 LocQosNull; - u8 LocBTQosNull; -}; - -struct P2P_PS_Offload_t { - u8 Offload_En:1; - u8 role:1; /* 1: Owner, 0: Client */ - u8 CTWindow_En:1; - u8 NoA0_En:1; - u8 NoA1_En:1; - u8 AllStaSleep:1; /* Only valid in Owner */ - u8 discovery:1; - u8 rsvd:1; -}; - -struct P2P_PS_CTWPeriod_t { - u8 CTWPeriod; /* TU */ -}; - -#define B_TDMA_EN BIT(0) -#define B_TDMA_FIXANTINBT BIT(1) -#define B_TDMA_TXPSPOLL BIT(2) -#define B_TDMA_VAL870 BIT(3) -#define B_TDMA_AUTOWAKEUP BIT(4) -#define B_TDMA_NOPS BIT(5) -#define B_TDMA_WLANHIGHPRI BIT(6) - -struct b_type_tdma_parm { - u8 option; - - u8 TBTTOnPeriod; - u8 MedPeriod; - u8 rsvd30; -} __packed; - -struct scan_en_parm { - u8 En; -} __packed; - -/* BT_PWR */ -#define SET_H2CCMD_BT_PWR_IDX(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd, 0, 8, __Value) - -/* BT_FW_PATCH */ -#define SET_H2CCMD_BT_FW_PATCH_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_4BYTE(__pH2CCmd, 0, 8, __Value) /* SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 8, __Value) */ -#define SET_H2CCMD_BT_FW_PATCH_SIZE(__pH2CCmd, __Value) SET_BITS_TO_LE_4BYTE(__pH2CCmd, 8, 16, __Value) /* SET_BITS_TO_LE_2BYTE((__pH2CCmd)+1, 0, 16, __Value) */ - -struct lowpwr_lps_parm{ - u8 bcn_count:4; - u8 tb_bcn_threshold:3; - u8 enable:1; - u8 bcn_interval; - u8 drop_threshold; - u8 max_early_period; - u8 max_bcn_timeout_period; -} __packed; - - -/* host message to firmware cmd */ -void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode); -void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus); -#ifdef CONFIG_8723AU_BT_COEXIST -void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter); -#else -#define rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter) do {} while(0) -#endif -int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u32 param); -int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg); -void rtl8723a_add_rateatid(struct rtw_adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level); - -int FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_dm.h b/drivers/staging/rtl8723au/include/rtl8723a_dm.h deleted file mode 100644 index bf236e8e47a2..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_dm.h +++ /dev/null @@ -1,137 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_DM_H__ -#define __RTL8723A_DM_H__ -/* */ -/* Description: */ -/* */ -/* This file is for 8723A dynamic mechanism only */ -/* */ -/* */ -/* */ -#define DYNAMIC_FUNC_BT BIT(0) - -enum{ - UP_LINK, - DOWN_LINK, -}; -/* */ -/* structure and define */ -/* */ - -/* duplicate code,will move to ODM ######### */ -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 -/* duplicate code,will move to ODM ######### */ -struct dm_priv { - u32 InitODMFlag; - - /* Upper and Lower Signal threshold for Rate Adaptive*/ - int UndecoratedSmoothedPWDB; - int UndecoratedSmoothedCCK; - int EntryMinUndecoratedSmoothedPWDB; - int EntryMaxUndecoratedSmoothedPWDB; - int MinUndecoratedPWDBForDM; - int LastMinUndecoratedPWDBForDM; - - s32 UndecoratedSmoothedBeacon; - #ifdef CONFIG_8723AU_BT_COEXIST - s32 BT_EntryMinUndecoratedSmoothedPWDB; - s32 BT_EntryMaxUndecoratedSmoothedPWDB; - #endif - - /* for High Power */ - u8 DynamicTxHighPowerLvl;/* Add by Jacken Tx Power Control for Near/Far Range 2008/03/06 */ - - /* for tx power tracking */ - u8 bTXPowerTracking; - u8 TXPowercount; - u8 bTXPowerTrackingInit; - u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking as default */ - u8 TM_Trigger; - - u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */ - u8 ThermalValue; - u8 ThermalValue_LCK; - u8 ThermalValue_IQK; - u8 ThermalValue_DPK; - - u8 bRfPiEnable; - - /* for APK */ - u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */ - u8 bAPKdone; - u8 bAPKThermalMeterIgnore; - u8 bDPdone; - u8 bDPPathAOK; - u8 bDPPathBOK; - - /* for IQK */ - u32 RegC04; - u32 Reg874; - u32 RegC08; - u32 RegB68; - u32 RegB6C; - u32 Reg870; - u32 Reg860; - u32 Reg864; - u32 ADDA_backup[IQK_ADDA_REG_NUM]; - u32 IQK_MAC_backup[IQK_MAC_REG_NUM]; - u32 IQK_BB_backup_recover[9]; - u32 IQK_BB_backup[IQK_BB_REG_NUM]; - u8 PowerIndex_backup[6]; - - u8 bCCKinCH14; - - u8 CCK_index; - u8 OFDM_index[2]; - - u8 bDoneTxpower; - u8 CCK_index_HP; - u8 OFDM_index_HP[2]; - u8 ThermalValue_HP[HP_THERMAL_NUM]; - u8 ThermalValue_HP_index; - - /* for TxPwrTracking */ - s32 RegE94; - s32 RegE9C; - s32 RegEB4; - s32 RegEBC; - - u32 TXPowerTrackingCallbackCnt; /* cosa add for debug */ - - u32 prv_traffic_idx; /* edca turbo */ - - s32 OFDM_Pkt_Cnt; - u8 RSSI_Select; -/* u8 DIG_Dynamic_MIN ; */ -/* duplicate code,will move to ODM ######### */ - /* Add for Reading Initial Data Rate SEL Register 0x484 during watchdog. Using for fill tx desc. 2011.3.21 by Thomas */ - u8 INIDATA_RATE[32]; -}; - - -/* */ -/* function prototype */ -/* */ - -void rtl8723a_init_dm_priv(struct rtw_adapter *padapter); - -void rtl8723a_InitHalDm(struct rtw_adapter *padapter); -void rtl8723a_HalDmWatchDog(struct rtw_adapter *padapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_hal.h b/drivers/staging/rtl8723au/include/rtl8723a_hal.h deleted file mode 100644 index 77a0fd485b51..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_hal.h +++ /dev/null @@ -1,538 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_HAL_H__ -#define __RTL8723A_HAL_H__ - -#include "rtl8723a_spec.h" -#include "rtl8723a_pg.h" -#include "Hal8723APhyReg.h" -#include "Hal8723APhyCfg.h" -#include "rtl8723a_rf.h" -#include "rtl8723a_bt_intf.h" -#ifdef CONFIG_8723AU_BT_COEXIST -#include "rtl8723a_bt-coexist.h" -#endif -#include "rtl8723a_dm.h" -#include "rtl8723a_recv.h" -#include "rtl8723a_xmit.h" -#include "rtl8723a_cmd.h" -#include "rtl8723a_sreset.h" -#include "rtw_efuse.h" -#include "rtw_eeprom.h" - -#include "odm_precomp.h" -#include "odm.h" - - -/* 2TODO: We should define 8192S firmware related macro settings here!! */ -#define RTL819X_DEFAULT_RF_TYPE RF_1T2R -#define RTL819X_TOTAL_RF_PATH 2 - -/* */ -/* RTL8723S From header */ -/* */ - -/* Fw Array */ -#define Rtl8723_FwImageArray Rtl8723UFwImgArray -#define Rtl8723_FwUMCBCutImageArrayWithBT Rtl8723UFwUMCBCutImgArrayWithBT -#define Rtl8723_FwUMCBCutImageArrayWithoutBT Rtl8723UFwUMCBCutImgArrayWithoutBT - -#define Rtl8723_ImgArrayLength Rtl8723UImgArrayLength -#define Rtl8723_UMCBCutImgArrayWithBTLength Rtl8723UUMCBCutImgArrayWithBTLength -#define Rtl8723_UMCBCutImgArrayWithoutBTLength Rtl8723UUMCBCutImgArrayWithoutBTLength - -#define Rtl8723_PHY_REG_Array_PG Rtl8723UPHY_REG_Array_PG -#define Rtl8723_PHY_REG_Array_PGLength Rtl8723UPHY_REG_Array_PGLength - -#define Rtl8723_FwUMCBCutMPImageArray Rtl8723SFwUMCBCutMPImgAr -#define Rtl8723_UMCBCutMPImgArrayLength Rtl8723SUMCBCutMPImgArrayLength - -#define DRVINFO_SZ 4 /* unit is 8bytes */ -#define PageNum_128(_Len) (u32)(((_Len)>>7) + ((_Len)&0x7F ? 1:0)) - -#define FW_8723A_SIZE 0x8000 -#define FW_8723A_START_ADDRESS 0x1000 -#define FW_8723A_END_ADDRESS 0x1FFF /* 0x5FFF */ - -#define MAX_PAGE_SIZE 4096 /* @ page : 4k bytes */ - -#define IS_FW_HEADER_EXIST(_pFwHdr) ((le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x92C0 ||\ - (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x88C0 ||\ - (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x2300) - -/* */ -/* This structure must be cared byte-ordering */ -/* */ -/* Added by tynli. 2009.12.04. */ -struct rt_8723a_firmware_hdr { - /* 8-byte alinment required */ - - /* LONG WORD 0 ---- */ - __le16 Signature; /* - * 92C0: test chip; 92C, 88C0: test chip; - * 88C1: MP A-cut; 92C1: MP A-cut - */ - u8 Category; /* AP/NIC and USB/PCI */ - u8 Function; /* Reserved for different FW function indcation, for further use when driver needs to download different FW in different conditions */ - __le16 Version; /* FW Version */ - u8 Subversion; /* FW Subversion, default 0x00 */ - u8 Rsvd1; - - - /* LONG WORD 1 ---- */ - u8 Month; /* Release time Month field */ - u8 Date; /* Release time Date field */ - u8 Hour; /* Release time Hour field */ - u8 Minute; /* Release time Minute field */ - __le16 RamCodeSize; /* The size of RAM code */ - __le16 Rsvd2; - - /* LONG WORD 2 ---- */ - __le32 SvnIdx; /* The SVN entry index */ - __le32 Rsvd3; - - /* LONG WORD 3 ---- */ - __le32 Rsvd4; - __le32 Rsvd5; -}; - -#define DRIVER_EARLY_INT_TIME 0x05 -#define BCN_DMA_ATIME_INT_TIME 0x02 - - -/* BK, BE, VI, VO, HCCA, MANAGEMENT, COMMAND, HIGH, BEACON. */ -#define MAX_TX_QUEUE 9 - -#define TX_SELE_HQ BIT(0) /* High Queue */ -#define TX_SELE_LQ BIT(1) /* Low Queue */ -#define TX_SELE_NQ BIT(2) /* Normal Queue */ - -/* Note: We will divide number of page equally for each queue other than public queue! */ -#define TX_TOTAL_PAGE_NUMBER 0xF8 -#define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1) - -/* For Normal Chip Setting */ -/* (HPQ + LPQ + NPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ -#define NORMAL_PAGE_NUM_PUBQ 0xE7 -#define NORMAL_PAGE_NUM_HPQ 0x0C -#define NORMAL_PAGE_NUM_LPQ 0x02 -#define NORMAL_PAGE_NUM_NPQ 0x02 - -/* For Test Chip Setting */ -/* (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ -#define TEST_PAGE_NUM_PUBQ 0x7E - -/* For Test Chip Setting */ -#define WMM_TEST_TX_TOTAL_PAGE_NUMBER 0xF5 -#define WMM_TEST_TX_PAGE_BOUNDARY (WMM_TEST_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */ - -#define WMM_TEST_PAGE_NUM_PUBQ 0xA3 -#define WMM_TEST_PAGE_NUM_HPQ 0x29 -#define WMM_TEST_PAGE_NUM_LPQ 0x29 - -/* Note: For Normal Chip Setting, modify later */ -#define WMM_NORMAL_TX_TOTAL_PAGE_NUMBER 0xF5 -#define WMM_NORMAL_TX_PAGE_BOUNDARY (WMM_TEST_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */ - -#define WMM_NORMAL_PAGE_NUM_PUBQ 0xB0 -#define WMM_NORMAL_PAGE_NUM_HPQ 0x29 -#define WMM_NORMAL_PAGE_NUM_LPQ 0x1C -#define WMM_NORMAL_PAGE_NUM_NPQ 0x1C - - -/* */ -/* Chip specific */ -/* */ -#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) -#define CHIP_BONDING_92C_1T2R 0x1 -#define CHIP_BONDING_88C_USB_MCARD 0x2 -#define CHIP_BONDING_88C_USB_HP 0x1 - -#include "HalVerDef.h" -#include "hal_com.h" - -/* */ -/* Channel Plan */ -/* */ -enum ChannelPlan -{ - CHPL_FCC = 0, - CHPL_IC = 1, - CHPL_ETSI = 2, - CHPL_SPAIN = 3, - CHPL_FRANCE = 4, - CHPL_MKK = 5, - CHPL_MKK1 = 6, - CHPL_ISRAEL = 7, - CHPL_TELEC = 8, - CHPL_GLOBAL = 9, - CHPL_WORLD = 10, -}; - -#define EFUSE_REAL_CONTENT_LEN 512 -#define EFUSE_MAP_LEN 128 -#define EFUSE_MAX_SECTION 16 -#define EFUSE_IC_ID_OFFSET 506 /* For some inferiority IC purpose. added by Roger, 2009.09.02. */ -#define AVAILABLE_EFUSE_ADDR(addr) (addr < EFUSE_REAL_CONTENT_LEN) -/* */ -/* */ -/* To prevent out of boundary programming case, */ -/* leave 1byte and program full section */ -/* 9bytes + 1byt + 5bytes and pre 1byte. */ -/* For worst case: */ -/* | 1byte|----8bytes----|1byte|--5bytes--| */ -/* | | Reserved(14bytes) | */ -/* */ - -/* PG data exclude header, dummy 6 bytes from CP test and reserved 1byte. */ -#define EFUSE_OOB_PROTECT_BYTES 15 - -#define EFUSE_REAL_CONTENT_LEN_8723A 512 -#define EFUSE_MAP_LEN_8723A 256 -#define EFUSE_MAX_SECTION_8723A 32 - -/* */ -/* EFUSE for BT definition */ -/* */ -#define EFUSE_BT_REAL_BANK_CONTENT_LEN 512 -#define EFUSE_BT_REAL_CONTENT_LEN 1536 /* 512*3 */ -#define EFUSE_BT_MAP_LEN 1024 /* 1k bytes */ -#define EFUSE_BT_MAX_SECTION 128 /* 1024/8 */ - -#define EFUSE_PROTECT_BYTES_BANK 16 - -/* */ -/* For RTL8723 WiFi/BT/GPS multi-function configuration. 2010.10.06. */ -/* */ -enum RT_MULTI_FUNC { - RT_MULTI_FUNC_NONE = 0x00, - RT_MULTI_FUNC_WIFI = 0x01, - RT_MULTI_FUNC_BT = 0x02, - RT_MULTI_FUNC_GPS = 0x04, -}; - -/* */ -/* For RTL8723 WiFi PDn/GPIO polarity control configuration. 2010.10.08. */ -/* */ -enum RT_POLARITY_CTL { - RT_POLARITY_LOW_ACT = 0, - RT_POLARITY_HIGH_ACT = 1, -}; - -/* For RTL8723 regulator mode. by tynli. 2011.01.14. */ -enum RT_REGULATOR_MODE { - RT_SWITCHING_REGULATOR = 0, - RT_LDO_REGULATOR = 1, -}; - -/* Description: Determine the types of C2H events that are the same in driver and Fw. */ -/* Fisrt constructed by tynli. 2009.10.09. */ -enum { - C2H_DBG = 0, - C2H_TSF = 1, - C2H_AP_RPT_RSP = 2, - C2H_CCX_TX_RPT = 3, /* The FW notify the report of the specific tx packet. */ - C2H_BT_RSSI = 4, - C2H_BT_OP_MODE = 5, - C2H_EXT_RA_RPT = 6, - C2H_HW_INFO_EXCH = 10, - C2H_C2H_H2C_TEST = 11, - C2H_BT_INFO = 12, - C2H_BT_MP_INFO = 15, - MAX_C2HEVENT -}; - -struct hal_data_8723a { - struct hal_version VersionID; - enum rt_customer_id CustomerID; - - u16 FirmwareVersion; - u16 FirmwareVersionRev; - u16 FirmwareSubVersion; - u16 FirmwareSignature; - - /* current WIFI_PHY values */ - u32 ReceiveConfig; - enum WIRELESS_MODE CurrentWirelessMode; - enum ht_channel_width CurrentChannelBW; - u8 CurrentChannel; - u8 nCur40MhzPrimeSC;/* Control channel sub-carrier */ - - u16 BasicRateSet; - - /* rf_ctrl */ - u8 rf_type; - u8 NumTotalRFPath; - - u8 BoardType; - u8 CrystalCap; - /* */ - /* EEPROM setting. */ - /* */ - u8 EEPROMVersion; - u8 EEPROMCustomerID; - u8 EEPROMSubCustomerID; - u8 EEPROMRegulatory; - u8 EEPROMThermalMeter; - u8 EEPROMBluetoothCoexist; - u8 EEPROMBluetoothType; - u8 EEPROMBluetoothAntNum; - u8 EEPROMBluetoothAntIsolation; - u8 EEPROMBluetoothRadioShared; - - u8 bTXPowerDataReadFromEEPORM; - u8 bAPKThermalMeterIgnore; - - u8 bIQKInitialized; - u8 bAntennaDetected; - - u8 TxPwrLevelCck[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - u8 TxPwrLevelHT40_1S[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; /* For HT 40MHZ pwr */ - u8 TxPwrLevelHT40_2S[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; /* For HT 40MHZ pwr */ - u8 TxPwrHt20Diff[RF_PATH_MAX][CHANNEL_MAX_NUMBER];/* HT 20<->40 Pwr diff */ - u8 TxPwrLegacyHtDiff[RF_PATH_MAX][CHANNEL_MAX_NUMBER];/* For HT<->legacy pwr diff */ - /* For power group */ - u8 PwrGroupHT20[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - u8 PwrGroupHT40[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - - u8 LegacyHTTxPowerDiff;/* Legacy to HT rate power diff */ - - /* Read/write are allow for following hardware information variables */ - u8 framesync; - u32 framesyncC34; - u8 framesyncMonitor; - u8 pwrGroupCnt; - u32 MCSTxPowerLevelOriginalOffset[7][16]; - u32 CCKTxPowerLevelOriginalOffset; - - u32 AntennaTxPath; /* Antenna path Tx */ - u32 AntennaRxPath; /* Antenna path Rx */ - u8 ExternalPA; - - u8 bLedOpenDrain; /* Support Open-drain arrangement for controlling the LED. Added by Roger, 2009.10.16. */ - - u8 b1x1RecvCombine; /* for 1T1R receive combining */ - - /* For EDCA Turbo mode */ - - u32 AcParam_BE; /* Original parameter for BE, use for EDCA turbo. */ - - /* vivi, for tx power tracking, 20080407 */ - /* u16 TSSI_13dBm; */ - /* u32 Pwr_Track; */ - /* The current Tx Power Level */ - u8 CurrentCckTxPwrIdx; - u8 CurrentOfdm24GTxPwrIdx; - - struct bb_reg_define PHYRegDef[4]; /* Radio A/B/C/D */ - - bool bRFPathRxEnable[4]; /* We support 4 RF path now. */ - - u32 RfRegChnlVal[2]; - - u8 bCckHighPower; - - /* RDG enable */ - bool bRDGEnable; - - /* for host message to fw */ - u8 LastHMEBoxNum; - - u8 RegTxPause; - /* Beacon function related global variable. */ - u8 RegFwHwTxQCtrl; - u8 RegReg542; - - struct dm_priv dmpriv; - struct dm_odm_t odmpriv; - struct sreset_priv srestpriv; - -#ifdef CONFIG_8723AU_BT_COEXIST - u8 bBTMode; - /* BT only. */ - struct bt_30info BtInfo; - /* For bluetooth co-existance */ - struct bt_coexist_str bt_coexist; -#endif - - u8 bDumpRxPkt;/* for debug */ - u8 FwRsvdPageStartOffset; /* 2010.06.23. Added by tynli. Reserve page start offset except beacon in TxQ. */ - - /* 2010/08/09 MH Add CU power down mode. */ - u8 pwrdown; - - u8 OutEpQueueSel; - u8 OutEpNumber; - - /* */ - /* Add For EEPROM Efuse switch and Efuse Shadow map Setting */ - /* */ - u8 EepromOrEfuse; - u16 EfuseUsedBytes; - u16 BTEfuseUsedBytes; - - /* Interrupt relatd register information. */ - u32 SysIntrStatus; - u32 SysIntrMask; - - /* */ - /* 2011/02/23 MH Add for 8723 mylti function definition. The define should be moved to an */ - /* independent file in the future. */ - /* */ - /* 8723-----------------------------------------*/ - enum RT_MULTI_FUNC MultiFunc; /* For multi-function consideration. */ - enum RT_POLARITY_CTL PolarityCtl; /* For Wifi PDn Polarity control. */ - enum RT_REGULATOR_MODE RegulatorMode; /* switching regulator or LDO */ - /* 8723----------------------------------------- - * 2011/02/23 MH Add for 8723 mylti function definition. The define should be moved to an */ - /* independent file in the future. */ - - /* Interrupt related register information. */ - u32 IntArray[2]; - u32 IntrMask[2]; -}; - -#define GET_HAL_DATA(__pAdapter) ((struct hal_data_8723a *)((__pAdapter)->HalData)) -#define GET_RF_TYPE(priv) (GET_HAL_DATA(priv)->rf_type) - -#define INCLUDE_MULTI_FUNC_BT(_Adapter) (GET_HAL_DATA(_Adapter)->MultiFunc & RT_MULTI_FUNC_BT) -#define INCLUDE_MULTI_FUNC_GPS(_Adapter) (GET_HAL_DATA(_Adapter)->MultiFunc & RT_MULTI_FUNC_GPS) - -struct rxreport_8723a { - u32 pktlen:14; - u32 crc32:1; - u32 icverr:1; - u32 drvinfosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 physt:1; - u32 swdec:1; - u32 ls:1; - u32 fs:1; - u32 eor:1; - u32 own:1; - - u32 macid:5; - u32 tid:4; - u32 hwrsvd:4; - u32 amsdu:1; - u32 paggr:1; - u32 faggr:1; - u32 a1fit:4; - u32 a2fit:4; - u32 pam:1; - u32 pwr:1; - u32 md:1; - u32 mf:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd0831:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 gf:1; - u32 splcp:1; - u32 bw:1; - u32 htc:1; - u32 eosp:1; - u32 bssidfit:2; - u32 rsvd1214:16; - u32 unicastwake:1; - u32 magicwake:1; - - u32 pattern0match:1; - u32 pattern1match:1; - u32 pattern2match:1; - u32 pattern3match:1; - u32 pattern4match:1; - u32 pattern5match:1; - u32 pattern6match:1; - u32 pattern7match:1; - u32 pattern8match:1; - u32 pattern9match:1; - u32 patternamatch:1; - u32 patternbmatch:1; - u32 patterncmatch:1; - u32 rsvd1613:19; - - u32 tsfl; - - u32 bassn:12; - u32 bavld:1; - u32 rsvd2413:19; -}; - -/* rtl8723a_hal_init.c */ -s32 rtl8723a_FirmwareDownload(struct rtw_adapter *padapter); -void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter); -void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter); - -void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter); -void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter); -void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter); -void rtl8723a_init_default_value(struct rtw_adapter *padapter); - -s32 InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary); - -s32 CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU); -s32 CardDisableWithoutHWSM(struct rtw_adapter *padapter); - -/* EFuse */ -u8 GetEEPROMSize8723A(struct rtw_adapter *padapter); -void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent); -void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo); -void Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter, u8 *PROMContent, bool AutoLoadFail); -void Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseCustomerID(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter, u8 *hwinfo, u8 AutoLoadFail); -void Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); - -/* register */ -void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits); -void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter); - -void rtl8723a_start_thread(struct rtw_adapter *padapter); -void rtl8723a_stop_thread(struct rtw_adapter *padapter); - -bool c2h_id_filter_ccx_8723a(u8 id); -int c2h_handler_8723a(struct rtw_adapter *padapter, struct c2h_evt_hdr *c2h_evt); - -void rtl8723a_read_adapter_info(struct rtw_adapter *Adapter); -void rtl8723a_read_chip_version(struct rtw_adapter *padapter); -void rtl8723a_notch_filter(struct rtw_adapter *adapter, bool enable); -void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter); -void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter, - enum hal_odm_variable eVariable, - void *pValue1, bool bSet); -void -rtl8723a_readefuse(struct rtw_adapter *padapter, - u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf); -u16 rtl8723a_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter); -u16 rtl8723a_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter); -void rtl8723a_update_ramask(struct rtw_adapter *padapter, - u32 mac_id, u8 rssi_level); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_pg.h b/drivers/staging/rtl8723au/include/rtl8723a_pg.h deleted file mode 100644 index 5c2ec448e568..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_pg.h +++ /dev/null @@ -1,98 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_PG_H__ -#define __RTL8723A_PG_H__ - -/* EEPROM/Efuse PG Offset for 8723E/8723U/8723S */ -#define EEPROM_CCK_TX_PWR_INX_8723A 0x10 -#define EEPROM_HT40_1S_TX_PWR_INX_8723A 0x16 -#define EEPROM_HT20_TX_PWR_INX_DIFF_8723A 0x1C -#define EEPROM_OFDM_TX_PWR_INX_DIFF_8723A 0x1F -#define EEPROM_HT40_MAX_PWR_OFFSET_8723A 0x22 -#define EEPROM_HT20_MAX_PWR_OFFSET_8723A 0x25 - -#define EEPROM_ChannelPlan_8723A 0x28 -#define EEPROM_TSSI_A_8723A 0x29 -#define EEPROM_THERMAL_METER_8723A 0x2A -#define RF_OPTION1_8723A 0x2B -#define RF_OPTION2_8723A 0x2C -#define RF_OPTION3_8723A 0x2D -#define RF_OPTION4_8723A 0x2E -#define EEPROM_VERSION_8723A 0x30 -#define EEPROM_CustomID_8723A 0x31 -#define EEPROM_SubCustomID_8723A 0x32 -#define EEPROM_XTAL_K_8723A 0x33 -#define EEPROM_Chipset_8723A 0x34 - -/* RTL8723AE */ -#define EEPROM_VID_8723AE 0x49 -#define EEPROM_DID_8723AE 0x4B -#define EEPROM_SVID_8723AE 0x4D -#define EEPROM_SMID_8723AE 0x4F -#define EEPROM_MAC_ADDR_8723AE 0x67 - -/* RTL8723AU */ -#define EEPROM_MAC_ADDR_8723AU 0xC6 -#define EEPROM_VID_8723AU 0xB7 -#define EEPROM_PID_8723AU 0xB9 - -/* RTL8723AS */ -#define EEPROM_MAC_ADDR_8723AS 0xAA - -/* EEPROM/Efuse Value Type */ -#define EETYPE_TX_PWR 0x0 - -/* EEPROM/Efuse Default Value */ -#define EEPROM_Default_CrystalCap_8723A 0x20 - - -/* EEPROM/EFUSE data structure definition. */ -#define MAX_CHNL_GROUP 3+9 - -struct txpowerinfo { - u8 CCKIndex[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT40_1SIndex[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT40_2SIndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT20IndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 OFDMIndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT40MaxOffset[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT20MaxOffset[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 TSSI_A[3]; - u8 TSSI_B[3]; - u8 TSSI_A_5G[3]; /* 5GL/5GM/5GH */ - u8 TSSI_B_5G[3]; -}; - -enum bt_ant_num { - Ant_x2 = 0, - Ant_x1 = 1 -}; - -enum bt_cotype { - BT_2Wire = 0, - BT_ISSC_3Wire = 1, - BT_Accel = 2, - BT_CSR_BC4 = 3, - BT_CSR_BC8 = 4, - BT_RTL8756 = 5, - BT_RTL8723A = 6 -}; - -enum bt_radioshared { - BT_Radio_Shared = 0, - BT_Radio_Individual = 1, -}; - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_recv.h b/drivers/staging/rtl8723au/include/rtl8723a_recv.h deleted file mode 100644 index 875d37b3b94c..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_recv.h +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_RECV_H__ -#define __RTL8723A_RECV_H__ - -#include -#include - -#define NR_RECVBUFF 4 - -#define NR_PREALLOC_RECV_SKB 8 - -#define RECV_BLK_SZ 512 -#define RECV_BLK_CNT 16 -#define RECV_BLK_TH RECV_BLK_CNT - -#define MAX_RECVBUF_SZ 15360 /* 15k < 16k */ - -#define PHY_RSSI_SLID_WIN_MAX 100 -#define PHY_LINKQUALITY_SLID_WIN_MAX 20 - - -struct phy_stat { - unsigned int phydw0; - unsigned int phydw1; - unsigned int phydw2; - unsigned int phydw3; - unsigned int phydw4; - unsigned int phydw5; - unsigned int phydw6; - unsigned int phydw7; -}; - -/* Rx smooth factor */ -#define Rx_Smooth_Factor 20 - -struct interrupt_msg_format { - unsigned int C2H_MSG0; - unsigned int C2H_MSG1; - unsigned int C2H_MSG2; - unsigned int C2H_MSG3; - unsigned int HISR; /* from HISR Reg0x124, read to clear */ - unsigned int HISRE;/* from HISRE Reg0x12c, read to clear */ - unsigned int MSG_EX; -}; - -int rtl8723au_init_recv_priv(struct rtw_adapter *padapter); -void rtl8723au_free_recv_priv(struct rtw_adapter *padapter); -void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe); -void update_recvframe_attrib(struct recv_frame *precvframe, struct recv_stat *prxstat); -void update_recvframe_phyinfo(struct recv_frame *precvframe, struct phy_stat *pphy_info); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_rf.h b/drivers/staging/rtl8723au/include/rtl8723a_rf.h deleted file mode 100644 index 0432799f53cf..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_rf.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_RF_H__ -#define __RTL8723A_RF_H__ - -/*--------------------------Define Parameters-------------------------------*/ - -/* */ -/* For RF 6052 Series */ -/* */ -#define RF6052_MAX_TX_PWR 0x3F -#define RF6052_MAX_REG 0x3F -#define RF6052_MAX_PATH 2 -/*--------------------------Define Parameters-------------------------------*/ - - -/*------------------------------Define structure----------------------------*/ - -/*------------------------------Define structure----------------------------*/ - - -/*------------------------Export global variable----------------------------*/ -/*------------------------Export global variable----------------------------*/ - -/*------------------------Export Marco Definition---------------------------*/ - -/*------------------------Export Marco Definition---------------------------*/ - - -/*--------------------------Exported Function prototype---------------------*/ - -/* */ -/* RF RL6052 Series API */ -/* */ -void rtl8723a_phy_rf6052set_bw(struct rtw_adapter *Adapter, - enum ht_channel_width Bandwidth); -void rtl823a_phy_rf6052setccktxpower(struct rtw_adapter *Adapter, - u8 *pPowerlevel); -void rtl8723a_PHY_RF6052SetOFDMTxPower(struct rtw_adapter *Adapter, - u8 *pPowerLevel, u8 Channel); - -/*--------------------------Exported Function prototype---------------------*/ - -int PHY_RF6052_Config8723A(struct rtw_adapter *Adapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_spec.h b/drivers/staging/rtl8723au/include/rtl8723a_spec.h deleted file mode 100644 index 2f186890dbb5..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_spec.h +++ /dev/null @@ -1,2148 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - *******************************************************************************/ -#ifndef __RTL8723A_SPEC_H__ -#define __RTL8723A_SPEC_H__ - -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 -#define REG_AFE_PLL_CTRL 0x0028 -#define REG_MAC_PHY_CTRL 0x002c -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_LEDCFG REG_LEDCFG2 -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c - /* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */ -#define REG_GPIO_PIN_CTRL_2 0x0060 - /* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */ -#define REG_GPIO_IO_SEL_2 0x0062 - /* RTL8723 WIFI/BT/GPS Multi-Function control source. */ -#define REG_MULTI_FUNC_CTRL 0x0068 -#define REG_MCUFWDL 0x0080 -#define REG_HMEBOX_EXT_0 0x0088 -#define REG_HMEBOX_EXT_1 0x008A -#define REG_HMEBOX_EXT_2 0x008C -#define REG_HMEBOX_EXT_3 0x008E - /* Host suspend counter on FPGA platform */ -#define REG_HOST_SUSP_CNT 0x00BC - /* Efuse access protection for RTL8723 */ -#define REG_EFUSE_ACCESS 0x00CF -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG 0x00F0 -#define REG_GPIO_OUTSTS 0x00F4 /* For RTL8723 only. */ - -/* */ -/* */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* */ -/* */ -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C -#define REG_HIMR 0x0120 -#define REG_HISR 0x0124 -#define REG_HIMRE 0x0128 -#define REG_HISRE 0x012C -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_CLEAR 0x01AF -#define REG_C2HEVT_MSG_TEST 0x01B8 -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 -#define REG_BB_ACCEESS_CTRL 0x01E8 -#define REG_BB_ACCESS_DATA 0x01EC - - -/* */ -/* */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* */ -/* */ -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -/* */ -/* */ -/* 0x0280h ~ 0x02FFh RXDMA Configuration */ -/* */ -/* */ -#define REG_RXDMA_AGG_PG_TH 0x0280 -#define REG_RXPKT_NUM 0x0284 -#define REG_RXDMA_STATUS 0x0288 - - -/* */ -/* */ -/* 0x0300h ~ 0x03FFh PCIe */ -/* */ -/* */ -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 /* Interrupt Migration */ - /* TX Beacon Descriptor Address */ -#define REG_BCNQ_DESA 0x0308 - /* TX High Queue Descriptor Address */ -#define REG_HQ_DESA 0x0310 - /* TX Manage Queue Descriptor Address */ -#define REG_MGQ_DESA 0x0318 - /* TX VO Queue Descriptor Address */ -#define REG_VOQ_DESA 0x0320 - /* TX VI Queue Descriptor Address */ -#define REG_VIQ_DESA 0x0328 - /* TX BE Queue Descriptor Address */ -#define REG_BEQ_DESA 0x0330 - /* TX BK Queue Descriptor Address */ -#define REG_BKQ_DESA 0x0338 - /* RX Queue Descriptor Address */ -#define REG_RX_DESA 0x0340 - /* Backdoor REG for Access Configuration */ -#define REG_DBI 0x0348 - /* MDIO for Access PCIE PHY */ -#define REG_MDIO 0x0354 - /* Debug Selection Register */ -#define REG_DBG_SEL 0x0360 - /* PCIe RPWM */ -#define REG_PCIE_HRPWM 0x0361 - /* PCIe CPWM */ -#define REG_PCIE_HCPWM 0x0363 - /* UART Control */ -#define REG_UART_CTRL 0x0364 - /* UART TX Descriptor Address */ -#define REG_UART_TX_DESA 0x0370 - /* UART Rx Descriptor Address */ -#define REG_UART_RX_DESA 0x0378 - - -/* spec version 11 */ -/* */ -/* */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* */ -/* */ -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 - - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_LIFETIME_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x0448 -#define REG_ARFR2 0x044C -#define REG_ARFR3 0x0450 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 - - -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_VO_VI_LIFE_TIME 0x04C0 -#define REG_PKT_BE_BK_LIFE_TIME 0x04C2 -#define REG_STBC_SETTING 0x04C4 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_MAX_AGGR_NUM 0x04CA -#define REG_RTS_MAX_AGGR_NUM 0x04CB -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_DUMMY 0x04FC - - - -/* */ -/* */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* */ -/* */ -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CCK 0x0514 -#define REG_SIFS_OFDM 0x0516 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_TSFTR_SYN_OFFSET 0x0518 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_BCN_CTRL_1 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 - /* The same as REG_MBSSID_BCN_SPACE */ -#define REG_BCN_INTERVAL 0x0554 -#define REG_MBSSID_BCN_SPACE 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_TSFTR1 0x0568 -#define REG_INIT_TSFTR 0x0564 -#define REG_ATIMWND_1 0x0570 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 -#define REG_ACMRSTCTRL 0x05C1 -#define REG_ACMAVG 0x05C2 -#define REG_VO_ADMTIME 0x05C4 -#define REG_VI_ADMTIME 0x05C6 -#define REG_BE_ADMTIME 0x05C8 -#define REG_EDCA_RANDOM_GEN 0x05CC -#define REG_SCH_TXCMD 0x05D0 - -/* define REG_FW_TSF_SYNC_CNT 0x04A0 */ -#define REG_FW_RESET_TSF_CNT_1 0x05FC -#define REG_FW_RESET_TSF_CNT_0 0x05FD -#define REG_FW_BCN_DIS_CNT 0x05FE - -/* */ -/* */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* */ -/* */ -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A - -/* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */ - /* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */ -#define REG_R2T_SIFS 0x063C - /* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */ -#define REG_T2T_SIFS 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -/* WMA, BA, CCX */ -#define REG_NAV_CTRL 0x0650 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_WMAC_TRXPTCL_CTL 0x0668 - - -/* Security */ -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -/* Power */ -#define REG_WOW_CTRL 0x0690 -#define REG_PSSTATUS 0x0691 -#define REG_PS_RX_INFO 0x0692 -#define REG_LPNAV_CTRL 0x0694 -#define REG_WKFMCAM_CMD 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_CALB32K_CTRL 0x06AC -#define REG_PKT_MON_CTRL 0x06B4 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_WMAC_RESP_TXINFO 0x06D8 - -#define REG_MACID1 0x0700 -#define REG_BSSID1 0x0708 - - -/* */ -/* */ -/* 0xFE00h ~ 0xFE55h USB Configuration */ -/* */ -/* */ -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -/* For test chip */ -#define REG_TEST_USB_TXQS 0xFE48 -#define REG_TEST_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */ -#define REG_TEST_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */ -#define REG_TEST_SIE_OPTIONAL 0xFE64 -#define REG_TEST_SIE_CHIRP_K 0xFE65 -#define REG_TEST_SIE_PHY 0xFE66 /* 0xFE66~0xFE6B */ -#define REG_TEST_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */ -#define REG_TEST_SIE_STRING 0xFE80 /* 0xFE80~0xFEB9 */ - - -/* For normal chip */ -#define REG_NORMAL_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */ -#define REG_NORMAL_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */ -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 /* 0xFE65~0xFE67 */ -#define REG_NORMAL_SIE_PHY 0xFE68 /* 0xFE68~0xFE6B */ -#define REG_NORMAL_SIE_OPTIONAL2 0xFE6C -#define REG_NORMAL_SIE_GPS_EP 0xFE6D /* RTL8723 only */ -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */ -#define REG_NORMAL_SIE_STRING 0xFE80 /* 0xFE80~0xFEDF */ - - -/* */ -/* */ -/* Redifine 8192C register definition for compatibility */ -/* */ -/* */ - -/* TODO: use these definition when using REG_xxx naming rule. */ -/* NOTE: DO NOT Remove these definition. Use later. */ - - /* System Isolation Interface Control. */ -#define SYS_ISO_CTRL REG_SYS_ISO_CTRL - /* System Function Enable. */ -#define SYS_FUNC_EN REG_SYS_FUNC_EN -#define SYS_CLK REG_SYS_CLKR - /* 93C46/93C56 Command Register. */ -#define CR9346 REG_9346CR - /* E-Fuse Control. */ -#define EFUSE_CTRL REG_EFUSE_CTRL - /* E-Fuse Test. */ -#define EFUSE_TEST REG_EFUSE_TEST - /* Media Status register */ -#define MSR (REG_CR + 2) -#define ISR REG_HISR - /* Timing Sync Function Timer Register. */ -#define TSFR REG_TSFTR - - /* MAC ID Register, Offset 0x0050-0x0053 */ -#define MACIDR0 REG_MACID - /* MAC ID Register, Offset 0x0054-0x0055 */ -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - - /* Redifine MACID register, to compatible prior ICs. */ -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - - -/* */ -/* 9. Security Control Registers (Offset: ) */ -/* */ - /* Software write CAM input content */ -#define WCAMI REG_CAMWRITE - /* Software read/write CAM config */ -#define RCAMO REG_CAMREAD -#define CAMDBG REG_CAMDBG - /* Security Configuration Register */ -#define SECR REG_SECCFG - -/* Unused register */ -#define UnusedRegister 0x1BF -#define DCAM UnusedRegister -#define PSR UnusedRegister -#define BBAddr UnusedRegister -#define PhyDataR UnusedRegister - -#define InvalidBBRFValue 0x12345678 - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -/* */ -/* 8192C Cmd9346CR bits (Offset 0xA, 16bit) */ -/* */ - /* EEPROM enable when set 1 */ -#define CmdEEPROM_En BIT(5) - /* System EEPROM select, 0: boot from E-FUSE, - 1: The EEPROM used is 9346 */ -#define CmdEERPOMSEL BIT(4) -#define Cmd9346CR_9356SEL BIT(4) -#define AutoLoadEEPROM (CmdEEPROM_En|CmdEERPOMSEL) -#define AutoLoadEFUSE CmdEEPROM_En - -/* */ -/* 8192C GPIO MUX Configuration Register (offset 0x40, 4 byte) */ -/* */ -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -/* */ -/* 8192C GPIO PIN Control Register (offset 0x44, 4 byte) */ -/* */ - /* GPIO pins input value */ -#define GPIO_IN REG_GPIO_PIN_CTRL - /* GPIO pins output value */ -#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) - /* GPIO pins output enable when a bit is set to "1"; - otherwise, input is configured. */ -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) - -/* */ -/* 8192C (MSR) Media Status Register (Offset 0x4C, 8 bits) */ -/* */ -/* -Network Type -00: No link -01: Link in ad hoc network -10: Link in infrastructure network -11: AP mode -Default: 00b. -*/ -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - -/* */ -/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */ -/* */ -/* */ -/* 8192C Response Rate Set Register (offset 0x181, 24bits) */ -/* */ -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) -#define BRSR_AckShortPmb BIT(23) -/* CCK ACK: use Short Preamble or not */ - -/* */ -/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */ -/* */ -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - - -/* */ -/* 8192C CAM Config Setting (offset 0x250, 1 byte) */ -/* */ -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_CONTENT_COUNT 8 - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_CONFIG_USEDK true -#define CAM_CONFIG_NO_USEDK false - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define SCR_UseDK 0x01 -#define SCR_TxSecEnable 0x02 -#define SCR_RxSecEnable 0x04 - - -/* */ -/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */ -/* */ -/* */ -/* 8190 IMR/ISR bits (offset 0xfd, 8bits) */ -/* */ -#define IMR8190_DISABLED 0x0 -/* IMR DW0 Bit 0-31 */ - -#define IMR_BCNDMAINT6 BIT(31) /* Beacon DMA Interrupt 6 */ -#define IMR_BCNDMAINT5 BIT(30) /* Beacon DMA Interrupt 5 */ -#define IMR_BCNDMAINT4 BIT(29) /* Beacon DMA Interrupt 4 */ -#define IMR_BCNDMAINT3 BIT(28) /* Beacon DMA Interrupt 3 */ -#define IMR_BCNDMAINT2 BIT(27) /* Beacon DMA Interrupt 2 */ -#define IMR_BCNDMAINT1 BIT(26) /* Beacon DMA Interrupt 1 */ -#define IMR_BCNDOK8 BIT(25) /* Beacon Queue DMA OK - Interrupt 8 */ -#define IMR_BCNDOK7 BIT(24) /* Beacon Queue DMA OK - Interrupt 7 */ -#define IMR_BCNDOK6 BIT(23) /* Beacon Queue DMA OK - Interrupt 6 */ -#define IMR_BCNDOK5 BIT(22) /* Beacon Queue DMA OK - Interrupt 5 */ -#define IMR_BCNDOK4 BIT(21) /* Beacon Queue DMA OK - Interrupt 4 */ -#define IMR_BCNDOK3 BIT(20) /* Beacon Queue DMA OK - Interrupt 3 */ -#define IMR_BCNDOK2 BIT(19) /* Beacon Queue DMA OK - Interrupt 2 */ -#define IMR_BCNDOK1 BIT(18) /* Beacon Queue DMA OK - Interrupt 1 */ -#define IMR_TIMEOUT2 BIT(17) /* Timeout interrupt 2 */ -#define IMR_TIMEOUT1 BIT(16) /* Timeout interrupt 1 */ -#define IMR_TXFOVW BIT(15) /* Transmit FIFO Overflow */ -#define IMR_PSTIMEOUT BIT(14) /* Power save time out - interrupt */ -#define IMR_BcnInt BIT(13) /* Beacon DMA Interrupt 0 */ -#define IMR_RXFOVW BIT(12) /* Receive FIFO Overflow */ -#define IMR_RDU BIT(11) /* Receive Descriptor - Unavailable */ -#define IMR_ATIMEND BIT(10) /* For 92C,ATIM Window - End Interrupt */ -#define IMR_BDOK BIT(9) /* Beacon Queue DMA OK - Interrup */ -#define IMR_HIGHDOK BIT(8) /* High Queue DMA OK - Interrupt */ -#define IMR_TBDOK BIT(7) /* Transmit Beacon OK - interrup */ -#define IMR_MGNTDOK BIT(6) /* Management Queue DMA OK - Interrupt */ -#define IMR_TBDER BIT(5) /* For 92C,Transmit Beacon - Error Interrupt */ -#define IMR_BKDOK BIT(4) /* AC_BK DMA OK Interrupt */ -#define IMR_BEDOK BIT(3) /* AC_BE DMA OK Interrupt */ -#define IMR_VIDOK BIT(2) /* AC_VI DMA OK Interrupt */ -#define IMR_VODOK BIT(1) /* AC_VO DMA Interrupt */ -#define IMR_ROK BIT(0) /* Receive DMA OK Interrupt */ - -#define IMR_RX_MASK (IMR_ROK|IMR_RDU|IMR_RXFOVW) -#define IMR_TX_MASK (IMR_VODOK|IMR_VIDOK|IMR_BEDOK| \ - IMR_BKDOK|IMR_MGNTDOK|IMR_HIGHDOK| \ - IMR_BDOK) - -/* 13. Host Interrupt Status Extension Register (Offset: 0x012C-012Eh) */ -#define IMR_BcnInt_E BIT(12) -#define IMR_TXERR BIT(11) -#define IMR_RXERR BIT(10) -#define IMR_C2HCMD BIT(9) -#define IMR_CPWM BIT(8) -/* RSVD [2-7] */ -#define IMR_OCPINT BIT(1) -#define IMR_WLANOFF BIT(0) - - -/* 8192C EEPROM/EFUSE share register definition. */ - -/* Default Value for EEPROM or EFUSE!!! */ -#define EEPROM_Default_TSSI 0x0 -#define EEPROM_Default_TxPowerDiff 0x0 -#define EEPROM_Default_CrystalCap 0x5 - /* Default: 2X2, RTL8192CE(QFPN68) */ -#define EEPROM_Default_BoardType 0x02 -#define EEPROM_Default_TxPower 0x1010 -#define EEPROM_Default_HT2T_TxPwr 0x10 - -#define EEPROM_Default_LegacyHTTxPowerDiff 0x3 -#define EEPROM_Default_ThermalMeter 0x12 - -#define EEPROM_Default_AntTxPowerDiff 0x0 -#define EEPROM_Default_TxPwDiff_CrystalCap 0x5 -#define EEPROM_Default_TxPowerLevel 0x22 -#define EEPROM_Default_HT40_2SDiff 0x0 - /* HT20<->40 default Tx Power Index Difference */ -#define EEPROM_Default_HT20_Diff 2 -#define EEPROM_Default_LegacyHTTxPowerDiff 0x3 -#define EEPROM_Default_HT40_PwrMaxOffset 0 -#define EEPROM_Default_HT20_PwrMaxOffset 0 - -/* For debug */ -#define EEPROM_Default_PID 0x1234 -#define EEPROM_Default_VID 0x5678 -#define EEPROM_Default_CustomerID 0xAB -#define EEPROM_Default_SubCustomerID 0xCD -#define EEPROM_Default_Version 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_USB_OPTIONAL1 0xE -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 - /* CCX test. By Bruce, 2009-02-25. */ -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D - /* added by chiyoko for dtm, 20090108 */ -#define EEPROM_CID_WHQL 0xFE - - -#define RTL_EEPROM_ID 0x8129 - -#define SUPPORT_HW_RADIO_DETECT(pHalData) \ - (pHalData->BoardType == BOARD_MINICARD || \ - pHalData->BoardType == BOARD_USB_SOLO || \ - pHalData->BoardType == BOARD_USB_COMBO) - -/* */ -/* EEPROM address for Test chip */ -/* */ -#define EEPROM_TEST_USB_OPT 0x0E -#define EEPROM_TEST_CHIRP_K 0x0F -#define EEPROM_TEST_EP_SETTING 0x0E -#define EEPROM_TEST_USB_PHY 0x10 - - -/* */ -/* EEPROM address for Normal chip */ -/* */ -#define EEPROM_NORMAL_USB_OPT 0x0E -#define EEPROM_NORMAL_CHIRP_K 0x0E /* Changed */ -#define EEPROM_NORMAL_EP_SETTING 0x0F /* Changed */ -#define EEPROM_NORMAL_USB_PHY 0x12 /* Changed */ - -enum { - BOARD_USB_DONGLE = 0, /* USB dongle */ - BOARD_USB_High_PA = 1, /* USB dongle with high power PA */ - BOARD_MINICARD = 2, /* Minicard */ - BOARD_USB_SOLO = 3, /* USB solo-Slim module */ - BOARD_USB_COMBO = 4, /* USB Combo-Slim module */ -}; - -/* Test chip and normal chip common define */ -/* */ -/* EEPROM address for both */ -/* */ -#define EEPROM_ID0 0x00 -#define EEPROM_ID1 0x01 -#define EEPROM_RTK_RSV1 0x02 -#define EEPROM_RTK_RSV2 0x03 -#define EEPROM_RTK_RSV3 0x04 -#define EEPROM_RTK_RSV4 0x05 -#define EEPROM_RTK_RSV5 0x06 -#define EEPROM_DBG_SEL 0x07 -#define EEPROM_RTK_RSV6 0x08 -#define EEPROM_VID 0x0A -#define EEPROM_PID 0x0C - -#define EEPROM_MAC_ADDR 0x16 -#define EEPROM_STRING 0x1C -#define EEPROM_SUBCUSTOMER_ID 0x59 -#define EEPROM_CCK_TX_PWR_INX 0x5A -#define EEPROM_HT40_1S_TX_PWR_INX 0x60 -#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66 -#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69 -#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C -#define EEPROM_HT40_MAX_PWR_OFFSET 0x6F -#define EEPROM_HT20_MAX_PWR_OFFSET 0x72 - -#define EEPROM_CHANNEL_PLAN 0x75 -#define EEPROM_TSSI_A 0x76 -#define EEPROM_TSSI_B 0x77 -#define EEPROM_THERMAL_METER 0x78 -#define EEPROM_RF_OPT1 0x79 -#define EEPROM_RF_OPT2 0x7A -#define EEPROM_RF_OPT3 0x7B -#define EEPROM_RF_OPT4 0x7C -#define EEPROM_VERSION 0x7E -#define EEPROM_CUSTOMER_ID 0x7F - - /* 0x0: RTL8188SU, 0x1: RTL8191SU, 0x2: RTL8192SU, 0x3: RTL8191GU */ -#define EEPROM_BoardType 0x54 - /* 0x5C-0x76, Tx Power index. */ -#define EEPROM_TxPwIndex 0x5C - /* Difference of gain index between legacy and high throughput OFDM. */ -#define EEPROM_PwDiff 0x67 - /* CCK Tx Power */ -#define EEPROM_TxPowerCCK 0x5A - -/* 2009/02/09 Cosa Add for SD3 requirement */ - /* HT20 Tx Power Index Difference */ -#define EEPROM_TX_PWR_HT20_DIFF 0x6e - /* HT20<->40 default Tx Power Index Difference */ -#define DEFAULT_HT20_TXPWR_DIFF 2 - /* OFDM Tx Power Index Difference */ -#define EEPROM_TX_PWR_OFDM_DIFF 0x71 - - /* Power diff for channel group */ -#define EEPROM_TxPWRGroup 0x73 - /* Check if power safety is need */ -#define EEPROM_Regulatory 0x79 - - /* 92cu, 0x7E[4] */ -#define EEPROM_BLUETOOTH_COEXIST 0x7E -#define EEPROM_NORMAL_BoardType EEPROM_RF_OPT1 /* 7:5] */ -#define BOARD_TYPE_NORMAL_MASK 0xE0 -#define BOARD_TYPE_TEST_MASK 0x0F - /* BIT0 1 for build-in module, 0 for external dongle */ -#define EEPROM_EASY_REPLACEMENT 0x50 -/* */ -/* EPROM content definitions */ -/* */ -#define OS_LINK_SPEED BIT(5) - -#define BOARD_TYPE_MASK 0xF - -#define BT_COEXISTENCE BIT(4) -#define BT_CO_SHIFT 4 - -#define EP_NUMBER_MASK 0x30 /* bit 4:5 0Eh */ -#define EP_NUMBER_SHIFT 4 - - -#define USB_PHY_PARA_SIZE 5 - - -/* */ -/* EEPROM default value definitions */ -/* */ -/* Use 0xABCD instead of 0x8192 for debug */ -#define EEPROM_DEF_ID_0 0xCD /* Byte 0x00 */ -#define EEPROM_DEF_ID_1 0xAB /* Byte 0x01 */ - -#define EEPROM_DEF_RTK_RSV_A3 0x74 /* Byte 0x03 */ -#define EEPROM_DEF_RTK_RSV_A4 0x6D /* Byte 0x04 */ -#define EEPROM_DEF_RTK_RSV_A8 0xFF /* Byte 0x08 */ - -#define EEPROM_DEF_VID_0 0x0A /* Byte 0x0A */ -#define EEPROM_DEF_VID_1 0x0B - -#define EEPROM_DEF_PID_0 0x92 /* Byte 0x0C */ -#define EEPROM_DEF_PID_1 0x81 - - -#define EEPROM_TEST_DEF_USB_OPT 0x80 /* Byte 0x0E */ -#define EEPROM_NORMAL_DEF_USB_OPT 0x00 /* Byte 0x0E */ - -#define EEPROM_DEF_CHIRPK 0x15 /* Byte 0x0F */ - -#define EEPROM_DEF_USB_PHY_0 0x85 /* Byte 0x10 */ -#define EEPROM_DEF_USB_PHY_1 0x62 /* Byte 0x11 */ -#define EEPROM_DEF_USB_PHY_2 0x9E /* Byte 0x12 */ -#define EEPROM_DEF_USB_PHY_3 0x06 /* Byte 0x13 */ - -#define EEPROM_DEF_TSSI_A 0x09 /* Byte 0x78 */ -#define EEPROM_DEF_TSSI_B 0x09 /* Byte 0x79 */ - - -#define EEPROM_DEF_THERMAL_METER 0x12 /* Byte 0x7A */ - - /* Check if power safety spec is need */ -#define RF_OPTION1 0x79 -#define RF_OPTION2 0x7A -#define RF_OPTION3 0x7B -#define RF_OPTION4 0x7C - - -#define EEPROM_USB_SN BIT(0) -#define EEPROM_USB_REMOTE_WAKEUP BIT(1) -#define EEPROM_USB_DEVICE_PWR BIT(2) -#define EEPROM_EP_NUMBER (BIT(3)|BIT(4)) - -/*=================================================================== -===================================================================== -Here the register defines are for 92C. When the define is as same with 92C, -we will use the 92C's define for the consistency -So the following defines for 92C is not entire!!!!!! -===================================================================== -=====================================================================*/ -/* -Based on Datasheet V33---090401 -Register Summary -Current IOREG MAP -0x0000h ~ 0x00FFh System Configuration (256 Bytes) -0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes) -0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes) -0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes) -0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes) -0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes) -0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes) -0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes) -0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes) -*/ - -/* */ -/* 8192C (RCR) Receive Configuration Register (Offset 0x608, 32 bits) */ -/* */ -#define RCR_APPFCS BIT(31) /* WMAC append FCS after payload*/ -#define RCR_APP_MIC BIT(30) -#define RCR_APP_PHYSTS BIT(28) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) /* Accept BA SSN */ -#define RCR_ENMBID BIT(24) /* Enable Multiple BssId. */ -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */ -#define RCR_AMF BIT(13) /* Accept management type frame */ -#define RCR_ACF BIT(12) /* Accept control type frame */ -#define RCR_ADF BIT(11) /* Accept data type frame */ -#define RCR_AICV BIT(9) /* Accept ICV error packet */ -#define RCR_ACRC32 BIT(8) /* Accept CRC32 error packet */ -#define RCR_CBSSID_BCN BIT(7) /* Accept BSSID match packet - (Rx beacon, probe rsp) */ -#define RCR_CBSSID_DATA BIT(6) /* Accept BSSID match packet - (Data) */ -#define RCR_CBSSID RCR_CBSSID_DATA /* Accept BSSID match - packet */ -#define RCR_APWRMGT BIT(5) /* Accept power management - packet */ -#define RCR_ADD3 BIT(4) /* Accept address 3 match - packet */ -#define RCR_AB BIT(3) /* Accept broadcast packet */ -#define RCR_AM BIT(2) /* Accept multicast packet */ -#define RCR_APM BIT(1) /* Accept physical match packet */ -#define RCR_AAP BIT(0) /* Accept all unicast packet */ -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - - - -/* */ -/* 8192c USB specific Regsiter Offset and Content definition, */ -/* 2009.08.18, added by vivi. for merge 92c and 92C into one driver */ -/* */ -/* define APS_FSMCO 0x0004 same with 92Ce */ -#define RSV_CTRL 0x001C -#define RD_CTRL 0x0524 - -/* */ -/* */ -/* 0xFE00h ~ 0xFE55h USB Configuration */ -/* */ -/* */ -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_USB_VID 0xFE60 -#define REG_USB_PID 0xFE62 -#define REG_USB_OPTIONAL 0xFE64 -#define REG_USB_CHIRP_K 0xFE65 -#define REG_USB_PHY 0xFE66 -#define REG_USB_MAC_ADDR 0xFE70 - -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -#define InvalidBBRFValue 0x12345678 - -/* */ -/* 8192C Regsiter Bit and Content definition */ -/* */ -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ - -/* 2 SPS0_CTRL */ -#define SW18_FPWM BIT(3) - - -/* 2 SYS_ISO_CTRL */ -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - - -/* 2 SYS_FUNC_EN */ -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTn BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -/* 2 APS_FSMCO */ -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define EnPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -/* 2 SYS_CLKR */ -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - - -/* 2 9346CR */ - - -#define EEDO BIT(0) -#define EEDI BIT(1) -#define EESK BIT(2) -#define EECS BIT(3) -/* define EERPROMSEL BIT(4) */ -/* define EEPROM_EN BIT(5) */ -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) -#define EEM0 BIT(6) -#define EEM1 BIT(7) - - -/* 2 AFE_MISC */ -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - - -/* 2 SPS0_CTRL */ - - -/* 2 SPS_OCP_CFG */ - - -/* 2 RSV_CTRL */ -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -/* 2 RF_CTRL */ -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - - - -/* 2 LDOA15_CTRL */ -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - - - -/* 2 LDOV12D_CTRL */ -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - - -/* 2 AFE_XTAL_CTRL */ -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - - -/* 2 AFE_PLL_CTRL */ -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - - -/* 2 EFUSE_CTRL */ -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -/* 2 EFUSE_TEST (For RTL8723 partially) */ -#define EF_TRPT BIT(7) - /* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */ -#define EF_CELL_SEL (BIT(8)|BIT(9)) -#define LDOE25_EN BIT(31) -#define EFUSE_SEL(x) (((x) & 0x3) << 8) -#define EFUSE_SEL_MASK 0x300 -#define EFUSE_WIFI_SEL_0 0x0 -#define EFUSE_BT_SEL_0 0x1 -#define EFUSE_BT_SEL_1 0x2 -#define EFUSE_BT_SEL_2 0x3 - -#define EFUSE_ACCESS_ON 0x69 /* For RTL8723 only. */ -#define EFUSE_ACCESS_OFF 0x00 /* For RTL8723 only. */ - -/* 2 PWR_DATA */ - -/* 2 CAL_TIMER */ - -/* 2 ACLK_MON */ -#define RSM_EN BIT(0) -#define Timer_EN BIT(4) - - -/* 2 GPIO_MUXCFG */ -#define TRSW0EN BIT(2) -#define TRSW1EN BIT(3) -#define EROM_EN BIT(4) -#define EnBT BIT(5) -#define EnUart BIT(8) -#define Uart_910 BIT(9) -#define EnPMAC BIT(10) -#define SIC_SWRST BIT(11) -#define EnSIC BIT(12) -#define SIC_23 BIT(13) -#define EnHDP BIT(14) -#define SIC_LBK BIT(15) - -/* 2 GPIO_PIN_CTRL */ - -/* GPIO BIT */ -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -/* 2 GPIO_INTM */ - -/* 2 LEDCFG */ -#define LED0PL BIT(4) -#define LED0DIS BIT(7) -#define LED1DIS BIT(15) -#define LED1PL BIT(12) - -#define SECCAM_CLR BIT(30) - - -/* 2 FSIMR */ - -/* 2 FSISR */ - - -/* 2 8051FWDL */ -/* 2 MCUFWDL */ -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_ChkSum_rpt BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define CPRST BIT(23) - -/* 2REG_HPON_FSM */ -#define BOND92CE_1T2R_CFG BIT(22) - - -/* 2 REG_SYS_CFG */ -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define CHIP_VER (BIT(12)|BIT(13)|BIT(14)|BIT(15)) -#define BT_FUNC BIT(16) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define CHIP_VER_RTL_MASK 0xF000 /* Bit 12 ~ 15 */ -#define CHIP_VER_RTL_SHIFT 12 - -/* 2REG_GPIO_OUTSTS (For RTL8723 only) */ -#define EFS_HCI_SEL (BIT(0)|BIT(1)) -#define PAD_HCI_SEL (BIT(2)|BIT(3)) -#define HCI_SEL (BIT(4)|BIT(5)) -#define PKG_SEL_HCI BIT(6) -#define FEN_GPS BIT(7) -#define FEN_BT BIT(8) -#define FEN_WL BIT(9) -#define FEN_PCI BIT(10) -#define FEN_USB BIT(11) -#define BTRF_HWPDN_N BIT(12) -#define WLRF_HWPDN_N BIT(13) -#define PDN_BT_N BIT(14) -#define PDN_GPS_N BIT(15) -#define BT_CTL_HWPDN BIT(16) -#define GPS_CTL_HWPDN BIT(17) -#define PPHY_SUSB BIT(20) -#define UPHY_SUSB BIT(21) -#define PCI_SUSEN BIT(22) -#define USB_SUSEN BIT(23) -#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28)) - -/* */ -/* */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* */ -/* */ - - -/* 2 Function Enable Registers */ -/* 2 CR */ - -#define REG_LBMODE (REG_CR + 3) - - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) - -#define _LBMODE(x) (((x) & 0xF) << 24) -#define MASK_LBMODE 0xF000000 -#define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB -#define LOOPBACK_MAC_DELAY 0x3 -#define LOOPBACK_PHY 0x1 -#define LOOPBACK_DMA 0x7 - - -/* 2 PBP - Page Size Register */ -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_64 0x0 -#define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - - -/* 2 TX/RXDMA */ -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -/* For normal driver, 0x10C */ -#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - - - -/* 2 TRXFF_BNDY */ - - -/* 2 LLT_INIT */ -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - - -/* 2 BB_ACCESS_CTRL */ -#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) -#define BB_WRITE_EN BIT(30) -#define BB_READ_EN BIT(31) -/* define BB_ADDR_MASK 0xFFF */ -/* define _BB_ADDR(x) ((x) & BB_ADDR_MASK) */ - -/* */ -/* */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* */ -/* */ -/* 2 RQPN */ -#define _HPQ(x) ((x) & 0xFF) -#define _LPQ(x) (((x) & 0xFF) << 8) -#define _PUBQ(x) (((x) & 0xFF) << 16) - /* NOTE: in RQPN_NPQ register */ -#define _NPQ(x) ((x) & 0xFF) - - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) -#define LD_RQPN BIT(31) - - -/* 2 TDECTRL */ -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -/* 2 TDECTL */ -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - - -/* 2 TXDMA_OFFSET_CHK */ -#define DROP_DATA_EN BIT(9) - -/* */ -/* */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* */ -/* */ -/* 2 FWHW_TXQ_CTRL */ -#define EN_AMPDU_RTY_NEW BIT(7) - -/* 2 INIRTSMCS_SEL */ -#define _INIRTSMCS_SEL(x) ((x) & 0x3F) - - -/* 2 SPEC SIFS */ -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - - -/* 2 RRSR */ - -#define RATE_REG_BITMAP_ALL 0xFFFFF - -#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) - -#define _RRSR_RSC(x) (((x) & 0x3) << 21) -#define RRSR_RSC_RESERVED 0x0 -#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 -#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 -#define RRSR_RSC_DUPLICATE_MODE 0x3 - - -/* 2 ARFR */ -#define USE_SHORT_G1 BIT(20) - -/* 2 AGGLEN_LMT_L */ -#define _AGGLMT_MCS0(x) ((x) & 0xF) -#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) -#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) -#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) -#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) -#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) -#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) -#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) - - -/* 2 RL */ -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - - -/* 2 DARFRC */ -#define _DARF_RC1(x) ((x) & 0x1F) -#define _DARF_RC2(x) (((x) & 0x1F) << 8) -#define _DARF_RC3(x) (((x) & 0x1F) << 16) -#define _DARF_RC4(x) (((x) & 0x1F) << 24) -/* NOTE: shift starting from address (DARFRC + 4) */ -#define _DARF_RC5(x) ((x) & 0x1F) -#define _DARF_RC6(x) (((x) & 0x1F) << 8) -#define _DARF_RC7(x) (((x) & 0x1F) << 16) -#define _DARF_RC8(x) (((x) & 0x1F) << 24) - - -/* 2 RARFRC */ -#define _RARF_RC1(x) ((x) & 0x1F) -#define _RARF_RC2(x) (((x) & 0x1F) << 8) -#define _RARF_RC3(x) (((x) & 0x1F) << 16) -#define _RARF_RC4(x) (((x) & 0x1F) << 24) -/* NOTE: shift starting from address (RARFRC + 4) */ -#define _RARF_RC5(x) ((x) & 0x1F) -#define _RARF_RC6(x) (((x) & 0x1F) << 8) -#define _RARF_RC7(x) (((x) & 0x1F) << 16) -#define _RARF_RC8(x) (((x) & 0x1F) << 24) - - -/* */ -/* */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* */ -/* */ - - - -/* 2 EDCA setting */ -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - - -/* 2 EDCA_VO_PARAM */ -#define _AIFS(x) (x) -#define _ECW_MAX_MIN(x) ((x) << 8) -#define _TXOP_LIMIT(x) ((x) << 16) - - -#define _BCNIFS(x) ((x) & 0xFF) -#define _BCNECW(x) (((x) & 0xF))<< 8) - - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - - -/* 2 SIFS_CCK */ -#define _SIFS_CCK_CTX(x) ((x) & 0xFF) -#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8); - - -/* 2 SIFS_OFDM */ -#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) -#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8); - - -/* 2 TBTT PROHIBIT */ -#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) - - -/* 2 REG_RD_CTRL */ -#define DIS_EDCA_CNT_DWN BIT(11) - - -/* 2 BCN_CTRL */ -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) -#define DIS_TSF_UPDATE BIT(3) - -/* The same function but different bit field. */ -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - -/* 2 ACMHWCTRL */ -#define AcmHw_HwEn BIT(0) -#define AcmHw_BeqEn BIT(1) -#define AcmHw_ViqEn BIT(2) -#define AcmHw_VoqEn BIT(3) -#define AcmHw_BeqStatus BIT(4) -#define AcmHw_ViqStatus BIT(5) -#define AcmHw_VoqStatus BIT(6) - - - -/* */ -/* */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* */ -/* */ - -/* 2 APSD_CTRL */ -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - - -/* 2 BWOPMODE */ -#define BW_20MHZ BIT(2) - - -#define RATE_BITMAP_ALL 0xFFFFF - -/* Only use CCK 1M rate for ACK */ -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -/* 2 TCR */ -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - - - -/* 2 RCR */ -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define EnMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -/* 2 RX_PKT_LIMIT */ - -/* 2 RX_DLK_TIME */ - -/* 2 MBIDCAMCFG */ - - - -/* 2 AMPDU_MIN_SPACE */ -#define _MIN_SPACE(x) ((x) & 0x7) -#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) - - -/* 2 RXERR_RPT */ -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDMfalse_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCKfalse_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HTfalse_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - - -/* 2 SECCFG */ -#define SCR_TxUseDK BIT(0) /* Force Tx Use Default Key */ -#define SCR_RxUseDK BIT(1) /* Force Rx Use Default Key */ -#define SCR_TxEncEnable BIT(2) /* Enable Tx Encryption */ -#define SCR_RxDecEnable BIT(3) /* Enable Rx Decryption */ -#define SCR_SKByA2 BIT(4) /* Search kEY BY A2 */ -#define SCR_NoSKMC BIT(5) /* No Key Search Multicast */ - - - -/* */ -/* */ -/* 0xFE00h ~ 0xFE55h USB Configuration */ -/* */ -/* */ - -/* 2 USB Information (0xFE17) */ -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -#define USB_TEST_EP_MASK 0x30 -#define USB_TEST_EP_SHIFT 4 - -/* 2 Special Option */ -#define USB_AGG_EN BIT(3) - - -/* 2REG_C2HEVT_CLEAR */ - /* Set by driver and notify FW that the driver has read the - C2H command message */ -#define C2H_EVT_HOST_CLOSE 0x00 - /* Set by FW indicating that FW had set the C2H command message - and it's not yet read by driver. */ -#define C2H_EVT_FW_CLOSE 0xFF - - -/* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */ - /* Enable GPIO[9] as WiFi HW PDn source */ -#define WL_HWPDN_EN BIT(0) - /* WiFi HW PDn polarity control */ -#define WL_HWPDN_SL BIT(1) - /* WiFi function enable */ -#define WL_FUNC_EN BIT(2) - /* Enable GPIO[9] as WiFi RF HW PDn source */ -#define WL_HWROF_EN BIT(3) - /* Enable GPIO[11] as BT HW PDn source */ -#define BT_HWPDN_EN BIT(16) - /* BT HW PDn polarity control */ -#define BT_HWPDN_SL BIT(17) - /* BT function enable */ -#define BT_FUNC_EN BIT(18) - /* Enable GPIO[11] as BT/GPS RF HW PDn source */ -#define BT_HWROF_EN BIT(19) - /* Enable GPIO[10] as GPS HW PDn source */ -#define GPS_HWPDN_EN BIT(20) - /* GPS HW PDn polarity control */ -#define GPS_HWPDN_SL BIT(21) - /* GPS function enable */ -#define GPS_FUNC_EN BIT(22) - -/* 3 REG_LIFECTRL_CTRL */ -#define HAL92C_EN_PKT_LIFE_TIME_BK BIT(3) -#define HAL92C_EN_PKT_LIFE_TIME_BE BIT(2) -#define HAL92C_EN_PKT_LIFE_TIME_VI BIT(1) -#define HAL92C_EN_PKT_LIFE_TIME_VO BIT(0) - -#define HAL92C_MSDU_LIFE_TIME_UNIT 128 /* in us, said by Tim. */ - -/* */ -/* General definitions */ -/* */ - -#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 1000 - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -/* */ -/* 8723A Regsiter offset definition */ -/* */ -#define HAL_8723A_NAV_UPPER_UNIT 128 /* micro-second */ - -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ -#define REG_SYSON_REG_LOCK 0x001C - - -/* */ -/* */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* */ -/* */ -#define REG_FTIMR 0x0138 - - -/* */ -/* */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* */ -/* */ - - -/* */ -/* */ -/* 0x0280h ~ 0x02FFh RXDMA Configuration */ -/* */ -/* */ - - -/* */ -/* */ -/* 0x0300h ~ 0x03FFh PCIe */ -/* */ -/* */ - - -/* */ -/* */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* */ -/* */ -#define REG_EARLY_MODE_CONTROL 0x4D0 - - -/* */ -/* */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* */ -/* */ - -/* 2 BCN_CTRL */ -#define DIS_ATIM BIT(0) -#define DIS_BCNQ_SUB BIT(1) -#define DIS_TSF_UDT BIT(4) - - -/* */ -/* */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* */ -/* */ -/* */ -/* Note: */ -/* The NAV upper value is very important to WiFi 11n 5.2.3 NAV test. - * The default value is always too small, but the WiFi TestPlan test - * by 25,000 microseconds of NAV through sending CTS in the air. We - * must update this value greater than 25,000 microseconds to pass the - * item. -* The offset of NAV_UPPER in 8192C Spec is incorrect, and the offset -* should be 0x0652. Commented by SD1 Scott. */ -/* By Bruce, 2011-07-18. */ -/* */ -#define REG_NAV_UPPER 0x0652 /* unit of 128 */ - - -/* */ -/* 8723 Regsiter Bit and Content definition */ -/* */ - -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ - -/* 2 SPS0_CTRL */ - -/* 2 SYS_ISO_CTRL */ - -/* 2 SYS_FUNC_EN */ - -/* 2 APS_FSMCO */ -#define EN_WLON BIT(16) - -/* 2 SYS_CLKR */ - -/* 2 9346CR */ - -/* 2 AFE_MISC */ - -/* 2 SPS0_CTRL */ - -/* 2 SPS_OCP_CFG */ - -/* 2 SYSON_REG_LOCK */ -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define WLOCK_1C_B6 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -/* 2 RF_CTRL */ - -/* 2 LDOA15_CTRL */ - -/* 2 LDOV12D_CTRL */ - -/* 2 AFE_XTAL_CTRL */ - -/* 2 AFE_PLL_CTRL */ - -/* 2 EFUSE_CTRL */ - -/* 2 EFUSE_TEST (For RTL8723 partially) */ - -/* 2 PWR_DATA */ - -/* 2 CAL_TIMER */ - -/* 2 ACLK_MON */ - -/* 2 GPIO_MUXCFG */ - -/* 2 GPIO_PIN_CTRL */ - -/* 2 GPIO_INTM */ - -/* 2 LEDCFG */ - -/* 2 FSIMR */ - -/* 2 FSISR */ - -/* 2 HSIMR */ -/* 8723 Host System Interrupt Mask Register (offset 0x58, 32 byte) */ -#define HSIMR_GPIO12_0_INT_EN BIT(0) -#define HSIMR_SPS_OCP_INT_EN BIT(5) -#define HSIMR_RON_INT_EN BIT(6) -#define HSIMR_PDNINT_EN BIT(7) -#define HSIMR_GPIO9_INT_EN BIT(25) - -/* 2 HSISR */ -/* 8723 Host System Interrupt Status Register (offset 0x5C, 32 byte) */ -#define HSISR_GPIO12_0_INT BIT(0) -#define HSISR_SPS_OCP_INT BIT(5) -#define HSISR_RON_INT BIT(6) -#define HSISR_PDNINT BIT(7) -#define HSISR_GPIO9_INT BIT(25) - -/* interrupt mask which needs to clear */ -#define MASK_HSISR_CLEAR (HSISR_GPIO12_0_INT | \ - HSISR_SPS_OCP_INT | \ - HSISR_RON_INT | \ - HSISR_PDNINT | \ - HSISR_GPIO9_INT) - -/* 2 MCUFWDL */ -#define RAM_DL_SEL BIT(7) /* 1:RAM, 0:ROM */ - -/* 2 HPON_FSM */ - -/* 2 SYS_CFG */ -#define RTL_ID BIT(23) /* TestChip ID, - 1:Test(RLE); 0:MP(RL) */ -#define SPS_SEL BIT(24) /* 1:LDO regulator mode; - 0:Switching regulator mode*/ - - -/* */ -/* */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* */ -/* */ - -/* 2 Function Enable Registers */ - -/* 2 CR */ -#define CALTMR_EN BIT(10) - -/* 2 PBP - Page Size Register */ - -/* 2 TX/RXDMA */ - -/* 2 TRXFF_BNDY */ - -/* 2 LLT_INIT */ - -/* 2 BB_ACCESS_CTRL */ - - -/* */ -/* */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* */ -/* */ - -/* 2 RQPN */ - -/* 2 TDECTRL */ - -/* 2 TDECTL */ - -/* 2 TXDMA_OFFSET_CHK */ - - -/* */ -/* */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* */ -/* */ - -/* 2 FWHW_TXQ_CTRL */ - -/* 2 INIRTSMCS_SEL */ - -/* 2 SPEC SIFS */ - -/* 2 RRSR */ - -/* 2 ARFR */ - -/* 2 AGGLEN_LMT_L */ - -/* 2 RL */ - -/* 2 DARFRC */ - -/* 2 RARFRC */ - - -/* */ -/* */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* */ -/* */ - -/* 2 EDCA setting */ - -/* 2 EDCA_VO_PARAM */ - -/* 2 SIFS_CCK */ - -/* 2 SIFS_OFDM */ - -/* 2 TBTT PROHIBIT */ - -/* 2 REG_RD_CTRL */ - -/* 2 BCN_CTRL */ - -/* 2 ACMHWCTRL */ - - -/* */ -/* */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* */ -/* */ - -/* 2 APSD_CTRL */ - -/* 2 BWOPMODE */ - -/* 2 TCR */ - -/* 2 RCR */ - -/* 2 RX_PKT_LIMIT */ - -/* 2 RX_DLK_TIME */ - -/* 2 MBIDCAMCFG */ - -/* 2 AMPDU_MIN_SPACE */ - -/* 2 RXERR_RPT */ - -/* 2 SECCFG */ - - -/* */ -/* */ -/* 0xFE00h ~ 0xFE55h RTL8723 SDIO Configuration */ -/* */ -/* */ - -/* I/O bus domain address mapping */ -#define WLAN_IOREG_BASE 0x10260000 -#define FIRMWARE_FIFO_BASE 0x10270000 -#define TX_HIQ_BASE 0x10310000 -#define TX_MIQ_BASE 0x10320000 -#define TX_LOQ_BASE 0x10330000 -#define RX_RX0FF_BASE 0x10340000 - -/* SDIO host local register space mapping. */ -#define WLAN_IOREG_MSK 0x7FFF -#define WLAN_FIFO_MSK 0x1FFF /* Aggregation Length[12:0] */ -#define WLAN_RX0FF_MSK 0x0003 - -#define WLAN_RX0FF_DEVICE_ID 7 /* 0b[16], 111b[15:13] */ -#define WLAN_IOREG_DEVICE_ID 8 /* 1b[16] */ - -/* 8723 EFUSE */ -#define HWSET_MAX_SIZE 256 - - -/* USB interrupt */ -#define UHIMR_TIMEOUT2 BIT(31) -#define UHIMR_TIMEOUT1 BIT(30) -#define UHIMR_PSTIMEOUT BIT(29) -#define UHIMR_GTINT4 BIT(28) -#define UHIMR_GTINT3 BIT(27) -#define UHIMR_TXBCNERR BIT(26) -#define UHIMR_TXBCNOK BIT(25) -#define UHIMR_TSF_BIT32_TOGGLE BIT(24) -#define UHIMR_BCNDMAINT3 BIT(23) -#define UHIMR_BCNDMAINT2 BIT(22) -#define UHIMR_BCNDMAINT1 BIT(21) -#define UHIMR_BCNDMAINT0 BIT(20) -#define UHIMR_BCNDOK3 BIT(19) -#define UHIMR_BCNDOK2 BIT(18) -#define UHIMR_BCNDOK1 BIT(17) -#define UHIMR_BCNDOK0 BIT(16) -#define UHIMR_HSISR_IND BIT(15) -#define UHIMR_BCNDMAINT_E BIT(14) -/* RSVD BIT(13) */ -#define UHIMR_CTW_END BIT(12) -/* RSVD BIT(11) */ -#define UHIMR_C2HCMD BIT(10) -#define UHIMR_CPWM2 BIT(9) -#define UHIMR_CPWM BIT(8) -#define UHIMR_HIGHDOK BIT(7) /* High Queue DMA OK - Interrupt */ -#define UHIMR_MGNTDOK BIT(6) /* Management Queue DMA OK - Interrupt */ -#define UHIMR_BKDOK BIT(5) /* AC_BK DMA OK Interrupt */ -#define UHIMR_BEDOK BIT(4) /* AC_BE DMA OK Interrupt */ -#define UHIMR_VIDOK BIT(3) /* AC_VI DMA OK Interrupt */ -#define UHIMR_VODOK BIT(2) /* AC_VO DMA Interrupt */ -#define UHIMR_RDU BIT(1) /* Receive Descriptor - Unavailable */ -#define UHIMR_ROK BIT(0) /* Receive DMA OK Interrupt */ - -/* USB Host Interrupt Status Extension bit */ -#define UHIMR_BCNDMAINT7 BIT(23) -#define UHIMR_BCNDMAINT6 BIT(22) -#define UHIMR_BCNDMAINT5 BIT(21) -#define UHIMR_BCNDMAINT4 BIT(20) -#define UHIMR_BCNDOK7 BIT(19) -#define UHIMR_BCNDOK6 BIT(18) -#define UHIMR_BCNDOK5 BIT(17) -#define UHIMR_BCNDOK4 BIT(16) -/* bit14-15: RSVD */ -#define UHIMR_ATIMEND_E BIT(13) -#define UHIMR_ATIMEND BIT(12) -#define UHIMR_TXERR BIT(11) -#define UHIMR_RXERR BIT(10) -#define UHIMR_TXFOVW BIT(9) -#define UHIMR_RXFOVW BIT(8) -/* bit2-7: RSVD */ -#define UHIMR_OCPINT BIT(1) -/* bit0: RSVD */ - -#define REG_USB_HIMR 0xFE38 -#define REG_USB_HIMRE 0xFE3C -#define REG_USB_HISR 0xFE78 -#define REG_USB_HISRE 0xFE7C - -#define USB_INTR_CPWM_OFFSET 16 -#define USB_INTR_CONTENT_HISR_OFFSET 48 -#define USB_INTR_CONTENT_HISRE_OFFSET 52 -#define USB_INTR_CONTENT_LENGTH 56 -#define USB_C2H_CMDID_OFFSET 0 -#define USB_C2H_SEQ_OFFSET 1 -#define USB_C2H_EVENT_OFFSET 2 -/* */ -/* General definitions */ -/* */ - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_sreset.h b/drivers/staging/rtl8723au/include/rtl8723a_sreset.h deleted file mode 100644 index 6197910a4a53..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_sreset.h +++ /dev/null @@ -1,24 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef _RTL8723A_SRESET_H_ -#define _RTL8723A_SRESET_H_ - -#include -#include -#include - -void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_xmit.h b/drivers/staging/rtl8723au/include/rtl8723a_xmit.h deleted file mode 100644 index 7db29f40ab70..000000000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_xmit.h +++ /dev/null @@ -1,225 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_XMIT_H__ -#define __RTL8723A_XMIT_H__ - -/* */ -/* Queue Select Value in TxDesc */ -/* */ -#define QSLT_BK 0x2/* 0x01 */ -#define QSLT_BE 0x0 -#define QSLT_VI 0x5/* 0x4 */ -#define QSLT_VO 0x7/* 0x6 */ -#define QSLT_BEACON 0x10 -#define QSLT_HIGH 0x11 -#define QSLT_MGNT 0x12 -#define QSLT_CMD 0x13 - -/* */ -/* defined for TX DESC Operation */ -/* */ - -#define MAX_TID (15) - -/* OFFSET 0 */ -#define OFFSET_SZ 0 -#define OFFSET_SHT 16 -#define BMC BIT(24) -#define LSG BIT(26) -#define FSG BIT(27) -#define OWN BIT(31) - - -/* OFFSET 4 */ -#define PKT_OFFSET_SZ 0 -#define BK BIT(6) -#define QSEL_SHT 8 -#define Rate_ID_SHT 16 -#define NAVUSEHDR BIT(20) -#define PKT_OFFSET_SHT 26 -#define HWPC BIT(31) - -/* OFFSET 8 */ -#define AGG_EN BIT(29) - -/* OFFSET 12 */ -#define SEQ_SHT 16 - -/* OFFSET 16 */ -#define QoS BIT(6) -#define HW_SEQ_EN BIT(7) -#define USERATE BIT(8) -#define DISDATAFB BIT(10) -#define DATA_SHORT BIT(24) -#define DATA_BW BIT(25) - -/* OFFSET 20 */ -#define SGI BIT(6) - -struct txdesc_8723a { - u32 pktlen:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 ls:1; - u32 fs:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:5; - u32 agg_en:1; - u32 bk:1; - u32 rd_en:1; - u32 qsel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rate_id:4; - u32 navusehdr:1; - u32 en_desc_id:1; - u32 sectype:2; - u32 rsvd0424:2; - u32 pkt_offset:5; /* unit: 8 bytes */ - u32 rsvd0431:1; - - u32 rts_rc:6; - u32 data_rc:6; - u32 rsvd0812:2; - u32 bar_rty_th:2; - u32 rsvd0816:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdu_density:3; - u32 bt_null:1; - u32 ant_sel_a:1; - u32 ant_sel_b:1; - u32 tx_ant_cck:2; - u32 tx_antl:2; - u32 tx_ant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 cpu_handle:1; - u32 tag1:1; - u32 trigger_int:1; - u32 hwseq_en:1; - - u32 rtsrate:5; - u32 ap_dcfe:1; - u32 hwseq_sel:2; - u32 userate:1; - u32 disrtsfb:1; - u32 disdatafb:1; - u32 cts2self:1; - u32 rtsen:1; - u32 hw_rts_en:1; - u32 port_id:1; - u32 rsvd1615:3; - u32 wait_dcts:1; - u32 cts2ap_en:1; - u32 data_sc:2; - u32 data_stbc:2; - u32 data_short:1; - u32 data_bw:1; - u32 rts_short:1; - u32 rts_bw:1; - u32 rts_sc:2; - u32 vcs_stbc:2; - - u32 datarate:6; - u32 sgi:1; - u32 try_rate:1; - u32 data_ratefb_lmt:5; - u32 rts_ratefb_lmt:4; - u32 rty_lmt_en:1; - u32 data_rt_lmt:6; - u32 usb_txagg_num:8; - - u32 txagg_a:5; - u32 txagg_b:5; - u32 use_max_len:1; - u32 max_agg_num:5; - u32 mcsg1_max_len:4; - u32 mcsg2_max_len:4; - u32 mcsg3_max_len:4; - u32 mcs7_sgi_max_len:4; - - u32 checksum:16; /* TxBuffSize(PCIe)/CheckSum(USB) */ - u32 mcsg4_max_len:4; - u32 mcsg5_max_len:4; - u32 mcsg6_max_len:4; - u32 mcs15_sgi_max_len:4; -}; - -#define txdesc_set_ccx_sw_8723a(txdesc, value) \ - do { \ - ((struct txdesc_8723a *)(txdesc))->mcsg4_max_len = (((value)>>8) & 0x0f); \ - ((struct txdesc_8723a *)(txdesc))->mcs15_sgi_max_len= (((value)>>4) & 0x0f); \ - ((struct txdesc_8723a *)(txdesc))->mcsg6_max_len = ((value) & 0x0f); \ - } while (0) - -struct txrpt_ccx_8723a { - /* offset 0 */ - u8 tag1:1; - u8 rsvd:4; - u8 int_bt:1; - u8 int_tri:1; - u8 int_ccx:1; - - /* offset 1 */ - u8 mac_id:5; - u8 pkt_drop:1; - u8 pkt_ok:1; - u8 bmc:1; - - /* offset 2 */ - u8 retry_cnt:6; - u8 lifetime_over:1; - u8 retry_over:1; - - /* offset 3 */ - u8 ccx_qtime0; - u8 ccx_qtime1; - - /* offset 5 */ - u8 final_data_rate; - - /* offset 6 */ - u8 sw1:4; - u8 qsel:4; - - /* offset 7 */ - u8 sw0; -}; - -#define txrpt_ccx_sw_8723a(txrpt_ccx) ((txrpt_ccx)->sw0 + ((txrpt_ccx)->sw1<<8)) -#define txrpt_ccx_qtime_8723a(txrpt_ccx) ((txrpt_ccx)->ccx_qtime0+((txrpt_ccx)->ccx_qtime1<<8)) - -void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf); -void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull); - -int rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe); -s32 rtl8723au_xmit_buf_handler(struct rtw_adapter *padapter); -#define hal_xmit_handler rtl8723au_xmit_buf_handler -bool rtl8723au_hal_xmit(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe); -int rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe); -bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf); - - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_ap.h b/drivers/staging/rtl8723au/include/rtw_ap.h deleted file mode 100644 index 55a708f9fc5b..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_ap.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_AP_H_ -#define __RTW_AP_H_ - -#include -#include - - -#ifdef CONFIG_8723AU_AP_MODE - -/* external function */ - -void init_mlme_ap_info23a(struct rtw_adapter *padapter); -void free_mlme_ap_info23a(struct rtw_adapter *padapter); -/* void update_BCNTIM(struct rtw_adapter *padapter); */ -void rtw_add_bcn_ie(struct rtw_adapter *padapter, struct wlan_bssid_ex *pnetwork, u8 index, u8 *data, u8 len); -void rtw_remove_bcn_ie(struct rtw_adapter *padapter, struct wlan_bssid_ex *pnetwork, u8 index); -void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx); -void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level); -void expire_timeout_chk23a(struct rtw_adapter *padapter); -void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta); -int rtw_check_beacon_data23a(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, unsigned int len); -void rtw_ap_restore_network(struct rtw_adapter *padapter); -void rtw_set_macaddr_acl23a(struct rtw_adapter *padapter, int mode); - -void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated); -void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta); -u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info *psta); -void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta); -void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta); -u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool active, u16 reason); -int rtw_sta_flush23a(struct rtw_adapter *padapter); -void start_ap_mode23a(struct rtw_adapter *padapter); -void stop_ap_mode23a(struct rtw_adapter *padapter); -#endif /* end of CONFIG_8723AU_AP_MODE */ - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_cmd.h b/drivers/staging/rtl8723au/include/rtw_cmd.h deleted file mode 100644 index d1fa95d28904..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_cmd.h +++ /dev/null @@ -1,815 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_CMD_H_ -#define __RTW_CMD_H_ - -#include -#include - -#define C2H_MEM_SZ (16*1024) - -#include -#include /* */ - - -#define MAX_CMDSZ 1024 -#define MAX_RSPSZ 512 -#define MAX_EVTSZ 1024 - -#define CMDBUFF_ALIGN_SZ 512 - -struct cmd_obj { - struct work_struct work; - struct rtw_adapter *padapter; - u16 cmdcode; - int res; - u32 cmdsz; - u8 *parmbuf; - u8 *rsp; - u32 rspsz; -}; - -struct cmd_priv { - struct workqueue_struct *wq; - u32 cmd_issued_cnt; - u32 cmd_done_cnt; - u32 rsp_cnt; - struct rtw_adapter *padapter; -}; - -#define C2H_QUEUE_MAX_LEN 10 - -struct evt_priv { - struct workqueue_struct *wq; - struct work_struct irq_wk; -}; - -#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \ -do {\ - pcmd->cmdcode = code;\ - pcmd->parmbuf = (u8 *)(pparm);\ - pcmd->cmdsz = sizeof (*pparm);\ - pcmd->rsp = NULL;\ - pcmd->rspsz = 0;\ -} while(0) - -struct c2h_evt_hdr { - u8 id:4; - u8 plen:4; - u8 seq; - u8 payload[0]; -}; - -/* - * Do not reorder - this allows for struct evt_work to be passed on to - * rtw_c2h_wk_cmd23a() as a 'struct c2h_evt_hdr *' without making an - * additional copy. - */ -struct evt_work { - union { - struct c2h_evt_hdr c2h_evt; - u8 buf[16]; - } u; - struct work_struct work; - struct rtw_adapter *adapter; -}; - -#define c2h_evt_exist(c2h_evt) ((c2h_evt)->id || (c2h_evt)->plen) - -void rtw_evt_work(struct work_struct *work); - -int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *obj); -void rtw_free_cmd_obj23a(struct cmd_obj *pcmd); - -int rtw_cmd_thread23a(void *context); - -int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv); - -u32 rtw_init_evt_priv23a (struct evt_priv *pevtpriv); -void rtw_free_evt_priv23a (struct evt_priv *pevtpriv); -void rtw_evt_notify_isr(struct evt_priv *pevtpriv); - -enum rtw_drvextra_cmd_id -{ - NONE_WK_CID, - DYNAMIC_CHK_WK_CID, - DM_CTRL_WK_CID, - PBC_POLLING_WK_CID, - POWER_SAVING_CTRL_WK_CID,/* IPS,AUTOSuspend */ - LPS_CTRL_WK_CID, - ANT_SELECT_WK_CID, - P2P_PS_WK_CID, - P2P_PROTO_WK_CID, - CHECK_HIQ_WK_CID,/* for softap mode, check hi queue if empty */ - C2H_WK_CID, - RTP_TIMER_CFG_WK_CID, - MAX_WK_CID -}; - -enum LPS_CTRL_TYPE -{ - LPS_CTRL_SCAN=0, - LPS_CTRL_JOINBSS=1, - LPS_CTRL_CONNECT=2, - LPS_CTRL_DISCONNECT=3, - LPS_CTRL_SPECIAL_PACKET=4, - LPS_CTRL_LEAVE=5, -}; - -enum RFINTFS { - SWSI, - HWSI, - HWPI, -}; - -/* -Caller Mode: Infra, Ad-HoC(C) - -Notes: To enter USB suspend mode - -Command Mode - -*/ -struct usb_suspend_parm { - u32 action;/* 1: sleep, 0:resume */ -}; - -/* -Caller Mode: Infra, Ad-HoC - -Notes: To join a known BSS. - -Command-Event Mode - -*/ - -/* -Caller Mode: Infra, Ad-HoC(C) - -Notes: To disconnect the current associated BSS - -Command Mode - -*/ -struct disconnect_parm { - u32 deauth_timeout_ms; -}; - -struct setopmode_parm { - enum nl80211_iftype mode; -}; - -/* -Caller Mode: AP, Ad-HoC, Infra - -Notes: To ask RTL8711 performing site-survey - -Command-Event Mode - -*/ - -#define RTW_SSID_SCAN_AMOUNT 9 /* for WEXT_CSCAN_AMOUNT 9 */ -#define RTW_CHANNEL_SCAN_AMOUNT (14+37) -struct sitesurvey_parm { - int scan_mode; /* active: 1, passive: 0 */ - u8 ssid_num; - u8 ch_num; - struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT]; -}; - -/* -Caller Mode: Any - -Notes: To set the auth type of RTL8711. open/shared/802.1x - -Command Mode - -*/ -struct setauth_parm { - u8 mode; /* 0: legacy open, 1: legacy shared 2: 802.1x */ - u8 _1x; /* 0: PSK, 1: TLS */ - u8 rsvd[2]; -}; - -/* -Caller Mode: Infra - -a. algorithm: wep40, wep104, tkip & aes -b. keytype: grp key/unicast key -c. key contents - -when shared key ==> keyid is the camid -when 802.1x ==> keyid [0:1] ==> grp key -when 802.1x ==> keyid > 2 ==> unicast key - -*/ -struct setkey_parm { - u32 algorithm; /* encryption algorithm, could be none, wep40, TKIP, CCMP, wep104 */ - u8 keyid; - u8 grpkey; /* 1: this is the grpkey for 802.1x. 0: this is the unicast key for 802.1x */ - u8 set_tx; /* 1: main tx key for wep. 0: other key. */ - u8 key[16]; /* this could be 40 or 104 */ -}; - -/* -When in AP or Ad-Hoc mode, this is used to -allocate an sw/hw entry for a newly associated sta. - -Command - -when shared key ==> algorithm/keyid - -*/ -struct set_stakey_parm { - u8 addr[ETH_ALEN]; - u8 id;/* currently for erasing cam entry if algorithm == _NO_PRIVACY_ */ - u32 algorithm; - u8 key[16]; -}; - -struct set_stakey_rsp { - u8 addr[ETH_ALEN]; - u8 keyid; - u8 rsvd; -}; - -/* -Caller Ad-Hoc/AP - -Command -Rsp(AID == CAMID) mode - -This is to force fw to add an sta_data entry per driver's request. - -FW will write an cam entry associated with it. - -*/ -struct set_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -struct set_assocsta_rsp { - u8 cam_id; - u8 rsvd[3]; -}; - -/* - Caller Ad-Hoc/AP - - Command mode - - This is to force fw to del an sta_data entry per driver's request - - FW will invalidate the cam entry associated with it. - -*/ -struct del_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -/* -Caller Mode: AP/Ad-HoC(M) - -Notes: To notify fw that given staid has changed its power state - -Command Mode - -*/ -struct setstapwrstate_parm { - u8 staid; - u8 status; - u8 hwaddr[6]; -}; - -/* -Caller Mode: Any - -Notes: To setup the basic rate of RTL8711 - -Command Mode - -*/ -struct setbasicrate_parm { - u8 basicrates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To read the current basic rate - -Command-Rsp Mode - -*/ -struct getbasicrate_parm { - u32 rsvd; -}; - -struct getbasicrate_rsp { - u8 basicrates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To setup the data rate of RTL8711 - -Command Mode - -*/ -struct setdatarate_parm { - u8 mac_id; - u8 datarates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To read the current data rate - -Command-Rsp Mode - -*/ -struct getdatarate_parm { - u32 rsvd; -}; - -struct getdatarate_rsp { - u8 datarates[NumRates]; -}; - - -/* -Caller Mode: Any -AP: AP can use the info for the contents of beacon frame -Infra: STA can use the info when sitesurveying -Ad-HoC(M): Like AP -Ad-HoC(C): Like STA - - -Notes: To set the phy capability of the NIC - -Command Mode - -*/ - -struct setphyinfo_parm { - struct regulatory_class class_sets[NUM_REGULATORYS]; - u8 status; -}; - -struct getphyinfo_parm { - u32 rsvd; -}; - -struct getphyinfo_rsp { - struct regulatory_class class_sets[NUM_REGULATORYS]; - u8 status; -}; - -/* -Caller Mode: Any - -Notes: To set the channel/modem/band -This command will be used when channel/modem/band is changed. - -Command Mode - -*/ -struct setphy_parm { - u8 rfchannel; - u8 modem; -}; - -/* -Caller Mode: Any - -Notes: To get the current setting of channel/modem/band - -Command-Rsp Mode - -*/ -struct getphy_parm { - u32 rsvd; -}; - -struct getphy_rsp { - u8 rfchannel; - u8 modem; -}; - -struct readBB_parm { - u8 offset; -}; - -struct readBB_rsp { - u8 value; -}; - -struct readTSSI_parm { - u8 offset; -}; - -struct readTSSI_rsp { - u8 value; -}; - -struct writeBB_parm { - u8 offset; - u8 value; -}; - -struct readRF_parm { - u8 offset; -}; - -struct readRF_rsp { - u32 value; -}; - -struct writeRF_parm { - u32 offset; - u32 value; -}; - -struct getrfintfs_parm { - u8 rfintfs; -}; - -struct Tx_Beacon_param { - struct wlan_bssid_ex network; -}; - -/* CMD param Formart for driver extra cmd handler */ -struct drvextra_cmd_parm { - int ec_id; /* extra cmd id */ - int type_size; /* Can use this field as the type id or command size */ - unsigned char *pbuf; -}; - -/*------------------- Below are used for RF/BB tunning ---------------------*/ - -struct setantenna_parm { - u8 tx_antset; - u8 rx_antset; - u8 tx_antenna; - u8 rx_antenna; -}; - -struct enrateadaptive_parm { - u32 en; -}; - -struct settxagctbl_parm { - u32 txagc[MAX_RATES_LENGTH]; -}; - -struct gettxagctbl_parm { - u32 rsvd; -}; - -struct gettxagctbl_rsp { - u32 txagc[MAX_RATES_LENGTH]; -}; - -struct setagcctrl_parm { - u32 agcctrl; /* 0: pure hw, 1: fw */ -}; - -struct setssup_parm { - u32 ss_ForceUp[MAX_RATES_LENGTH]; -}; - -struct getssup_parm { - u32 rsvd; -}; - -struct getssup_rsp { - u8 ss_ForceUp[MAX_RATES_LENGTH]; -}; - -struct setssdlevel_parm { - u8 ss_DLevel[MAX_RATES_LENGTH]; -}; - -struct getssdlevel_parm { - u32 rsvd; -}; - -struct getssdlevel_rsp { - u8 ss_DLevel[MAX_RATES_LENGTH]; -}; - -struct setssulevel_parm { - u8 ss_ULevel[MAX_RATES_LENGTH]; -}; - -struct getssulevel_parm { - u32 rsvd; -}; - -struct getssulevel_rsp { - u8 ss_ULevel[MAX_RATES_LENGTH]; -}; - -struct setcountjudge_parm { - u8 count_judge[MAX_RATES_LENGTH]; -}; - -struct getcountjudge_parm { - u32 rsvd; -}; - -struct getcountjudge_rsp { - u8 count_judge[MAX_RATES_LENGTH]; -}; - -struct setratable_parm { - u8 ss_ForceUp[NumRates]; - u8 ss_ULevel[NumRates]; - u8 ss_DLevel[NumRates]; - u8 count_judge[NumRates]; -}; - -struct getratable_parm { - uint rsvd; -}; - -struct getratable_rsp { - u8 ss_ForceUp[NumRates]; - u8 ss_ULevel[NumRates]; - u8 ss_DLevel[NumRates]; - u8 count_judge[NumRates]; -}; - -/* to get TX,RX retry count */ -struct gettxretrycnt_parm{ - unsigned int rsvd; -}; -struct gettxretrycnt_rsp{ - unsigned long tx_retrycnt; -}; - -struct getrxretrycnt_parm{ - unsigned int rsvd; -}; -struct getrxretrycnt_rsp{ - unsigned long rx_retrycnt; -}; - -/* to get BCNOK,BCNERR count */ -struct getbcnokcnt_parm{ - unsigned int rsvd; -}; -struct getbcnokcnt_rsp{ - unsigned long bcnokcnt; -}; - -struct getbcnerrcnt_parm{ - unsigned int rsvd; -}; -struct getbcnerrcnt_rsp{ - unsigned long bcnerrcnt; -}; - -/* to get current TX power level */ -struct getcurtxpwrlevel_parm{ - unsigned int rsvd; -}; - -struct getcurtxpwrlevel_rsp{ - unsigned short tx_power; -}; - -struct setprobereqextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[0]; -}; - -struct setassocreqextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[0]; -}; - -struct setproberspextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[0]; -}; - -struct setassocrspextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[0]; -}; - -struct addBaReq_parm { - unsigned int tid; - u8 addr[ETH_ALEN]; -}; - -/*H2C Handler index: 46 */ -struct set_ch_parm { - u8 ch; - u8 bw; - u8 ch_offset; -}; - -/*H2C Handler index: 59 */ -struct SetChannelPlan_param { - u8 channel_plan; -}; - -/*H2C Handler index: 60 */ -struct LedBlink_param { - struct led_8723a *pLed; -}; - -/*H2C Handler index: 61 */ -struct SetChannelSwitch_param { - u8 new_ch_no; -}; - -/*H2C Handler index: 62 */ -struct TDLSoption_param { - u8 addr[ETH_ALEN]; - u8 option; -}; - -#define GEN_CMD_CODE(cmd) cmd ## _CMD_ - - -/* - -Result: -0x00: success -0x01: success, and check Response. -0x02: cmd ignored due to duplicated sequcne number -0x03: cmd dropped due to invalid cmd code -0x04: reserved. - -*/ - -#define H2C_RSP_OFFSET 512 - -#define H2C_SUCCESS 0x00 -#define H2C_SUCCESS_RSP 0x01 -#define H2C_DUPLICATED 0x02 -#define H2C_DROPPED 0x03 -#define H2C_PARAMETERS_ERROR 0x04 -#define H2C_REJECTED 0x05 -#define H2C_CMD_OVERFLOW 0x06 -#define H2C_RESERVED 0x07 - -int rtw_setassocsta_cmd(struct rtw_adapter *padapter, u8 *mac_addr); -int rtw_setstandby_cmd(struct rtw_adapter *padapter, uint action); -int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter, struct cfg80211_ssid *ssid, int ssid_num, struct rtw_ieee80211_channel *ch, int ch_num); -int rtw_createbss_cmd23a(struct rtw_adapter *padapter); -int rtw_createbss_cmd23a_ex(struct rtw_adapter *padapter, unsigned char *pbss, unsigned int sz); -int rtw_setphy_cmd(struct rtw_adapter *padapter, u8 modem, u8 ch); -int rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key); -int rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry, u8 enqueue); -int rtw_joinbss_cmd23a(struct rtw_adapter *padapter, struct wlan_network* pnetwork); -int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, bool enqueue); -int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, enum nl80211_iftype ifmode); -int rtw_setdatarate_cmd(struct rtw_adapter *padapter, u8 *rateset); -int rtw_setbasicrate_cmd(struct rtw_adapter *padapter, u8 *rateset); -int rtw_setbbreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 val); -int rtw_setrfreg_cmd(struct rtw_adapter *padapter, u8 offset, u32 val); -int rtw_getbbreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); -int rtw_getrfreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); -int rtw_setrfintfs_cmd(struct rtw_adapter *padapter, u8 mode); -int rtw_setrttbl_cmd(struct rtw_adapter *padapter, struct setratable_parm *prate_table); -int rtw_getrttbl_cmd(struct rtw_adapter *padapter, struct getratable_rsp *pval); - -int rtw_gettssi_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); -int rtw_setfwdig_cmd(struct rtw_adapter*padapter, u8 type); -int rtw_setfwra_cmd(struct rtw_adapter*padapter, u8 type); - -int rtw_addbareq_cmd23a(struct rtw_adapter*padapter, u8 tid, u8 *addr); - -int rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter *adapter); - -int rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter*padapter, u8 lps_ctrl_type, u8 enqueue); - -int rtw_ps_cmd23a(struct rtw_adapter*padapter); - -#ifdef CONFIG_8723AU_AP_MODE -int rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter); -#endif - -int rtw_set_chplan_cmd(struct rtw_adapter*padapter, u8 chplan, u8 enqueue); -int rtw_led_blink_cmd(struct rtw_adapter*padapter, struct led_8723a *pLed); -int rtw_set_csa_cmd(struct rtw_adapter*padapter, u8 new_ch_no); - -int rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt); - -int rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); - -void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd); - -void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd); - -struct _cmd_callback { - u32 cmd_code; - void (*callback)(struct rtw_adapter *padapter, struct cmd_obj *cmd); -}; - -enum rtw_h2c_cmd { - GEN_CMD_CODE(_Read_MACREG) , /*0*/ - GEN_CMD_CODE(_Write_MACREG) , - GEN_CMD_CODE(_Read_BBREG) , - GEN_CMD_CODE(_Write_BBREG) , - GEN_CMD_CODE(_Read_RFREG) , - GEN_CMD_CODE(_Write_RFREG) , /*5*/ - GEN_CMD_CODE(_Read_EEPROM) , - GEN_CMD_CODE(_Write_EEPROM) , - GEN_CMD_CODE(_Read_EFUSE) , - GEN_CMD_CODE(_Write_EFUSE) , - - GEN_CMD_CODE(_Read_CAM) , /*10*/ - GEN_CMD_CODE(_Write_CAM) , - GEN_CMD_CODE(_setBCNITV), - GEN_CMD_CODE(_setMBIDCFG), - GEN_CMD_CODE(_JoinBss), /*14*/ - GEN_CMD_CODE(_DisConnect) , /*15*/ - GEN_CMD_CODE(_CreateBss) , - GEN_CMD_CODE(_SetOpMode) , - GEN_CMD_CODE(_SiteSurvey), /*18*/ - GEN_CMD_CODE(_SetAuth) , - - GEN_CMD_CODE(_SetKey) , /*20*/ - GEN_CMD_CODE(_SetStaKey) , - GEN_CMD_CODE(_SetAssocSta) , - GEN_CMD_CODE(_DelAssocSta) , - GEN_CMD_CODE(_SetStaPwrState) , - GEN_CMD_CODE(_SetBasicRate) , /*25*/ - GEN_CMD_CODE(_GetBasicRate) , - GEN_CMD_CODE(_SetDataRate) , - GEN_CMD_CODE(_GetDataRate) , - GEN_CMD_CODE(_SetPhyInfo) , - - GEN_CMD_CODE(_GetPhyInfo) , /*30*/ - GEN_CMD_CODE(_SetPhy) , - GEN_CMD_CODE(_GetPhy) , - GEN_CMD_CODE(_readRssi) , - GEN_CMD_CODE(_readGain) , - GEN_CMD_CODE(_SetAtim) , /*35*/ - GEN_CMD_CODE(_SetPwrMode) , - GEN_CMD_CODE(_JoinbssRpt), - GEN_CMD_CODE(_SetRaTable) , - GEN_CMD_CODE(_GetRaTable) , - - GEN_CMD_CODE(_GetCCXReport), /*40*/ - GEN_CMD_CODE(_GetDTMReport), - GEN_CMD_CODE(_GetTXRateStatistics), - GEN_CMD_CODE(_SetUsbSuspend), - GEN_CMD_CODE(_SetH2cLbk), - GEN_CMD_CODE(_AddBAReq) , /*45*/ - GEN_CMD_CODE(_SetChannel), /*46*/ - GEN_CMD_CODE(_SetTxPower), - GEN_CMD_CODE(_SwitchAntenna), - GEN_CMD_CODE(_SetCrystalCap), - GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/ - - GEN_CMD_CODE(_SetSingleToneTx),/*51*/ - GEN_CMD_CODE(_SetCarrierSuppressionTx), - GEN_CMD_CODE(_SetContinuousTx), - GEN_CMD_CODE(_SwitchBandwidth), /*54*/ - GEN_CMD_CODE(_TX_Beacon), /*55*/ - - GEN_CMD_CODE(_Set_MLME_EVT), /*56*/ - GEN_CMD_CODE(_Set_Drv_Extra), /*57*/ - GEN_CMD_CODE(_Set_H2C_MSG), /*58*/ - - GEN_CMD_CODE(_SetChannelPlan), /*59*/ - GEN_CMD_CODE(_LedBlink), /*60*/ - - GEN_CMD_CODE(_SetChannelSwitch), /*61*/ - GEN_CMD_CODE(_TDLS), /*62*/ - - MAX_H2CCMD -}; - -extern struct _cmd_callback rtw_cmd_callback[]; - -#endif /* _CMD_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_debug.h b/drivers/staging/rtl8723au/include/rtw_debug.h deleted file mode 100644 index 159183e9cab0..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_debug.h +++ /dev/null @@ -1,191 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - * - ******************************************************************************/ -#ifndef __RTW_DEBUG_H__ -#define __RTW_DEBUG_H__ - -#include -#include - -#define _drv_always_ 1 -#define _drv_emerg_ 2 -#define _drv_alert_ 3 -#define _drv_err_ 4 -#define _drv_warning_ 5 -#define _drv_notice_ 6 -#define _drv_info_ 7 -#define _drv_debug_ 8 - -#define _module_rtl871x_xmit_c_ BIT(0) -#define _module_xmit_osdep_c_ BIT(1) -#define _module_rtl871x_recv_c_ BIT(2) -#define _module_recv_osdep_c_ BIT(3) -#define _module_rtl871x_mlme_c_ BIT(4) -#define _module_mlme_osdep_c_ BIT(5) -#define _module_rtl871x_sta_mgt_c_ BIT(6) -#define _module_rtl871x_cmd_c_ BIT(7) -#define _module_cmd_osdep_c_ BIT(8) -#define _module_rtl871x_io_c_ BIT(9) -#define _module_io_osdep_c_ BIT(10) -#define _module_os_intfs_c_ BIT(11) -#define _module_rtl871x_security_c_ BIT(12) -#define _module_rtl871x_eeprom_c_ BIT(13) -#define _module_hal_init_c_ BIT(14) -#define _module_hci_hal_init_c_ BIT(15) -#define _module_rtl871x_ioctl_c_ BIT(16) -#define _module_rtl871x_ioctl_set_c_ BIT(17) -#define _module_rtl871x_ioctl_query_c_ BIT(18) -#define _module_rtl871x_pwrctrl_c_ BIT(19) -#define _module_hci_intfs_c_ BIT(20) -#define _module_hci_ops_c_ BIT(21) -#define _module_osdep_service_c_ BIT(22) -#define _module_mp_ BIT(23) -#define _module_hci_ops_os_c_ BIT(24) -#define _module_rtl871x_ioctl_os_c BIT(25) -#define _module_rtl8712_cmd_c_ BIT(26) -#define _module_rtl8192c_xmit_c_ BIT(28) -#define _module_hal_xmit_c_ BIT(28) /* duplication intentional */ -#define _module_efuse_ BIT(29) -#define _module_rtl8712_recv_c_ BIT(30) -#define _module_rtl8712_led_c_ BIT(31) - -#undef _MODULE_DEFINE_ - -#if defined _RTW_XMIT_C_ - #define _MODULE_DEFINE_ _module_rtl871x_xmit_c_ -#elif defined _XMIT_OSDEP_C_ - #define _MODULE_DEFINE_ _module_xmit_osdep_c_ -#elif defined _RTW_RECV_C_ - #define _MODULE_DEFINE_ _module_rtl871x_recv_c_ -#elif defined _RECV_OSDEP_C_ - #define _MODULE_DEFINE_ _module_recv_osdep_c_ -#elif defined _RTW_MLME_C_ - #define _MODULE_DEFINE_ _module_rtl871x_mlme_c_ -#elif defined _MLME_OSDEP_C_ - #define _MODULE_DEFINE_ _module_mlme_osdep_c_ -#elif defined _RTW_MLME_EXT_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _RTW_STA_MGT_C_ - #define _MODULE_DEFINE_ _module_rtl871x_sta_mgt_c_ -#elif defined _RTW_CMD_C_ - #define _MODULE_DEFINE_ _module_rtl871x_cmd_c_ -#elif defined _CMD_OSDEP_C_ - #define _MODULE_DEFINE_ _module_cmd_osdep_c_ -#elif defined _RTW_IO_C_ - #define _MODULE_DEFINE_ _module_rtl871x_io_c_ -#elif defined _IO_OSDEP_C_ - #define _MODULE_DEFINE_ _module_io_osdep_c_ -#elif defined _OS_INTFS_C_ - #define _MODULE_DEFINE_ _module_os_intfs_c_ -#elif defined _RTW_SECURITY_C_ - #define _MODULE_DEFINE_ _module_rtl871x_security_c_ -#elif defined _RTW_EEPROM_C_ - #define _MODULE_DEFINE_ _module_rtl871x_eeprom_c_ -#elif defined _HAL_INTF_C_ - #define _MODULE_DEFINE_ _module_hal_init_c_ -#elif (defined _HCI_HAL_INIT_C_) || (defined _SDIO_HALINIT_C_) - #define _MODULE_DEFINE_ _module_hci_hal_init_c_ -#elif defined _RTL871X_IOCTL_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_c_ -#elif defined _RTL871X_IOCTL_SET_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_set_c_ -#elif defined _RTL871X_IOCTL_QUERY_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_query_c_ -#elif defined _RTL871X_PWRCTRL_C_ - #define _MODULE_DEFINE_ _module_rtl871x_pwrctrl_c_ -#elif defined _RTW_PWRCTRL_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _HCI_INTF_C_ - #define _MODULE_DEFINE_ _module_hci_intfs_c_ -#elif defined _HCI_OPS_C_ - #define _MODULE_DEFINE_ _module_hci_ops_c_ -#elif defined _SDIO_OPS_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _OSDEP_HCI_INTF_C_ - #define _MODULE_DEFINE_ _module_hci_intfs_c_ -#elif defined _OSDEP_SERVICE_C_ - #define _MODULE_DEFINE_ _module_osdep_service_c_ -#elif defined _HCI_OPS_OS_C_ - #define _MODULE_DEFINE_ _module_hci_ops_os_c_ -#elif defined _RTL871X_IOCTL_LINUX_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_os_c -#elif defined _RTL8712_CMD_C_ - #define _MODULE_DEFINE_ _module_rtl8712_cmd_c_ -#elif defined _RTL8192C_XMIT_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _RTL8723AS_XMIT_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _RTL8712_RECV_C_ - #define _MODULE_DEFINE_ _module_rtl8712_recv_c_ -#elif defined _RTL8192CU_RECV_C_ - #define _MODULE_DEFINE_ _module_rtl8712_recv_c_ -#elif defined _RTL871X_MLME_EXT_C_ - #define _MODULE_DEFINE_ _module_mlme_osdep_c_ -#elif defined _RTW_MP_C_ - #define _MODULE_DEFINE_ _module_mp_ -#elif defined _RTW_MP_IOCTL_C_ - #define _MODULE_DEFINE_ _module_mp_ -#elif defined _RTW_EFUSE_C_ - #define _MODULE_DEFINE_ _module_efuse_ -#endif - -#define DRIVER_PREFIX "RTL8723AU: " -#define DEBUG_LEVEL (_drv_err_) -#define DBG_8723A_LEVEL(_level, fmt, arg...) \ - do { \ - if (_level <= GlobalDebugLevel23A) \ - pr_info(DRIVER_PREFIX fmt, ##arg);\ - } while (0) - -#define DBG_8723A(...) \ - do { \ - if (_drv_err_ <= GlobalDebugLevel23A) \ - pr_info(DRIVER_PREFIX __VA_ARGS__); \ - } while (0) - -#define MSG_8723A(...) \ - do { \ - if (_drv_err_ <= GlobalDebugLevel23A) \ - pr_info(DRIVER_PREFIX __VA_ARGS__); \ - } while (0) - -extern u32 GlobalDebugLevel23A; - -__printf(3, 4) -void rt_trace(int comp, int level, const char *fmt, ...); - -#define RT_TRACE(_Comp, _Level, Fmt, ...) \ -do { \ - if (_Level <= GlobalDebugLevel23A) \ - rt_trace(_Comp, _Level, Fmt, ##__VA_ARGS__); \ -} while (0) - -#define RT_PRINT_DATA(_Comp, _Level, _TitleString, _HexData, \ - _HexDataLen) \ - if (_Level <= GlobalDebugLevel23A) { \ - int __i; \ - u8 *ptr = (u8 *)_HexData; \ - pr_info("%s", DRIVER_PREFIX); \ - pr_info(_TitleString); \ - for (__i = 0; __i < (int)_HexDataLen; __i++) { \ - printk("%02X%s", ptr[__i], \ - (((__i + 1) % 4) == 0) ? " " : " "); \ - if (((__i + 1) % 16) == 0) \ - printk("\n"); \ - } \ - printk("\n"); \ - } - -#endif /* __RTW_DEBUG_H__ */ diff --git a/drivers/staging/rtl8723au/include/rtw_eeprom.h b/drivers/staging/rtl8723au/include/rtw_eeprom.h deleted file mode 100644 index a86f36e49dd1..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_eeprom.h +++ /dev/null @@ -1,135 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_EEPROM_H__ -#define __RTW_EEPROM_H__ - -#include -#include - -#define RTL8712_EEPROM_ID 0x8712 -/* define EEPROM_MAX_SIZE 256 */ - -#define HWSET_MAX_SIZE_512 512 -#define EEPROM_MAX_SIZE HWSET_MAX_SIZE_512 - -#define CLOCK_RATE 50 /* 100us */ - -/* EEPROM opcodes */ -#define EEPROM_READ_OPCODE 06 -#define EEPROM_WRITE_OPCODE 05 -#define EEPROM_ERASE_OPCODE 07 -#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable */ -#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable */ - -/* Country codes */ -#define USA 0x555320 -#define EUROPE 0x1 /* temp, should be provided later */ -#define JAPAN 0x2 /* temp, should be provided later */ - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_ALPHA 0x1 -#define EEPROM_CID_Senao 0x3 -#define EEPROM_CID_NetCore 0x5 -#define EEPROM_CID_CAMEO 0X8 -#define EEPROM_CID_SITECOM 0x9 -#define EEPROM_CID_COREGA 0xB -#define EEPROM_CID_EDIMAX_BELKIN 0xC -#define EEPROM_CID_SERCOMM_BELKIN 0xE -#define EEPROM_CID_CAMEO1 0xF -#define EEPROM_CID_WNC_COREGA 0x12 -#define EEPROM_CID_CLEVO 0x13 -#define EEPROM_CID_WHQL 0xFE /* added by chiyoko for dtm, 20090108 */ - -/* */ -/* Customer ID, note that: */ -/* This variable is initiailzed through EEPROM or registry, */ -/* however, its definition may be different with that in EEPROM for */ -/* EEPROM size consideration. So, we have to perform proper translation between them. */ -/* Besides, CustomerID of registry has precedence of that of EEPROM. */ -/* defined below. 060703, by rcnjko. */ -/* */ -enum rt_customer_id -{ - RT_CID_DEFAULT = 0, - RT_CID_8187_ALPHA0 = 1, - RT_CID_8187_SERCOMM_PS = 2, - RT_CID_8187_HW_LED = 3, - RT_CID_8187_NETGEAR = 4, - RT_CID_WHQL = 5, - RT_CID_819x_CAMEO = 6, - RT_CID_819x_RUNTOP = 7, - RT_CID_819x_Senao = 8, - RT_CID_TOSHIBA = 9, /* Merge by Jacken, 2008/01/31. */ - RT_CID_819x_Netcore = 10, - RT_CID_Nettronix = 11, - RT_CID_DLINK = 12, - RT_CID_PRONET = 13, - RT_CID_COREGA = 14, - RT_CID_CHINA_MOBILE = 15, - RT_CID_819x_ALPHA = 16, - RT_CID_819x_Sitecom = 17, - RT_CID_CCX = 18, /* It's set under CCX logo test and isn't demanded for CCX functions, but for test behavior like retry limit and tx report. By Bruce, 2009-02-17. */ - RT_CID_819x_Lenovo = 19, - RT_CID_819x_QMI = 20, - RT_CID_819x_Edimax_Belkin = 21, - RT_CID_819x_Sercomm_Belkin = 22, - RT_CID_819x_CAMEO1 = 23, - RT_CID_819x_MSI = 24, - RT_CID_819x_Acer = 25, - RT_CID_819x_AzWave_ASUS = 26, - RT_CID_819x_AzWave = 27, /* For AzWave in PCIe, The ID is AzWave use and not only Asus */ - RT_CID_819x_HP = 28, - RT_CID_819x_WNC_COREGA = 29, - RT_CID_819x_Arcadyan_Belkin = 30, - RT_CID_819x_SAMSUNG = 31, - RT_CID_819x_CLEVO = 32, - RT_CID_819x_DELL = 33, - RT_CID_819x_PRONETS = 34, - RT_CID_819x_Edimax_ASUS = 35, - RT_CID_819x_CAMEO_NETGEAR = 36, - RT_CID_PLANEX = 37, - RT_CID_CC_C = 38, - RT_CID_819x_Xavi = 39, - RT_CID_819x_FUNAI_TV = 40, - RT_CID_819x_ALPHA_WD=41, -}; - -struct eeprom_priv { - u8 mac_addr[6]; /* PermanentAddress */ - u8 bautoload_fail_flag; - u8 bloadfile_fail_flag; - u8 bloadmac_fail_flag; - /* u8 bempty; */ - /* u8 sys_config; */ - /* u8 config0; */ - u16 channel_plan; - /* u8 country_string[3]; */ - /* u8 tx_power_b[15]; */ - /* u8 tx_power_g[15]; */ - /* u8 tx_power_a[201]; */ - - u8 EepromOrEfuse; - - u8 efuse_eeprom_data[HWSET_MAX_SIZE_512]; /* 92C:256bytes, 88E:512bytes, we use union set (512bytes) */ -}; - -void eeprom_write16(struct rtw_adapter *padapter, u16 reg, u16 data); -u16 eeprom_read16(struct rtw_adapter *padapter, u16 reg); -void read_eeprom_content(struct rtw_adapter *padapter); -void eeprom_read_sz(struct rtw_adapter *padapter, u16 reg, u8 *data, u32 sz); - -void read_eeprom_content_by_attrib(struct rtw_adapter *padapter); - -#endif /* __RTL871X_EEPROM_H__ */ diff --git a/drivers/staging/rtl8723au/include/rtw_efuse.h b/drivers/staging/rtl8723au/include/rtw_efuse.h deleted file mode 100644 index c577e260f151..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_efuse.h +++ /dev/null @@ -1,109 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - * - ******************************************************************************/ -#ifndef __RTW_EFUSE_H__ -#define __RTW_EFUSE_H__ - -#include - -#define EFUSE_ERROE_HANDLE 1 - -#define PG_STATE_HEADER 0x01 -#define PG_STATE_WORD_0 0x02 -#define PG_STATE_WORD_1 0x04 -#define PG_STATE_WORD_2 0x08 -#define PG_STATE_WORD_3 0x10 -#define PG_STATE_DATA 0x20 - -#define PG_SWBYTE_H 0x01 -#define PG_SWBYTE_L 0x02 - -#define PGPKT_DATA_SIZE 8 - -#define EFUSE_WIFI 0 -#define EFUSE_BT 1 - -enum _EFUSE_DEF_TYPE { - TYPE_EFUSE_MAX_SECTION = 0, - TYPE_EFUSE_REAL_CONTENT_LEN = 1, - TYPE_AVAILABLE_EFUSE_BYTES_BANK = 2, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL = 3, - TYPE_EFUSE_MAP_LEN = 4, - TYPE_EFUSE_PROTECT_BYTES_BANK = 5, - TYPE_EFUSE_CONTENT_LEN_BANK = 6, -}; - -/* E-Fuse */ -#define EFUSE_MAP_SIZE 256 - -#define EFUSE_MAX_SIZE 512 -/* end of E-Fuse */ - -#define EFUSE_MAX_MAP_LEN 256 -#define EFUSE_MAX_HW_SIZE 512 -#define EFUSE_MAX_SECTION_BASE 16 - -#define EXT_HEADER(header) ((header & 0x1F) == 0x0F) -#define ALL_WORDS_DISABLED(wde) ((wde & 0x0F) == 0x0F) -#define GET_HDR_OFFSET_2_0(header) ( (header & 0xE0) >> 5) - -#define EFUSE_REPEAT_THRESHOLD_ 3 - -/* */ -/* The following is for BT Efuse definition */ -/* */ -#define EFUSE_BT_MAX_MAP_LEN 1024 -#define EFUSE_MAX_BANK 4 -#define EFUSE_MAX_BT_BANK (EFUSE_MAX_BANK-1) -/* */ -/*--------------------------Define Parameters-------------------------------*/ -#define EFUSE_MAX_WORD_UNIT 4 - -/*------------------------------Define structure----------------------------*/ -struct pg_pkt_struct { - u8 offset; - u8 word_en; - u8 data[8]; - u8 word_cnts; -}; - -/*------------------------Export global variable----------------------------*/ - -u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter); -int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bRead, u16 start_addr, u16 cnts, u8 *data); -int rtw_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data); -u8 rtw_efuse_map_write(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data); -int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data); -u8 rtw_BT_efuse_map_write(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data); - -u16 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType); -u8 Efuse_CalculateWordCnts23a(u8 word_en); -void ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf); -void EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType, u8 type, void *pOut); -int efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data); -int efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data); - -void Efuse_PowerSwitch23a(struct rtw_adapter *pAdapter, u8 bWrite, - u8 PwrState); -int Efuse_PgPacketRead23a(struct rtw_adapter *pAdapter, u8 offset, u8 *data); -int Efuse_PgPacketWrite23a(struct rtw_adapter *pAdapter, u8 offset, u8 word_en, u8 *data); -void efuse_WordEnableDataRead23a(u8 word_en, u8 *sourdata, u8 *targetdata); -u8 Efuse_WordEnableDataWrite23a(struct rtw_adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data); - -u8 EFUSE_Read1Byte23a(struct rtw_adapter *pAdapter, u16 Address); -void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType); -void EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, u8 Type, u16 Offset, u32 *Value); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_event.h b/drivers/staging/rtl8723au/include/rtw_event.h deleted file mode 100644 index 4557aeccc604..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_event.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_EVENT_H_ -#define _RTW_EVENT_H_ - -#include -#include - -/* -Used to report a bss has been scanned -*/ -struct survey_event { - struct wlan_bssid_ex *bss; -}; - -/* -Used to report that the requested site survey has been done. -bss_cnt indicates the number of bss that has been reported. -*/ -struct surveydone_event { - unsigned int bss_cnt; -}; - -/* -Used to report the link result of joinning the given bss -join_res: --1: authentication fail --2: association fail -> 0: TID -*/ -struct joinbss_event { - struct wlan_network network; -}; - -/* -Used to report a given STA has joinned the created BSS. -It is used in AP/Ad-HoC(M) mode. -*/ -struct stassoc_event { - unsigned char macaddr[6]; - unsigned char rsvd[2]; - int cam_id; -}; - -struct stadel_event { - unsigned char macaddr[6]; - unsigned char rsvd[2]; /* for reason */ - int mac_id; -}; - -struct addba_event { - unsigned int tid; -}; - -#define GEN_EVT_CODE(event) event ## _EVT_ - -struct fwevent { - u32 parmsize; - void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf); -}; - -#endif /* _WLANEVENT_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_ht.h b/drivers/staging/rtl8723au/include/rtw_ht.h deleted file mode 100644 index 780eb8944118..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_ht.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_HT_H_ -#define _RTW_HT_H_ - -#include -#include "linux/ieee80211.h" -#include "wifi.h" - -struct ht_priv { - bool ht_option; - bool ampdu_enable;/* for enable Tx A-MPDU */ - /* u8 baddbareq_issued[16]; */ - u32 tx_amsdu_enable;/* for enable Tx A-MSDU */ - u32 tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */ - u32 rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, updated when join_callback. */ - - u8 bwmode;/* */ - u8 ch_offset;/* PRIME_CHNL_OFFSET */ - u8 sgi;/* short GI */ - - /* for processing Tx A-MPDU */ - u16 agg_enable_bitmap; - /* u8 ADDBA_retry_count; */ - u16 candidate_tid_bitmap; - - struct ieee80211_ht_cap ht_cap; -}; - -#endif /* _RTL871X_HT_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_io.h b/drivers/staging/rtl8723au/include/rtw_io.h deleted file mode 100644 index c8119e2c6545..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_io.h +++ /dev/null @@ -1,237 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#ifndef _RTW_IO_H_ -#define _RTW_IO_H_ - -#include -#include - -#include -#include -#include -/* include */ -#include -#include - -#include -#include - -#define rtw_usb_buffer_alloc(dev, size, dma) usb_alloc_coherent((dev), (size), (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), (dma)) -#define rtw_usb_buffer_free(dev, size, addr, dma) usb_free_coherent((dev), (size), (addr), (dma)) - -#define NUM_IOREQ 8 - -#define MAX_PROT_SZ (64-16) - -#define _IOREADY 0 -#define _IO_WAIT_COMPLETE 1 -#define _IO_WAIT_RSP 2 - -/* IO COMMAND TYPE */ -#define _IOSZ_MASK_ (0x7F) -#define _IO_WRITE_ BIT(7) -#define _IO_FIXED_ BIT(8) -#define _IO_BURST_ BIT(9) -#define _IO_BYTE_ BIT(10) -#define _IO_HW_ BIT(11) -#define _IO_WORD_ BIT(12) -#define _IO_SYNC_ BIT(13) -#define _IO_CMDMASK_ (0x1F80) - - -/* - For prompt mode accessing, caller shall free io_req - Otherwise, io_handler will free io_req -*/ - - - -/* IO STATUS TYPE */ -#define _IO_ERR_ BIT(2) -#define _IO_SUCCESS_ BIT(1) -#define _IO_DONE_ BIT(0) - - -#define IO_RD32 (_IO_SYNC_ | _IO_WORD_) -#define IO_RD16 (_IO_SYNC_ | _IO_HW_) -#define IO_RD8 (_IO_SYNC_ | _IO_BYTE_) - -#define IO_RD32_ASYNC (_IO_WORD_) -#define IO_RD16_ASYNC (_IO_HW_) -#define IO_RD8_ASYNC (_IO_BYTE_) - -#define IO_WR32 (_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_) -#define IO_WR16 (_IO_WRITE_ | _IO_SYNC_ | _IO_HW_) -#define IO_WR8 (_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_) - -#define IO_WR32_ASYNC (_IO_WRITE_ | _IO_WORD_) -#define IO_WR16_ASYNC (_IO_WRITE_ | _IO_HW_) -#define IO_WR8_ASYNC (_IO_WRITE_ | _IO_BYTE_) - -/* - - Only Sync. burst accessing is provided. - -*/ - -#define IO_WR_BURST(x) (_IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | ( (x) & _IOSZ_MASK_)) -#define IO_RD_BURST(x) (_IO_SYNC_ | _IO_BURST_ | ( (x) & _IOSZ_MASK_)) - - - -/* below is for the intf_option bit defition... */ - -#define _INTF_ASYNC_ BIT(0) /* support async io */ - -struct intf_priv; - -struct io_req { - struct list_head list; - u32 addr; - volatile u32 val; - u32 command; - u32 status; - u8 *pbuf; - struct semaphore sema; - - void (*_async_io_callback)(struct rtw_adapter *padater, struct io_req *pio_req, u8 *cnxt); - u8 *cnxt; -}; - -struct reg_protocol_rd { - -#ifdef __LITTLE_ENDIAN - - /* DW1 */ - u32 NumOfTrans:4; - u32 Reserved1:4; - u32 Reserved2:24; - /* DW2 */ - u32 ByteCount:7; - u32 WriteEnable:1; /* 0:read, 1:write */ - u32 FixOrContinuous:1; /* 0:continuous, 1: Fix */ - u32 BurstMode:1; - u32 Byte1Access:1; - u32 Byte2Access:1; - u32 Byte4Access:1; - u32 Reserved3:3; - u32 Reserved4:16; - /* DW3 */ - u32 BusAddress; - /* DW4 */ - /* u32 Value; */ -#else - - -/* DW1 */ - u32 Reserved1 :4; - u32 NumOfTrans :4; - - u32 Reserved2 :24; - - /* DW2 */ - u32 WriteEnable : 1; - u32 ByteCount :7; - - - u32 Reserved3 : 3; - u32 Byte4Access : 1; - - u32 Byte2Access : 1; - u32 Byte1Access : 1; - u32 BurstMode :1 ; - u32 FixOrContinuous : 1; - - u32 Reserved4 : 16; - - /* DW3 */ - u32 BusAddress; - - /* DW4 */ - /* u32 Value; */ - -#endif - -}; - - -struct reg_protocol_wt { - - -#ifdef __LITTLE_ENDIAN - - /* DW1 */ - u32 NumOfTrans:4; - u32 Reserved1:4; - u32 Reserved2:24; - /* DW2 */ - u32 ByteCount:7; - u32 WriteEnable:1; /* 0:read, 1:write */ - u32 FixOrContinuous:1; /* 0:continuous, 1: Fix */ - u32 BurstMode:1; - u32 Byte1Access:1; - u32 Byte2Access:1; - u32 Byte4Access:1; - u32 Reserved3:3; - u32 Reserved4:16; - /* DW3 */ - u32 BusAddress; - /* DW4 */ - u32 Value; - -#else - /* DW1 */ - u32 Reserved1 :4; - u32 NumOfTrans :4; - - u32 Reserved2 :24; - - /* DW2 */ - u32 WriteEnable : 1; - u32 ByteCount :7; - - u32 Reserved3 : 3; - u32 Byte4Access : 1; - - u32 Byte2Access : 1; - u32 Byte1Access : 1; - u32 BurstMode :1 ; - u32 FixOrContinuous : 1; - - u32 Reserved4 : 16; - - /* DW3 */ - u32 BusAddress; - - /* DW4 */ - u32 Value; - -#endif - -}; - -#define PlatformEFIOWrite1Byte(_a, _b, _c) \ - rtl8723au_write8(_a, _b, _c) -#define PlatformEFIOWrite2Byte(_a, _b, _c) \ - rtl8723au_write16(_a, _b, _c) -#define PlatformEFIOWrite4Byte(_a, _b, _c) \ - rtl8723au_write32(_a, _b, _c) - -#define PlatformEFIORead1Byte(_a, _b) rtl8723au_read8(_a, _b) -#define PlatformEFIORead2Byte(_a, _b) rtl8723au_read16(_a, _b) -#define PlatformEFIORead4Byte(_a, _b) rtl8723au_read32(_a, _b) - -#endif /* _RTL8711_IO_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_mlme.h b/drivers/staging/rtl8723au/include/rtw_mlme.h deleted file mode 100644 index dbd3a5f5c523..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_mlme.h +++ /dev/null @@ -1,340 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - * - ******************************************************************************/ -#ifndef __RTW_MLME_H_ -#define __RTW_MLME_H_ - -#include -#include -#include -#include - -#define MAX_BSS_CNT 128 -#define MAX_JOIN_TIMEOUT 6500 - -/* Increase the scanning timeout because of increasing the SURVEY_TO value. */ - -#define SCANNING_TIMEOUT 8000 - -#define SCAN_INTERVAL (30) /* unit:2sec, 30*2 = 60sec */ - -#define SCANQUEUE_LIFETIME 20 /* unit:sec */ - -#define WIFI_NULL_STATE 0x00000000 - -#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state.*/ -#define WIFI_REASOC_STATE 0x00000002 -#define WIFI_SLEEP_STATE 0x00000004 -#define WIFI_STATION_STATE 0x00000008 - -#define WIFI_AP_STATE 0x00000010 -#define WIFI_ADHOC_STATE 0x00000020 -#define WIFI_ADHOC_MASTER_STATE 0x00000040 -#define WIFI_UNDER_LINKING 0x00000080 - -#define WIFI_UNDER_WPS 0x00000100 -#define WIFI_STA_ALIVE_CHK_STATE 0x00000400 -/* to indicate the station is under site surveying */ -#define WIFI_SITE_MONITOR 0x00000800 - -#define WIFI_MP_STATE 0x00010000 -#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in continuous tx background */ -#define WIFI_MP_CTX_ST 0x00040000 /* in continuous tx with single-tone */ -#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in continuous tx background due to out of skb */ -#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx */ -#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in continuous tx with carrier suppression */ -#define WIFI_MP_LPBK_STATE 0x00400000 - -#define _FW_UNDER_LINKING WIFI_UNDER_LINKING -#define _FW_LINKED WIFI_ASOC_STATE -#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR - - -enum dot11AuthAlgrthmNum { - dot11AuthAlgrthm_Open = 0, - dot11AuthAlgrthm_Shared, - dot11AuthAlgrthm_8021X, - dot11AuthAlgrthm_Auto, - dot11AuthAlgrthm_MaxNum -}; - -/* Scan type including active and passive scan. */ -enum rt_scan_type { - SCAN_PASSIVE, - SCAN_ACTIVE, - SCAN_MIX, -}; - -enum { - GHZ24_50 = 0, - GHZ_50, - GHZ_24, -}; - -/* - -there are several "locks" in mlme_priv, -since mlme_priv is a shared resource between many threads, -like ISR/Call-Back functions, the OID handlers, and even timer functions. - - -Each _queue has its own locks, already. -Other items are protected by mlme_priv.lock. - -To avoid possible dead lock, any thread trying to modifiying mlme_priv -SHALL not lock up more than one locks at a time! -*/ - -struct rt_link_detect { - u32 NumTxOkInPeriod; - u32 NumRxOkInPeriod; - u32 NumRxUnicastOkInPeriod; - bool bBusyTraffic; - bool bTxBusyTraffic; - bool bRxBusyTraffic; - bool bHigherBusyTraffic; /* For interrupt migration purpose. */ - bool bHigherBusyRxTraffic; /* We may disable Tx interrupt according as Rx traffic. */ - bool bHigherBusyTxTraffic; /* We may disable Tx interrupt according as Tx traffic. */ -}; - -struct mlme_priv { - spinlock_t lock; - int fw_state; - u8 bScanInProcess; - u8 to_join; /* flag */ - u8 to_roaming; /* roaming trying times */ - - struct rtw_adapter *nic_hdl; - - u8 not_indic_disco; - struct rtw_queue scanned_queue; - - struct cfg80211_ssid assoc_ssid; - u8 assoc_bssid[6]; - - struct wlan_network cur_network; - - /* uint wireless_mode; no used, remove it */ - - u32 scan_interval; - - struct timer_list assoc_timer; - - uint assoc_by_bssid; - uint assoc_by_rssi; - - struct timer_list scan_to_timer; - - struct timer_list set_scan_deny_timer; - atomic_t set_scan_deny; /* 0: allowed, 1: deny */ - - unsigned int qos_option; - - /* Number of non-HT AP/stations */ - int num_sta_no_ht; - - int num_FortyMHzIntolerant; - - struct ht_priv htpriv; - - struct rt_link_detect LinkDetectInfo; - struct timer_list dynamic_chk_timer; /* dynamic/periodic check timer */ - - u8 key_mask; /* use for ips to set wep key after ips_leave23a */ - u8 acm_mask; /* for wmm acm mask */ - u8 ChannelPlan; - enum rt_scan_type scan_mode; /* active: 1, passive: 0 */ - - u8 *wps_probe_req_ie; - u32 wps_probe_req_ie_len; - u8 *assoc_req; - u32 assoc_req_len; - u32 assoc_rsp_len; - u8 *assoc_rsp; - -#ifdef CONFIG_8723AU_AP_MODE - /* Number of associated Non-ERP stations (i.e., stations using 802.11b - * in 802.11g BSS) */ - int num_sta_non_erp; - - /* Number of associated stations that do not support Short Slot Time */ - int num_sta_no_short_slot_time; - - /* Number of associated stations that do not support Short Preamble */ - int num_sta_no_short_preamble; - - int olbc; /* Overlapping Legacy BSS Condition */ - - /* Number of HT associated stations that do not support greenfield */ - int num_sta_ht_no_gf; - - /* Number of associated non-HT stations */ - /* int num_sta_no_ht; */ - - /* Number of HT associated stations 20 MHz */ - int num_sta_ht_20mhz; - - /* Overlapping BSS information */ - int olbc_ht; - - u16 ht_op_mode; - - spinlock_t bcn_update_lock; - u8 update_bcn; - -#endif /* ifdef CONFIG_8723AU_AP_MODE */ -}; - -void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf); -void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf); -void rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf); -void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf); -void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf); -void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf); - -int event_thread(void *context); -void rtw23a_join_to_handler(unsigned long); - -void rtw_free_network_queue23a(struct rtw_adapter *adapter); -int rtw_init_mlme_priv23a(struct rtw_adapter *adapter); - -void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv); - -int rtw_do_join_adhoc(struct rtw_adapter *adapter); -int rtw_do_join_network(struct rtw_adapter *adapter, - struct wlan_network *candidate); -int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv); -int rtw_set_key23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv, int keyid, u8 set_tx); -int rtw_set_auth23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv); - -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; -} - -static inline bool check_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - if (pmlmepriv->fw_state & state) - return true; - - return false; -} - -static inline int get_fwstate(struct mlme_priv *pmlmepriv) -{ - return pmlmepriv->fw_state; -} - -/* - * No Limit on the calling context, - * therefore set it to be the critical section... - * - * ### NOTE:#### (!!!!) - * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock - */ -static inline void set_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - pmlmepriv->fw_state |= state; - /* FOR HW integration */ - if (_FW_UNDER_SURVEY == state) - pmlmepriv->bScanInProcess = true; -} - -static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, int state) -{ - pmlmepriv->fw_state &= ~state; - /* FOR HW integration */ - if (_FW_UNDER_SURVEY == state) - pmlmepriv->bScanInProcess = false; -} - -/* - * No Limit on the calling context, - * therefore set it to be the critical section... - */ -static inline void clr_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - spin_lock_bh(&pmlmepriv->lock); - if (check_fwstate(pmlmepriv, state)) - pmlmepriv->fw_state ^= state; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state) -{ - spin_lock_bh(&pmlmepriv->lock); - _clr_fwstate_(pmlmepriv, state); - spin_unlock_bh(&pmlmepriv->lock); -} - -void rtw_disconnect_hdl23a_under_linked(struct rtw_adapter *adapter, - struct sta_info *psta, u8 free_assoc); -void rtw_generate_random_ibss23a(u8 *pibss); -struct wlan_network *rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr); -struct wlan_network *rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue); - -void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, - int lock_scanned_queue); -void rtw_indicate_disconnect23a(struct rtw_adapter *adapter); -void rtw_indicate_connect23a(struct rtw_adapter *adapter); -void rtw_scan_abort23a(struct rtw_adapter *adapter); - -int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len); -int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len, uint initial_out_len); -void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter); - -void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter); - -void rtw_scan_timeout_handler23a(unsigned long data); - -void rtw_dynamic_check_timer_handler(unsigned long data); -bool rtw_is_scan_deny(struct rtw_adapter *adapter); -void rtw_clear_scan_deny(struct rtw_adapter *adapter); -void rtw_set_scan_deny_timer_hdl(unsigned long data); -void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms); - -void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv); - -void _rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv); - -struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp); - -int rtw_if_up23a(struct rtw_adapter *padapter); - -int rtw_linked_check(struct rtw_adapter *padapter); - -void rtw_joinbss_reset23a(struct rtw_adapter *padapter); - -bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint *pout_len); -void rtw_update_ht_cap23a(struct rtw_adapter *padapter, - u8 *pie, uint ie_len); -void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); - -bool rtw_is_same_ibss23a(struct rtw_adapter *adapter, - struct wlan_network *pnetwork); -int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst); - -void rtw23a_roaming(struct rtw_adapter *adapter, - struct wlan_network *tgt_network); -void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming); - -#endif /* __RTL871X_MLME_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h deleted file mode 100644 index 0e7d3da91471..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h +++ /dev/null @@ -1,683 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_MLME_EXT_H_ -#define __RTW_MLME_EXT_H_ - -#include -#include -#include - - -/* Commented by Albert 20101105 */ -/* Increase the SURVEY_TO value from 100 to 150 ( 100ms to 150ms ) */ -/* The Realtek 8188CE SoftAP will spend around 100ms to send the probe response after receiving the probe request. */ -/* So, this driver tried to extend the dwell time for each scanning channel. */ -/* This will increase the chance to receive the probe response from SoftAP. */ - -#define SURVEY_TO (100) -#define REAUTH_TO (300) /* 50) */ -#define REASSOC_TO (300) /* 50) */ -/* define DISCONNECT_TO (3000) */ -#define ADDBA_TO (2000) - -#define LINKED_TO (1) /* unit:2 sec, 1x2=2 sec */ - -#define REAUTH_LIMIT (4) -#define REASSOC_LIMIT (4) -#define READDBA_LIMIT (2) - -#define ROAMING_LIMIT 8 - -#define DYNAMIC_FUNC_DISABLE (0x0) - -/* ====== enum odm_ability ======== */ -/* BB ODM section BIT 0-15 */ -#define DYNAMIC_BB_DIG BIT(0) -#define DYNAMIC_BB_RA_MASK BIT(1) -#define DYNAMIC_BB_DYNAMIC_TXPWR BIT(2) -#define DYNAMIC_BB_BB_FA_CNT BIT(3) - -#define DYNAMIC_BB_RSSI_MONITOR BIT(4) -#define DYNAMIC_BB_CCK_PD BIT(5) -#define DYNAMIC_BB_ANT_DIV BIT(6) -#define DYNAMIC_BB_PWR_SAVE BIT(7) -#define DYNAMIC_BB_PWR_TRAIN BIT(8) -#define DYNAMIC_BB_RATE_ADAPTIVE BIT(9) -#define DYNAMIC_BB_PATH_DIV BIT(10) -#define DYNAMIC_BB_PSD BIT(11) - -/* MAC DM section BIT 16-23 */ -#define DYNAMIC_MAC_struct edca_turboURBO BIT(16) -#define DYNAMIC_MAC_EARLY_MODE BIT(17) - -/* RF ODM section BIT 24-31 */ -#define DYNAMIC_RF_TX_PWR_TRACK BIT(24) -#define DYNAMIC_RF_RX_GAIN_TRACK BIT(25) -#define DYNAMIC_RF_CALIBRATION BIT(26) - -#define DYNAMIC_ALL_FUNC_ENABLE 0xFFFFFFF - -#define _HW_STATE_NOLINK_ 0x00 -#define _HW_STATE_ADHOC_ 0x01 -#define _HW_STATE_STATION_ 0x02 -#define _HW_STATE_AP_ 0x03 - - -#define _1M_RATE_ 0 -#define _2M_RATE_ 1 -#define _5M_RATE_ 2 -#define _11M_RATE_ 3 -#define _6M_RATE_ 4 -#define _9M_RATE_ 5 -#define _12M_RATE_ 6 -#define _18M_RATE_ 7 -#define _24M_RATE_ 8 -#define _36M_RATE_ 9 -#define _48M_RATE_ 10 -#define _54M_RATE_ 11 - - -extern unsigned char WMM_OUI23A[]; -extern unsigned char WPS_OUI23A[]; -extern unsigned char WFD_OUI23A[]; -extern unsigned char P2P_OUI23A[]; - -extern unsigned char WMM_INFO_OUI23A[]; -extern unsigned char WMM_PARA_OUI23A[]; - - -/* */ -/* Channel Plan Type. */ -/* Note: */ -/* We just add new channel plan when the new channel plan is different from any of the following */ -/* channel plan. */ -/* If you just want to customize the actions(scan period or join actions) about one of the channel plan, */ -/* customize them in struct rt_channel_info in the RT_CHANNEL_LIST. */ -/* */ -enum { /* _RT_CHANNEL_DOMAIN */ - /* old channel plan mapping ===== */ - RT_CHANNEL_DOMAIN_FCC = 0x00, - RT_CHANNEL_DOMAIN_IC = 0x01, - RT_CHANNEL_DOMAIN_ETSI = 0x02, - RT_CHANNEL_DOMAIN_SPAIN = 0x03, - RT_CHANNEL_DOMAIN_FRANCE = 0x04, - RT_CHANNEL_DOMAIN_MKK = 0x05, - RT_CHANNEL_DOMAIN_MKK1 = 0x06, - RT_CHANNEL_DOMAIN_ISRAEL = 0x07, - RT_CHANNEL_DOMAIN_TELEC = 0x08, - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 0x09, - RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 0x0A, - RT_CHANNEL_DOMAIN_TAIWAN = 0x0B, - RT_CHANNEL_DOMAIN_CHINA = 0x0C, - RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO = 0x0D, - RT_CHANNEL_DOMAIN_KOREA = 0x0E, - RT_CHANNEL_DOMAIN_TURKEY = 0x0F, - RT_CHANNEL_DOMAIN_JAPAN = 0x10, - RT_CHANNEL_DOMAIN_FCC_NO_DFS = 0x11, - RT_CHANNEL_DOMAIN_JAPAN_NO_DFS = 0x12, - RT_CHANNEL_DOMAIN_WORLD_WIDE_5G = 0x13, - RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS = 0x14, - - /* new channel plan mapping, (2GDOMAIN_5GDOMAIN) ===== */ - RT_CHANNEL_DOMAIN_WORLD_NULL = 0x20, - RT_CHANNEL_DOMAIN_ETSI1_NULL = 0x21, - RT_CHANNEL_DOMAIN_FCC1_NULL = 0x22, - RT_CHANNEL_DOMAIN_MKK1_NULL = 0x23, - RT_CHANNEL_DOMAIN_ETSI2_NULL = 0x24, - RT_CHANNEL_DOMAIN_FCC1_FCC1 = 0x25, - RT_CHANNEL_DOMAIN_WORLD_ETSI1 = 0x26, - RT_CHANNEL_DOMAIN_MKK1_MKK1 = 0x27, - RT_CHANNEL_DOMAIN_WORLD_KCC1 = 0x28, - RT_CHANNEL_DOMAIN_WORLD_FCC2 = 0x29, - RT_CHANNEL_DOMAIN_WORLD_FCC3 = 0x30, - RT_CHANNEL_DOMAIN_WORLD_FCC4 = 0x31, - RT_CHANNEL_DOMAIN_WORLD_FCC5 = 0x32, - RT_CHANNEL_DOMAIN_WORLD_FCC6 = 0x33, - RT_CHANNEL_DOMAIN_FCC1_FCC7 = 0x34, - RT_CHANNEL_DOMAIN_WORLD_ETSI2 = 0x35, - RT_CHANNEL_DOMAIN_WORLD_ETSI3 = 0x36, - RT_CHANNEL_DOMAIN_MKK1_MKK2 = 0x37, - RT_CHANNEL_DOMAIN_MKK1_MKK3 = 0x38, - RT_CHANNEL_DOMAIN_FCC1_NCC1 = 0x39, - RT_CHANNEL_DOMAIN_FCC1_NCC2 = 0x40, - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G = 0x41, - /* Add new channel plan above this line=============== */ - RT_CHANNEL_DOMAIN_MAX, - RT_CHANNEL_DOMAIN_REALTEK_DEFINE = 0x7F, -}; - -enum { /* _RT_CHANNEL_DOMAIN_2G */ - RT_CHANNEL_DOMAIN_2G_WORLD = 0x00, /* Worldwird 13 */ - RT_CHANNEL_DOMAIN_2G_ETSI1 = 0x01, /* Europe */ - RT_CHANNEL_DOMAIN_2G_FCC1 = 0x02, /* US */ - RT_CHANNEL_DOMAIN_2G_MKK1 = 0x03, /* Japan */ - RT_CHANNEL_DOMAIN_2G_ETSI2 = 0x04, /* France */ - RT_CHANNEL_DOMAIN_2G_NULL = 0x05, - /* Add new channel plan above this line=============== */ - RT_CHANNEL_DOMAIN_2G_MAX, -}; - -enum { /* _RT_CHANNEL_DOMAIN_5G */ - RT_CHANNEL_DOMAIN_5G_NULL = 0x00, - RT_CHANNEL_DOMAIN_5G_ETSI1 = 0x01, /* Europe */ - RT_CHANNEL_DOMAIN_5G_ETSI2 = 0x02, /* Australia, New Zealand */ - RT_CHANNEL_DOMAIN_5G_ETSI3 = 0x03, /* Russia */ - RT_CHANNEL_DOMAIN_5G_FCC1 = 0x04, /* US */ - RT_CHANNEL_DOMAIN_5G_FCC2 = 0x05, /* FCC o/w DFS Channels */ - RT_CHANNEL_DOMAIN_5G_FCC3 = 0x06, /* India, Mexico */ - RT_CHANNEL_DOMAIN_5G_FCC4 = 0x07, /* Venezuela */ - RT_CHANNEL_DOMAIN_5G_FCC5 = 0x08, /* China */ - RT_CHANNEL_DOMAIN_5G_FCC6 = 0x09, /* Israel */ - RT_CHANNEL_DOMAIN_5G_FCC7_IC1 = 0x0A, /* US, Canada */ - RT_CHANNEL_DOMAIN_5G_KCC1 = 0x0B, /* Korea */ - RT_CHANNEL_DOMAIN_5G_MKK1 = 0x0C, /* Japan */ - RT_CHANNEL_DOMAIN_5G_MKK2 = 0x0D, /* Japan (W52, W53) */ - RT_CHANNEL_DOMAIN_5G_MKK3 = 0x0E, /* Japan (W56) */ - RT_CHANNEL_DOMAIN_5G_NCC1 = 0x0F, /* Taiwan */ - RT_CHANNEL_DOMAIN_5G_NCC2 = 0x10, /* Taiwan o/w DFS */ - /* Add new channel plan above this line=============== */ - /* Driver Self Defined ===== */ - RT_CHANNEL_DOMAIN_5G_FCC = 0x11, - RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS = 0x12, - RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS = 0x13, - RT_CHANNEL_DOMAIN_5G_MAX, -}; - -#define rtw_is_channel_plan_valid(chplan) (chplansurvey_timer, jiffies + msecs_to_jiffies(ms)); - -#define set_link_timer(mlmeext, ms) \ - /*DBG_8723A("%s set_link_timer(%p, %d)\n", __func__, (mlmeext), (ms));*/ \ - mod_timer(&mlmeext->link_timer, jiffies + msecs_to_jiffies(ms)); - -int cckrates_included23a(unsigned char *rate, int ratelen); -int cckratesonly_included23a(unsigned char *rate, int ratelen); - -void process_addba_req23a(struct rtw_adapter *padapter, u8 *paddba_req, u8 *addr); - -void correct_TSF23a(struct rtw_adapter *padapter, struct mlme_ext_priv *pmlmeext); - -struct cmd_hdl { - uint parmsize; - int (*h2cfuns)(struct rtw_adapter *padapter, const u8 *pbuf); -}; - - -int read_macreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int write_macreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int read_bbreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int write_bbreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int read_rfreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int write_rfreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); - - -int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_assocsta_hdl(struct rtw_adapter *padapter, const u8 *pbuf); -int del_assocsta_hdl(struct rtw_adapter *padapter, const u8 *pbuf); -int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); - -int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); /* Kurt: Handling DFS channel switch announcement ie. */ -int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); - -#define GEN_DRV_CMD_HANDLER(size, cmd) {size, &cmd ## _hdl23a}, -#define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd}, - -struct C2HEvent_Header { -#ifdef __LITTLE_ENDIAN - - unsigned int len:16; - unsigned int ID:8; - unsigned int seq:8; - -#elif defined(__BIG_ENDIAN) - - unsigned int seq:8; - unsigned int ID:8; - unsigned int len:16; - -#else - -# error "Must be LITTLE or BIG Endian" - -#endif - - unsigned int rsvd; -}; - -enum rtw_c2h_event { - GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ - GEN_EVT_CODE(_Read_BBREG), - GEN_EVT_CODE(_Read_RFREG), - GEN_EVT_CODE(_Read_EEPROM), - GEN_EVT_CODE(_Read_EFUSE), - GEN_EVT_CODE(_Read_CAM), /*5*/ - GEN_EVT_CODE(_Get_BasicRate), - GEN_EVT_CODE(_Get_DataRate), - GEN_EVT_CODE(_Survey), /*8*/ - GEN_EVT_CODE(_SurveyDone), /*9*/ - - GEN_EVT_CODE(_JoinBss) , /*10*/ - GEN_EVT_CODE(_AddSTA), - GEN_EVT_CODE(_DelSTA), - GEN_EVT_CODE(_AtimDone) , - GEN_EVT_CODE(_TX_Report), - GEN_EVT_CODE(_CCX_Report), /*15*/ - GEN_EVT_CODE(_DTM_Report), - GEN_EVT_CODE(_TX_Rate_Statistics), - GEN_EVT_CODE(_C2HLBK), - GEN_EVT_CODE(_FWDBG), - GEN_EVT_CODE(_C2HFEEDBACK), /*20*/ - GEN_EVT_CODE(_ADDBA), - GEN_EVT_CODE(_C2HBCN), - GEN_EVT_CODE(_ReportPwrState), /* filen: only for PCIE, USB */ - GEN_EVT_CODE(_CloseRF), /* filen: only for PCIE, work around ASPM */ - MAX_C2HEVT -}; - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_pwrctrl.h b/drivers/staging/rtl8723au/include/rtw_pwrctrl.h deleted file mode 100644 index 599fed9b365d..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_pwrctrl.h +++ /dev/null @@ -1,241 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_PWRCTRL_H_ -#define __RTW_PWRCTRL_H_ - -#include -#include - -#define FW_PWR0 0 -#define FW_PWR1 1 -#define FW_PWR2 2 -#define FW_PWR3 3 - - -#define HW_PWR0 7 -#define HW_PWR1 6 -#define HW_PWR2 2 -#define HW_PWR3 0 -#define HW_PWR4 8 - -#define FW_PWRMSK 0x7 - - -#define XMIT_ALIVE BIT(0) -#define RECV_ALIVE BIT(1) -#define CMD_ALIVE BIT(2) -#define EVT_ALIVE BIT(3) - -enum Power_Mgnt { - PS_MODE_ACTIVE = 0, - PS_MODE_MIN, - PS_MODE_MAX, - PS_MODE_DTIM, - PS_MODE_VOIP, - PS_MODE_UAPSD_WMM, - PS_MODE_UAPSD, - PS_MODE_IBSS, - PS_MODE_WWLAN, - PM_Radio_Off, - PM_Card_Disable, - PS_MODE_NUM -}; - - -/* BIT[2:0] = HW state - * BIT[3] = Protocol PS state, 0: active, 1: sleep state - * BIT[4] = sub-state - */ - -#define PS_DPS BIT(0) -#define PS_LCLK (PS_DPS) -#define PS_RF_OFF BIT(1) -#define PS_ALL_ON BIT(2) -#define PS_ST_ACTIVE BIT(3) - -#define PS_ISR_ENABLE BIT(4) -#define PS_IMR_ENABLE BIT(5) -#define PS_ACK BIT(6) -#define PS_TOGGLE BIT(7) - -#define PS_STATE_MASK (0x0F) -#define PS_STATE_HW_MASK (0x07) -#define PS_SEQ_MASK (0xc0) - -#define PS_STATE(x) (PS_STATE_MASK & (x)) -#define PS_STATE_HW(x) (PS_STATE_HW_MASK & (x)) -#define PS_SEQ(x) (PS_SEQ_MASK & (x)) - -#define PS_STATE_S0 (PS_DPS) -#define PS_STATE_S1 (PS_LCLK) -#define PS_STATE_S2 (PS_RF_OFF) -#define PS_STATE_S3 (PS_ALL_ON) -#define PS_STATE_S4 ((PS_ST_ACTIVE) | (PS_ALL_ON)) - - -#define PS_IS_RF_ON(x) ((x) & (PS_ALL_ON)) -#define PS_IS_ACTIVE(x) ((x) & (PS_ST_ACTIVE)) -#define CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) - - -struct reportpwrstate_parm { - unsigned char mode; - unsigned char state; /* the CPWM value */ - unsigned short rsvd; -}; - -#define LPS_DELAY_TIME (1*HZ) /* 1 sec */ - -#define EXE_PWR_NONE 0x01 -#define EXE_PWR_IPS 0x02 -#define EXE_PWR_LPS 0x04 - -/* RF state. */ -enum rt_rf_power_state { - rf_on, /* RF is on after RFSleep or RFOff */ - rf_sleep, /* 802.11 Power Save mode */ - rf_off, /* HW/SW Radio OFF or Inactive Power Save */ - /* Add the new RF state above this line===== */ - rf_max -}; - -/* RF Off Level for IPS or HW/SW radio off */ -#define RT_RF_OFF_LEVL_ASPM BIT(0) /* PCI ASPM */ -#define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /* PCI clock request */ -#define RT_RF_OFF_LEVL_PCI_D3 BIT(2) /* PCI D3 mode */ -/* NIC halt, re-init hw params */ -#define RT_RF_OFF_LEVL_HALT_NIC BIT(3) -/* FW free, re-download the FW */ -#define RT_RF_OFF_LEVL_FREE_FW BIT(4) -#define RT_RF_OFF_LEVL_FW_32K BIT(5) /* FW in 32k */ -/* Always enable ASPM and Clock Req in initialization. */ -#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT(6) -/* When LPS is on, disable 2R if no packet is received or transmittd. */ -#define RT_RF_LPS_DISALBE_2R BIT(30) -#define RT_RF_LPS_LEVEL_ASPM BIT(31) /* LPS with ASPM */ - -#define RT_IN_PS_LEVEL(ppsc, _PS_FLAG) \ - ((ppsc->cur_ps_level & _PS_FLAG) ? true : false) -#define RT_CLEAR_PS_LEVEL(ppsc, _PS_FLAG) \ - (ppsc->cur_ps_level &= (~(_PS_FLAG))) -#define RT_SET_PS_LEVEL(ppsc, _PS_FLAG) \ - (ppsc->cur_ps_level |= _PS_FLAG) - - -enum { - PSBBREG_RF0 = 0, - PSBBREG_RF1, - PSBBREG_RF2, - PSBBREG_AFE0, - PSBBREG_TOTALCNT -}; - -enum { /* for ips_mode */ - IPS_NONE = 0, - IPS_NORMAL, - IPS_LEVEL_2, -}; - -struct pwrctrl_priv { - struct semaphore lock; - volatile u8 rpwm; /* requested power state for fw */ - volatile u8 cpwm; /* fw current power state. updated when 1. - * read from HCPWM 2. driver lowers power level - */ - volatile u8 tog; /* toggling */ - - u8 pwr_mode; - u8 smart_ps; - u8 bcn_ant_mode; - - u8 bpower_saving; - - u8 reg_rfoff; - u32 rfoff_reason; - - /* RF OFF Level */ - u32 cur_ps_level; - u32 reg_rfps_level; - - uint ips_enter23a_cnts; - uint ips_leave23a_cnts; - - u8 ips_mode; - u8 ips_mode_req; /* used to accept the mode setting request */ - uint bips_processing; - unsigned long ips_deny_time; /* deny IPS when system time is smaller */ - u8 ps_processing; /* used to mark whether in rtw_ps_processor23a */ - - u8 bLeisurePs; - u8 LpsIdleCount; - u8 power_mgnt; - u8 bFwCurrentInPSMode; - unsigned long DelayLPSLastTimeStamp; - u8 btcoex_rfon; - - u8 bInSuspend; -#ifdef CONFIG_8723AU_BT_COEXIST - u8 bAutoResume; - u8 autopm_cnt; -#endif - u8 bSupportRemoteWakeup; - struct timer_list pwr_state_check_timer; - int pwr_state_check_interval; - u8 pwr_state_check_cnts; - - enum rt_rf_power_state rf_pwrstate;/* cur power state */ - enum rt_rf_power_state change_rfpwrstate; - - u8 bkeepfwalive; - unsigned long PS_BBRegBackup[PSBBREG_TOTALCNT]; -}; - -#define RTW_PWR_STATE_CHK_INTERVAL 2000 - -#define _rtw_set_pwr_state_check_timer(pwrctrlpriv, ms) \ - (mod_timer(&pwrctrlpriv->pwr_state_check_timer, jiffies + \ - msecs_to_jiffies(ms))) - -#define rtw_set_pwr_state_check_timer(pwrctrlpriv) \ - (_rtw_set_pwr_state_check_timer((pwrctrlpriv), \ - (pwrctrlpriv)->pwr_state_check_interval)) - -void rtw_init_pwrctrl_priv23a(struct rtw_adapter *adapter); -void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter); - -void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, - u8 smart_ps, u8 bcn_ant_mode); -void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 val8); -void LeaveAllPowerSaveMode23a(struct rtw_adapter *adapter); -void ips_enter23a(struct rtw_adapter *padapter); -int ips_leave23a(struct rtw_adapter *padapter); - -void rtw_ps_processor23a(struct rtw_adapter *padapter); - -enum rt_rf_power_state RfOnOffDetect23a(struct rtw_adapter *adapter); - -s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms); -void LPS_Enter23a(struct rtw_adapter *padapter); -void LPS_Leave23a(struct rtw_adapter *padapter); - -void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms); -int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms, - const char *caller); -#define rtw_pwr_wakeup(adapter) _rtw_pwr_wakeup23a(adapter, \ - RTW_PWR_STATE_CHK_INTERVAL, __func__) -int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode); -int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode); - -#endif /* __RTL871X_PWRCTRL_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_recv.h b/drivers/staging/rtl8723au/include/rtw_recv.h deleted file mode 100644 index 85a5edb450e3..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_recv.h +++ /dev/null @@ -1,305 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_RECV_H_ -#define _RTW_RECV_H_ - -#include -#include -#include - -#define NR_RECVFRAME 256 - -#define MAX_RXFRAME_CNT 512 -#define MAX_RX_NUMBLKS (32) -#define RECVFRAME_HDR_ALIGN 128 - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define MAX_SUBFRAME_COUNT 64 - -/* for Rx reordering buffer control */ -struct recv_reorder_ctrl { - struct rtw_adapter *padapter; - u8 enable; - u16 indicate_seq;/* wstart_b, init_value=0xffff */ - u16 wend_b; - u8 wsize_b; - struct rtw_queue pending_recvframe_queue; - struct timer_list reordering_ctrl_timer; -}; - -struct stainfo_rxcache { - u16 tid_rxseq[16]; -/* - unsigned short tid0_rxseq; - unsigned short tid1_rxseq; - unsigned short tid2_rxseq; - unsigned short tid3_rxseq; - unsigned short tid4_rxseq; - unsigned short tid5_rxseq; - unsigned short tid6_rxseq; - unsigned short tid7_rxseq; - unsigned short tid8_rxseq; - unsigned short tid9_rxseq; - unsigned short tid10_rxseq; - unsigned short tid11_rxseq; - unsigned short tid12_rxseq; - unsigned short tid13_rxseq; - unsigned short tid14_rxseq; - unsigned short tid15_rxseq; -*/ -}; - -struct smooth_rssi_data { - u32 elements[100]; /* array to store values */ - u32 index; /* index to current array to store */ - u32 total_num; /* num of valid elements */ - u32 total_val; /* sum of valid elements */ -}; - -struct signal_stat { - u8 update_req; /* used to indicate */ - u8 avg_val; /* avg of valid elements */ - u32 total_num; /* num of valid elements */ - u32 total_val; /* sum of valid elements */ -}; - -struct phy_info { - u8 RxPWDBAll; - u8 SignalQuality; /* in 0-100 index. */ - u8 RxMIMOSignalQuality[RF_PATH_MAX]; /* EVM */ - u8 RxMIMOSignalStrength[RF_PATH_MAX];/* 0~100 */ - s8 RxPower; /* in dBm Translate from PWdB */ - /* Real power in dBm for this packet, no beautification and aggregation. - * Keep this raw info to be used for the other procedures. - */ - s8 RecvSignalPower; - u8 BTRxRSSIPercentage; - u8 SignalStrength; /* in 0-100 index. */ - u8 RxPwr[RF_PATH_MAX];/* per-path's pwdb */ - u8 RxSNR[RF_PATH_MAX];/* per-path's SNR */ -}; - - -struct rx_pkt_attrib { - u16 pkt_len; - u8 physt; - u8 drvinfo_sz; - u8 shift_sz; - u8 hdrlen; /* the WLAN Header Len */ - u8 amsdu; - u8 qos; - u8 priority; - u8 pw_save; - u8 mdata; - u16 seq_num; - u8 frag_num; - u8 mfrag; - u8 order; - u8 privacy; /* in frame_ctrl field */ - u8 bdecrypted; - /* when 0 indicate no encrypt. when non-zero, indicate the algorith */ - u32 encrypt; - u8 iv_len; - u8 icv_len; - u8 crc_err; - u8 icv_err; - - u16 eth_type; - - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 ta[ETH_ALEN]; - u8 ra[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - - u8 ack_policy; - - u8 tcpchk_valid; /* 0: invalid, 1: valid */ - u8 ip_chkrpt; /* 0: incorrect, 1: correct */ - u8 tcp_chkrpt; /* 0: incorrect, 1: correct */ - u8 key_index; - - u8 mcs_rate; - u8 rxht; - u8 sgi; - u8 pkt_rpt_type; - u32 MacIDValidEntry[2]; /* 64 bits present 64 entry. */ - struct phy_info phy_info; -}; - -/* These definition is used for Rx packet reordering. */ -#define SN_LESS(a, b) (((a-b) & 0x800) != 0) -#define SN_EQUAL(a, b) (a == b) -#define REORDER_WAIT_TIME (50) /* (ms) */ - -#define RECVBUFF_ALIGN_SZ 8 - -#define RXDESC_SIZE 24 -#define RXDESC_OFFSET RXDESC_SIZE - -struct recv_stat { - __le32 rxdw0; - __le32 rxdw1; - __le32 rxdw2; - __le32 rxdw3; - __le32 rxdw4; - __le32 rxdw5; -}; - -/* accesser of recv_priv: rtw_recv_entry23a(dispatch / passive level); \ - * recv_thread(passive) ; returnpkt(dispatch) ; halt(passive) ; - * - * using enter_critical section to protect - */ -struct recv_priv { - spinlock_t lock; - - struct rtw_queue free_recv_queue; - struct rtw_queue recv_pending_queue; - struct rtw_queue uc_swdec_pending_queue; - - int free_recvframe_cnt; - - struct rtw_adapter *adapter; - - u32 bIsAnyNonBEPkts; - u64 rx_bytes; - u64 rx_pkts; - u64 rx_drop; - u64 last_rx_bytes; - - uint rx_icv_err; - uint rx_largepacket_crcerr; - uint rx_smallpacket_crcerr; - uint rx_middlepacket_crcerr; - - /* u8 *pallocated_urb_buf; */ - u8 rx_pending_cnt; - - struct urb *int_in_urb; - - u8 *int_in_buf; - - struct tasklet_struct irq_prepare_beacon_tasklet; - struct tasklet_struct recv_tasklet; - struct sk_buff_head free_recv_skb_queue; - struct sk_buff_head rx_skb_queue; - u8 *precv_buf; - - /* For display the phy informatiom */ - s8 rxpwdb; - u8 signal_strength; - u8 signal_qual; - u8 noise; - int RxSNRdB[2]; - s8 RxRssi[2]; - int FalseAlmCnt_all; - - struct timer_list signal_stat_timer; - u32 signal_stat_sampling_interval; - /* u32 signal_stat_converging_constant; */ - struct signal_stat signal_qual_data; - struct signal_stat signal_strength_data; -}; - -#define rtw_set_signal_stat_timer(recvpriv) \ - mod_timer(&(recvpriv)->signal_stat_timer, jiffies + \ - msecs_to_jiffies((recvpriv)->signal_stat_sampling_interval)) - -struct sta_recv_priv { - spinlock_t lock; - int option; - - /* struct rtw_queue blk_strms[MAX_RX_NUMBLKS]; */ - struct rtw_queue defrag_q; /* keeping the fragment frame until defrag */ - - struct stainfo_rxcache rxcache; - - /* uint sta_rx_bytes; */ - /* uint sta_rx_pkts; */ - /* uint sta_rx_fail; */ - -}; - - -struct recv_buf { - struct list_head list; - - struct rtw_adapter *adapter; - - struct urb *purb; - struct sk_buff *pskb; -}; - -/* head -----> - * - * data -----> - * - * payload - * - * tail -----> - * - * end -----> - * - * len = (unsigned int )(tail - data); - * - */ -struct recv_frame { - struct list_head list; - struct sk_buff *pkt; - - struct rtw_adapter *adapter; - - struct rx_pkt_attrib attrib; - - struct sta_info *psta; - - /* for A-MPDU Rx reordering buffer control */ - struct recv_reorder_ctrl *preorder_ctrl; -}; - -/* get a free recv_frame from pfree_recv_queue */ -struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue); -int rtw_free_recvframe23a(struct recv_frame *precvframe); - -int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue); - -u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter); - -struct recv_buf *rtw_dequeue_recvbuf23a(struct rtw_queue *queue); - -void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext); - -static inline s32 translate_percentage_to_dbm(u32 SignalStrengthIndex) -{ - s32 SignalPower; /* in dBm. */ - - /* Translate to dBm (x=0.5y-95). */ - SignalPower = (s32)((SignalStrengthIndex + 1) >> 1); - SignalPower -= 95; - - return SignalPower; -} - - -struct sta_info; - -void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv); - -void mgt_dispatcher23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_rf.h b/drivers/staging/rtl8723au/include/rtw_rf.h deleted file mode 100644 index a7de714137b8..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_rf.h +++ /dev/null @@ -1,102 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_RF_H_ -#define __RTW_RF_H_ - -#include - -#define OFDM_PHY 1 -#define MIXED_PHY 2 -#define CCK_PHY 3 - -#define NumRates (13) - -/* slot time for 11g */ -#define SHORT_SLOT_TIME 9 -#define NON_SHORT_SLOT_TIME 20 - -/* We now define the max channels in each channel plan. */ -#define MAX_CHANNEL_NUM_2G 14 -#define MAX_CHANNEL_NUM_5G 24 -#define MAX_CHANNEL_NUM 38/* 14+24 */ - -/* define NUM_REGULATORYS 21 */ -#define NUM_REGULATORYS 1 - -/* Country codes */ -#define USA 0x555320 -#define EUROPE 0x1 /* temp, should be provided later */ -#define JAPAN 0x2 /* temp, should be provided later */ - -struct regulatory_class { - u32 starting_freq; /* MHz, */ - u8 channel_set[MAX_CHANNEL_NUM]; - u8 channel_cck_power[MAX_CHANNEL_NUM];/* dbm */ - u8 channel_ofdm_power[MAX_CHANNEL_NUM];/* dbm */ - u8 txpower_limit; /* dbm */ - u8 channel_spacing; /* MHz */ - u8 modem; -}; - -enum { - cESS = 0x0001, - cIBSS = 0x0002, - cPollable = 0x0004, - cPollReq = 0x0008, - cPrivacy = 0x0010, - cShortPreamble = 0x0020, - cPBCC = 0x0040, - cChannelAgility = 0x0080, - cSpectrumMgnt = 0x0100, - cQos = 0x0200, /* For HCCA, use with CF-Pollable and CF-PollReq */ - cShortSlotTime = 0x0400, - cAPSD = 0x0800, - cRM = 0x1000, /* RRM (Radio Request Measurement) */ - cDSSS_OFDM = 0x2000, - cDelayedBA = 0x4000, - cImmediateBA = 0x8000, -}; - -enum { - PREAMBLE_LONG = 1, - PREAMBLE_AUTO = 2, - PREAMBLE_SHORT = 3, -}; - -/* Bandwidth Offset */ -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -/* Represent Channel Width in HT Capabilities */ -enum ht_channel_width { - HT_CHANNEL_WIDTH_20 = 0, - HT_CHANNEL_WIDTH_40 = 1, - HT_CHANNEL_WIDTH_80 = 2, - HT_CHANNEL_WIDTH_160 = 3, - HT_CHANNEL_WIDTH_10 = 4, -}; - -/* 2007/11/15 MH Define different RF type. */ -enum { - RF_1T2R = 0, - RF_2T4R = 1, - RF_2T2R = 2, - RF_1T1R = 3, - RF_2T2R_GREEN = 4, - RF_819X_MAX_TYPE = 5, -}; - -#endif /* _RTL8711_RF_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_security.h b/drivers/staging/rtl8723au/include/rtw_security.h deleted file mode 100644 index 624a9d788e45..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_security.h +++ /dev/null @@ -1,331 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_SECURITY_H_ -#define __RTW_SECURITY_H_ - -#include -#include -#include - - -#define is_wep_enc(alg) (alg == WLAN_CIPHER_SUITE_WEP40 || \ - alg == WLAN_CIPHER_SUITE_WEP104) - -#define SHA256_MAC_LEN 32 -#define AES_BLOCK_SIZE 16 -#define AES_PRIV_SIZE (4 * 44) - -enum ENCRYP_PROTOCOL { - ENCRYP_PROTOCOL_OPENSYS, /* open system */ - ENCRYP_PROTOCOL_WEP, /* WEP */ - ENCRYP_PROTOCOL_WPA, /* WPA */ - ENCRYP_PROTOCOL_WPA2, /* WPA2 */ - ENCRYP_PROTOCOL_MAX -}; - -#ifndef Ndis802_11AuthModeWPA2 -#define Ndis802_11AuthModeWPA2 (Ndis802_11AuthModeWPANone + 1) -#endif - -#ifndef Ndis802_11AuthModeWPA2PSK -#define Ndis802_11AuthModeWPA2PSK (Ndis802_11AuthModeWPANone + 2) -#endif - -union pn48 { - u64 val; - -#ifdef __LITTLE_ENDIAN - -struct { - u8 TSC0; - u8 TSC1; - u8 TSC2; - u8 TSC3; - u8 TSC4; - u8 TSC5; - u8 TSC6; - u8 TSC7; -} _byte_; - -#elif defined(__BIG_ENDIAN) - -struct { - u8 TSC7; - u8 TSC6; - u8 TSC5; - u8 TSC4; - u8 TSC3; - u8 TSC2; - u8 TSC1; - u8 TSC0; -} _byte_; -#else -#error Need BIG or LITTLE endian - -#endif - -}; - -union Keytype { - u8 skey[16]; - u32 lkey[4]; -}; - -struct rtw_wep_key { - u8 key[WLAN_KEY_LEN_WEP104 + 1]; /* 14 */ - u16 keylen; -}; - -struct rt_pmkid_list { - u8 bUsed; - u8 Bssid[6]; - u8 PMKID[16]; - u8 SsidBuf[33]; - u8 *ssid_octet; - u16 ssid_length; -}; - -struct security_priv { - u32 dot11AuthAlgrthm; /* 802.11 auth, could be open, shared, - * 8021x and authswitch */ - u32 dot11PrivacyAlgrthm; /* This specifies the privacy for - * shared auth. algorithm. - */ - /* WEP */ - u32 dot11PrivacyKeyIndex; /* this is only valid for legendary - * wep, 0~3 for key id. (tx key index) - */ - struct rtw_wep_key wep_key[NUM_WEP_KEYS]; - - u32 dot118021XGrpPrivacy; /* specify the privacy algthm. - * used for Grp key - */ - u32 dot118021XGrpKeyid; /* key id used for Grp Key - * (tx key index) - */ - union Keytype dot118021XGrpKey[4];/* 802.1x Grp Key, inx0 and inx1 */ - union Keytype dot118021XGrptxmickey[4]; - union Keytype dot118021XGrprxmickey[4]; - union pn48 dot11Grptxpn; /* PN48 used for Grp Key xmit.*/ - union pn48 dot11Grprxpn; /* PN48 used for Grp Key recv.*/ - -#ifdef CONFIG_8723AU_AP_MODE - /* extend security capabilities for AP_MODE */ - unsigned int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */ - unsigned int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */ - unsigned int wpa_group_cipher; - unsigned int wpa2_group_cipher; - unsigned int wpa_pairwise_cipher; - unsigned int wpa2_pairwise_cipher; -#endif - - u8 wps_ie[MAX_WPS_IE_LEN];/* added in assoc req */ - int wps_ie_len; - unsigned int binstallGrpkey:1; - unsigned int busetkipkey:1; - unsigned int bcheck_grpkey:1; - unsigned int hw_decrypted:1; - u32 ndisauthtype; /* enum ndis_802_11_auth_mode */ - u32 ndisencryptstatus; /* NDIS_802_11_ENCRYPTION_STATUS */ - struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */ - u8 assoc_info[600]; - u8 szofcapability[256]; /* for wpa2 usage */ - u8 oidassociation[512]; /* for wpa/wpa2 usage */ - u8 supplicant_ie[256]; /* store sta security information element */ - - /* for tkip countermeasure */ - unsigned long last_mic_err_time; - u8 btkip_countermeasure; - u8 btkip_wait_report; - unsigned long btkip_countermeasure_time; - - /* For WPA2 Pre-Authentication. */ - struct rt_pmkid_list PMKIDList[NUM_PMKID_CACHE]; - u8 PMKIDIndex; - u8 bWepDefaultKeyIdxSet; -}; - -struct sha256_state { - u64 length; - u32 state[8], curlen; - u8 buf[64]; -}; - -#define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst)\ -do {\ - switch (psecuritypriv->dot11AuthAlgrthm) {\ - case dot11AuthAlgrthm_Open:\ - case dot11AuthAlgrthm_Shared:\ - case dot11AuthAlgrthm_Auto:\ - encry_algo = psecuritypriv->dot11PrivacyAlgrthm;\ - break;\ - case dot11AuthAlgrthm_8021X:\ - if (bmcst)\ - encry_algo = psecuritypriv->dot118021XGrpPrivacy;\ - else\ - encry_algo = psta->dot118021XPrivacy;\ - break;\ - } \ -} while (0) - -#define GET_TKIP_PN(iv, dot11txpn)\ -do {\ - dot11txpn._byte_.TSC0 = iv[2];\ - dot11txpn._byte_.TSC1 = iv[0];\ - dot11txpn._byte_.TSC2 = iv[4];\ - dot11txpn._byte_.TSC3 = iv[5];\ - dot11txpn._byte_.TSC4 = iv[6];\ - dot11txpn._byte_.TSC5 = iv[7];\ -} while (0) - -#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) -#define ROR32(A, n) ROL32((A), 32-(n)) - -struct mic_data { - u32 K0, K1; /* Key */ - u32 L, R; /* Current state */ - u32 M; /* Message accumulator (single word) */ - u32 nBytesInM; /* # bytes in M */ -}; - -extern const u32 Te0[256]; -extern const u32 Te1[256]; -extern const u32 Te2[256]; -extern const u32 Te3[256]; -extern const u32 Te4[256]; -extern const u32 Td0[256]; -extern const u32 Td1[256]; -extern const u32 Td2[256]; -extern const u32 Td3[256]; -extern const u32 Td4[256]; -extern const u32 rcon[10]; -extern const u8 Td4s[256]; -extern const u8 rcons[10]; - -#define RCON(i) (rcons[(i)] << 24) - -static inline u32 rotr(u32 val, int bits) -{ - return (val >> bits) | (val << (32 - bits)); -} - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) -#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) -#define TE3(i) rotr(Te0[(i) & 0xff], 24) -#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) -#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) -#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) -#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) -#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) -#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) -#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) -#define TD3(i) rotr(Td0[(i) & 0xff], 24) -#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) -#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) -#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) -#define TD44(i) (Td4s[(i) & 0xff]) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) rotr(Td0[(i) & 0xff], 8) -#define TD2_(i) rotr(Td0[(i) & 0xff], 16) -#define TD3_(i) rotr(Td0[(i) & 0xff], 24) - -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ - ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) - -#define PUTU32(ct, st) { \ -(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ -(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } - -#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \ - (((u32) (a)[2]) << 8) | ((u32) (a)[3])) - -#define WPA_PUT_LE16(a, val) \ - do { \ - (a)[1] = ((u16) (val)) >> 8; \ - (a)[0] = ((u16) (val)) & 0xff; \ - } while (0) - -#define WPA_PUT_BE32(a, val) \ - do { \ - (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[3] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#define WPA_PUT_BE64(a, val) \ - do { \ - (a)[0] = (u8) (((u64) (val)) >> 56); \ - (a)[1] = (u8) (((u64) (val)) >> 48); \ - (a)[2] = (u8) (((u64) (val)) >> 40); \ - (a)[3] = (u8) (((u64) (val)) >> 32); \ - (a)[4] = (u8) (((u64) (val)) >> 24); \ - (a)[5] = (u8) (((u64) (val)) >> 16); \ - (a)[6] = (u8) (((u64) (val)) >> 8); \ - (a)[7] = (u8) (((u64) (val)) & 0xff); \ - } while (0) - -/* ===== start - public domain SHA256 implementation ===== */ - -/* This is based on SHA256 implementation in LibTomCrypt that was released into - * public domain by Tom St Denis. */ - -/* the K array */ -static const unsigned long K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, - 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, - 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, - 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, - 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, - 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, - 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, - 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, - 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; - -void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 *key); -void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b); -void rtw_secmicappend23a(struct mic_data *pmicdata, u8 *src, u32 nbBytes); -void rtw_secgetmic23a(struct mic_data *pmicdata, u8 *dst); - -void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len, - u8 *Miccode, u8 priorityi); - -int rtw_aes_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -int rtw_tkip_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -void rtw_wep_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -int rtw_aes_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe); -int rtw_tkip_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe); -void rtw_wep_decrypt23a(struct rtw_adapter *padapter, struct recv_frame *precvframe); - -void rtw_use_tkipkey_handler23a(void *FunctionContext); - -#endif /* __RTL871X_SECURITY_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_sreset.h b/drivers/staging/rtl8723au/include/rtw_sreset.h deleted file mode 100644 index 60fa8296e1ff..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_sreset.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_SRESET_C_ -#define _RTW_SRESET_C_ - -#include -#include - -struct sreset_priv { - struct mutex silentreset_mutex; - u8 silent_reset_inprogress; - unsigned long last_tx_time; - unsigned long last_tx_complete_time; -}; - -#include - -void rtw_sreset_init(struct rtw_adapter *padapter); -void rtw_sreset_reset_value(struct rtw_adapter *padapter); -bool rtw_sreset_inprogress(struct rtw_adapter *padapter); -void sreset_set_trigger_point(struct rtw_adapter *padapter, s32 tgp); -void rtw_sreset_reset(struct rtw_adapter *active_adapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_version.h b/drivers/staging/rtl8723au/include/rtw_version.h deleted file mode 100644 index c947733a3e3e..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_version.h +++ /dev/null @@ -1 +0,0 @@ -#define DRIVERVERSION "v4.1.6_7336.20130426" diff --git a/drivers/staging/rtl8723au/include/rtw_xmit.h b/drivers/staging/rtl8723au/include/rtw_xmit.h deleted file mode 100644 index 2b7d6d08238b..000000000000 --- a/drivers/staging/rtl8723au/include/rtw_xmit.h +++ /dev/null @@ -1,385 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_XMIT_H_ -#define _RTW_XMIT_H_ - -#include -#include - -#define MAX_XMITBUF_SZ 2048 -#define NR_XMITBUFF 4 - -#define XMITBUF_ALIGN_SZ 512 - -/* xmit extension buff defination */ -#define MAX_XMIT_EXTBUF_SZ 1536 -#define NR_XMIT_EXTBUFF 32 - -#define MAX_NUMBLKS 1 - -#define XMIT_VO_QUEUE 0 -#define XMIT_VI_QUEUE 1 -#define XMIT_BE_QUEUE 2 -#define XMIT_BK_QUEUE 3 - -#define VO_QUEUE_INX 0 -#define VI_QUEUE_INX 1 -#define BE_QUEUE_INX 2 -#define BK_QUEUE_INX 3 -#define BCN_QUEUE_INX 4 -#define MGT_QUEUE_INX 5 -#define HIGH_QUEUE_INX 6 -#define TXCMD_QUEUE_INX 7 - -#define HW_QUEUE_ENTRY 8 - -#define WEP_IV(pattrib_iv, dot11txpn, keyidx) \ -do { \ - pattrib_iv[0] = dot11txpn._byte_.TSC0; \ - pattrib_iv[1] = dot11txpn._byte_.TSC1; \ - pattrib_iv[2] = dot11txpn._byte_.TSC2; \ - pattrib_iv[3] = ((keyidx & 0x3) << 6); \ - dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : \ - (dot11txpn.val+1); \ -} while (0) - -#define TKIP_IV(pattrib_iv, dot11txpn, keyidx) \ -do { \ - pattrib_iv[0] = dot11txpn._byte_.TSC1; \ - pattrib_iv[1] = (dot11txpn._byte_.TSC1 | 0x20) & 0x7f; \ - pattrib_iv[2] = dot11txpn._byte_.TSC0; \ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6); \ - pattrib_iv[4] = dot11txpn._byte_.TSC2; \ - pattrib_iv[5] = dot11txpn._byte_.TSC3; \ - pattrib_iv[6] = dot11txpn._byte_.TSC4; \ - pattrib_iv[7] = dot11txpn._byte_.TSC5; \ - dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : \ - (dot11txpn.val+1); \ -} while (0) - -#define AES_IV(pattrib_iv, dot11txpn, keyidx)\ -do { \ - pattrib_iv[0] = dot11txpn._byte_.TSC0; \ - pattrib_iv[1] = dot11txpn._byte_.TSC1; \ - pattrib_iv[2] = 0; \ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6); \ - pattrib_iv[4] = dot11txpn._byte_.TSC2; \ - pattrib_iv[5] = dot11txpn._byte_.TSC3; \ - pattrib_iv[6] = dot11txpn._byte_.TSC4; \ - pattrib_iv[7] = dot11txpn._byte_.TSC5; \ - dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : \ - (dot11txpn.val+1); \ -} while (0) - -#define HWXMIT_ENTRY 4 - -#define TXDESC_SIZE 32 - -#define PACKET_OFFSET_SZ 8 -#define TXDESC_OFFSET (TXDESC_SIZE + PACKET_OFFSET_SZ) - -struct tx_desc { - /* DWORD 0 */ - __le32 txdw0; - __le32 txdw1; - __le32 txdw2; - __le32 txdw3; - __le32 txdw4; - __le32 txdw5; - __le32 txdw6; - __le32 txdw7; -}; - -union txdesc { - struct tx_desc txdesc; - unsigned int value[TXDESC_SIZE>>2]; -}; - -struct hw_xmit { - struct rtw_queue *sta_queue; - int accnt; -}; - -/* reduce size */ -struct pkt_attrib { - u16 type; - u8 bswenc; - u8 dhcp_pkt; - u16 ether_type; - u16 seqnum; - u16 pkt_hdrlen; /* the original 802.3 pkt header len */ - u16 hdrlen; /* the WLAN Header Len */ - u32 pktlen; /* the original 802.3 pkt raw_data len */ - u32 last_txcmdsz; - u32 encrypt; /* when 0 indicate no encrypt. */ - u8 nr_frags; - u8 iv_len; - u8 icv_len; - u8 iv[18]; - u8 icv[16]; - u8 priority; - u8 ack_policy; - u8 mac_id; - u8 vcs_mode; /* virtual carrier sense method */ - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 ta[ETH_ALEN]; - u8 ra[ETH_ALEN]; - u8 key_idx; - u8 qos_en; - u8 ht_en; - u8 raid;/* rate adpative id */ - u8 bwmode; - u8 ch_offset;/* PRIME_CHNL_OFFSET */ - u8 sgi;/* short GI */ - u8 ampdu_en;/* tx ampdu enable */ - u8 mdata;/* more data bit */ - u8 pctrl;/* per packet txdesc control enable */ - u8 triggered;/* for ap mode handling Power Saving sta */ - u8 qsel; - u8 eosp; - u8 rate; - u8 retry_ctrl; - struct sta_info *psta; -}; - -#define WLANHDR_OFFSET 64 - -#define NULL_FRAMETAG 0x0 -#define DATA_FRAMETAG 0x01 -#define L2_FRAMETAG 0x02 -#define MGNT_FRAMETAG 0x03 -#define AMSDU_FRAMETAG 0x04 - -#define EII_FRAMETAG 0x05 -#define IEEE8023_FRAMETAG 0x06 - -#define MP_FRAMETAG 0x07 - -#define TXAGG_FRAMETAG 0x08 - -struct submit_ctx { - u32 timeout_ms; /* <0: not synchronous, 0: wait forever, - * >0: up to ms waiting - */ - int status; /* status for operation */ - struct completion done; -}; - -enum { - RTW_SCTX_SUBMITTED = -1, - RTW_SCTX_DONE_SUCCESS = 0, - RTW_SCTX_DONE_UNKNOWN, - RTW_SCTX_DONE_TIMEOUT, - RTW_SCTX_DONE_BUF_ALLOC, - RTW_SCTX_DONE_BUF_FREE, - RTW_SCTX_DONE_WRITE_PORT_ERR, - RTW_SCTX_DONE_TX_DESC_NA, - RTW_SCTX_DONE_TX_DENY, - RTW_SCTX_DONE_CCX_PKT_FAIL, - RTW_SCTX_DONE_DRV_STOP, - RTW_SCTX_DONE_DEV_REMOVE, -}; - -void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms); -int rtw_sctx_wait23a(struct submit_ctx *sctx); -void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status); - -struct xmit_buf { - struct list_head list, list2; - struct rtw_adapter *padapter; - - u8 *pallocated_buf; - u8 *pbuf; - void *priv_data; - - u16 ext_tag; /* 0: Normal xmitbuf, 1: extension xmitbuf. */ - u16 flags; - u32 alloc_sz; - u32 len; - struct submit_ctx *sctx; - u32 ff_hwaddr; - struct urb *pxmit_urb[8]; - u8 bpending[8]; - int last[8]; -#if defined(DBG_XMIT_BUF) || defined(DBG_XMIT_BUF_EXT) - u8 no; -#endif -}; - -struct xmit_frame { - struct list_head list; - struct pkt_attrib attrib; - struct sk_buff *pkt; - int frame_tag; - struct rtw_adapter *padapter; - u8 *buf_addr; - struct xmit_buf *pxmitbuf; - - s8 pkt_offset; - - u8 ack_report; - - u8 ext_tag; /* 0:data, 1:mgmt */ -}; - -struct tx_servq { - struct list_head tx_pending; - struct rtw_queue sta_pending; - int qcnt; -}; - -struct sta_xmit_priv { - spinlock_t lock; - int option; - int apsd_setting; /* When bit mask is on, the associated edca - * queue supports APSD. - */ - struct tx_servq be_q; /* priority == 0,3 */ - struct tx_servq bk_q; /* priority == 1,2 */ - struct tx_servq vi_q; /* priority == 4,5 */ - struct tx_servq vo_q; /* priority == 6,7 */ - struct list_head legacy_dz; - struct list_head apsd; - u16 txseq_tid[16]; -}; - -struct hw_txqueue { - volatile int head; - volatile int tail; - volatile int free_sz; /* in units of 64 bytes */ - volatile int free_cmdsz; - volatile int txsz[8]; - uint ff_hwaddr; - uint cmd_hwaddr; - int ac_tag; -}; - -struct agg_pkt_info { - u16 offset; - u16 pkt_len; -}; - -struct xmit_priv { - spinlock_t lock; - - struct semaphore xmit_sema; - struct semaphore terminate_xmitthread_sema; - - struct rtw_queue be_pending; - struct rtw_queue bk_pending; - struct rtw_queue vi_pending; - struct rtw_queue vo_pending; - struct rtw_queue bm_pending; - - int free_xmitframe_cnt; - struct rtw_queue free_xmit_queue; - - int free_xframe_ext_cnt; - struct rtw_queue free_xframe_ext_queue; - - uint frag_len; - - struct rtw_adapter *adapter; - - u64 tx_bytes; - u64 tx_pkts; - u64 tx_drop; - u64 last_tx_bytes; - u64 last_tx_pkts; - - struct hw_xmit *hwxmits; - u8 hwxmit_entry; - u8 vcs; - u8 nqos_ssn; - - u8 wmm_para_seq[4];/* sequence for wmm ac parameter strength from - * large to small. it's value is 0->vo, 1->vi, - * 2->be, 3->bk. - */ - - struct semaphore tx_retevt;/* all tx return event; */ - - struct tasklet_struct xmit_tasklet; - - struct rtw_queue free_xmitbuf_queue; - struct list_head xmitbuf_list; /* track buffers for cleanup */ - struct rtw_queue pending_xmitbuf_queue; - uint free_xmitbuf_cnt; - - struct rtw_queue free_xmit_extbuf_queue; - struct list_head xmitextbuf_list; /* track buffers for cleanup */ - uint free_xmit_extbuf_cnt; - - int ack_tx; - struct mutex ack_tx_mutex; - struct submit_ctx ack_tx_ops; - spinlock_t lock_sctx; -}; - -struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); - -struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf); - -void rtw_count_tx_stats23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe, int sz); -void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len); -struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv); -struct xmit_frame *rtw_alloc_xmitframe23a_once(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, - struct xmit_frame *pxmitframe); -void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv, struct rtw_queue *pframequeue); -struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, - struct sta_info *psta, int up, u8 *ac); -s32 rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -struct xmit_frame *rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, - struct hw_xmit *phwxmit_i, int entry); -s32 rtw_xmit23a_classifier(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt, - struct xmit_frame *pxmitframe); -s32 _rtw_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); -void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv); - -s32 rtw_txframes_pending23a(struct rtw_adapter *padapter); -s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib); -void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry); -int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, - struct rtw_adapter *padapter); -void _rtw_free_xmit_priv23a(struct xmit_priv *pxmitpriv); -void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter); -void rtw_free_hwxmits23a(struct rtw_adapter *padapter); -int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *pkt); -#if defined(CONFIG_8723AU_AP_MODE) -int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta); -void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta); -void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter, - struct sta_info *psta); -#endif -u8 qos_acm23a(u8 acm_mask, u8 priority); -u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe); -int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms); - -/* include after declaring struct xmit_buf, in order to avoid warning */ -#include - -#endif /* _RTL871X_XMIT_H_ */ diff --git a/drivers/staging/rtl8723au/include/sta_info.h b/drivers/staging/rtl8723au/include/sta_info.h deleted file mode 100644 index e7260050e533..000000000000 --- a/drivers/staging/rtl8723au/include/sta_info.h +++ /dev/null @@ -1,373 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __STA_INFO_H_ -#define __STA_INFO_H_ - -#include -#include -#include - -#define IBSS_START_MAC_ID 2 -#define NUM_STA 32 -#define NUM_ACL 16 - - -/* if mode ==0, then the sta is allowed once the addr is hit. */ -/* if mode ==1, then the sta is rejected once the addr is non-hit. */ -struct rtw_wlan_acl_node { - struct list_head list; - u8 addr[ETH_ALEN]; - u8 valid; -}; - -/* mode=0, disable */ -/* mode=1, accept unless in deny list */ -/* mode=2, deny unless in accept list */ -struct wlan_acl_pool { - int mode; - int num; - struct rtw_wlan_acl_node aclnode[NUM_ACL]; - struct rtw_queue acl_node_q; -}; - -struct rssi_sta { - s32 UndecoratedSmoothedPWDB; - s32 UndecoratedSmoothedCCK; - s32 UndecoratedSmoothedOFDM; - u64 PacketMap; - u8 ValidBit; -}; - -struct stainfo_stats { - u64 rx_mgnt_pkts; - u64 rx_beacon_pkts; - u64 rx_probereq_pkts; - u64 rx_probersp_pkts; - u64 rx_probersp_bm_pkts; - u64 rx_probersp_uo_pkts; - u64 rx_ctrl_pkts; - u64 rx_data_pkts; - - u64 last_rx_mgnt_pkts; - u64 last_rx_beacon_pkts; - u64 last_rx_probereq_pkts; - u64 last_rx_probersp_pkts; - u64 last_rx_probersp_bm_pkts; - u64 last_rx_probersp_uo_pkts; - u64 last_rx_ctrl_pkts; - u64 last_rx_data_pkts; - - u64 rx_bytes; - u64 rx_drops; - - u64 tx_pkts; - u64 tx_bytes; - u64 tx_drops; - -}; - -struct sta_info { - spinlock_t lock; - struct list_head list; /* free_sta_queue */ - struct list_head hash_list; /* sta_hash */ - struct rtw_adapter *padapter; - - struct sta_xmit_priv sta_xmitpriv; - struct sta_recv_priv sta_recvpriv; - - struct rtw_queue sleep_q; - unsigned int sleepq_len; - - uint state; - uint aid; - uint mac_id; - uint qos_option; - u8 hwaddr[ETH_ALEN]; - - uint ieee8021x_blocked; /* 0: allowed, 1:blocked */ - u32 dot118021XPrivacy; /* aes, tkip... */ - union Keytype dot11tkiptxmickey; - union Keytype dot11tkiprxmickey; - union Keytype dot118021x_UncstKey; - union pn48 dot11txpn; /* PN48 used for Unicast xmit. */ - union pn48 dot11rxpn; /* PN48 used for Unicast recv. */ - - - u8 bssrateset[16]; - u32 bssratelen; - s32 rssi; - s32 signal_quality; - - u8 cts2self; - u8 rtsen; - - u8 raid; - u8 init_rate; - u32 ra_mask; - u8 wireless_mode; /* NETWORK_TYPE */ - struct stainfo_stats sta_stats; - - /* for A-MPDU TX, ADDBA timeout check */ - struct timer_list addba_retry_timer; - - /* for A-MPDU Rx reordering buffer control */ - struct recv_reorder_ctrl recvreorder_ctrl[16]; - - /* for A-MPDU Tx */ - /* unsigned char ampdu_txen_bitmap; */ - u16 BA_starting_seqctrl[16]; - - struct ht_priv htpriv; - - /* Notes: */ - /* STA_Mode: */ - /* curr_network(mlme_priv/security_priv/qos/ht) + sta_info: (STA & AP) CAP/INFO */ - /* scan_q: AP CAP/INFO */ - - /* AP_Mode: */ - /* curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO */ - /* sta_info: (AP & STA) CAP/INFO */ - - struct list_head asoc_list; - struct list_head auth_list; - - unsigned int expire_to; - unsigned int auth_seq; - unsigned int authalg; - unsigned char chg_txt[128]; - - u16 capability; - int flags; - - int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */ - int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */ - int wpa_group_cipher; - int wpa2_group_cipher; - int wpa_pairwise_cipher; - int wpa2_pairwise_cipher; - - u8 bpairwise_key_installed; - - u8 wpa_ie[32]; - - u8 nonerp_set; - u8 no_short_slot_time_set; - u8 no_short_preamble_set; - u8 no_ht_gf_set; - u8 no_ht_set; - u8 ht_20mhz_set; - - unsigned int tx_ra_bitmap; - u8 qos_info; - - u8 max_sp_len; - u8 uapsd_bk;/* BIT(0): Delivery enabled, BIT(1): Trigger enabled */ - u8 uapsd_be; - u8 uapsd_vi; - u8 uapsd_vo; - - u8 has_legacy_ac; - unsigned int sleepq_ac_len; - - /* p2p priv data */ - u8 is_p2p_device; - u8 p2p_status_code; - - u8 keep_alive_trycnt; - - /* p2p client info */ - u8 dev_addr[ETH_ALEN]; - u8 dev_cap; - u16 config_methods; - u8 primary_dev_type[8]; - u8 num_of_secdev_type; - u8 secdev_types_list[32];/* 32/8 == 4; */ - u16 dev_name_len; - u8 dev_name[32]; - u8 *passoc_req; - u32 assoc_req_len; - - /* for DM */ - struct rssi_sta rssi_stat; - - /* */ - /* ================ODM Relative Info======================= */ - /* Please be care, dont declare too much structure here. It will cost memory * STA support num. */ - /* */ - /* */ - /* 2011/10/20 MH Add for ODM STA info. */ - /* */ - /* Driver Write */ - u8 bValid; /* record the sta status link or not? */ - u8 rssi_level; /* for Refresh RA mask */ - /* ODM Write */ - /* 1 PHY_STATUS_INFO */ - u8 RSSI_Path[4]; /* */ - u8 RSSI_Ave; - u8 RXEVM[4]; - u8 RXSNR[4]; - - /* ODM Write */ - /* 1 TX_INFO (may changed by IC) */ - /* ================ODM Relative Info======================= */ - /* */ - - /* To store the sequence number of received management frame */ - u16 RxMgmtFrameSeqNum; -}; - -#define sta_rx_pkts(sta) \ - (sta->sta_stats.rx_mgnt_pkts \ - + sta->sta_stats.rx_ctrl_pkts \ - + sta->sta_stats.rx_data_pkts) - -#define sta_last_rx_pkts(sta) \ - (sta->sta_stats.last_rx_mgnt_pkts \ - + sta->sta_stats.last_rx_ctrl_pkts \ - + sta->sta_stats.last_rx_data_pkts) - -#define sta_rx_data_pkts(sta) \ - (sta->sta_stats.rx_data_pkts) - -#define sta_last_rx_data_pkts(sta) \ - (sta->sta_stats.last_rx_data_pkts) - -#define sta_rx_mgnt_pkts(sta) \ - (sta->sta_stats.rx_mgnt_pkts) - -#define sta_last_rx_mgnt_pkts(sta) \ - (sta->sta_stats.last_rx_mgnt_pkts) - -#define sta_rx_beacon_pkts(sta) \ - (sta->sta_stats.rx_beacon_pkts) - -#define sta_last_rx_beacon_pkts(sta) \ - (sta->sta_stats.last_rx_beacon_pkts) - -#define sta_rx_probereq_pkts(sta) \ - (sta->sta_stats.rx_probereq_pkts) - -#define sta_last_rx_probereq_pkts(sta) \ - (sta->sta_stats.last_rx_probereq_pkts) - -#define sta_rx_probersp_pkts(sta) \ - (sta->sta_stats.rx_probersp_pkts) - -#define sta_last_rx_probersp_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_pkts) - -#define sta_rx_probersp_bm_pkts(sta) \ - (sta->sta_stats.rx_probersp_bm_pkts) - -#define sta_last_rx_probersp_bm_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_bm_pkts) - -#define sta_rx_probersp_uo_pkts(sta) \ - (sta->sta_stats.rx_probersp_uo_pkts) - -#define sta_last_rx_probersp_uo_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_uo_pkts) - -#define sta_update_last_rx_pkts(sta) \ - do { \ - sta->sta_stats.last_rx_mgnt_pkts = sta->sta_stats.rx_mgnt_pkts; \ - sta->sta_stats.last_rx_beacon_pkts = sta->sta_stats.rx_beacon_pkts; \ - sta->sta_stats.last_rx_probereq_pkts = sta->sta_stats.rx_probereq_pkts; \ - sta->sta_stats.last_rx_probersp_pkts = sta->sta_stats.rx_probersp_pkts; \ - sta->sta_stats.last_rx_probersp_bm_pkts = sta->sta_stats.rx_probersp_bm_pkts; \ - sta->sta_stats.last_rx_probersp_uo_pkts = sta->sta_stats.rx_probersp_uo_pkts; \ - sta->sta_stats.last_rx_ctrl_pkts = sta->sta_stats.rx_ctrl_pkts; \ - sta->sta_stats.last_rx_data_pkts = sta->sta_stats.rx_data_pkts; \ - } while (0) - -#define STA_RX_PKTS_ARG(sta) \ - sta->sta_stats.rx_mgnt_pkts \ - , sta->sta_stats.rx_ctrl_pkts \ - , sta->sta_stats.rx_data_pkts - -#define STA_LAST_RX_PKTS_ARG(sta) \ - sta->sta_stats.last_rx_mgnt_pkts, \ - sta->sta_stats.last_rx_ctrl_pkts, \ - sta->sta_stats.last_rx_data_pkts - -#define STA_RX_PKTS_DIFF_ARG(sta) \ - sta->sta_stats.rx_mgnt_pkts - sta->sta_stats.last_rx_mgnt_pkts, \ - sta->sta_stats.rx_ctrl_pkts - sta->sta_stats.last_rx_ctrl_pkts, \ - sta->sta_stats.rx_data_pkts - sta->sta_stats.last_rx_data_pkts - -#define STA_PKTS_FMT "(m:%llu, c:%llu, d:%llu)" - -struct sta_priv { - spinlock_t sta_hash_lock; - struct list_head sta_hash[NUM_STA]; - int asoc_sta_count; - - struct rtw_adapter *padapter; - struct list_head asoc_list; - struct list_head auth_list; - spinlock_t asoc_list_lock; - spinlock_t auth_list_lock; - u8 asoc_list_cnt; - u8 auth_list_cnt; - - unsigned int auth_to; /* sec, time to expire in authenticating. */ - unsigned int assoc_to; /* sec, time to expire before associating. */ - unsigned int expire_to; /* sec , time to expire after associated. */ - - /* pointers to STA info; based on allocated AID or NULL if AID free - * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1 - * and so on - */ - struct sta_info *sta_aid[NUM_STA]; - - u16 sta_dz_bitmap;/* only support 15 stations, station aid bitmap - * for sleeping sta. */ - u16 tim_bitmap;/* only support 15 stations, - * aid=0~15 mapping bit0~bit15 */ - - u16 max_num_sta; - - struct wlan_acl_pool acl_list; -}; - -static inline u32 wifi_mac_hash(const u8 *mac) -{ - u32 x; - - x = mac[0]; - x = (x << 2) ^ mac[1]; - x = (x << 2) ^ mac[2]; - x = (x << 2) ^ mac[3]; - x = (x << 2) ^ mac[4]; - x = (x << 2) ^ mac[5]; - - x ^= x >> 8; - x = x & (NUM_STA - 1); - - return x; -} - -int _rtw_init_sta_priv23a(struct sta_priv *pstapriv); -int _rtw_free_sta_priv23a(struct sta_priv *pstapriv); - -struct sta_info *rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp); -int rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta); -void rtw_free_all_stainfo23a(struct rtw_adapter *padapter); -struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr); -int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter); -struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter); -bool rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr); - -#endif /* _STA_INFO_H_ */ diff --git a/drivers/staging/rtl8723au/include/usb_ops.h b/drivers/staging/rtl8723au/include/usb_ops.h deleted file mode 100644 index ff11e13b24a8..000000000000 --- a/drivers/staging/rtl8723au/include/usb_ops.h +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __USB_OPS_H_ -#define __USB_OPS_H_ - -#include -#include -#include -#include - -#define REALTEK_USB_VENQT_READ 0xC0 -#define REALTEK_USB_VENQT_WRITE 0x40 -#define REALTEK_USB_VENQT_CMD_REQ 0x05 -#define REALTEK_USB_VENQT_CMD_IDX 0x00 - -enum { - VENDOR_WRITE = 0x00, - VENDOR_READ = 0x01, -}; - -#define ALIGNMENT_UNIT 16 -#define MAX_VENDOR_REQ_CMD_SIZE 254 /* 8188cu SIE Support */ -#define MAX_USB_IO_CTL_SIZE (MAX_VENDOR_REQ_CMD_SIZE +ALIGNMENT_UNIT) - -void rtl8723au_set_hw_type(struct rtw_adapter *padapter); - -void rtl8723au_recv_tasklet(void *priv); - -void rtl8723au_xmit_tasklet(void *priv); - -/* Increase and check if the continual_urb_error of this @param dvobjprive is - * larger than MAX_CONTINUAL_URB_ERR. Return result - */ -static inline int rtw_inc_and_chk_continual_urb_error(struct dvobj_priv *dvobj) -{ - int ret = false; - int value; - - value = atomic_inc_return(&dvobj->continual_urb_error); - if (value > MAX_CONTINUAL_URB_ERR) { - DBG_8723A("[dvobj:%p][ERROR] continual_urb_error:%d > %d\n", - dvobj, value, MAX_CONTINUAL_URB_ERR); - ret = true; - } - return ret; -} - -/* Set the continual_urb_error of this @param dvobjprive to 0 */ -static inline void rtw_reset_continual_urb_error(struct dvobj_priv *dvobj) -{ - atomic_set(&dvobj->continual_urb_error, 0); -} - -bool rtl8723au_chip_configure(struct rtw_adapter *padapter); - -#endif /* __USB_OPS_H_ */ diff --git a/drivers/staging/rtl8723au/include/usb_ops_linux.h b/drivers/staging/rtl8723au/include/usb_ops_linux.h deleted file mode 100644 index af2f14b8b360..000000000000 --- a/drivers/staging/rtl8723au/include/usb_ops_linux.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __USB_OPS_LINUX_H__ -#define __USB_OPS_LINUX_H__ - -#define VENDOR_CMD_MAX_DATA_LEN 254 - -#define RTW_USB_CONTROL_MSG_TIMEOUT 500/* ms */ - -#define MAX_USBCTRL_VENDORREQ_TIMES 10 - -int rtl8723au_read_port(struct rtw_adapter *adapter, u32 cnt, - struct recv_buf *precvbuf); -void rtl8723au_read_port_cancel(struct rtw_adapter *padapter); -int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt, - struct xmit_buf *pxmitbuf); -void rtl8723au_write_port_cancel(struct rtw_adapter *padapter); -int rtl8723au_read_interrupt(struct rtw_adapter *adapter); - -u8 rtl8723au_read8(struct rtw_adapter *padapter, u16 addr); -u16 rtl8723au_read16(struct rtw_adapter *padapter, u16 addr); -u32 rtl8723au_read32(struct rtw_adapter *padapter, u16 addr); -int rtl8723au_write8(struct rtw_adapter *padapter, u16 addr, u8 val); -int rtl8723au_write16(struct rtw_adapter *padapter, u16 addr, u16 val); -int rtl8723au_write32(struct rtw_adapter *padapter, u16 addr, u32 val); -int rtl8723au_writeN(struct rtw_adapter *padapter, - u16 addr, u16 length, u8 *pdata); - -#endif diff --git a/drivers/staging/rtl8723au/include/wifi.h b/drivers/staging/rtl8723au/include/wifi.h deleted file mode 100644 index 25d573c3e232..000000000000 --- a/drivers/staging/rtl8723au/include/wifi.h +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef _WIFI_H_ -#define _WIFI_H_ - -/* This value is tested by WiFi 11n Test Plan 5.2.3. - * This test verifies the WLAN NIC can update the NAV through sending - * the CTS with large duration. - */ -#define WiFiNavUpperUs 30000 /* 30 ms */ - -/*----------------------------------------------------------------------------- - Below is the definition for 802.11n -------------------------------------------------------------------------------*/ - -struct AC_param { - u8 ACI_AIFSN; - u8 CW; - __le16 TXOP_limit; -} __packed; - -struct WMM_para_element { - unsigned char QoS_info; - unsigned char reserved; - struct AC_param ac_param[4]; -} __packed; - -struct ADDBA_request { - u8 dialog_token; - __le16 BA_para_set; - __le16 BA_timeout_value; - __le16 BA_starting_seqctrl; -} __packed; - - -/* ===============WPS Section=============== */ -/* WPS attribute ID */ -#define WPS_ATTR_VER1 0x104A -#define WPS_ATTR_SIMPLE_CONF_STATE 0x1044 -#define WPS_ATTR_RESP_TYPE 0x103B -#define WPS_ATTR_UUID_E 0x1047 -#define WPS_ATTR_MANUFACTURER 0x1021 -#define WPS_ATTR_MODEL_NAME 0x1023 -#define WPS_ATTR_MODEL_NUMBER 0x1024 -#define WPS_ATTR_SERIAL_NUMBER 0x1042 -#define WPS_ATTR_PRIMARY_DEV_TYPE 0x1054 -#define WPS_ATTR_SEC_DEV_TYPE_LIST 0x1055 -#define WPS_ATTR_DEVICE_NAME 0x1011 -#define WPS_ATTR_CONF_METHOD 0x1008 -#define WPS_ATTR_RF_BANDS 0x103C -#define WPS_ATTR_DEVICE_PWID 0x1012 -#define WPS_ATTR_REQUEST_TYPE 0x103A -#define WPS_ATTR_ASSOCIATION_STATE 0x1002 -#define WPS_ATTR_CONFIG_ERROR 0x1009 -#define WPS_ATTR_VENDOR_EXT 0x1049 -#define WPS_ATTR_SELECTED_REGISTRAR 0x1041 - -/* WPS Configuration Method */ -#define WPS_CM_NONE 0x0000 -#define WPS_CM_LABEL 0x0004 -#define WPS_CM_DISPLYA 0x0008 -#define WPS_CM_EXTERNAL_NFC_TOKEN 0x0010 -#define WPS_CM_INTEGRATED_NFC_TOKEN 0x0020 -#define WPS_CM_NFC_INTERFACE 0x0040 -#define WPS_CM_PUSH_BUTTON 0x0080 -#define WPS_CM_KEYPAD 0x0100 -#define WPS_CM_SW_PUHS_BUTTON 0x0280 -#define WPS_CM_HW_PUHS_BUTTON 0x0480 -#define WPS_CM_SW_DISPLAY_PIN 0x2008 -#define WPS_CM_LCD_DISPLAY_PIN 0x4008 - -#endif /* _WIFI_H_ */ diff --git a/drivers/staging/rtl8723au/include/wlan_bssdef.h b/drivers/staging/rtl8723au/include/wlan_bssdef.h deleted file mode 100644 index 95b32e15a4d0..000000000000 --- a/drivers/staging/rtl8723au/include/wlan_bssdef.h +++ /dev/null @@ -1,123 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __WLAN_BSSDEF_H__ -#define __WLAN_BSSDEF_H__ - - -#define MAX_IE_SZ 768 - - -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 - -/* Length is the 4 bytes multiples of the sum of - * sizeof(6 * sizeof(unsigned char)) + 2 + sizeof(struct ndis_802_11_ssid) + - * sizeof(u32) + sizeof(long) + sizeof(enum ndis_802_11_net_type) + - * sizeof(struct ndis_802_11_config) + sizeof(sizeof(unsigned char) * - * NDIS_802_11_LENGTH_RATES_EX) + IELength - * - * Except the IELength, all other fields are fixed length. Therefore, - * we can define a macro to present the partial sum. - */ - -enum ndis_802_11_auth_mode { - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - dis802_11AuthModeMax /* upper bound */ -}; - -enum { - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent, -}; - -struct wlan_bcn_info { - /* these infor get from rtw_get_encrypt_info when - * * translate scan to UI */ - u8 encryp_protocol;/* ENCRYP_PROTOCOL_E: OPEN/WEP/WPA/WPA2 */ - int group_cipher; /* WPA/WPA2 group cipher */ - int pairwise_cipher;/* WPA/WPA2/WEP pairwise cipher */ - int is_8021x; - - /* bwmode 20/40 and ch_offset UP/LOW */ -}; - -struct wlan_bssid_ex { - u32 Length; - u8 MacAddress[ETH_ALEN]; - u16 reserved; - struct cfg80211_ssid Ssid; - u32 Privacy; - long Rssi;/* in dBM, raw data , get from PHY) */ - u16 beacon_interval; - u16 capability; - u64 tsf; - u32 ATIMWindow; /* units are Kusec */ - u32 DSConfig; /* Frequency, units are kHz */ - enum nl80211_iftype ifmode; - unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; - u8 SignalStrength;/* in percentage */ - u8 SignalQuality;/* in percentage */ - u32 IELength; - u8 IEs[MAX_IE_SZ]; /* timestamp, beacon interval, and capability info*/ -} __packed; - -static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) -{ - return sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->IELength; -} - -struct wlan_network { - struct list_head list; - int network_type; /* refer to ieee80211.h for 11A/B/G */ - /* set to fixed when not to be removed as site-surveying */ - int fixed; - unsigned long last_scanned; /* timestamp for the network */ - int join_res; - struct wlan_bssid_ex network; /* must be the last item */ - struct wlan_bcn_info BcnInfo; -}; - -enum VRTL_CARRIER_SENSE { - DISABLE_VCS, - ENABLE_VCS, - AUTO_VCS -}; - -enum VCS_TYPE { - NONE_VCS, - RTS_CTS, - CTS_TO_SELF -}; - -/* john */ -#define NUM_PRE_AUTH_KEY 16 -#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY - -#endif /* ifndef WLAN_BSSDEF_H_ */ diff --git a/drivers/staging/rtl8723au/include/xmit_osdep.h b/drivers/staging/rtl8723au/include/xmit_osdep.h deleted file mode 100644 index 2be04c48656c..000000000000 --- a/drivers/staging/rtl8723au/include/xmit_osdep.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#ifndef __XMIT_OSDEP_H_ -#define __XMIT_OSDEP_H_ - -#include -#include - - -#define NR_XMITFRAME 256 - -int rtw_xmit23a_entry23a(struct sk_buff *pkt, struct net_device *pnetdev); - -void rtw_os_xmit_schedule23a(struct rtw_adapter *padapter); - -int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter, - struct xmit_buf *pxmitbuf, u32 alloc_sz); -void rtw_os_xmit_resource_free23a(struct rtw_adapter *padapter, - struct xmit_buf *pxmitbuf); - -void rtw_os_pkt_complete23a(struct rtw_adapter *padapter, struct sk_buff *pkt); -void rtw_os_xmit_complete23a(struct rtw_adapter *padapter, - struct xmit_frame *pxframe); -int netdev_open23a(struct net_device *pnetdev); - -#endif /* __XMIT_OSDEP_H_ */ diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c deleted file mode 100644 index d0ba3778990e..000000000000 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ /dev/null @@ -1,3348 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _IOCTL_CFG80211_C_ - -#include -#include -#include - -#include "ioctl_cfg80211.h" - -#define RTW_MAX_MGMT_TX_CNT 8 - -#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535 /* ms */ -#define RTW_MAX_NUM_PMKIDS 4 - -static const u32 rtw_cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, - WLAN_CIPHER_SUITE_TKIP, - WLAN_CIPHER_SUITE_CCMP, -}; - -#define RATETAB_ENT(_rate, _rateid, _flags) { \ - .bitrate = (_rate), \ - .hw_value = (_rateid), \ - .flags = (_flags), \ -} - -#define CHAN2G(_channel, _freq, _flags) { \ - .band = NL80211_BAND_2GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -#define CHAN5G(_channel, _flags) { \ - .band = NL80211_BAND_5GHZ, \ - .center_freq = 5000 + (5 * (_channel)), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -static struct ieee80211_rate rtw_rates[] = { - RATETAB_ENT(10, 0x1, 0), - RATETAB_ENT(20, 0x2, 0), - RATETAB_ENT(55, 0x4, 0), - RATETAB_ENT(110, 0x8, 0), - RATETAB_ENT(60, 0x10, 0), - RATETAB_ENT(90, 0x20, 0), - RATETAB_ENT(120, 0x40, 0), - RATETAB_ENT(180, 0x80, 0), - RATETAB_ENT(240, 0x100, 0), - RATETAB_ENT(360, 0x200, 0), - RATETAB_ENT(480, 0x400, 0), - RATETAB_ENT(540, 0x800, 0), -}; - -#define rtw_a_rates (rtw_rates + 4) -#define RTW_A_RATES_NUM 8 -#define rtw_g_rates (rtw_rates + 0) -#define RTW_G_RATES_NUM 12 - -#define RTW_2G_CHANNELS_NUM 14 -#define RTW_5G_CHANNELS_NUM 37 - -static struct ieee80211_channel rtw_2ghz_channels[] = { - CHAN2G(1, 2412, 0), - CHAN2G(2, 2417, 0), - CHAN2G(3, 2422, 0), - CHAN2G(4, 2427, 0), - CHAN2G(5, 2432, 0), - CHAN2G(6, 2437, 0), - CHAN2G(7, 2442, 0), - CHAN2G(8, 2447, 0), - CHAN2G(9, 2452, 0), - CHAN2G(10, 2457, 0), - CHAN2G(11, 2462, 0), - CHAN2G(12, 2467, 0), - CHAN2G(13, 2472, 0), - CHAN2G(14, 2484, 0), -}; - -static struct ieee80211_channel rtw_5ghz_a_channels[] = { - CHAN5G(34, 0), CHAN5G(36, 0), - CHAN5G(38, 0), CHAN5G(40, 0), - CHAN5G(42, 0), CHAN5G(44, 0), - CHAN5G(46, 0), CHAN5G(48, 0), - CHAN5G(52, 0), CHAN5G(56, 0), - CHAN5G(60, 0), CHAN5G(64, 0), - CHAN5G(100, 0), CHAN5G(104, 0), - CHAN5G(108, 0), CHAN5G(112, 0), - CHAN5G(116, 0), CHAN5G(120, 0), - CHAN5G(124, 0), CHAN5G(128, 0), - CHAN5G(132, 0), CHAN5G(136, 0), - CHAN5G(140, 0), CHAN5G(149, 0), - CHAN5G(153, 0), CHAN5G(157, 0), - CHAN5G(161, 0), CHAN5G(165, 0), - CHAN5G(184, 0), CHAN5G(188, 0), - CHAN5G(192, 0), CHAN5G(196, 0), - CHAN5G(200, 0), CHAN5G(204, 0), - CHAN5G(208, 0), CHAN5G(212, 0), - CHAN5G(216, 0), -}; - -static void rtw_2g_channels_init(struct ieee80211_channel *channels) -{ - memcpy((void *)channels, (void *)rtw_2ghz_channels, - sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM); -} - -static void rtw_5g_channels_init(struct ieee80211_channel *channels) -{ - memcpy((void *)channels, (void *)rtw_5ghz_a_channels, - sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM); -} - -static void rtw_2g_rates_init(struct ieee80211_rate *rates) -{ - memcpy(rates, rtw_g_rates, - sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM); -} - -static void rtw_5g_rates_init(struct ieee80211_rate *rates) -{ - memcpy(rates, rtw_a_rates, - sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM); -} - -static struct ieee80211_supported_band * -rtw_spt_band_alloc(enum nl80211_band band) -{ - struct ieee80211_supported_band *spt_band = NULL; - int n_channels, n_bitrates; - - if (band == NL80211_BAND_2GHZ) { - n_channels = RTW_2G_CHANNELS_NUM; - n_bitrates = RTW_G_RATES_NUM; - } else if (band == NL80211_BAND_5GHZ) { - n_channels = RTW_5G_CHANNELS_NUM; - n_bitrates = RTW_A_RATES_NUM; - } else { - goto exit; - } - spt_band = kzalloc(sizeof(struct ieee80211_supported_band) + - sizeof(struct ieee80211_channel) * n_channels + - sizeof(struct ieee80211_rate) * n_bitrates, - GFP_KERNEL); - if (!spt_band) - goto exit; - - spt_band->channels = - (struct ieee80211_channel *)(((u8 *) spt_band) + - sizeof(struct - ieee80211_supported_band)); - spt_band->bitrates = - (struct ieee80211_rate *)(((u8 *) spt_band->channels) + - sizeof(struct ieee80211_channel) * - n_channels); - spt_band->band = band; - spt_band->n_channels = n_channels; - spt_band->n_bitrates = n_bitrates; - - if (band == NL80211_BAND_2GHZ) { - rtw_2g_channels_init(spt_band->channels); - rtw_2g_rates_init(spt_band->bitrates); - } else if (band == NL80211_BAND_5GHZ) { - rtw_5g_channels_init(spt_band->channels); - rtw_5g_rates_init(spt_band->bitrates); - } - - /* spt_band.ht_cap */ - -exit: - return spt_band; -} - -static const struct ieee80211_txrx_stypes -rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_ADHOC] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) - }, - [NL80211_IFTYPE_STATION] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_AP] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4) - }, - [NL80211_IFTYPE_AP_VLAN] = { - /* copy AP */ - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4) - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4) - }, -}; - -static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, - struct wlan_network *pnetwork) -{ - int ret = 0; - struct ieee80211_channel *notify_channel; - struct cfg80211_bss *bss; - u16 channel; - u32 freq; - u8 *notify_ie; - size_t notify_ielen; - s32 notify_signal; - struct wireless_dev *wdev = padapter->rtw_wdev; - struct wiphy *wiphy = wdev->wiphy; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - channel = pnetwork->network.DSConfig; - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - notify_channel = ieee80211_get_channel(wiphy, freq); - - notify_ie = pnetwork->network.IEs; - notify_ielen = pnetwork->network.IELength; - - /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: - * signal strength in mBm (100*dBm) - */ - if (check_fwstate(pmlmepriv, _FW_LINKED) && - is_same_network23a(&pmlmepriv->cur_network.network, - &pnetwork->network)) { - notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */ - } else { - notify_signal = 100 * translate_percentage_to_dbm( - pnetwork->network.SignalStrength); /* dbm */ - } - - bss = cfg80211_inform_bss(wiphy, notify_channel, - CFG80211_BSS_FTYPE_UNKNOWN, - pnetwork->network.MacAddress, - pnetwork->network.tsf, - pnetwork->network.capability, - pnetwork->network.beacon_interval, - notify_ie, notify_ielen, - notify_signal, GFP_ATOMIC); - - if (unlikely(!bss)) { - DBG_8723A("rtw_cfg80211_inform_bss error\n"); - return -EINVAL; - } - - cfg80211_put_bss(wiphy, bss); - - return ret; -} - -void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wireless_dev *pwdev = padapter->rtw_wdev; - - DBG_8723A("%s(padapter =%p)\n", __func__, padapter); - - if (pwdev->iftype != NL80211_IFTYPE_STATION && - pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT) - return; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return; - - if (padapter->mlmepriv.to_roaming > 0) { - struct wiphy *wiphy = pwdev->wiphy; - struct ieee80211_channel *notify_channel; - u32 freq; - u16 channel = cur_network->network.DSConfig; - - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = - ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = - ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - notify_channel = ieee80211_get_channel(wiphy, freq); - - DBG_8723A("%s call cfg80211_roamed\n", __func__); - cfg80211_roamed(padapter->pnetdev, notify_channel, - cur_network->network.MacAddress, - pmlmepriv->assoc_req + - sizeof(struct ieee80211_hdr_3addr) + 2, - pmlmepriv->assoc_req_len - - sizeof(struct ieee80211_hdr_3addr) - 2, - pmlmepriv->assoc_rsp + - sizeof(struct ieee80211_hdr_3addr) + 6, - pmlmepriv->assoc_rsp_len - - sizeof(struct ieee80211_hdr_3addr) - 6, - GFP_ATOMIC); - } else { - cfg80211_connect_result(padapter->pnetdev, - cur_network->network.MacAddress, - pmlmepriv->assoc_req + - sizeof(struct ieee80211_hdr_3addr) + 2, - pmlmepriv->assoc_req_len - - sizeof(struct ieee80211_hdr_3addr) - 2, - pmlmepriv->assoc_rsp + - sizeof(struct ieee80211_hdr_3addr) + 6, - pmlmepriv->assoc_rsp_len - - sizeof(struct ieee80211_hdr_3addr) - 6, - WLAN_STATUS_SUCCESS, GFP_ATOMIC); - } -} - -void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wireless_dev *pwdev = padapter->rtw_wdev; - - DBG_8723A("%s(padapter =%p)\n", __func__, padapter); - - if (pwdev->iftype != NL80211_IFTYPE_STATION && - pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT) - return; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return; - - if (!padapter->mlmepriv.not_indic_disco) { - if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) { - cfg80211_connect_result(padapter->pnetdev, NULL, NULL, - 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_ATOMIC); - } else { - cfg80211_disconnected(padapter->pnetdev, 0, NULL, - 0, false, GFP_ATOMIC); - } - } -} - -#ifdef CONFIG_8723AU_AP_MODE -static int set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (ph2c == NULL) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL); - if (psetstakey_para == NULL) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - - psetstakey_para->algorithm = psta->dot118021XPrivacy; - - ether_addr_copy(psetstakey_para->addr, psta->hwaddr); - - memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - return res; -} - -static int set_group_key(struct rtw_adapter *padapter, struct key_params *parms, - u32 alg, u8 keyid) -{ - struct cmd_obj *pcmd; - struct setkey_parm *psetkeyparm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - DBG_8723A("%s\n", __func__); - - if (keyid >= 4) { - res = _FAIL; - goto exit; - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; - goto exit; - } - psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL); - if (!psetkeyparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - psetkeyparm->keyid = keyid; - if (is_wep_enc(alg)) - padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid); - - psetkeyparm->algorithm = alg; - - psetkeyparm->set_tx = 1; - - memcpy(&psetkeyparm->key, parms->key, parms->key_len); - - pcmd->cmdcode = _SetKey_CMD_; - pcmd->parmbuf = (u8 *) psetkeyparm; - pcmd->cmdsz = sizeof(struct setkey_parm); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - return res; -} - -static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, u8 key_index, - int set_tx, const u8 *sta_addr, - struct key_params *keyparms) -{ - int key_len; - struct sta_info *psta = NULL, *pbcmc_sta = NULL; - struct rtw_adapter *padapter = netdev_priv(dev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A("%s\n", __func__); - - if (!is_broadcast_ether_addr(sta_addr)) { - psta = rtw_get_stainfo23a(pstapriv, sta_addr); - if (!psta) { - /* ret = -EINVAL; */ - DBG_8723A("rtw_set_encryption(), sta has already " - "been removed or never been added\n"); - goto exit; - } - } - - key_len = keyparms->key_len; - - if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) { - DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n"); - - DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n", - key_index, key_len); - - if (psecuritypriv->bWepDefaultKeyIdxSet == 0) { - /* wep default key has not been set, so use - this key index as default key. */ - - psecuritypriv->ndisencryptstatus = - Ndis802_11Encryption1Enabled; - psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher; - psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher; - - psecuritypriv->dot11PrivacyKeyIndex = key_index; - } - - memcpy(&psecuritypriv->wep_key[key_index].key, - keyparms->key, key_len); - - psecuritypriv->wep_key[key_index].keylen = key_len; - - set_group_key(padapter, keyparms, keyparms->cipher, key_index); - - goto exit; - } - - if (!psta) { /* group key */ - if (set_tx == 0) { /* group key */ - if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { - DBG_8723A("%s, set group_key, WEP\n", __func__); - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, key_len); - - psecuritypriv->dot118021XGrpPrivacy = - keyparms->cipher; - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { - DBG_8723A("%s, set group_key, TKIP\n", - __func__); - - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_TKIP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - - /* set mic key */ - memcpy(psecuritypriv-> - dot118021XGrptxmickey[key_index].skey, - &keyparms->key[16], 8); - memcpy(psecuritypriv-> - dot118021XGrprxmickey[key_index].skey, - &keyparms->key[24], 8); - - psecuritypriv->busetkipkey = 1; - - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { - DBG_8723A("%s, set group_key, CCMP\n", - __func__); - - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_CCMP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - } else { - DBG_8723A("%s, set group_key, none\n", - __func__); - - psecuritypriv->dot118021XGrpPrivacy = 0; - } - - psecuritypriv->dot118021XGrpKeyid = key_index; - - psecuritypriv->binstallGrpkey = 1; - - psecuritypriv->dot11PrivacyAlgrthm = - psecuritypriv->dot118021XGrpPrivacy; - - set_group_key(padapter, keyparms, - psecuritypriv->dot118021XGrpPrivacy, - key_index); - - pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (pbcmc_sta) { - pbcmc_sta->ieee8021x_blocked = false; - /* rx will use bmc_sta's dot118021XPrivacy */ - pbcmc_sta->dot118021XPrivacy = - psecuritypriv->dot118021XGrpPrivacy; - - } - - } - - goto exit; - } - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { - /* psk/802_1x */ - if (set_tx == 1) { - /* pairwise key */ - memcpy(psta->dot118021x_UncstKey.skey, - keyparms->key, (min(16, key_len))); - - if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { - DBG_8723A("%s, set pairwise key, WEP\n", - __func__); - - psecuritypriv->dot118021XGrpPrivacy = - keyparms->cipher; - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { - DBG_8723A("%s, set pairwise key, TKIP\n", - __func__); - - psta->dot118021XPrivacy = - WLAN_CIPHER_SUITE_TKIP; - - /* set mic key */ - memcpy(psta->dot11tkiptxmickey.skey, - &keyparms->key[16], 8); - memcpy(psta->dot11tkiprxmickey.skey, - &keyparms->key[24], 8); - - psecuritypriv->busetkipkey = 1; - - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { - DBG_8723A("%s, set pairwise key, CCMP\n", - __func__); - - psta->dot118021XPrivacy = - WLAN_CIPHER_SUITE_CCMP; - } else { - DBG_8723A("%s, set pairwise key, none\n", - __func__); - - psta->dot118021XPrivacy = 0; - } - - set_pairwise_key(padapter, psta); - - psta->ieee8021x_blocked = false; - - psta->bpairwise_key_installed = true; - } else { /* group key??? */ - if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, key_len); - - psecuritypriv->dot118021XGrpPrivacy = - keyparms->cipher; - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_TKIP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - - /* set mic key */ - memcpy(psecuritypriv-> - dot118021XGrptxmickey[key_index].skey, - &keyparms->key[16], 8); - memcpy(psecuritypriv-> - dot118021XGrprxmickey[key_index].skey, - &keyparms->key[24], 8); - - psecuritypriv->busetkipkey = 1; - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_CCMP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - } else { - psecuritypriv->dot118021XGrpPrivacy = 0; - } - - psecuritypriv->dot118021XGrpKeyid = key_index; - - psecuritypriv->binstallGrpkey = 1; - - psecuritypriv->dot11PrivacyAlgrthm = - psecuritypriv->dot118021XGrpPrivacy; - - set_group_key(padapter, keyparms, - psecuritypriv->dot118021XGrpPrivacy, - key_index); - - pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (pbcmc_sta) { - /* rx will use bmc_sta's - dot118021XPrivacy */ - pbcmc_sta->ieee8021x_blocked = false; - pbcmc_sta->dot118021XPrivacy = - psecuritypriv->dot118021XGrpPrivacy; - } - } - } - -exit: - - return 0; -} -#endif - -static int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index, - int set_tx, const u8 *sta_addr, - struct key_params *keyparms) -{ - int ret = 0; - int key_len; - struct rtw_adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s\n", __func__); - - key_len = keyparms->key_len; - - if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, - "wpa_set_encryption, crypt.alg = WEP\n"); - DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n"); - - if (psecuritypriv->bWepDefaultKeyIdxSet == 0) { - /* wep default key has not been set, so use this - key index as default key. */ - - psecuritypriv->ndisencryptstatus = - Ndis802_11Encryption1Enabled; - psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher; - psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher; - - psecuritypriv->dot11PrivacyKeyIndex = key_index; - } - - memcpy(&psecuritypriv->wep_key[key_index].key, - keyparms->key, key_len); - - psecuritypriv->wep_key[key_index].keylen = key_len; - - rtw_set_key23a(padapter, psecuritypriv, key_index, 0); - - goto exit; - } - - if (padapter->securitypriv.dot11AuthAlgrthm == - dot11AuthAlgrthm_8021X) { /* 802_1x */ - struct sta_info *psta, *pbcmc_sta; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (check_fwstate(pmlmepriv, - WIFI_STATION_STATE | WIFI_MP_STATE)) { - /* sta mode */ - psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv)); - if (psta == NULL) { - DBG_8723A("%s, : Obtain Sta_info fail\n", - __func__); - } else { - /* Jeff: don't disable ieee8021x_blocked - while clearing key */ - if (keyparms->cipher != IW_AUTH_CIPHER_NONE && - keyparms->cipher != 0) - psta->ieee8021x_blocked = false; - - if ((padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption2Enabled) || - (padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption3Enabled)) { - psta->dot118021XPrivacy = - padapter->securitypriv. - dot11PrivacyAlgrthm; - } - - if (set_tx == 1) { - /* pairwise key */ - DBG_8723A("%s, : set_tx == 1\n", - __func__); - - memcpy(psta->dot118021x_UncstKey.skey, - keyparms->key, - (min(16, key_len))); - - if (keyparms->cipher == - WLAN_CIPHER_SUITE_TKIP) { - memcpy(psta->dot11tkiptxmickey. - skey, - &keyparms->key[16], 8); - memcpy(psta->dot11tkiprxmickey. - skey, - &keyparms->key[24], 8); - - padapter->securitypriv. - busetkipkey = 0; - } - DBG_8723A(" ~~~~set sta key:unicastkey\n"); - - rtw_setstakey_cmd23a(padapter, - (unsigned char *)psta, - true); - } else { /* group key */ - memcpy(padapter->securitypriv. - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - memcpy(padapter->securitypriv. - dot118021XGrptxmickey[key_index]. - skey, &keyparms->key[16], 8); - memcpy(padapter->securitypriv. - dot118021XGrprxmickey[key_index]. - skey, &keyparms->key[24], 8); - padapter->securitypriv.binstallGrpkey = - 1; - DBG_8723A - (" ~~~~set sta key:groupkey\n"); - - padapter->securitypriv. - dot118021XGrpKeyid = key_index; - - rtw_set_key23a(padapter, - &padapter->securitypriv, - key_index, 1); - } - } - - pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (pbcmc_sta) { - /* Jeff: don't disable ieee8021x_blocked - while clearing key */ - if (keyparms->cipher != IW_AUTH_CIPHER_NONE && - keyparms->cipher != 0) - pbcmc_sta->ieee8021x_blocked = false; - - if ((padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption2Enabled) || - (padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption3Enabled)) { - pbcmc_sta->dot118021XPrivacy = - padapter->securitypriv. - dot11PrivacyAlgrthm; - } - } - } - } - -exit: - - DBG_8723A("%s, ret =%d\n", __func__, ret); - - - - return ret; -} - -static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, bool pairwise, - const u8 *mac_addr, struct key_params *params) -{ - int set_tx, ret = 0; - struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy); - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 sta_addr[ETH_ALEN]; - - DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name, - mac_addr); - DBG_8723A("cipher = 0x%x\n", params->cipher); - DBG_8723A("key_len = 0x%x\n", params->key_len); - DBG_8723A("seq_len = 0x%x\n", params->seq_len); - DBG_8723A("key_index =%d\n", key_index); - DBG_8723A("pairwise =%d\n", pairwise); - - switch (params->cipher) { - case IW_AUTH_CIPHER_NONE: - case WLAN_CIPHER_SUITE_WEP40: - if (params->key_len != WLAN_KEY_LEN_WEP40) { - ret = -EINVAL; - goto exit; - } - case WLAN_CIPHER_SUITE_WEP104: - if (params->key_len != WLAN_KEY_LEN_WEP104) { - ret = -EINVAL; - goto exit; - } - case WLAN_CIPHER_SUITE_TKIP: - case WLAN_CIPHER_SUITE_CCMP: - break; - default: - ret = -ENOTSUPP; - goto exit; - } - - if (key_index >= WEP_KEYS || params->key_len < 0) { - ret = -EINVAL; - goto exit; - } - - eth_broadcast_addr(sta_addr); - - if (!mac_addr || is_broadcast_ether_addr(mac_addr)) - set_tx = 0; /* for wpa/wpa2 group key */ - else - set_tx = 1; /* for wpa/wpa2 pairwise key */ - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ret = rtw_cfg80211_set_encryption(ndev, key_index, set_tx, - sta_addr, params); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { -#ifdef CONFIG_8723AU_AP_MODE - if (mac_addr) - ether_addr_copy(sta_addr, mac_addr); - - ret = rtw_cfg80211_ap_set_encryption(ndev, key_index, set_tx, - sta_addr, params); -#endif - } else { - DBG_8723A("error! fw_state = 0x%x, iftype =%d\n", - pmlmepriv->fw_state, rtw_wdev->iftype); - - } - -exit: - return ret; -} - -static int -cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, bool pairwise, const u8 *mac_addr, - void *cookie, - void (*callback) (void *cookie, struct key_params *)) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, bool pairwise, - const u8 *mac_addr) -{ - struct rtw_adapter *padapter = netdev_priv(ndev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index); - - if (key_index == psecuritypriv->dot11PrivacyKeyIndex) { - /* clear the flag of wep default key set. */ - psecuritypriv->bWepDefaultKeyIdxSet = 0; - } - - return 0; -} - -static int cfg80211_rtw_set_default_key(struct wiphy *wiphy, - struct net_device *ndev, u8 key_index, - bool unicast, bool multicast) -{ - struct rtw_adapter *padapter = netdev_priv(ndev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n", - __func__, ndev->name, key_index, unicast, multicast); - - if (key_index < NUM_WEP_KEYS && - (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 || - psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) { - /* set wep default key */ - psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; - - psecuritypriv->dot11PrivacyKeyIndex = key_index; - - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; - if (psecuritypriv->wep_key[key_index].keylen == 13) { - psecuritypriv->dot11PrivacyAlgrthm = - WLAN_CIPHER_SUITE_WEP104; - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP104; - } - - /* set the flag to represent that wep default key - has been set */ - psecuritypriv->bWepDefaultKeyIdxSet = 1; - } - - return 0; -} - -static u16 rtw_get_cur_max_rate(struct rtw_adapter *adapter) -{ - int i = 0; - const u8 *p; - u16 rate = 0, max_rate = 0; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - struct ieee80211_ht_cap *pht_capie; - u8 rf_type = 0; - u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0; - u16 mcs_rate = 0; - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, - pcur_bss->IEs, pcur_bss->IELength); - if (p && p[1] > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - - memcpy(&mcs_rate, &pht_capie->mcs, 2); - - /* bw_40MHz = (pht_capie->cap_info& - IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */ - /* cur_bwmod is updated by beacon, pmlmeinfo is - updated by association response */ - bw_40MHz = (pmlmeext->cur_bwmode && - (pmlmeinfo->HT_info.ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) ? 1:0; - - /* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP - _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */ - short_GI_20 = (pmlmeinfo->ht_cap.cap_info & - cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) ? 1:0; - short_GI_40 = (pmlmeinfo->ht_cap.cap_info & - cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) ? 1:0; - - rf_type = rtl8723a_get_rf_type(adapter); - max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz & - pregistrypriv->cbw40_enable, - short_GI_20, short_GI_40, - &pmlmeinfo->ht_cap.mcs); - } else { - while (pcur_bss->SupportedRates[i] != 0 && - pcur_bss->SupportedRates[i] != 0xFF) { - rate = pcur_bss->SupportedRates[i] & 0x7F; - if (rate > max_rate) - max_rate = rate; - i++; - } - - max_rate = max_rate * 10 / 2; - } - - return max_rate; -} - -static int cfg80211_rtw_get_station(struct wiphy *wiphy, - struct net_device *ndev, - const u8 *mac, struct station_info *sinfo) -{ - int ret = 0; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - - sinfo->filled = 0; - - if (!mac) { - DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac); - ret = -ENOENT; - goto exit; - } - - psta = rtw_get_stainfo23a(pstapriv, mac); - if (psta == NULL) { - DBG_8723A("%s, sta_info is null\n", __func__); - ret = -ENOENT; - goto exit; - } - DBG_8723A("%s(%s): mac=%pM\n", __func__, ndev->name, mac); - - /* for infra./P2PClient mode */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - struct wlan_network *cur_network = &pmlmepriv->cur_network; - - if (!ether_addr_equal(mac, cur_network->network.MacAddress)) { - DBG_8723A("%s, mismatch bssid=%pM\n", - __func__, cur_network->network.MacAddress); - ret = -ENOENT; - goto exit; - } - - sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); - sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv. - signal_strength); - - sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); - sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter); - - sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); - sinfo->rx_packets = sta_rx_data_pkts(psta); - - sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); - sinfo->tx_packets = psta->sta_stats.tx_pkts; - } - - /* for Ad-Hoc/AP mode */ - if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_AP_STATE)) && - check_fwstate(pmlmepriv, _FW_LINKED) - ) { - /* TODO: should acquire station info... */ - } - -exit: - return ret; -} - -static int cfg80211_infrastructure_mode(struct rtw_adapter *padapter, - enum nl80211_iftype ifmode) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - enum nl80211_iftype old_mode; - - old_mode = cur_network->network.ifmode; - - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_, - "+%s: old =%d new =%d fw_state = 0x%08x\n", __func__, - old_mode, ifmode, get_fwstate(pmlmepriv)); - - if (old_mode != ifmode) { - spin_lock_bh(&pmlmepriv->lock); - - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "change mode!\n"); - - if (old_mode == NL80211_IFTYPE_AP || - old_mode == NL80211_IFTYPE_P2P_GO) { - /* change to other mode from Ndis802_11APMode */ - cur_network->join_res = -1; - -#ifdef CONFIG_8723AU_AP_MODE - stop_ap_mode23a(padapter); -#endif - } - - if (check_fwstate(pmlmepriv, _FW_LINKED) || - old_mode == NL80211_IFTYPE_ADHOC) - rtw_disassoc_cmd23a(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) - rtw_free_assoc_resources23a(padapter, 1); - - if (old_mode == NL80211_IFTYPE_STATION || - old_mode == NL80211_IFTYPE_P2P_CLIENT || - old_mode == NL80211_IFTYPE_ADHOC) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - /* will clr Linked_state; before this function, - we must have chked whether issue - dis-assoc_cmd or not */ - rtw_indicate_disconnect23a(padapter); - } - } - - cur_network->network.ifmode = ifmode; - - _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE); - - switch (ifmode) { - case NL80211_IFTYPE_ADHOC: - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - break; - - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - set_fwstate(pmlmepriv, WIFI_STATION_STATE); - break; - - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - set_fwstate(pmlmepriv, WIFI_AP_STATE); -#ifdef CONFIG_8723AU_AP_MODE - start_ap_mode23a(padapter); - /* rtw_indicate_connect23a(padapter); */ -#endif - break; - - default: - break; - } - - /* SecClearAllKeys(adapter); */ - - spin_unlock_bh(&pmlmepriv->lock); - } - - return _SUCCESS; -} - -static int cfg80211_rtw_change_iface(struct wiphy *wiphy, - struct net_device *ndev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - enum nl80211_iftype old_type; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy); - int ret = 0; - - DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name); - - old_type = rtw_wdev->iftype; - DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n", - __func__, ndev->name, old_type, type); - - if (old_type != type) { - pmlmeext->action_public_rxseq = 0xffff; - pmlmeext->action_public_dialog_token = 0xff; - } - - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_UNSPECIFIED: - break; - default: - return -EOPNOTSUPP; - } - - rtw_wdev->iftype = type; - - if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) { - rtw_wdev->iftype = old_type; - ret = -EPERM; - goto exit; - } - - rtw_setopmode_cmd23a(padapter, type); - -exit: - return ret; -} - -void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv, - bool aborted) -{ - spin_lock_bh(&pwdev_priv->scan_req_lock); - if (pwdev_priv->scan_request != NULL) { - DBG_8723A("%s with scan req\n", __func__); - - if (pwdev_priv->scan_request->wiphy != - pwdev_priv->rtw_wdev->wiphy) { - DBG_8723A("error wiphy compare\n"); - } else { - struct cfg80211_scan_info info = { - .aborted = aborted, - }; - - cfg80211_scan_done(pwdev_priv->scan_request, &info); - } - - pwdev_priv->scan_request = NULL; - } else { - DBG_8723A("%s without scan req\n", __func__); - } - spin_unlock_bh(&pwdev_priv->scan_req_lock); -} - -void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork, *ptmp; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - phead = get_list_head(queue); - list_for_each_entry_safe(pnetwork, ptmp, phead, list) { - /* report network only if the current channel set - contains the channel to which this network belongs */ - if (rtw_ch_set_search_ch23a - (padapter->mlmeextpriv.channel_set, - pnetwork->network.DSConfig) >= 0) - rtw_cfg80211_inform_bss(padapter, pnetwork); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - /* call this after other things have been done */ - rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev), - false); -} - -static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter, - char *buf, int len) -{ - int ret = 0; - const u8 *wps_ie; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - DBG_8723A("%s, ielen =%d\n", __func__, len); - - if (len > 0) { - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - buf, len); - if (wps_ie) { - DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]); - - if (pmlmepriv->wps_probe_req_ie) { - pmlmepriv->wps_probe_req_ie_len = 0; - kfree(pmlmepriv->wps_probe_req_ie); - pmlmepriv->wps_probe_req_ie = NULL; - } - - pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1], - GFP_KERNEL); - if (pmlmepriv->wps_probe_req_ie == NULL) { - DBG_8723A("%s()-%d: kmalloc() ERROR!\n", - __func__, __LINE__); - return -EINVAL; - } - pmlmepriv->wps_probe_req_ie_len = wps_ie[1]; - } - } - - return ret; -} - -static int cfg80211_rtw_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request) -{ - int i; - u8 _status = false; - int ret = 0; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT]; - struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev); - struct cfg80211_ssid *ssids = request->ssids; - bool need_indicate_scan_done = false; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - spin_lock_bh(&pwdev_priv->scan_req_lock); - pwdev_priv->scan_request = request; - spin_unlock_bh(&pwdev_priv->scan_req_lock); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - DBG_8723A("%s under WIFI_AP_STATE\n", __func__); - /* need_indicate_scan_done = true; */ - /* goto check_need_indicate_scan_done; */ - } - - if (rtw_pwr_wakeup(padapter) == _FAIL) { - need_indicate_scan_done = true; - goto check_need_indicate_scan_done; - } - - if (request->ie && request->ie_len > 0) { - rtw_cfg80211_set_probe_req_wpsp2pie(padapter, - (u8 *) request->ie, - request->ie_len); - } - - if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) { - DBG_8723A("%s, bBusyTraffic == true\n", __func__); - need_indicate_scan_done = true; - goto check_need_indicate_scan_done; - } - if (rtw_is_scan_deny(padapter)) { - DBG_8723A("%s(%s): scan deny\n", __func__, - padapter->pnetdev->name); - need_indicate_scan_done = true; - goto check_need_indicate_scan_done; - } - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == - true) { - DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state); - need_indicate_scan_done = true; - goto check_need_indicate_scan_done; - } - - memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT); - /* parsing request ssids, n_ssids */ - for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) { - DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid, - ssids[i].ssid_len); - memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len); - ssid[i].ssid_len = ssids[i].ssid_len; - } - - /* parsing channels, n_channels */ - memset(ch, 0, - sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT); - - if (request->n_channels == 1) { - for (i = 0; i < request->n_channels && - i < RTW_CHANNEL_SCAN_AMOUNT; i++) { - DBG_8723A("%s:(%s):" CHAN_FMT "\n", - __func__, padapter->pnetdev->name, - CHAN_ARG(request->channels[i])); - ch[i].hw_value = request->channels[i]->hw_value; - ch[i].flags = request->channels[i]->flags; - } - } - - spin_lock_bh(&pmlmepriv->lock); - if (request->n_channels == 1) { - memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel)); - memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel)); - _status = rtw_sitesurvey_cmd23a(padapter, ssid, - RTW_SSID_SCAN_AMOUNT, ch, 3); - } else { - _status = rtw_sitesurvey_cmd23a(padapter, ssid, - RTW_SSID_SCAN_AMOUNT, NULL, 0); - } - spin_unlock_bh(&pmlmepriv->lock); - - if (_status == false) - ret = -1; - -check_need_indicate_scan_done: - if (need_indicate_scan_done) - rtw_cfg80211_surveydone_event_callback(padapter); - return ret; -} - -static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed) -{ - DBG_8723A("%s\n", __func__); - return 0; -} - -static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_ibss_params *params) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, - u32 wpa_version) -{ - DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version); - - if (!wpa_version) { - psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; - return 0; - } - - if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) - psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK; - -/* - if (wpa_version & NL80211_WPA_VERSION_2) - { - psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK; - } -*/ - - return 0; -} - -static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv, - enum nl80211_auth_type sme_auth_type) -{ - DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type); - - switch (sme_auth_type) { - case NL80211_AUTHTYPE_AUTOMATIC: - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto; - - break; - case NL80211_AUTHTYPE_OPEN_SYSTEM: - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - - if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA) - psecuritypriv->dot11AuthAlgrthm = - dot11AuthAlgrthm_8021X; - break; - case NL80211_AUTHTYPE_SHARED_KEY: - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; - - psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - default: - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - /* return -ENOTSUPP; */ - } - - return 0; -} - -static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, - u32 cipher, bool ucast) -{ - u32 ndisencryptstatus = Ndis802_11EncryptionDisabled; - - u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm : - &psecuritypriv->dot118021XGrpPrivacy; - - DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher); - - if (!cipher) { - *profile_cipher = 0; - psecuritypriv->ndisencryptstatus = ndisencryptstatus; - return 0; - } - - switch (cipher) { - case IW_AUTH_CIPHER_NONE: - *profile_cipher = 0; - ndisencryptstatus = Ndis802_11EncryptionDisabled; - break; - case WLAN_CIPHER_SUITE_WEP40: - *profile_cipher = WLAN_CIPHER_SUITE_WEP40; - ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - case WLAN_CIPHER_SUITE_WEP104: - *profile_cipher = WLAN_CIPHER_SUITE_WEP104; - ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - case WLAN_CIPHER_SUITE_TKIP: - *profile_cipher = WLAN_CIPHER_SUITE_TKIP; - ndisencryptstatus = Ndis802_11Encryption2Enabled; - break; - case WLAN_CIPHER_SUITE_CCMP: - *profile_cipher = WLAN_CIPHER_SUITE_CCMP; - ndisencryptstatus = Ndis802_11Encryption3Enabled; - break; - default: - DBG_8723A("Unsupported cipher: 0x%x\n", cipher); - return -ENOTSUPP; - } - - if (ucast) - psecuritypriv->ndisencryptstatus = ndisencryptstatus; - - return 0; -} - -static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv, - u32 key_mgt) -{ - DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt); - - if (key_mgt == WLAN_AKM_SUITE_8021X) - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - else if (key_mgt == WLAN_AKM_SUITE_PSK) - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - else - DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt); - - return 0; -} - -static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, - size_t ielen) -{ - const u8 *wps_ie; - int group_cipher = 0, pairwise_cipher = 0; - int ret = 0; - const u8 *pwpa, *pwpa2; - int i; - - if (!pie || !ielen) { - /* Treat this as normal case, but need to clear - WIFI_UNDER_WPS */ - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - goto exit; - } - if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) { - ret = -EINVAL; - goto exit; - } - - /* dump */ - DBG_8723A("set wpa_ie(length:%zu):\n", ielen); - for (i = 0; i < ielen; i = i + 8) - DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x " - "0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", - pie[i], pie[i + 1], pie[i + 2], pie[i + 3], - pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]); - if (ielen < RSN_HEADER_LEN) { - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, - "Ie len too short %d\n", (int)ielen); - ret = -1; - goto exit; - } - - pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pie, ielen); - if (pwpa && pwpa[1] > 0) { - if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - padapter->securitypriv.dot11AuthAlgrthm = - dot11AuthAlgrthm_8021X; - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeWPAPSK; - memcpy(padapter->securitypriv.supplicant_ie, pwpa, - pwpa[1] + 2); - - DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]); - } - } - - pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen); - if (pwpa2 && pwpa2[1] > 0) { - if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - padapter->securitypriv.dot11AuthAlgrthm = - dot11AuthAlgrthm_8021X; - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeWPA2PSK; - memcpy(padapter->securitypriv.supplicant_ie, pwpa2, - pwpa2[1] + 2); - - DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]); - } - } - - if (group_cipher == 0) { - group_cipher = WPA_CIPHER_NONE; - } - if (pairwise_cipher == 0) { - pairwise_cipher = WPA_CIPHER_NONE; - } - - switch (group_cipher) { - case WPA_CIPHER_NONE: - padapter->securitypriv.dot118021XGrpPrivacy = 0; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11EncryptionDisabled; - break; - case WPA_CIPHER_WEP40: - padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - break; - case WPA_CIPHER_TKIP: - padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption2Enabled; - break; - case WPA_CIPHER_CCMP: - padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption3Enabled; - break; - case WPA_CIPHER_WEP104: - padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - break; - } - - switch (pairwise_cipher) { - case WPA_CIPHER_NONE: - padapter->securitypriv.dot11PrivacyAlgrthm = 0; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11EncryptionDisabled; - break; - case WPA_CIPHER_WEP40: - padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - break; - case WPA_CIPHER_TKIP: - padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption2Enabled; - break; - case WPA_CIPHER_CCMP: - padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption3Enabled; - break; - case WPA_CIPHER_WEP104: - padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - break; - } - - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - pie, ielen); - if (wps_ie && wps_ie[1] > 0) { - DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ie[1]); - padapter->securitypriv.wps_ie_len = wps_ie[1]; - memcpy(padapter->securitypriv.wps_ie, wps_ie, - padapter->securitypriv.wps_ie_len); - set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); - } else { - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - } - - /* TKIP and AES disallow multicast packets until installing group key */ - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_TKIP || - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) - /* WPS open need to enable multicast */ - /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/ - rtl8723a_off_rcr_am(padapter); - - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, - "rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n", - pairwise_cipher, - padapter->securitypriv.ndisencryptstatus, - padapter->securitypriv.ndisauthtype); - -exit: - if (ret) - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - return ret; -} - -static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter, - struct rtw_wep_key *wep, u8 keyid) -{ - int res; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - if (keyid >= NUM_WEP_KEYS) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, - "%s:keyid>4 =>fail\n", __func__); - res = _FAIL; - goto exit; - } - - switch (wep->keylen) { - case WLAN_KEY_LEN_WEP40: - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:wep->KeyLength = 5\n", __func__); - break; - case WLAN_KEY_LEN_WEP104: - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:wep->KeyLength = 13\n", __func__); - break; - default: - psecuritypriv->dot11PrivacyAlgrthm = 0; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:wep->KeyLength!= 5 or 13\n", __func__); - res = _FAIL; - goto exit; - } - - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n", - __func__, wep->keylen, keyid); - - memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key)); - - psecuritypriv->dot11PrivacyKeyIndex = keyid; - - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n", - __func__, - psecuritypriv->wep_key[keyid].key[0], - psecuritypriv->wep_key[keyid].key[1], - psecuritypriv->wep_key[keyid].key[2], - psecuritypriv->wep_key[keyid].key[3], - psecuritypriv->wep_key[keyid].key[4], - psecuritypriv->wep_key[keyid].key[5], - psecuritypriv->wep_key[keyid].key[6], - psecuritypriv->wep_key[keyid].key[7], - psecuritypriv->wep_key[keyid].key[8], - psecuritypriv->wep_key[keyid].key[9], - psecuritypriv->wep_key[keyid].key[10], - psecuritypriv->wep_key[keyid].key[11], - psecuritypriv->wep_key[keyid].key[12]); - - res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1); - -exit: - - return res; -} - -static int rtw_set_ssid(struct rtw_adapter *padapter, - struct wlan_network *newnetwork) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *pnetwork = &pmlmepriv->cur_network; - int status = _SUCCESS; - u32 cur_time = 0; - - DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n", - newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv)); - - if (padapter->hw_init_completed == false) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, - "set_ssid: hw_init_completed == false =>exit!!!\n"); - status = _FAIL; - goto exit; - } - - spin_lock_bh(&pmlmepriv->lock); - - DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv)); - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - goto handle_tkip_countermeasure; - - if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"); - - if (pmlmepriv->assoc_ssid.ssid_len == - newnetwork->network.Ssid.ssid_len && - !memcmp(&pmlmepriv->assoc_ssid.ssid, - newnetwork->network.Ssid.ssid, - newnetwork->network.Ssid.ssid_len)) { - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, - _drv_err_, - "New SSID is same SSID, fw_state = 0x%08x\n", - get_fwstate(pmlmepriv)); - - if (rtw_is_same_ibss23a(padapter, pnetwork)) { - /* - * it means driver is in - * WIFI_ADHOC_MASTER_STATE, we needn't - * create bss again. - */ - goto release_mlme_lock; - } - - /* - * if in WIFI_ADHOC_MASTER_STATE | - * WIFI_ADHOC_STATE, create bss or - * rejoin again - */ - rtw_disassoc_cmd23a(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_indicate_disconnect23a(padapter); - - rtw_free_assoc_resources23a(padapter, 1); - - if (check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, - WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, - WIFI_ADHOC_STATE); - } - } else { - rtw_lps_ctrl_wk_cmd23a(padapter, - LPS_CTRL_JOINBSS, 1); - } - } else { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "Set SSID not the same ssid\n"); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "set_ssid =[%s] len = 0x%x\n", - newnetwork->network.Ssid.ssid, - newnetwork->network.Ssid.ssid_len); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "assoc_ssid =[%s] len = 0x%x\n", - pmlmepriv->assoc_ssid.ssid, - pmlmepriv->assoc_ssid.ssid_len); - - rtw_disassoc_cmd23a(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_indicate_disconnect23a(padapter); - - rtw_free_assoc_resources23a(padapter, 1); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - } - } - } - -handle_tkip_countermeasure: - - if (padapter->securitypriv.btkip_countermeasure == true) { - cur_time = jiffies; - - if ((cur_time - - padapter->securitypriv.btkip_countermeasure_time) > - 60 * HZ) { - padapter->securitypriv.btkip_countermeasure = false; - padapter->securitypriv.btkip_countermeasure_time = 0; - } else { - status = _FAIL; - goto release_mlme_lock; - } - } - - memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid, - sizeof(struct cfg80211_ssid)); - - pmlmepriv->assoc_by_bssid = false; - - pmlmepriv->to_join = true; - - if (!check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - pmlmepriv->cur_network.join_res = -2; - - status = rtw_do_join_network(padapter, newnetwork); - if (status == _SUCCESS) { - pmlmepriv->to_join = false; - } else { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - /* switch to ADHOC_MASTER */ - status = rtw_do_join_adhoc(padapter); - if (status != _SUCCESS) - goto release_mlme_lock; - } else { - /* can't associate ; reset under-linking */ - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - status = _FAIL; - pmlmepriv->to_join = false; - } - } - } -release_mlme_lock: - spin_unlock_bh(&pmlmepriv->lock); - -exit: - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, - "-%s: status =%d\n", __func__, status); - - return status; -} - -static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_connect_params *sme) -{ - int ret = 0; - struct list_head *phead, *plist, *ptmp; - struct wlan_network *pnetwork = NULL; - /* u8 matched_by_bssid = false; */ - /* u8 matched_by_ssid = false; */ - u8 matched = false; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - - DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name); - DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n", - sme->privacy, sme->key, sme->key_len, sme->key_idx); - - if (_FAIL == rtw_pwr_wakeup(padapter)) { - ret = -EPERM; - goto exit; - } - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - ret = -EPERM; - goto exit; - } - - if (!sme->ssid || !sme->ssid_len || - sme->ssid_len > IEEE80211_MAX_SSID_LEN) { - ret = -EINVAL; - goto exit; - } - - DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len); - - if (sme->bssid) - DBG_8723A("bssid=%pM\n", sme->bssid); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - ret = -EBUSY; - DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__, - pmlmepriv->fw_state); - goto exit; - } - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - rtw_scan_abort23a(padapter); - } - - spin_lock_bh(&queue->lock); - - phead = get_list_head(queue); - - list_for_each_safe(plist, ptmp, phead) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (sme->bssid) { - if (!ether_addr_equal(pnetwork->network.MacAddress, - sme->bssid)) - continue; - } - - if (sme->ssid && sme->ssid_len) { - if (pnetwork->network.Ssid.ssid_len != sme->ssid_len || - memcmp(pnetwork->network.Ssid.ssid, sme->ssid, - sme->ssid_len)) - continue; - } - - if (sme->bssid) { - if (ether_addr_equal(pnetwork->network.MacAddress, - sme->bssid)) { - DBG_8723A("matched by bssid\n"); - - matched = true; - break; - } - } else if (sme->ssid && sme->ssid_len) { - if (!memcmp(pnetwork->network.Ssid.ssid, - sme->ssid, sme->ssid_len) && - pnetwork->network.Ssid.ssid_len == sme->ssid_len) { - DBG_8723A("matched by ssid\n"); - - matched = true; - break; - } - } - } - - spin_unlock_bh(&queue->lock); - - if (!matched || !pnetwork) { - ret = -ENOENT; - DBG_8723A("connect, matched == false, goto exit\n"); - goto exit; - } - - if (cfg80211_infrastructure_mode( - padapter, pnetwork->network.ifmode) != _SUCCESS) { - ret = -EPERM; - goto exit; - } - - psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled; - psecuritypriv->dot11PrivacyAlgrthm = 0; - psecuritypriv->dot118021XGrpPrivacy = 0; - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; - - ret = rtw_cfg80211_set_wpa_version(psecuritypriv, - sme->crypto.wpa_versions); - if (ret < 0) - goto exit; - - ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type); - - if (ret < 0) - goto exit; - - DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len); - - ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len); - if (ret < 0) - goto exit; - - if (sme->crypto.n_ciphers_pairwise) { - ret = rtw_cfg80211_set_cipher(psecuritypriv, - sme->crypto.ciphers_pairwise[0], - true); - if (ret < 0) - goto exit; - } - - /* For WEP Shared auth */ - if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared || - psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) && - sme->key) { - struct rtw_wep_key wep_key; - u8 wep_key_idx, wep_key_len; - DBG_8723A("%s(): Shared/Auto WEP\n", __func__); - - wep_key_idx = sme->key_idx; - wep_key_len = sme->key_len; - - if (wep_key_idx > WEP_KEYS || !wep_key_len || - wep_key_len > WLAN_KEY_LEN_WEP104) { - ret = -EINVAL; - goto exit; - } - - wep_key_len = wep_key_len <= 5 ? 5 : 13; - - memset(&wep_key, 0, sizeof(struct rtw_wep_key)); - - wep_key.keylen = wep_key_len; - - if (wep_key_len == 13) { - padapter->securitypriv.dot11PrivacyAlgrthm = - WLAN_CIPHER_SUITE_WEP104; - padapter->securitypriv.dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP104; - } else { - padapter->securitypriv.dot11PrivacyAlgrthm = - WLAN_CIPHER_SUITE_WEP40; - padapter->securitypriv.dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP40; - } - - memcpy(wep_key.key, (void *)sme->key, wep_key.keylen); - - if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) != - _SUCCESS) - ret = -EOPNOTSUPP; - - if (ret < 0) - goto exit; - } - - ret = rtw_cfg80211_set_cipher(psecuritypriv, - sme->crypto.cipher_group, false); - if (ret < 0) - goto exit; - - if (sme->crypto.n_akm_suites) { - ret = rtw_cfg80211_set_key_mgt(psecuritypriv, - sme->crypto.akm_suites[0]); - if (ret < 0) - goto exit; - } - - if (psecuritypriv->ndisauthtype > 3) - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - if (rtw_set_auth23a(padapter, psecuritypriv) != _SUCCESS) { - ret = -EBUSY; - goto exit; - } - - /* rtw_set_802_11_encryption_mode(padapter, - padapter->securitypriv.ndisencryptstatus); */ - - if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) { - ret = -EBUSY; - goto exit; - } - - DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, " - "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm, - psecuritypriv->dot11PrivacyAlgrthm, - psecuritypriv->dot118021XGrpPrivacy); - -exit: - - DBG_8723A("<=%s, ret %d\n", __func__, ret); - - return ret; -} - -static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev, - u16 reason_code) -{ - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - rtw_set_roaming(padapter, 0); - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - rtw_scan_abort23a(padapter); - LeaveAllPowerSaveMode23a(padapter); - rtw_disassoc_cmd23a(padapter, 500, false); - - DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__); - - padapter->mlmepriv.not_indic_disco = true; - rtw_indicate_disconnect23a(padapter); - padapter->mlmepriv.not_indic_disco = false; - - rtw_free_assoc_resources23a(padapter, 1); - } - - return 0; -} - -static int cfg80211_rtw_set_txpower(struct wiphy *wiphy, - struct wireless_dev *wdev, - enum nl80211_tx_power_setting type, int mbm) -{ - DBG_8723A("%s\n", __func__); - return 0; -} - -static int cfg80211_rtw_get_txpower(struct wiphy *wiphy, - struct wireless_dev *wdev, int *dbm) -{ - DBG_8723A("%s\n", __func__); - *dbm = 12; - return 0; -} - -inline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter) -{ - struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev); - return rtw_wdev_priv->power_mgmt; -} - -static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy, - struct net_device *ndev, - bool enabled, int timeout) -{ - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev); - - DBG_8723A("%s(%s): enabled:%u, timeout:%d\n", - __func__, ndev->name, enabled, timeout); - - rtw_wdev_priv->power_mgmt = enabled; - - if (!enabled) - LPS_Leave23a(padapter); - - return 0; -} - -static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy, - struct net_device *netdev, - struct cfg80211_pmksa *pmksa) -{ - u8 index, blInserted = false; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s)\n", __func__, netdev->name); - - if (is_zero_ether_addr(pmksa->bssid)) - return -EINVAL; - - blInserted = false; - - /* overwrite PMKID */ - for (index = 0; index < NUM_PMKID_CACHE; index++) { - if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid, - pmksa->bssid)) { - /* BSSID is matched, the same AP => rewrite with - new PMKID. */ - DBG_8723A("%s(%s): BSSID exists in the PMKList.\n", - __func__, netdev->name); - - memcpy(psecuritypriv->PMKIDList[index].PMKID, - pmksa->pmkid, WLAN_PMKID_LEN); - psecuritypriv->PMKIDList[index].bUsed = true; - psecuritypriv->PMKIDIndex = index + 1; - blInserted = true; - break; - } - } - - if (!blInserted) { - /* Find a new entry */ - DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n", - __func__, netdev->name, psecuritypriv->PMKIDIndex); - - ether_addr_copy( - psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex]. - Bssid, pmksa->bssid); - memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex]. - PMKID, pmksa->pmkid, WLAN_PMKID_LEN); - - psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = - true; - psecuritypriv->PMKIDIndex++; - if (psecuritypriv->PMKIDIndex == 16) { - psecuritypriv->PMKIDIndex = 0; - } - } - - return 0; -} - -static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy, - struct net_device *netdev, - struct cfg80211_pmksa *pmksa) -{ - u8 index, bMatched = false; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s)\n", __func__, netdev->name); - - for (index = 0; index < NUM_PMKID_CACHE; index++) { - if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid, - pmksa->bssid)) { - /* BSSID is matched, the same AP => Remove this PMKID - information and reset it. */ - eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid); - memset(psecuritypriv->PMKIDList[index].PMKID, 0x00, - WLAN_PMKID_LEN); - psecuritypriv->PMKIDList[index].bUsed = false; - bMatched = true; - break; - } - } - - if (false == bMatched) { - DBG_8723A("%s(%s): do not have matched BSSID\n", __func__, - netdev->name); - return -EINVAL; - } - - return 0; -} - -static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy, - struct net_device *netdev) -{ - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s)\n", __func__, netdev->name); - - memset(&psecuritypriv->PMKIDList[0], 0x00, - sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - psecuritypriv->PMKIDIndex = 0; - - return 0; -} - -#ifdef CONFIG_8723AU_AP_MODE -void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter, - u8 *pmgmt_frame, uint frame_len) -{ - s32 freq; - int channel; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct net_device *ndev = padapter->pnetdev; - - DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name); - -#if defined(RTW_USE_CFG80211_STA_EVENT) - { - struct station_info sinfo; - u8 ie_offset; - - if (ieee80211_is_assoc_req(hdr->frame_control)) - ie_offset = offsetof(struct ieee80211_mgmt, - u.assoc_req.variable); - else /* WIFI_REASSOCREQ */ - ie_offset = offsetof(struct ieee80211_mgmt, - u.reassoc_req.variable); - - sinfo.filled = 0; - sinfo.assoc_req_ies = pmgmt_frame + ie_offset; - sinfo.assoc_req_ies_len = frame_len - ie_offset; - cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC); - } -#else /* defined(RTW_USE_CFG80211_STA_EVENT) */ - channel = pmlmeext->cur_channel; - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len, - 0); -#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */ -} - -void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter, - unsigned char *da, - unsigned short reason) -{ - s32 freq; - int channel; - uint frame_len; - struct ieee80211_mgmt mgmt; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct net_device *ndev = padapter->pnetdev; - - DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name); - - memset(&mgmt, 0, sizeof(struct ieee80211_mgmt)); - -#if defined(RTW_USE_CFG80211_STA_EVENT) - cfg80211_del_sta(ndev, da, GFP_ATOMIC); -#else /* defined(RTW_USE_CFG80211_STA_EVENT) */ - channel = pmlmeext->cur_channel; - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - mgmt.frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - - ether_addr_copy(mgmt.da, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt.sa, da); - ether_addr_copy(mgmt.bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - mgmt.u.disassoc.reason_code = cpu_to_le16(reason); - - frame_len = sizeof(struct ieee80211_hdr_3addr) + 2; - - cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len, - 0); -#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */ -} - -static int rtw_cfg80211_monitor_if_open(struct net_device *ndev) -{ - DBG_8723A("%s\n", __func__); - - return 0; -} - -static int rtw_cfg80211_monitor_if_close(struct net_device *ndev) -{ - DBG_8723A("%s\n", __func__); - - return 0; -} - -static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, - struct net_device *ndev) -{ - int ret = 0; - int rtap_len; - int qos_len = 0; - int dot11_hdr_len = 24; - int snap_len = 6; - unsigned char *pdata; - unsigned char src_mac_addr[6]; - unsigned char dst_mac_addr[6]; - struct ieee80211_hdr *dot11_hdr; - struct ieee80211_radiotap_header *rtap_hdr; - struct rtw_adapter *padapter = netdev_priv(ndev); - - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) - goto fail; - - rtap_hdr = (struct ieee80211_radiotap_header *)skb->data; - if (unlikely(rtap_hdr->it_version)) - goto fail; - - rtap_len = ieee80211_get_radiotap_len(skb->data); - if (unlikely(skb->len < rtap_len)) - goto fail; - - if (rtap_len != 14) { - DBG_8723A("radiotap len (should be 14): %d\n", rtap_len); - goto fail; - } - - /* Skip the ratio tap header */ - skb_pull(skb, rtap_len); - - dot11_hdr = (struct ieee80211_hdr *)skb->data; - /* Check if the QoS bit is set */ - if (ieee80211_is_data(dot11_hdr->frame_control)) { - /* Check if this ia a Wireless Distribution System (WDS) frame - * which has 4 MAC addresses - */ - if (ieee80211_is_data_qos(dot11_hdr->frame_control)) - qos_len = IEEE80211_QOS_CTL_LEN; - if (ieee80211_has_a4(dot11_hdr->frame_control)) - dot11_hdr_len += 6; - - memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr)); - memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr)); - - /* - * Skip the 802.11 header, QoS (if any) and SNAP, - * but leave spaces for two MAC addresses - */ - skb_pull(skb, dot11_hdr_len + qos_len + snap_len - - ETH_ALEN * 2); - pdata = (unsigned char *)skb->data; - ether_addr_copy(pdata, dst_mac_addr); - ether_addr_copy(pdata + ETH_ALEN, src_mac_addr); - - DBG_8723A("should be eapol packet\n"); - - /* Use the real net device to transmit the packet */ - ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev); - - return ret; - - } else if (ieee80211_is_action(dot11_hdr->frame_control)) { - struct ieee80211_mgmt *mgmt; - /* only for action frames */ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - /* u8 category, action, OUI_Subtype, dialogToken = 0; */ - /* unsigned char *frame_body; */ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - u32 len = skb->len; - u8 category, action; - - mgmt = (struct ieee80211_mgmt *)dot11_hdr; - - DBG_8723A("RTW_Tx:da=%pM via %s(%s)\n", - mgmt->da, __func__, ndev->name); - category = mgmt->u.action.category; - action = mgmt->u.action.u.wme_action.action_code; - DBG_8723A("RTW_Tx:category(%u), action(%u)\n", - category, action); - - /* starting alloc mgmt frame to dump it */ - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (pmgntframe == NULL) - goto fail; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - - memcpy(pframe, skb->data, len); - pattrib->pktlen = len; - - /* update seq number */ - pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4; - pattrib->seqnum = pmlmeext->mgnt_seq; - pmlmeext->mgnt_seq++; - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); - } - -fail: - - dev_kfree_skb(skb); - - return 0; -} - -static int -rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr) -{ - DBG_8723A("%s\n", __func__); - - return 0; -} - -static const struct net_device_ops rtw_cfg80211_monitor_if_ops = { - .ndo_open = rtw_cfg80211_monitor_if_open, - .ndo_stop = rtw_cfg80211_monitor_if_close, - .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry, - .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address, -}; - -static int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name, - unsigned char name_assign_type, - struct net_device **ndev) -{ - int ret = 0; - struct net_device *mon_ndev = NULL; - struct wireless_dev *mon_wdev = NULL; - struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev); - - if (!name) { - DBG_8723A("%s(%s): without specific name\n", - __func__, padapter->pnetdev->name); - ret = -EINVAL; - goto out; - } - - if (pwdev_priv->pmon_ndev) { - DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__, - padapter->pnetdev->name, pwdev_priv->pmon_ndev->name); - ret = -EBUSY; - goto out; - } - - mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter)); - if (!mon_ndev) { - DBG_8723A("%s(%s): allocate ndev fail\n", __func__, - padapter->pnetdev->name); - ret = -ENOMEM; - goto out; - } - - mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP; - strncpy(mon_ndev->name, name, IFNAMSIZ); - mon_ndev->name[IFNAMSIZ - 1] = 0; - mon_ndev->name_assign_type = name_assign_type; - mon_ndev->destructor = rtw_ndev_destructor; - - mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops; - - /* wdev */ - mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!mon_wdev) { - ret = -ENOMEM; - goto out; - } - - mon_wdev->wiphy = padapter->rtw_wdev->wiphy; - mon_wdev->netdev = mon_ndev; - mon_wdev->iftype = NL80211_IFTYPE_MONITOR; - mon_ndev->ieee80211_ptr = mon_wdev; - - ret = register_netdevice(mon_ndev); - if (ret) { - goto out; - } - - *ndev = pwdev_priv->pmon_ndev = mon_ndev; - memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1); - -out: - if (ret) { - kfree(mon_wdev); - mon_wdev = NULL; - } - - if (ret && mon_ndev) { - free_netdev(mon_ndev); - *ndev = mon_ndev = NULL; - } - - return ret; -} - -static struct wireless_dev * -cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name, - unsigned char name_assign_type, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - int ret = 0; - struct net_device *ndev = NULL; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - - DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__, - padapter->pnetdev->name, wiphy_name(wiphy), name, type); - - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MESH_POINT: - ret = -ENODEV; - break; - case NL80211_IFTYPE_MONITOR: - ret = - rtw_cfg80211_add_monitor_if(padapter, (char *)name, - name_assign_type, &ndev); - break; - - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - ret = -ENODEV; - break; - - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - ret = -ENODEV; - break; - default: - ret = -ENODEV; - DBG_8723A("Unsupported interface type\n"); - break; - } - - DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__, - padapter->pnetdev->name, - ndev, ret); - - return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret); -} - -static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy, - struct wireless_dev *wdev) -{ - struct rtw_wdev_priv *pwdev_priv = - (struct rtw_wdev_priv *)wiphy_priv(wiphy); - struct net_device *ndev; - ndev = wdev ? wdev->netdev : NULL; - - if (!ndev) - goto exit; - - unregister_netdevice(ndev); - - if (ndev == pwdev_priv->pmon_ndev) { - pwdev_priv->pmon_ndev = NULL; - pwdev_priv->ifname_mon[0] = '\0'; - DBG_8723A("%s(%s): remove monitor interface\n", - __func__, ndev->name); - } - -exit: - return 0; -} - -static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head, - size_t head_len, const u8 *tail, size_t tail_len) -{ - int ret = 0; - u8 *pbuf; - uint len, ielen, wps_ielen = 0; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network; - const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head; - struct ieee80211_mgmt *tmpmgmt; - /* struct sta_priv *pstapriv = &padapter->stapriv; */ - - DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n", - __func__, head_len, tail_len); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) - return -EINVAL; - - if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable)) - return -EINVAL; - - pbuf = kzalloc(head_len + tail_len, GFP_KERNEL); - if (!pbuf) - return -ENOMEM; - tmpmgmt = (struct ieee80211_mgmt *)pbuf; - - bss->beacon_interval = get_unaligned_le16(&mgmt->u.beacon.beacon_int); - bss->capability = get_unaligned_le16(&mgmt->u.beacon.capab_info); - bss->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp); - - /* 24 = beacon header len. */ - memcpy(pbuf, (void *)head, head_len); - memcpy(pbuf + head_len, (void *)tail, tail_len); - - len = head_len + tail_len; - ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - /* check wps ie if inclued */ - if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - tmpmgmt->u.beacon.variable, ielen)) - DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen); - - /* pbss_network->IEs will not include p2p_ie, wfd ie */ - rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0, - WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4); - rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0, - WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4); - - len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable); - if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) { - ret = 0; - } else { - ret = -EINVAL; - } - - kfree(pbuf); - - return ret; -} - -static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_ap_settings *settings) -{ - int ret = 0; - struct rtw_adapter *adapter = wiphy_to_adapter(wiphy); - - DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n", - __func__, ndev->name, settings->hidden_ssid, - settings->auth_type); - - ret = rtw_add_beacon(adapter, settings->beacon.head, - settings->beacon.head_len, settings->beacon.tail, - settings->beacon.tail_len); - - adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode = - settings->hidden_ssid; - - if (settings->ssid && settings->ssid_len) { - struct wlan_bssid_ex *pbss_network = - &adapter->mlmepriv.cur_network.network; - struct wlan_bssid_ex *pbss_network_ext = - &adapter->mlmeextpriv.mlmext_info.network; - - memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid, - settings->ssid_len); - pbss_network->Ssid.ssid_len = settings->ssid_len; - memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid, - settings->ssid_len); - pbss_network_ext->Ssid.ssid_len = settings->ssid_len; - } - - return ret; -} - -static int cfg80211_rtw_change_beacon(struct wiphy *wiphy, - struct net_device *ndev, - struct cfg80211_beacon_data *info) -{ - int ret = 0; - struct rtw_adapter *adapter = wiphy_to_adapter(wiphy); - - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, - info->tail_len); - - return ret; -} - -static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int cfg80211_rtw_add_station(struct wiphy *wiphy, - struct net_device *ndev, const u8 *mac, - struct station_parameters *params) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - return 0; -} - -static int cfg80211_rtw_del_station(struct wiphy *wiphy, - struct net_device *ndev, - struct station_del_parameters *params) -{ - const u8 *mac = params->mac; - int ret = 0; - struct list_head *phead; - u8 updated = 0; - struct sta_info *psta, *ptmp; - struct rtw_adapter *padapter = netdev_priv(ndev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A("+%s(%s)\n", __func__, ndev->name); - - if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) { - DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n", - __func__); - return -EINVAL; - } - - if (!mac) { - DBG_8723A("flush all sta, and cam_entry\n"); - - flush_all_cam_entry23a(padapter); /* clear CAM */ - - ret = rtw_sta_flush23a(padapter); - - return ret; - } - - DBG_8723A("free sta macaddr=%pM\n", mac); - - if (is_broadcast_ether_addr(mac)) - return -EINVAL; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - /* check asoc_queue */ - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) { - if (ether_addr_equal(mac, psta->hwaddr)) { - if (psta->dot8021xalg == 1 && - psta->bpairwise_key_installed == false) { - DBG_8723A("%s, sta's dot8021xalg = 1 and " - "key_installed = false\n", __func__); - } else { - DBG_8723A("free psta =%p, aid =%d\n", psta, - psta->aid); - - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - /* spin_unlock_bh(&pstapriv->asoc_list_lock); */ - updated = - ap_free_sta23a(padapter, psta, true, - WLAN_REASON_DEAUTH_LEAVING); - /* spin_lock_bh(&pstapriv->asoc_list_lock); */ - - psta = NULL; - - break; - } - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update23a(padapter, updated); - - DBG_8723A("-%s(%s)\n", __func__, ndev->name); - - return ret; -} - -static int cfg80211_rtw_change_station(struct wiphy *wiphy, - struct net_device *ndev, const u8 *mac, - struct station_parameters *params) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int cfg80211_rtw_dump_station(struct wiphy *wiphy, - struct net_device *ndev, int idx, u8 *mac, - struct station_info *sinfo) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - /* TODO: dump scanned queue */ - - return -ENOENT; -} - -static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev, - struct bss_parameters *params) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} -#endif /* CONFIG_8723AU_AP_MODE */ - -static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch, - const u8 *buf, size_t len) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - int ret = _FAIL; - struct ieee80211_hdr *pwlanhdr; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (_FAIL == rtw_pwr_wakeup(padapter)) { - ret = -EFAULT; - goto exit; - } - - rtw_set_scan_deny(padapter, 1000); - - rtw_scan_abort23a(padapter); - - if (tx_ch != rtw_get_oper_ch23a(padapter)) { - if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) - pmlmeext->cur_channel = tx_ch; - set_channel_bwmode23a(padapter, tx_ch, - HAL_PRIME_CHNL_OFFSET_DONT_CARE, - HT_CHANNEL_WIDTH_20); - } - - /* starting alloc mgmt frame to dump it */ - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) { - /* ret = -ENOMEM; */ - ret = _FAIL; - goto exit; - } - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET; - - memcpy(pframe, (void *)buf, len); - pattrib->pktlen = len; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - /* update seq number */ - pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4; - pattrib->seqnum = pmlmeext->mgnt_seq; - pmlmeext->mgnt_seq++; - - pattrib->last_txcmdsz = pattrib->pktlen; - - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - - if (ret != _SUCCESS) - DBG_8723A("%s, ack == false\n", __func__); - else - DBG_8723A("%s, ack == true\n", __func__); - -exit: - - DBG_8723A("%s, ret =%d\n", __func__, ret); - - return ret; -} - -static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct cfg80211_mgmt_tx_params *params, - u64 *cookie) -{ - struct rtw_adapter *padapter = - (struct rtw_adapter *)wiphy_to_adapter(wiphy); - int ret = 0; - int tx_ret; - u32 dump_limit = RTW_MAX_MGMT_TX_CNT; - u32 dump_cnt = 0; - bool ack = true; - u8 category, action; - unsigned long start = jiffies; - size_t len = params->len; - struct ieee80211_channel *chan = params->chan; - const u8 *buf = params->buf; - struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)buf; - u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq); - - if (!ieee80211_is_action(hdr->frame_control)) - return -EINVAL; - - /* cookie generation */ - *cookie = (unsigned long)buf; - - DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__, - padapter->pnetdev->name, len, tx_ch); - - /* indicate ack before issue frame to avoid racing with rsp frame */ - cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack, - GFP_KERNEL); - - DBG_8723A("RTW_Tx:tx_ch =%d, da =%pM\n", tx_ch, hdr->da); - category = hdr->u.action.category; - action = hdr->u.action.u.wme_action.action_code; - DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action); - - do { - dump_cnt++; - tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len); - } while (dump_cnt < dump_limit && tx_ret != _SUCCESS); - - if (tx_ret != _SUCCESS || dump_cnt > 1) { - DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n", - __func__, padapter->pnetdev->name, - tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt, - dump_limit, jiffies_to_msecs(jiffies - start)); - } - - return ret; -} - -static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, - struct wireless_dev *wdev, - u16 frame_type, bool reg) -{ - if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) - return; - - return; -} - -static struct cfg80211_ops rtw_cfg80211_ops = { - .change_virtual_intf = cfg80211_rtw_change_iface, - .add_key = cfg80211_rtw_add_key, - .get_key = cfg80211_rtw_get_key, - .del_key = cfg80211_rtw_del_key, - .set_default_key = cfg80211_rtw_set_default_key, - .get_station = cfg80211_rtw_get_station, - .scan = cfg80211_rtw_scan, - .set_wiphy_params = cfg80211_rtw_set_wiphy_params, - .connect = cfg80211_rtw_connect, - .disconnect = cfg80211_rtw_disconnect, - .join_ibss = cfg80211_rtw_join_ibss, - .leave_ibss = cfg80211_rtw_leave_ibss, - .set_tx_power = cfg80211_rtw_set_txpower, - .get_tx_power = cfg80211_rtw_get_txpower, - .set_power_mgmt = cfg80211_rtw_set_power_mgmt, - .set_pmksa = cfg80211_rtw_set_pmksa, - .del_pmksa = cfg80211_rtw_del_pmksa, - .flush_pmksa = cfg80211_rtw_flush_pmksa, - -#ifdef CONFIG_8723AU_AP_MODE - .add_virtual_intf = cfg80211_rtw_add_virtual_intf, - .del_virtual_intf = cfg80211_rtw_del_virtual_intf, - - .start_ap = cfg80211_rtw_start_ap, - .change_beacon = cfg80211_rtw_change_beacon, - .stop_ap = cfg80211_rtw_stop_ap, - - .add_station = cfg80211_rtw_add_station, - .del_station = cfg80211_rtw_del_station, - .change_station = cfg80211_rtw_change_station, - .dump_station = cfg80211_rtw_dump_station, - .change_bss = cfg80211_rtw_change_bss, -#endif /* CONFIG_8723AU_AP_MODE */ - - .mgmt_tx = cfg80211_rtw_mgmt_tx, - .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, -}; - -static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, - enum nl80211_band band, u8 rf_type) -{ - -#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ -#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */ - - ht_cap->ht_supported = true; - - ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; - - /* - *Maximum length of AMPDU that the STA can receive. - *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) - */ - ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - - /*Minimum MPDU start spacing , */ - ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; - - ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - - /* - *hw->wiphy->bands[NL80211_BAND_2GHZ] - *base on ant_num - *rx_mask: RX mask - *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 - *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 - *if rx_ant >= 3 rx_mask[2]= 0xff; - *if BW_40 rx_mask[4]= 0x01; - *highest supported RX rate - */ - if (rf_type == RF_1T1R) { - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0x00; - ht_cap->mcs.rx_mask[4] = 0x01; - - ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); - } else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) { - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0xFF; - ht_cap->mcs.rx_mask[4] = 0x01; - - ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); - } else { - DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type); - } - -} - -void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter) -{ - u8 rf_type; - struct ieee80211_supported_band *bands; - struct wireless_dev *pwdev = padapter->rtw_wdev; - struct wiphy *wiphy = pwdev->wiphy; - - rf_type = rtl8723a_get_rf_type(padapter); - - DBG_8723A("%s:rf_type =%d\n", __func__, rf_type); - - /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */ - { - bands = wiphy->bands[NL80211_BAND_2GHZ]; - if (bands) - rtw_cfg80211_init_ht_capab(&bands->ht_cap, - NL80211_BAND_2GHZ, - rf_type); - } - - /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */ - { - bands = wiphy->bands[NL80211_BAND_5GHZ]; - if (bands) - rtw_cfg80211_init_ht_capab(&bands->ht_cap, - NL80211_BAND_5GHZ, - rf_type); - } -} - -static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter, - struct wiphy *wiphy) -{ - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT; - wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; - wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS; - - wiphy->max_remain_on_channel_duration = - RTW_MAX_REMAIN_ON_CHANNEL_DURATION; - - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | -#ifdef CONFIG_8723AU_AP_MODE - BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | -#endif - 0; - -#ifdef CONFIG_8723AU_AP_MODE - wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes; -#endif /* CONFIG_8723AU_AP_MODE */ - - wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); - - /* - wiphy->iface_combinations = &rtw_combinations; - wiphy->n_iface_combinations = 1; - */ - - wiphy->cipher_suites = rtw_cipher_suites; - wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites); - - /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */ - wiphy->bands[NL80211_BAND_2GHZ] = - rtw_spt_band_alloc(NL80211_BAND_2GHZ); - /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */ - wiphy->bands[NL80211_BAND_5GHZ] = - rtw_spt_band_alloc(NL80211_BAND_5GHZ); - - wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME; - - if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE) - wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; - else - wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; -} - -int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev) -{ - int ret = 0; - struct wiphy *wiphy; - struct wireless_dev *wdev; - struct rtw_wdev_priv *pwdev_priv; - struct net_device *pnetdev = padapter->pnetdev; - - DBG_8723A("%s(padapter =%p)\n", __func__, padapter); - - /* wiphy */ - wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv)); - if (!wiphy) { - DBG_8723A("Couldn't allocate wiphy device\n"); - ret = -ENOMEM; - goto exit; - } - - /* wdev */ - wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) { - ret = -ENOMEM; - goto free_wiphy; - } - - set_wiphy_dev(wiphy, dev); - rtw_cfg80211_preinit_wiphy(padapter, wiphy); - - ret = wiphy_register(wiphy); - if (ret < 0) { - DBG_8723A("Couldn't register wiphy device\n"); - goto free_wdev; - } - - wdev->wiphy = wiphy; - wdev->netdev = pnetdev; - /* wdev->iftype = NL80211_IFTYPE_STATION; */ - /* for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */ - wdev->iftype = NL80211_IFTYPE_MONITOR; - padapter->rtw_wdev = wdev; - pnetdev->ieee80211_ptr = wdev; - - /* init pwdev_priv */ - pwdev_priv = wdev_to_priv(wdev); - pwdev_priv->rtw_wdev = wdev; - pwdev_priv->pmon_ndev = NULL; - pwdev_priv->ifname_mon[0] = '\0'; - pwdev_priv->padapter = padapter; - pwdev_priv->scan_request = NULL; - spin_lock_init(&pwdev_priv->scan_req_lock); - - pwdev_priv->p2p_enabled = false; - - if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE) - pwdev_priv->power_mgmt = true; - else - pwdev_priv->power_mgmt = false; - - return ret; -free_wdev: - kfree(wdev); -free_wiphy: - wiphy_free(wiphy); -exit: - return ret; -} - -void rtw_wdev_free(struct wireless_dev *wdev) -{ - DBG_8723A("%s(wdev =%p)\n", __func__, wdev); - - if (!wdev) - return; - - kfree(wdev->wiphy->bands[NL80211_BAND_2GHZ]); - kfree(wdev->wiphy->bands[NL80211_BAND_5GHZ]); - - wiphy_free(wdev->wiphy); - - kfree(wdev); -} - -void rtw_wdev_unregister(struct wireless_dev *wdev) -{ - struct rtw_wdev_priv *pwdev_priv; - - DBG_8723A("%s(wdev =%p)\n", __func__, wdev); - - if (!wdev) - return; - - pwdev_priv = wdev_to_priv(wdev); - - rtw_cfg80211_indicate_scan_done(pwdev_priv, true); - - if (pwdev_priv->pmon_ndev) { - DBG_8723A("%s, unregister monitor interface\n", __func__); - unregister_netdev(pwdev_priv->pmon_ndev); - } - - wiphy_unregister(wdev->wiphy); -} diff --git a/drivers/staging/rtl8723au/os_dep/mlme_linux.c b/drivers/staging/rtl8723au/os_dep/mlme_linux.c deleted file mode 100644 index ca24369f1208..000000000000 --- a/drivers/staging/rtl8723au/os_dep/mlme_linux.c +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ - -#define _MLME_OSDEP_C_ - -#include -#include -#include - -static struct rt_pmkid_list backupPMKIDList[NUM_PMKID_CACHE]; - -void rtw_reset_securitypriv23a(struct rtw_adapter *adapter) -{ - u8 backupPMKIDIndex = 0; - u8 backupTKIPCountermeasure = 0x00; - unsigned long backupTKIPcountermeasure_time = 0; - - if (adapter->securitypriv.dot11AuthAlgrthm == - dot11AuthAlgrthm_8021X) { /* 802.1x */ - /* We have to backup the PMK information for WiFi PMK - * Caching test item. - * Backup the btkip_countermeasure information. - * When the countermeasure is trigger, the driver have to - * disconnect with AP for 60 seconds. - */ - memcpy(&backupPMKIDList[0], &adapter->securitypriv.PMKIDList[0], - sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - backupPMKIDIndex = adapter->securitypriv.PMKIDIndex; - backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure; - backupTKIPcountermeasure_time = adapter->securitypriv.btkip_countermeasure_time; - - memset((unsigned char *)&adapter->securitypriv, 0, - sizeof (struct security_priv)); - /* Restore the PMK information to securitypriv structure - * for the following connection. - */ - memcpy(&adapter->securitypriv.PMKIDList[0], &backupPMKIDList[0], - sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - adapter->securitypriv.PMKIDIndex = backupPMKIDIndex; - adapter->securitypriv.btkip_countermeasure = backupTKIPCountermeasure; - adapter->securitypriv.btkip_countermeasure_time = backupTKIPcountermeasure_time; - - adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; - } else { /* reset values in securitypriv */ - struct security_priv *psec_priv = &adapter->securitypriv; - - /* open system */ - psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - psec_priv->dot11PrivacyAlgrthm = 0; - psec_priv->dot11PrivacyKeyIndex = 0; - - psec_priv->dot118021XGrpPrivacy = 0; - psec_priv->dot118021XGrpKeyid = 1; - - psec_priv->ndisauthtype = Ndis802_11AuthModeOpen; - psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled; - } -} - -void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter) -{ - /* Do it first for tx broadcast pkt after disconnection issue! */ - netif_carrier_off(adapter->pnetdev); - - rtw_cfg80211_indicate_disconnect(adapter); - - rtw_reset_securitypriv23a(adapter); -} diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c deleted file mode 100644 index b8848c25beb4..000000000000 --- a/drivers/staging/rtl8723au/os_dep/os_intfs.c +++ /dev/null @@ -1,852 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _OS_INTFS_C_ - -#include -#include -#include -#include -#include -#include - -#include - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek Wireless Lan Driver"); -MODULE_AUTHOR("Realtek Semiconductor Corp."); -MODULE_AUTHOR("Larry Finger "); -MODULE_AUTHOR("Jes Sorensen "); -MODULE_VERSION(DRIVERVERSION); -MODULE_FIRMWARE("rtlwifi/rtl8723aufw_A.bin"); -MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B.bin"); -MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B_NoBT.bin"); - -/* module param defaults */ -static int rtw_chip_version; -static int rtw_rfintfs = HWPI; -static int rtw_debug = 1; - -static int rtw_channel = 1;/* ad-hoc support requirement */ -static int rtw_wireless_mode = WIRELESS_11BG_24N; -static int rtw_vrtl_carrier_sense = AUTO_VCS; -static int rtw_vcs_type = RTS_CTS;/* */ -static int rtw_rts_thresh = 2347;/* */ -static int rtw_frag_thresh = 2346;/* */ -static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */ -static int rtw_scan_mode = 1;/* active, passive */ -static int rtw_adhoc_tx_pwr = 1; -static int rtw_soft_ap; -static int rtw_power_mgnt = 1; -static int rtw_ips_mode = IPS_NORMAL; - -static int rtw_smart_ps = 2; - -module_param(rtw_ips_mode, int, 0644); -MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode"); - -static int rtw_long_retry_lmt = 7; -static int rtw_short_retry_lmt = 7; -static int rtw_busy_thresh = 40; -static int rtw_ack_policy = NORMAL_ACK; - -static int rtw_acm_method;/* 0:By SW 1:By HW. */ - -static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */ -static int rtw_uapsd_enable; - -static int rtw_ht_enable = 1; -/* 0 :diable, bit(0): enable 2.4g, bit(1): enable 5g */ -static int rtw_cbw40_enable = 3; -static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */ -/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable - * 2.4GHZ for IOT issue with bufflao's AP at 5GHZ - */ -static int rtw_rx_stbc = 1; -static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */ - -/* Use 2 path Tx to transmit MCS0~7 and legacy mode */ -static int rtw_lowrate_two_xmit = 1; - -/* int rf_config = RF_1T2R; 1T2R */ -static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */ -static int rtw_low_power; -static int rtw_wifi_spec; -static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX; - -#ifdef CONFIG_8723AU_BT_COEXIST -static int rtw_btcoex_enable = 1; -static int rtw_bt_iso = 2;/* 0:Low, 1:High, 2:From Efuse */ -/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy */ -static int rtw_bt_sco = 3; -/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ -static int rtw_bt_ampdu = 1; -#endif - -/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */ -static int rtw_AcceptAddbaReq = true; - -static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */ -static int rtw_antdiv_type; /* 0:decide by efuse */ - -static int rtw_enusbss;/* 0:disable, 1:enable */ - -static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */ - -static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */ - -static int rtw_hw_wps_pbc = 1; - -static int rtw_80211d; - -static int rtw_regulatory_id = 0xff;/* Regulatory tab id, 0xff = follow efuse's setting */ - -module_param(rtw_regulatory_id, int, 0644); - -static char *ifname = "wlan%d"; -module_param(ifname, charp, 0644); -MODULE_PARM_DESC(ifname, "The default name to allocate for first interface"); - -static char *if2name = "wlan%d"; -module_param(if2name, charp, 0644); -MODULE_PARM_DESC(if2name, "The default name to allocate for second interface"); - -module_param(rtw_channel_plan, int, 0644); -module_param(rtw_chip_version, int, 0644); -module_param(rtw_rfintfs, int, 0644); -module_param(rtw_channel, int, 0644); -module_param(rtw_wmm_enable, int, 0644); -module_param(rtw_vrtl_carrier_sense, int, 0644); -module_param(rtw_vcs_type, int, 0644); -module_param(rtw_busy_thresh, int, 0644); -module_param(rtw_ht_enable, int, 0644); -module_param(rtw_cbw40_enable, int, 0644); -module_param(rtw_ampdu_enable, int, 0644); -module_param(rtw_rx_stbc, int, 0644); -module_param(rtw_ampdu_amsdu, int, 0644); - -module_param(rtw_lowrate_two_xmit, int, 0644); - -module_param(rtw_rf_config, int, 0644); -module_param(rtw_power_mgnt, int, 0644); -module_param(rtw_smart_ps, int, 0644); -module_param(rtw_low_power, int, 0644); -module_param(rtw_wifi_spec, int, 0644); - -module_param(rtw_antdiv_cfg, int, 0644); - -module_param(rtw_enusbss, int, 0644); -module_param(rtw_hwpdn_mode, int, 0644); -module_param(rtw_hwpwrp_detect, int, 0644); - -module_param(rtw_hw_wps_pbc, int, 0644); - -static uint rtw_max_roaming_times = 2; -module_param(rtw_max_roaming_times, uint, 0644); -MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try"); - -module_param(rtw_80211d, int, 0644); -MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism"); - -#ifdef CONFIG_8723AU_BT_COEXIST -module_param(rtw_btcoex_enable, int, 0644); -MODULE_PARM_DESC(rtw_btcoex_enable, "Enable BT co-existence mechanism"); -#endif - -static uint rtw_notch_filter; -module_param(rtw_notch_filter, uint, 0644); -MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P"); -module_param_named(debug, rtw_debug, int, 0444); -MODULE_PARM_DESC(debug, "Set debug level (1-9) (default 1)"); - -static int netdev_close(struct net_device *pnetdev); - -static void loadparam(struct rtw_adapter *padapter, struct net_device *pnetdev) -{ - struct registry_priv *registry_par = &padapter->registrypriv; - - GlobalDebugLevel23A = rtw_debug; - registry_par->chip_version = (u8)rtw_chip_version; - registry_par->rfintfs = (u8)rtw_rfintfs; - memcpy(registry_par->ssid.ssid, "ANY", 3); - registry_par->ssid.ssid_len = 3; - registry_par->channel = (u8)rtw_channel; - registry_par->wireless_mode = (u8)rtw_wireless_mode; - 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; - registry_par->frag_thresh = (u16)rtw_frag_thresh; - registry_par->preamble = (u8)rtw_preamble; - registry_par->scan_mode = (u8)rtw_scan_mode; - registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr; - registry_par->soft_ap = (u8)rtw_soft_ap; - registry_par->smart_ps = (u8)rtw_smart_ps; - registry_par->power_mgnt = (u8)rtw_power_mgnt; - registry_par->ips_mode = (u8)rtw_ips_mode; - registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt; - registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt; - registry_par->busy_thresh = (u16)rtw_busy_thresh; - registry_par->ack_policy = (u8)rtw_ack_policy; - registry_par->acm_method = (u8)rtw_acm_method; - /* UAPSD */ - registry_par->wmm_enable = (u8)rtw_wmm_enable; - registry_par->uapsd_enable = (u8)rtw_uapsd_enable; - registry_par->ht_enable = (u8)rtw_ht_enable; - registry_par->cbw40_enable = (u8)rtw_cbw40_enable; - registry_par->ampdu_enable = (u8)rtw_ampdu_enable; - registry_par->rx_stbc = (u8)rtw_rx_stbc; - registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu; - registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit; - registry_par->rf_config = (u8)rtw_rf_config; - registry_par->low_power = (u8)rtw_low_power; - registry_par->wifi_spec = (u8)rtw_wifi_spec; - registry_par->channel_plan = (u8)rtw_channel_plan; -#ifdef CONFIG_8723AU_BT_COEXIST - registry_par->btcoex = (u8)rtw_btcoex_enable; - registry_par->bt_iso = (u8)rtw_bt_iso; - registry_par->bt_sco = (u8)rtw_bt_sco; - registry_par->bt_ampdu = (u8)rtw_bt_ampdu; -#endif - registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq; - registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; - registry_par->antdiv_type = (u8)rtw_antdiv_type; - - /* 0:disable, 1:enable, 2:by EFUSE config */ - registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode; - /* 0:disable, 1:enable */ - registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect; - registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc; - registry_par->max_roaming_times = (u8)rtw_max_roaming_times; - registry_par->enable80211d = (u8)rtw_80211d; - snprintf(registry_par->ifname, 16, "%s", ifname); - snprintf(registry_par->if2name, 16, "%s", if2name); - registry_par->notch_filter = (u8)rtw_notch_filter; - registry_par->regulatory_tid = (u8)rtw_regulatory_id; -} - -static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - struct sockaddr *addr = p; - - if (!padapter->bup) - ether_addr_copy(padapter->eeprompriv.mac_addr, addr->sa_data); - return 0; -} - -static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct recv_priv *precvpriv = &padapter->recvpriv; - - padapter->stats.tx_packets = pxmitpriv->tx_pkts; - padapter->stats.rx_packets = precvpriv->rx_pkts; - padapter->stats.tx_dropped = pxmitpriv->tx_drop; - padapter->stats.rx_dropped = precvpriv->rx_drop; - padapter->stats.tx_bytes = pxmitpriv->tx_bytes; - padapter->stats.rx_bytes = precvpriv->rx_bytes; - - return &padapter->stats; -} - -/* - * AC to queue mapping - * - * AC_VO -> queue 0 - * AC_VI -> queue 1 - * AC_BE -> queue 2 - * AC_BK -> queue 3 - */ -static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; - -/* Given a data frame determine the 802.1p/1d tag to use. */ -static u32 rtw_classify8021d(struct sk_buff *skb) -{ - u32 dscp; - - /* skb->priority values from 256->263 are magic values to - * directly indicate a specific 802.1d priority. This is used - * to allow 802.1d priority to be passed directly in from VLAN - * tags, etc. - */ - if (skb->priority >= 256 && skb->priority <= 263) - return skb->priority - 256; - switch (skb->protocol) { - case htons(ETH_P_IP): - dscp = ip_hdr(skb)->tos & 0xfc; - break; - default: - return 0; - } - return dscp >> 5; -} - -static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv, - select_queue_fallback_t fallback) -{ - struct rtw_adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - skb->priority = rtw_classify8021d(skb); - - if (pmlmepriv->acm_mask != 0) - skb->priority = qos_acm23a(pmlmepriv->acm_mask, skb->priority); - return rtw_1d_to_queue[skb->priority]; -} - -u16 rtw_recv_select_queue23a(struct sk_buff *skb) -{ - struct iphdr *piphdr; - struct ethhdr *eth = (struct ethhdr *)skb->data; - unsigned int dscp; - u16 eth_type = get_unaligned_be16(ð->h_proto); - u32 priority; - u8 *pdata = skb->data; - - switch (eth_type) { - case ETH_P_IP: - piphdr = (struct iphdr *)(pdata + ETH_HLEN); - dscp = piphdr->tos & 0xfc; - priority = dscp >> 5; - break; - default: - priority = 0; - } - return rtw_1d_to_queue[priority]; -} - -static const struct net_device_ops rtw_netdev_ops = { - .ndo_open = netdev_open23a, - .ndo_stop = netdev_close, - .ndo_start_xmit = rtw_xmit23a_entry23a, - .ndo_select_queue = rtw_select_queue, - .ndo_set_mac_address = rtw_net_set_mac_address, - .ndo_get_stats = rtw_net_get_stats, -}; - -int rtw_init_netdev23a_name23a(struct net_device *pnetdev, const char *ifname) -{ - if (dev_alloc_name(pnetdev, ifname) < 0) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "dev_alloc_name, fail!\n"); - } - netif_carrier_off(pnetdev); - return 0; -} - -static const struct device_type wlan_type = { - .name = "wlan", -}; - -struct net_device *rtw_init_netdev23a(struct rtw_adapter *old_padapter) -{ - struct rtw_adapter *padapter; - struct net_device *pnetdev; - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "+init_net_dev\n"); - - pnetdev = alloc_etherdev_mq(sizeof(struct rtw_adapter), 4); - if (!pnetdev) - return NULL; - - pnetdev->dev.type = &wlan_type; - padapter = netdev_priv(pnetdev); - padapter->pnetdev = pnetdev; - - DBG_8723A("register rtw_netdev_ops to netdev_ops\n"); - pnetdev->netdev_ops = &rtw_netdev_ops; - - pnetdev->watchdog_timeo = HZ*3; /* 3 second timeout */ - - loadparam(padapter, pnetdev); - return pnetdev; -} - -static int rtw_init_default_value(struct rtw_adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - /* xmit_priv */ - pxmitpriv->vcs = pregistrypriv->vcs_type; - /* pxmitpriv->rts_thresh = pregistrypriv->rts_thresh; */ - pxmitpriv->frag_len = pregistrypriv->frag_thresh; - - /* mlme_priv */ - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - pmlmepriv->scan_mode = SCAN_ACTIVE; - - /* ht_priv */ - pmlmepriv->htpriv.ampdu_enable = false;/* set to disabled */ - - /* security_priv */ - psecuritypriv->binstallGrpkey = 0; - - /* open system */ - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - psecuritypriv->dot11PrivacyAlgrthm = 0; - - psecuritypriv->dot11PrivacyKeyIndex = 0; - - psecuritypriv->dot118021XGrpPrivacy = 0; - psecuritypriv->dot118021XGrpKeyid = 1; - - psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; - psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled; - - /* registry_priv */ - rtw_init_registrypriv_dev_network23a(padapter); - rtw_update_registrypriv_dev_network23a(padapter); - - /* hal_priv */ - rtl8723a_init_default_value(padapter); - - /* misc. */ - padapter->bReadPortCancel = false; - padapter->bWritePortCancel = false; - return _SUCCESS; -} - -int rtw_reset_drv_sw23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - /* hal_priv */ - rtl8723a_init_default_value(padapter); - padapter->bReadPortCancel = false; - padapter->bWritePortCancel = false; - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - - padapter->xmitpriv.tx_pkts = 0; - padapter->recvpriv.rx_pkts = 0; - - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING); - - rtw_sreset_reset_value(padapter); - pwrctrlpriv->pwr_state_check_cnts = 0; - - /* mlmeextpriv */ - padapter->mlmeextpriv.sitesurvey_res.state = SCAN_DISABLE; - - rtw_set_signal_stat_timer(&padapter->recvpriv); - return _SUCCESS; -} - -int rtw_init_drv_sw23a(struct rtw_adapter *padapter) -{ - int ret8 = _SUCCESS; - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "+rtw_init_drv_sw23a\n"); - - if (rtw_init_cmd_priv23a(&padapter->cmdpriv) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't init cmd_priv\n"); - ret8 = _FAIL; - goto exit; - } - - padapter->cmdpriv.padapter = padapter; - - if (rtw_init_evt_priv23a(&padapter->evtpriv) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't init evt_priv\n"); - ret8 = _FAIL; - goto exit; - } - - if (rtw_init_mlme_priv23a(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't init mlme_priv\n"); - ret8 = _FAIL; - goto exit; - } - - - if (init_mlme_ext_priv23a(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't init mlme_ext_priv\n"); - ret8 = _FAIL; - goto exit; - } - - if (_rtw_init_xmit_priv23a(&padapter->xmitpriv, padapter) == _FAIL) { - DBG_8723A("Can't _rtw_init_xmit_priv23a\n"); - ret8 = _FAIL; - goto exit; - } - - if (_rtw_init_recv_priv23a(&padapter->recvpriv, padapter) == _FAIL) { - DBG_8723A("Can't _rtw_init_recv_priv23a\n"); - ret8 = _FAIL; - goto exit; - } - - if (_rtw_init_sta_priv23a(&padapter->stapriv) == _FAIL) { - DBG_8723A("Can't _rtw_init_sta_priv23a\n"); - ret8 = _FAIL; - goto exit; - } - - padapter->stapriv.padapter = padapter; - padapter->setband = GHZ24_50; - rtw_init_bcmc_stainfo23a(padapter); - - rtw_init_pwrctrl_priv23a(padapter); - - ret8 = rtw_init_default_value(padapter); - - rtl8723a_init_dm_priv(padapter); - - rtw_sreset_init(padapter); - -exit: - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "-rtw_init_drv_sw23a\n"); - return ret8; -} - -void rtw_cancel_all_timer23a(struct rtw_adapter *padapter) -{ - RT_TRACE(_module_os_intfs_c_, _drv_info_, - "+rtw_cancel_all_timer23a\n"); - - del_timer_sync(&padapter->mlmepriv.assoc_timer); - RT_TRACE(_module_os_intfs_c_, _drv_info_, - "%s:cancel association timer complete!\n", __func__); - - del_timer_sync(&padapter->mlmepriv.scan_to_timer); - RT_TRACE(_module_os_intfs_c_, _drv_info_, - "%s:cancel scan_to_timer!\n", __func__); - - del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer); - RT_TRACE(_module_os_intfs_c_, _drv_info_, - "%s:cancel dynamic_chk_timer!\n", __func__); - - del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer); - - del_timer_sync(&padapter->mlmepriv.set_scan_deny_timer); - rtw_clear_scan_deny(padapter); - RT_TRACE(_module_os_intfs_c_, _drv_info_, - "%s:cancel set_scan_deny_timer!\n", __func__); - - del_timer_sync(&padapter->recvpriv.signal_stat_timer); -} - -int rtw_free_drv_sw23a(struct rtw_adapter *padapter) -{ - RT_TRACE(_module_os_intfs_c_, _drv_info_, "==>rtw_free_drv_sw23a\n"); - - free_mlme_ext_priv23a(&padapter->mlmeextpriv); - - rtw_free_evt_priv23a(&padapter->evtpriv); - - rtw_free_mlme_priv23a(&padapter->mlmepriv); - - _rtw_free_xmit_priv23a(&padapter->xmitpriv); - - /* will free bcmc_stainfo here */ - _rtw_free_sta_priv23a(&padapter->stapriv); - - _rtw_free_recv_priv23a(&padapter->recvpriv); - - rtw_free_pwrctrl_priv(padapter); - - kfree(padapter->HalData); - padapter->HalData = NULL; - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "-rtw_free_drv_sw23a\n"); - return _SUCCESS; -} - -static int _rtw_drv_register_netdev(struct rtw_adapter *padapter, char *name) -{ - struct net_device *pnetdev = padapter->pnetdev; - int ret = _SUCCESS; - - /* alloc netdev name */ - rtw_init_netdev23a_name23a(pnetdev, name); - - ether_addr_copy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr); - - /* Tell the network stack we exist */ - if (register_netdev(pnetdev)) { - DBG_8723A("%s(%s): Failed!\n", __func__, pnetdev->name); - ret = _FAIL; - goto error_register_netdev; - } - DBG_8723A("%s, MAC Address (if%d) = %pM\n", - __func__, padapter->iface_id + 1, pnetdev->dev_addr); - return ret; - -error_register_netdev: - - if (padapter->iface_id > IFACE_ID0) { - rtw_free_drv_sw23a(padapter); - - free_netdev(pnetdev); - } - return ret; -} - -int rtw_drv_register_netdev(struct rtw_adapter *if1) -{ - struct dvobj_priv *dvobj = if1->dvobj; - int i, status = _SUCCESS; - - if (dvobj->iface_nums >= IFACE_ID_MAX) { - status = _FAIL; /* -EINVAL */ - goto exit; - } - - for (i = 0; i < dvobj->iface_nums; i++) { - struct rtw_adapter *padapter = dvobj->padapters[i]; - - if (padapter) { - char *name; - - if (padapter->iface_id == IFACE_ID0) - name = if1->registrypriv.ifname; - else if (padapter->iface_id == IFACE_ID1) - name = if1->registrypriv.if2name; - else - name = "wlan%d"; - status = _rtw_drv_register_netdev(padapter, name); - if (status != _SUCCESS) - break; - } - } - -exit: - return status; -} - -int netdev_open23a(struct net_device *pnetdev) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - struct pwrctrl_priv *pwrctrlpriv; - int ret = 0; - int status; - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "+871x_drv - dev_open\n"); - DBG_8723A("+871x_drv - drv_open, bup =%d\n", padapter->bup); - - mutex_lock(&adapter_to_dvobj(padapter)->hw_init_mutex); - - pwrctrlpriv = &padapter->pwrctrlpriv; - - if (!padapter->bup) { - padapter->bDriverStopped = false; - padapter->bSurpriseRemoved = false; - padapter->bCardDisableWOHSM = false; - - status = rtl8723au_hal_init(padapter); - if (status == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "rtl871x_hal_init(): Can't init h/w!\n"); - goto netdev_open23a_error; - } - - DBG_8723A("MAC Address = %pM\n", pnetdev->dev_addr); - - if (init_hw_mlme_ext23a(padapter) == _FAIL) { - DBG_8723A("can't init mlme_ext_priv\n"); - goto netdev_open23a_error; - } - - rtl8723au_inirp_init(padapter); - - rtw_cfg80211_init_wiphy(padapter); - - padapter->bup = true; - } - padapter->net_closed = false; - - mod_timer(&padapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(2000)); - - padapter->pwrctrlpriv.bips_processing = false; - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - - /* netif_carrier_on(pnetdev);call this func when - rtw23a_joinbss_event_cb return success */ - if (!rtw_netif_queue_stopped(pnetdev)) - netif_tx_start_all_queues(pnetdev); - else - netif_tx_wake_all_queues(pnetdev); - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "-871x_drv - dev_open\n"); - DBG_8723A("-871x_drv - drv_open, bup =%d\n", padapter->bup); -exit: - mutex_unlock(&adapter_to_dvobj(padapter)->hw_init_mutex); - return ret; - -netdev_open23a_error: - padapter->bup = false; - - netif_carrier_off(pnetdev); - netif_tx_stop_all_queues(pnetdev); - - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "-871x_drv - dev_open, fail!\n"); - DBG_8723A("-871x_drv - drv_open fail, bup =%d\n", padapter->bup); - - ret = -1; - goto exit; -} - -static int ips_netdrv_open(struct rtw_adapter *padapter) -{ - int status = _SUCCESS; - - padapter->net_closed = false; - DBG_8723A("===> %s.........\n", __func__); - - padapter->bDriverStopped = false; - padapter->bSurpriseRemoved = false; - padapter->bCardDisableWOHSM = false; - - status = rtl8723au_hal_init(padapter); - if (status == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "ips_netdrv_open(): Can't init h/w!\n"); - goto netdev_open23a_error; - } - - rtl8723au_inirp_init(padapter); - - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - mod_timer(&padapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(5000)); - - return _SUCCESS; - -netdev_open23a_error: - /* padapter->bup = false; */ - DBG_8723A("-ips_netdrv_open - drv_open failure, bup =%d\n", - padapter->bup); - - return _FAIL; -} - -int rtw_ips_pwr_up23a(struct rtw_adapter *padapter) -{ - int result; - unsigned long start_time = jiffies; - - DBG_8723A("===> rtw_ips_pwr_up23a..............\n"); - rtw_reset_drv_sw23a(padapter); - - result = ips_netdrv_open(padapter); - - DBG_8723A("<=== rtw_ips_pwr_up23a.............. in %dms\n", - jiffies_to_msecs(jiffies - start_time)); - return result; -} - -void rtw_ips_pwr_down23a(struct rtw_adapter *padapter) -{ - unsigned long start_time = jiffies; - - DBG_8723A("===> rtw_ips_pwr_down23a...................\n"); - - padapter->bCardDisableWOHSM = true; - padapter->net_closed = true; - - rtw_ips_dev_unload23a(padapter); - padapter->bCardDisableWOHSM = false; - DBG_8723A("<=== rtw_ips_pwr_down23a..................... in %dms\n", - jiffies_to_msecs(jiffies - start_time)); -} - -void rtw_ips_dev_unload23a(struct rtw_adapter *padapter) -{ - rtl8723a_fifo_cleanup(padapter); - - rtl8723a_usb_intf_stop(padapter); - - /* s5. */ - if (!padapter->bSurpriseRemoved) - rtl8723au_hal_deinit(padapter); -} - -int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal) -{ - int status; - - if (bnormal) - status = netdev_open23a(pnetdev); - else - status = (_SUCCESS == ips_netdrv_open(netdev_priv(pnetdev))) ? - (0) : (-1); - - return status; -} - -static int netdev_close(struct net_device *pnetdev) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "+871x_drv - drv_close\n"); - - padapter->net_closed = true; - - if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) { - DBG_8723A("(2)871x_drv - drv_close, bup =%d, " - "hw_init_completed =%d\n", padapter->bup, - padapter->hw_init_completed); - - /* s1. */ - if (pnetdev) { - if (!rtw_netif_queue_stopped(pnetdev)) - netif_tx_stop_all_queues(pnetdev); - } - - /* s2. */ - LeaveAllPowerSaveMode23a(padapter); - rtw_disassoc_cmd23a(padapter, 500, false); - /* s2-2. indicate disconnect to os */ - rtw_indicate_disconnect23a(padapter); - /* s2-3. */ - rtw_free_assoc_resources23a(padapter, 1); - /* s2-4. */ - rtw_free_network_queue23a(padapter); - } - - rtw_scan_abort23a(padapter); - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "-871x_drv - drv_close\n"); - DBG_8723A("-871x_drv - drv_close, bup =%d\n", padapter->bup); - - return 0; -} - -void rtw_ndev_destructor(struct net_device *ndev) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - kfree(ndev->ieee80211_ptr); - free_netdev(ndev); -} - -void _rtw_init_queue23a(struct rtw_queue *pqueue) -{ - INIT_LIST_HEAD(&pqueue->queue); - spin_lock_init(&pqueue->lock); -} diff --git a/drivers/staging/rtl8723au/os_dep/recv_linux.c b/drivers/staging/rtl8723au/os_dep/recv_linux.c deleted file mode 100644 index 084b506ae161..000000000000 --- a/drivers/staging/rtl8723au/os_dep/recv_linux.c +++ /dev/null @@ -1,165 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _RECV_OSDEP_C_ - -#include -#include - -#include -#include - -#include - -#include - -void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup) -{ - enum nl80211_key_type key_type = 0; - union iwreq_data wrqu; - struct iw_michaelmicfailure ev; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - unsigned long cur_time; - - if (psecuritypriv->last_mic_err_time == 0) { - psecuritypriv->last_mic_err_time = jiffies; - } else { - cur_time = jiffies; - - if (cur_time - psecuritypriv->last_mic_err_time < 60*HZ) { - psecuritypriv->btkip_countermeasure = true; - psecuritypriv->last_mic_err_time = 0; - psecuritypriv->btkip_countermeasure_time = cur_time; - } else { - psecuritypriv->last_mic_err_time = jiffies; - } - } - - if (bgroup) - key_type |= NL80211_KEYTYPE_GROUP; - else - key_type |= NL80211_KEYTYPE_PAIRWISE; - - cfg80211_michael_mic_failure(padapter->pnetdev, - (u8 *)&pmlmepriv->assoc_bssid[0], - key_type, -1, NULL, GFP_ATOMIC); - - memset(&ev, 0x00, sizeof(ev)); - if (bgroup) - ev.flags |= IW_MICFAILURE_GROUP; - else - ev.flags |= IW_MICFAILURE_PAIRWISE; - - ev.src_addr.sa_family = ARPHRD_ETHER; - ether_addr_copy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0]); - - memset(&wrqu, 0x00, sizeof(wrqu)); - wrqu.data.length = sizeof(ev); -} - -int rtw_recv_indicatepkt23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct recv_priv *precvpriv; - struct sk_buff *skb; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - precvpriv = &padapter->recvpriv; - - skb = precv_frame->pkt; - if (!skb) { - RT_TRACE(_module_recv_osdep_c_, _drv_err_, - "rtw_recv_indicatepkt23a():skb == NULL!!!!\n"); - goto _recv_indicatepkt_drop; - } - - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - "rtw_recv_indicatepkt23a():skb != NULL !!!\n"); - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - "rtw_recv_indicatepkt23a():precv_frame->hdr.rx_data =%p\n", - precv_frame->pkt->data); - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - "skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n", - skb->head, skb->data, - skb_tail_pointer(skb), skb_end_pointer(skb), skb->len); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { - struct sk_buff *pskb2 = NULL; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - int bmcast = is_multicast_ether_addr(pattrib->dst); - - /* DBG_8723A("bmcast =%d\n", bmcast); */ - - if (!ether_addr_equal(pattrib->dst, - myid(&padapter->eeprompriv))) { - /* DBG_8723A("not ap psta =%p, addr =%pM\n", psta, pattrib->dst); */ - if (bmcast) { - psta = rtw_get_bcmc_stainfo23a(padapter); - pskb2 = skb_clone(skb, GFP_ATOMIC); - } else { - psta = rtw_get_stainfo23a(pstapriv, pattrib->dst); - } - - if (psta) { - struct net_device *pnetdev = padapter->pnetdev; - - /* DBG_8723A("directly forwarding to the rtw_xmit23a_entry23a\n"); */ - - /* skb->ip_summed = CHECKSUM_NONE; */ - skb->dev = pnetdev; - skb_set_queue_mapping(skb, rtw_recv_select_queue23a(skb)); - - rtw_xmit23a_entry23a(skb, pnetdev); - - if (bmcast) - skb = pskb2; - else - goto _recv_indicatepkt_end; - } - } else { /* to APself */ - /* DBG_8723A("to APSelf\n"); */ - } - } - - skb->ip_summed = CHECKSUM_NONE; - skb->dev = padapter->pnetdev; - skb->protocol = eth_type_trans(skb, padapter->pnetdev); - - netif_rx(skb); - -_recv_indicatepkt_end: - - precv_frame->pkt = NULL; /* pointers to NULL before rtw_free_recvframe23a() */ - - rtw_free_recvframe23a(precv_frame); - - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - "rtw_recv_indicatepkt23a :after netif_rx!!!!\n"); - return _SUCCESS; - -_recv_indicatepkt_drop: - - rtw_free_recvframe23a(precv_frame); - return _FAIL; -} - -void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl) -{ - setup_timer(&preorder_ctrl->reordering_ctrl_timer, - rtw_reordering_ctrl_timeout_handler23a, - (unsigned long)preorder_ctrl); -} diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c deleted file mode 100644 index cf83efffbffd..000000000000 --- a/drivers/staging/rtl8723au/os_dep/usb_intf.c +++ /dev/null @@ -1,627 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _HCI_INTF_C_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int rtw_suspend(struct usb_interface *intf, pm_message_t message); -static int rtw_resume(struct usb_interface *intf); -static int rtw_drv_init(struct usb_interface *pusb_intf, - const struct usb_device_id *pdid); -static void rtw_disconnect(struct usb_interface *pusb_intf); - -#define USB_VENDER_ID_REALTEK 0x0BDA - -#define RTL8723A_USB_IDS \ - {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x8724, \ - 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \ - {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x1724, \ - 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \ - {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x0724, \ - 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ - -static struct usb_device_id rtl8723a_usb_id_tbl[] = { - RTL8723A_USB_IDS - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, rtl8723a_usb_id_tbl); - -static struct usb_driver rtl8723a_usb_drv = { - .name = (char *)"rtl8723au", - .probe = rtw_drv_init, - .disconnect = rtw_disconnect, - .id_table = rtl8723a_usb_id_tbl, - .suspend = rtw_suspend, - .resume = rtw_resume, - .reset_resume = rtw_resume, -}; - -static struct usb_driver *usb_drv = &rtl8723a_usb_drv; - -static int rtw_init_intf_priv(struct dvobj_priv *dvobj) -{ - mutex_init(&dvobj->usb_vendor_req_mutex); - - return _SUCCESS; -} - -static int rtw_deinit_intf_priv(struct dvobj_priv *dvobj) -{ - mutex_destroy(&dvobj->usb_vendor_req_mutex); - - return _SUCCESS; -} - -static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) -{ - struct dvobj_priv *pdvobjpriv; - struct usb_host_config *phost_conf; - struct usb_config_descriptor *pconf_desc; - struct usb_host_interface *phost_iface; - struct usb_interface_descriptor *piface_desc; - struct usb_endpoint_descriptor *pendp_desc; - struct usb_device *pusbd; - int i, status = _FAIL; - - pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); - if (!pdvobjpriv) - goto exit; - - mutex_init(&pdvobjpriv->hw_init_mutex); - mutex_init(&pdvobjpriv->h2c_fwcmd_mutex); - mutex_init(&pdvobjpriv->setch_mutex); - mutex_init(&pdvobjpriv->setbw_mutex); - - pdvobjpriv->pusbintf = usb_intf; - pusbd = interface_to_usbdev(usb_intf); - pdvobjpriv->pusbdev = pusbd; - usb_set_intfdata(usb_intf, pdvobjpriv); - - pdvobjpriv->RtNumInPipes = 0; - pdvobjpriv->RtNumOutPipes = 0; - - phost_conf = pusbd->actconfig; - pconf_desc = &phost_conf->desc; - - phost_iface = &usb_intf->altsetting[0]; - piface_desc = &phost_iface->desc; - - pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces; - pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber; - pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints; - - for (i = 0; i < pdvobjpriv->nr_endpoint; i++) { - pendp_desc = &phost_iface->endpoint[i].desc; - - DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i); - DBG_8723A("bLength =%x\n", pendp_desc->bLength); - DBG_8723A("bDescriptorType =%x\n", pendp_desc->bDescriptorType); - DBG_8723A("bEndpointAddress =%x\n", - pendp_desc->bEndpointAddress); - DBG_8723A("wMaxPacketSize =%d\n", - le16_to_cpu(pendp_desc->wMaxPacketSize)); - DBG_8723A("bInterval =%x\n", pendp_desc->bInterval); - - if (usb_endpoint_is_bulk_in(pendp_desc)) { - DBG_8723A("usb_endpoint_is_bulk_in = %x\n", - usb_endpoint_num(pendp_desc)); - pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumInPipes++; - } else if (usb_endpoint_is_int_in(pendp_desc)) { - DBG_8723A("usb_endpoint_is_int_in = %x, Interval = " - "%x\n", usb_endpoint_num(pendp_desc), - pendp_desc->bInterval); - pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumInPipes++; - } else if (usb_endpoint_is_bulk_out(pendp_desc)) { - DBG_8723A("usb_endpoint_is_bulk_out = %x\n", - usb_endpoint_num(pendp_desc)); - pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumOutPipes++; - } - pdvobjpriv->ep_num[i] = usb_endpoint_num(pendp_desc); - } - DBG_8723A("nr_endpoint =%d, in_num =%d, out_num =%d\n\n", - pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes, - pdvobjpriv->RtNumOutPipes); - - if (pusbd->speed == USB_SPEED_HIGH) { - pdvobjpriv->ishighspeed = true; - DBG_8723A("USB_SPEED_HIGH\n"); - } else { - pdvobjpriv->ishighspeed = false; - DBG_8723A("NON USB_SPEED_HIGH\n"); - } - - if (rtw_init_intf_priv(pdvobjpriv) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't INIT rtw_init_intf_priv\n"); - goto free_dvobj; - } - /* 3 misc */ - rtw_reset_continual_urb_error(pdvobjpriv); - usb_get_dev(pusbd); - status = _SUCCESS; -free_dvobj: - if (status != _SUCCESS && pdvobjpriv) { - usb_set_intfdata(usb_intf, NULL); - mutex_destroy(&pdvobjpriv->hw_init_mutex); - mutex_destroy(&pdvobjpriv->h2c_fwcmd_mutex); - mutex_destroy(&pdvobjpriv->setch_mutex); - mutex_destroy(&pdvobjpriv->setbw_mutex); - kfree(pdvobjpriv); - pdvobjpriv = NULL; - } -exit: - return pdvobjpriv; -} - -static void usb_dvobj_deinit(struct usb_interface *usb_intf) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf); - - usb_set_intfdata(usb_intf, NULL); - if (dvobj) { - /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */ - if ((dvobj->NumInterfaces != 2 && dvobj->NumInterfaces != 3) || - (dvobj->InterfaceNumber == 1)) { - if (interface_to_usbdev(usb_intf)->state != - USB_STATE_NOTATTACHED) { - /* If we didn't unplug usb dongle and - * remove/insert module, driver fails on - * sitesurvey for the first time when - * device is up . - * Reset usb port for sitesurvey fail issue. - */ - DBG_8723A("usb attached..., try to reset usb device\n"); - usb_reset_device(interface_to_usbdev(usb_intf)); - } - } - rtw_deinit_intf_priv(dvobj); - mutex_destroy(&dvobj->hw_init_mutex); - mutex_destroy(&dvobj->h2c_fwcmd_mutex); - mutex_destroy(&dvobj->setch_mutex); - mutex_destroy(&dvobj->setbw_mutex); - kfree(dvobj); - } - usb_put_dev(interface_to_usbdev(usb_intf)); -} - -void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter) -{ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+usb_intf_stop\n"); - - /* disable_hw_interrupt */ - if (!padapter->bSurpriseRemoved) { - /* device still exists, so driver can do i/o operation - * TODO: - */ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "SurpriseRemoved == false\n"); - } - - /* cancel in irp */ - rtl8723au_inirp_deinit(padapter); - - /* cancel out irp */ - rtl8723au_write_port_cancel(padapter); - - /* todo:cancel other irps */ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-usb_intf_stop\n"); -} - -static void rtw_dev_unload(struct rtw_adapter *padapter) -{ - struct submit_ctx *pack_tx_ops = &padapter->xmitpriv.ack_tx_ops; - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_dev_unload\n"); - - if (padapter->bup) { - DBG_8723A("===> rtw_dev_unload\n"); - - padapter->bDriverStopped = true; - if (padapter->xmitpriv.ack_tx) - rtw23a_sctx_done_err(&pack_tx_ops, - RTW_SCTX_DONE_DRV_STOP); - - /* s3. */ - rtl8723a_usb_intf_stop(padapter); - - /* s4. */ - flush_workqueue(padapter->cmdpriv.wq); - - /* s5. */ - if (!padapter->bSurpriseRemoved) { - rtl8723au_hal_deinit(padapter); - padapter->bSurpriseRemoved = true; - } - padapter->bup = false; - } else { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "r871x_dev_unload():padapter->bup == false\n"); - } - DBG_8723A("<=== rtw_dev_unload\n"); - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-rtw_dev_unload\n"); -} - -static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); - struct rtw_adapter *padapter = dvobj->if1; - struct net_device *pnetdev = padapter->pnetdev; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - int ret = 0; - unsigned long start_time = jiffies; - - DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid); - - if ((!padapter->bup) || (padapter->bDriverStopped) || - (padapter->bSurpriseRemoved)) { - DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n", - padapter->bup, padapter->bDriverStopped, - padapter->bSurpriseRemoved); - goto exit; - } - pwrpriv->bInSuspend = true; - rtw_cancel_all_timer23a(padapter); - LeaveAllPowerSaveMode23a(padapter); - - down(&pwrpriv->lock); - /* padapter->net_closed = true; */ - /* s1. */ - if (pnetdev) { - netif_carrier_off(pnetdev); - netif_tx_stop_all_queues(pnetdev); - } - - /* s2. */ - rtw_disassoc_cmd23a(padapter, 0, false); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - DBG_8723A("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n", - __func__, __LINE__, - pmlmepriv->cur_network.network.Ssid.ssid, - pmlmepriv->cur_network.network.MacAddress, - pmlmepriv->cur_network.network.Ssid.ssid_len, - pmlmepriv->assoc_ssid.ssid_len); - - rtw_set_roaming(padapter, 1); - } - /* s2-2. indicate disconnect to os */ - rtw_indicate_disconnect23a(padapter); - /* s2-3. */ - rtw_free_assoc_resources23a(padapter, 1); - /* s2-4. */ - rtw_free_network_queue23a(padapter); - - rtw_dev_unload(padapter); - up(&pwrpriv->lock); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - rtw_cfg80211_indicate_scan_done( - wdev_to_priv(padapter->rtw_wdev), true); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - rtw_indicate_disconnect23a(padapter); - -exit: - DBG_8723A("<=== %s return %d.............. in %dms\n", __func__, - ret, jiffies_to_msecs(jiffies - start_time)); - - return ret; -} - -static int rtw_resume(struct usb_interface *pusb_intf) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); - struct rtw_adapter *padapter = dvobj->if1; - struct net_device *pnetdev; - struct pwrctrl_priv *pwrpriv = NULL; - int ret = -1; - unsigned long start_time = jiffies; - - DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid); - - if (!padapter) - goto exit; - pnetdev = padapter->pnetdev; - pwrpriv = &padapter->pwrctrlpriv; - - down(&pwrpriv->lock); - rtw_reset_drv_sw23a(padapter); - pwrpriv->bkeepfwalive = false; - - DBG_8723A("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive); - if (pm_netdev_open23a(pnetdev, true) != 0) { - up(&pwrpriv->lock); - goto exit; - } - - netif_device_attach(pnetdev); - netif_carrier_on(pnetdev); - - up(&pwrpriv->lock); - - if (padapter->pid[1] != 0) { - DBG_8723A("pid[1]:%d\n", padapter->pid[1]); - kill_pid(find_vpid(padapter->pid[1]), SIGUSR2, 1); - } - - rtw23a_roaming(padapter, NULL); - - ret = 0; -exit: - if (pwrpriv) - pwrpriv->bInSuspend = false; - DBG_8723A("<=== %s return %d.............. in %dms\n", __func__, - ret, jiffies_to_msecs(jiffies - start_time)); - - return ret; -} - -/* - * drv_init() - a device potentially for us - * - * notes: drv_init() is called when the bus driver has located a card - * for us to support. - * We accept the new device by returning 0. - */ -static struct rtw_adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, - struct usb_interface *pusb_intf, - const struct usb_device_id *pdid) -{ - struct rtw_adapter *padapter = NULL; - struct net_device *pnetdev = NULL; - int status = _FAIL; - - pnetdev = rtw_init_netdev23a(padapter); - if (!pnetdev) - goto free_adapter; - padapter = netdev_priv(pnetdev); - - padapter->dvobj = dvobj; - padapter->bDriverStopped = true; - dvobj->if1 = padapter; - dvobj->padapters[dvobj->iface_nums++] = padapter; - padapter->iface_id = IFACE_ID0; - - rtl8723au_set_hw_type(padapter); - - SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj)); - - if (rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj))) - goto free_adapter; - - /* step 2. allocate HalData */ - padapter->HalData = kzalloc(sizeof(struct hal_data_8723a), GFP_KERNEL); - if (!padapter->HalData) - goto free_wdev; - - /* step read_chip_version */ - rtl8723a_read_chip_version(padapter); - - /* step usb endpoint mapping */ - if (!rtl8723au_chip_configure(padapter)) - goto free_hal_data; - - /* step read efuse/eeprom data and get mac_addr */ - rtl8723a_read_adapter_info(padapter); - - /* step 5. */ - if (rtw_init_drv_sw23a(padapter) == _FAIL) { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "Initialize driver software resource Failed!\n"); - goto free_hal_data; - } - -#ifdef CONFIG_PM - if (padapter->pwrctrlpriv.bSupportRemoteWakeup) { - dvobj->pusbdev->do_remote_wakeup = 1; - pusb_intf->needs_remote_wakeup = 1; - device_init_wakeup(&pusb_intf->dev, 1); - DBG_8723A("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n"); - DBG_8723A("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n", - device_may_wakeup(&pusb_intf->dev)); - } -#endif - /* 2012-07-11 Move here to prevent the 8723AS-VAU BT - * auto suspend influence - */ - if (usb_autopm_get_interface(pusb_intf) < 0) - DBG_8723A("can't get autopm:\n"); -#ifdef CONFIG_8723AU_BT_COEXIST - padapter->pwrctrlpriv.autopm_cnt = 1; -#endif - - /* If the eeprom mac address is corrupted, assign a random address */ - if (is_broadcast_ether_addr(padapter->eeprompriv.mac_addr) || - is_zero_ether_addr(padapter->eeprompriv.mac_addr)) - eth_random_addr(padapter->eeprompriv.mac_addr); - - DBG_8723A("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved, - padapter->bup, padapter->hw_init_completed - ); - status = _SUCCESS; - -free_hal_data: - if (status != _SUCCESS) - kfree(padapter->HalData); -free_wdev: - if (status != _SUCCESS) { - rtw_wdev_unregister(padapter->rtw_wdev); - rtw_wdev_free(padapter->rtw_wdev); - } -free_adapter: - if (status != _SUCCESS) { - if (pnetdev) - free_netdev(pnetdev); - padapter = NULL; - } - return padapter; -} - -static void rtw_usb_if1_deinit(struct rtw_adapter *if1) -{ - struct net_device *pnetdev = if1->pnetdev; - struct mlme_priv *pmlmepriv = &if1->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_disassoc_cmd23a(if1, 0, false); - -#ifdef CONFIG_8723AU_AP_MODE - free_mlme_ap_info23a(if1); -#endif - - if (pnetdev) - unregister_netdev(pnetdev); /* will call netdev_close() */ - - rtw_cancel_all_timer23a(if1); - - rtw_dev_unload(if1); - - DBG_8723A("+r871xu_dev_remove, hw_init_completed =%d\n", - if1->hw_init_completed); - - if (if1->rtw_wdev) { - rtw_wdev_unregister(if1->rtw_wdev); - rtw_wdev_free(if1->rtw_wdev); - } - -#ifdef CONFIG_8723AU_BT_COEXIST - if (1 == if1->pwrctrlpriv.autopm_cnt) { - usb_autopm_put_interface(adapter_to_dvobj(if1)->pusbintf); - if1->pwrctrlpriv.autopm_cnt--; - } -#endif - - rtw_free_drv_sw23a(if1); - - if (pnetdev) - free_netdev(pnetdev); -} - -static int rtw_drv_init(struct usb_interface *pusb_intf, - const struct usb_device_id *pdid) -{ - struct rtw_adapter *if1 = NULL; - struct dvobj_priv *dvobj; - struct usb_device *udev; - int status = _FAIL; - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_init\n"); - - /* Initialize dvobj_priv */ - dvobj = usb_dvobj_init(pusb_intf); - if (!dvobj) { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "initialize device object priv Failed!\n"); - goto exit; - } - - udev = dvobj->pusbdev; - dev_warn(&udev->dev, "WARNING: The rtl8723au driver is deprecated!"); - dev_warn(&udev->dev, "Please use the rtl8xxxu driver for this device!"); - - if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid); - if (!if1) { - DBG_8723A("rtw_init_primary_adapter Failed!\n"); - goto free_dvobj; - } - - /* dev_alloc_name && register_netdev */ - status = rtw_drv_register_netdev(if1); - if (status != _SUCCESS) - goto free_if1; - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "-871x_drv - drv_init, success!\n"); - - status = _SUCCESS; - -free_if1: - if (status != _SUCCESS && if1) - rtw_usb_if1_deinit(if1); -free_dvobj: - if (status != _SUCCESS) - usb_dvobj_deinit(pusb_intf); -exit: - return status == _SUCCESS ? 0 : -ENODEV; -} - -/* dev_remove() - our device is being removed */ -static void rtw_disconnect(struct usb_interface *pusb_intf) -{ - struct dvobj_priv *dvobj; - struct rtw_adapter *padapter; - struct net_device *pnetdev; - struct mlme_priv *pmlmepriv; - - dvobj = usb_get_intfdata(pusb_intf); - if (!dvobj) - return; - - padapter = dvobj->if1; - pnetdev = padapter->pnetdev; - pmlmepriv = &padapter->mlmepriv; - - usb_set_intfdata(pusb_intf, NULL); - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+dev_remove()\n"); - - rtw_pm_set_ips23a(padapter, IPS_NONE); - rtw_pm_set_lps23a(padapter, PS_MODE_ACTIVE); - - LeaveAllPowerSaveMode23a(padapter); - - rtw_usb_if1_deinit(padapter); - - usb_dvobj_deinit(pusb_intf); - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-dev_remove()\n"); - DBG_8723A("-r871xu_dev_remove, done\n"); -} - -static int __init rtw_drv_entry(void) -{ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_entry\n"); - return usb_register(usb_drv); -} - -static void __exit rtw_drv_halt(void) -{ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_halt\n"); - DBG_8723A("+rtw_drv_halt\n"); - - usb_deregister(usb_drv); - - DBG_8723A("-rtw_drv_halt\n"); -} - -module_init(rtw_drv_entry); -module_exit(rtw_drv_halt); diff --git a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c deleted file mode 100644 index cf4a50618670..000000000000 --- a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c +++ /dev/null @@ -1,233 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _USB_OPS_LINUX_C_ - -#include -#include -#include - -void rtl8723au_read_port_cancel(struct rtw_adapter *padapter) -{ - struct recv_buf *precvbuf; - int i; - - precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf; - - DBG_8723A("%s\n", __func__); - - padapter->bReadPortCancel = true; - - for (i = 0; i < NR_RECVBUFF ; i++) { - if (precvbuf->purb) - usb_kill_urb(precvbuf->purb); - precvbuf++; - } - usb_kill_urb(padapter->recvpriv.int_in_urb); -} - -static void usb_write_port23a_complete(struct urb *purb) -{ - struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context; - struct rtw_adapter *padapter = pxmitbuf->padapter; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct hal_data_8723a *phaldata; - unsigned long irqL; - - switch (pxmitbuf->flags) { - case HIGH_QUEUE_INX: -#ifdef CONFIG_8723AU_AP_MODE - rtw_chk_hi_queue_cmd23a(padapter); -#endif - break; - default: - break; - } - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped || - padapter->bWritePortCancel) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved); - DBG_8723A("%s(): TX Warning! bDriverStopped(%d) OR " - "bSurpriseRemoved(%d) bWritePortCancel(%d) " - "pxmitbuf->ext_tag(%x)\n", __func__, - padapter->bDriverStopped, padapter->bSurpriseRemoved, - padapter->bReadPortCancel, pxmitbuf->ext_tag); - - goto check_completion; - } - - if (purb->status) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete : purb->status(%d) != 0\n", - purb->status); - DBG_8723A("###=> urb_write_port_complete status(%d)\n", - purb->status); - if (purb->status == -EPIPE || purb->status == -EPROTO) { - } else if (purb->status == -EINPROGRESS) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete: EINPROGESS\n"); - goto check_completion; - } else if (purb->status == -ENOENT) { - DBG_8723A("%s: -ENOENT\n", __func__); - goto check_completion; - } else if (purb->status == -ECONNRESET) { - DBG_8723A("%s: -ECONNRESET\n", __func__); - goto check_completion; - } else if (purb->status == -ESHUTDOWN) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete: ESHUTDOWN\n"); - padapter->bDriverStopped = true; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete:bDriverStopped = true\n"); - goto check_completion; - } else { - padapter->bSurpriseRemoved = true; - DBG_8723A("bSurpriseRemoved = true\n"); - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete:bSurpriseRemoved = true\n"); - goto check_completion; - } - } - phaldata = GET_HAL_DATA(padapter); - phaldata->srestpriv.last_tx_complete_time = jiffies; - -check_completion: - spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); - rtw23a_sctx_done_err(&pxmitbuf->sctx, - purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : - RTW_SCTX_DONE_SUCCESS); - spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); - - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); -} - -int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt, - struct xmit_buf *pxmitbuf) -{ - struct urb *purb = NULL; - struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_frame *pxmitframe; - struct usb_device *pusbd = pdvobj->pusbdev; - unsigned long irqL; - unsigned int pipe, ep_num; - int status; - int ret = _FAIL; - - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "+usb_write_port23a\n"); - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "%s:(padapter->bDriverStopped || padapter->bSurpriseRemoved)!!!\n", - __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); - goto exit; - } - - pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; - spin_lock_irqsave(&pxmitpriv->lock, irqL); - - switch (addr) { - case VO_QUEUE_INX: - pxmitbuf->flags = VO_QUEUE_INX; - break; - case VI_QUEUE_INX: - pxmitbuf->flags = VI_QUEUE_INX; - break; - case BE_QUEUE_INX: - pxmitbuf->flags = BE_QUEUE_INX; - break; - case BK_QUEUE_INX: - pxmitbuf->flags = BK_QUEUE_INX; - break; - case HIGH_QUEUE_INX: - pxmitbuf->flags = HIGH_QUEUE_INX; - break; - default: - pxmitbuf->flags = MGT_QUEUE_INX; - break; - } - - spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - - purb = pxmitbuf->pxmit_urb[0]; - - /* translate DMA FIFO addr to pipehandle */ - ep_num = pdvobj->Queue2Pipe[addr]; - pipe = usb_sndbulkpipe(pusbd, ep_num); - - usb_fill_bulk_urb(purb, pusbd, pipe, - pxmitframe->buf_addr, /* pxmitbuf->pbuf */ - cnt, usb_write_port23a_complete, - pxmitbuf);/* context is pxmitbuf */ - - status = usb_submit_urb(purb, GFP_ATOMIC); - if (!status) { - struct hal_data_8723a *phaldata = GET_HAL_DATA(padapter); - phaldata->srestpriv.last_tx_time = jiffies; - } else { - rtw23a_sctx_done_err(&pxmitbuf->sctx, - RTW_SCTX_DONE_WRITE_PORT_ERR); - DBG_8723A("usb_write_port23a, status =%d\n", status); - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a(): usb_submit_urb, status =%x\n", - status); - - switch (status) { - case -ENODEV: - padapter->bDriverStopped = true; - break; - default: - break; - } - goto exit; - } - ret = _SUCCESS; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "-usb_write_port23a\n"); - -exit: - if (ret != _SUCCESS) - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - - return ret; -} - -void rtl8723au_write_port_cancel(struct rtw_adapter *padapter) -{ - struct xmit_buf *pxmitbuf; - int j; - - DBG_8723A("%s\n", __func__); - - padapter->bWritePortCancel = true; - - list_for_each_entry(pxmitbuf, &padapter->xmitpriv.xmitbuf_list, - list2) { - for (j = 0; j < 8; j++) { - if (pxmitbuf->pxmit_urb[j]) - usb_kill_urb(pxmitbuf->pxmit_urb[j]); - } - } - list_for_each_entry(pxmitbuf, &padapter->xmitpriv.xmitextbuf_list, - list2) { - for (j = 0; j < 8; j++) { - if (pxmitbuf->pxmit_urb[j]) - usb_kill_urb(pxmitbuf->pxmit_urb[j]); - } - } -} diff --git a/drivers/staging/rtl8723au/os_dep/xmit_linux.c b/drivers/staging/rtl8723au/os_dep/xmit_linux.c deleted file mode 100644 index 64be72ac38ee..000000000000 --- a/drivers/staging/rtl8723au/os_dep/xmit_linux.c +++ /dev/null @@ -1,154 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. 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 for - * more details. - * - ******************************************************************************/ -#define _XMIT_OSDEP_C_ - -#include -#include - -#include -#include -#include -#include -#include -#include - -int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter, - struct xmit_buf *pxmitbuf, u32 alloc_sz) -{ - int i; - - pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL); - if (pxmitbuf->pallocated_buf == NULL) - return _FAIL; - - pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ); - - for (i = 0; i < 8; i++) { - pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!pxmitbuf->pxmit_urb[i]) { - DBG_8723A("pxmitbuf->pxmit_urb[i]==NULL"); - return _FAIL; - } - } - return _SUCCESS; -} - -void rtw_os_xmit_resource_free23a(struct rtw_adapter *padapter, - struct xmit_buf *pxmitbuf) -{ - int i; - - for (i = 0; i < 8; i++) - usb_free_urb(pxmitbuf->pxmit_urb[i]); - kfree(pxmitbuf->pallocated_buf); -} - -#define WMM_XMIT_THRESHOLD (NR_XMITFRAME*2/5) - -void rtw_os_pkt_complete23a(struct rtw_adapter *padapter, struct sk_buff *pkt) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u16 queue; - - queue = skb_get_queue_mapping(pkt); - if (padapter->registrypriv.wifi_spec) { - if (__netif_subqueue_stopped(padapter->pnetdev, queue) && - (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD)) - netif_wake_subqueue(padapter->pnetdev, queue); - } else { - if (__netif_subqueue_stopped(padapter->pnetdev, queue)) - netif_wake_subqueue(padapter->pnetdev, queue); - } - dev_kfree_skb_any(pkt); -} - -void rtw_os_xmit_complete23a(struct rtw_adapter *padapter, - struct xmit_frame *pxframe) -{ - if (pxframe->pkt) - rtw_os_pkt_complete23a(padapter, pxframe->pkt); - - pxframe->pkt = NULL; -} - -void rtw_os_xmit_schedule23a(struct rtw_adapter *padapter) -{ - struct xmit_priv *pxmitpriv; - - if (!padapter) - return; - pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - if (rtw_txframes_pending23a(padapter)) - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - spin_unlock_bh(&pxmitpriv->lock); -} - -static void rtw_check_xmit_resource(struct rtw_adapter *padapter, - struct sk_buff *pkt) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u16 queue; - - queue = skb_get_queue_mapping(pkt); - if (padapter->registrypriv.wifi_spec) { - /* No free space for Tx, tx_worker is too slow */ - if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD) - netif_stop_subqueue(padapter->pnetdev, queue); - } else { - if (pxmitpriv->free_xmitframe_cnt <= 4) { - if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue))) - netif_stop_subqueue(padapter->pnetdev, queue); - } - } -} - -int rtw_xmit23a_entry23a(struct sk_buff *skb, struct net_device *pnetdev) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int res = 0; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, "+xmit_enry\n"); - - if (!rtw_if_up23a(padapter)) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a_entry23a: rtw_if_up23a fail\n"); - goto drop_packet; - } - - rtw_check_xmit_resource(padapter, skb); - - res = rtw_xmit23a(padapter, skb); - if (res < 0) - goto drop_packet; - - pxmitpriv->tx_pkts++; - RT_TRACE(_module_xmit_osdep_c_, _drv_info_, - "rtw_xmit23a_entry23a: tx_pkts=%d\n", - (u32)pxmitpriv->tx_pkts); - goto exit; - -drop_packet: - pxmitpriv->tx_drop++; - dev_kfree_skb_any(skb); - RT_TRACE(_module_xmit_osdep_c_, _drv_notice_, - "rtw_xmit23a_entry23a: drop, tx_drop=%d\n", - (u32)pxmitpriv->tx_drop); -exit: - return 0; -} diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 0f0cd4a03cd4..f27df0b4cb44 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -63,12 +63,12 @@ static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode, rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, - 0xFF, MS_TRANSFER_START | trans_mode); + 0xFF, MS_TRANSFER_START | trans_mode); rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); + MS_TRANSFER_END, MS_TRANSFER_END); rtsx_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0); @@ -109,8 +109,8 @@ static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode, } static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode, - u8 tpc, u16 sec_cnt, u8 cfg, bool mode_2k, - int use_sg, void *buf, int buf_len) + u8 tpc, u16 sec_cnt, u8 cfg, bool mode_2k, + int use_sg, void *buf, int buf_len) { int retval; u8 val, err_code = 0; @@ -206,7 +206,7 @@ static int ms_write_bytes(struct rtsx_chip *chip, rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES); @@ -253,7 +253,7 @@ static int ms_write_bytes(struct rtsx_chip *chip, } static int ms_read_bytes(struct rtsx_chip *chip, - u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len) + u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len) { struct ms_info *ms_card = &chip->ms_card; int retval, i; @@ -270,12 +270,12 @@ static int ms_read_bytes(struct rtsx_chip *chip, rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_READ_BYTES); + MS_TRANSFER_START | MS_TM_READ_BYTES); rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); + MS_TRANSFER_END, MS_TRANSFER_END); for (i = 0; i < data_len - 1; i++) rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); @@ -284,7 +284,7 @@ static int ms_read_bytes(struct rtsx_chip *chip, rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0); else rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1, - 0, 0); + 0, 0); retval = rtsx_send_cmd(chip, MS_CARD, 5000); if (retval < 0) { @@ -334,8 +334,8 @@ static int ms_read_bytes(struct rtsx_chip *chip, return STATUS_SUCCESS; } -static int ms_set_rw_reg_addr(struct rtsx_chip *chip, - u8 read_start, u8 read_cnt, u8 write_start, u8 write_cnt) +static int ms_set_rw_reg_addr(struct rtsx_chip *chip, u8 read_start, + u8 read_cnt, u8 write_start, u8 write_cnt) { int retval, i; u8 data[4]; @@ -1417,7 +1417,6 @@ static int ms_read_status_reg(struct rtsx_chip *chip) return STATUS_SUCCESS; } - static int ms_read_extra_data(struct rtsx_chip *chip, u16 block_addr, u8 page_num, u8 *buf, int buf_len) { @@ -1582,7 +1581,6 @@ static int ms_write_extra_data(struct rtsx_chip *chip, return STATUS_SUCCESS; } - static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) { struct ms_info *ms_card = &chip->ms_card; @@ -1667,7 +1665,6 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) return STATUS_SUCCESS; } - static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) { struct ms_info *ms_card = &chip->ms_card; @@ -1738,7 +1735,6 @@ static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) return STATUS_SUCCESS; } - static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk) { struct ms_info *ms_card = &chip->ms_card; @@ -1808,7 +1804,6 @@ ERASE_RTY: return STATUS_SUCCESS; } - static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len) { if (!extra || (extra_len < MS_EXTRA_SIZE)) @@ -2152,7 +2147,6 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, return STATUS_SUCCESS; } - static int reset_ms(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; @@ -2471,7 +2465,7 @@ static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off) if (!ms_card->segment) return 0xFFFF; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; if (segment->l2p_table) return segment->l2p_table[log_off]; @@ -2488,7 +2482,7 @@ static void ms_set_l2p_tbl(struct rtsx_chip *chip, if (!ms_card->segment) return; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; if (segment->l2p_table) segment->l2p_table[log_off] = phy_blk; } @@ -2500,7 +2494,7 @@ static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk) int seg_no; seg_no = (int)phy_blk >> 9; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; segment->free_table[segment->set_index++] = phy_blk; if (segment->set_index >= MS_FREE_TABLE_CNT) @@ -2515,7 +2509,7 @@ static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no) struct zone_entry *segment; u16 phy_blk; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; if (segment->unused_blk_cnt <= 0) return 0xFFFF; @@ -2544,7 +2538,7 @@ static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk, u16 tmp_blk; seg_no = (int)phy_blk >> 9; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; tmp_blk = segment->l2p_table[log_off]; if (us1 != us2) { @@ -2608,7 +2602,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) else table_size = 496; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; if (!segment->l2p_table) { segment->l2p_table = vmalloc(table_size * 2); @@ -2717,7 +2711,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) us2 = extra[0] & 0x10; (void)ms_arbitrate_l2p(chip, phy_blk, - log_blk-ms_start_idx[seg_no], us1, us2); + log_blk - ms_start_idx[seg_no], us1, us2); continue; } @@ -2809,7 +2803,6 @@ BUILD_FAIL: return STATUS_FAIL; } - int reset_ms_card(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; @@ -2896,7 +2889,6 @@ static int mspro_set_rw_cmd(struct rtsx_chip *chip, return STATUS_SUCCESS; } - void mspro_stop_seq_mode(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; @@ -3312,7 +3304,6 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, return STATUS_FAIL; } - static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, u8 start_page, u8 end_page, u8 *buf, unsigned int *index, @@ -3719,7 +3710,6 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, return STATUS_SUCCESS; } - static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, u16 log_blk, u8 page_off) { @@ -3770,7 +3760,7 @@ static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, int ms_delay_write(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; - struct ms_delay_write_tag *delay_write = &(ms_card->delay_write); + struct ms_delay_write_tag *delay_write = &ms_card->delay_write; int retval; if (delay_write->delay_write_flag) { @@ -3816,7 +3806,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u8 start_page, end_page = 0, page_cnt; u8 *ptr; #ifdef MS_DELAY_WRITE - struct ms_delay_write_tag *delay_write = &(ms_card->delay_write); + struct ms_delay_write_tag *delay_write = &ms_card->delay_write; #endif ms_set_err_code(chip, MS_NO_ERROR); @@ -3996,7 +3986,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) { - if (log_blk < ms_start_idx[seg_no+1]) + if (log_blk < ms_start_idx[seg_no + 1]) break; } @@ -4082,13 +4072,12 @@ int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, return retval; } - void ms_free_l2p_tbl(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; int i = 0; - if (ms_card->segment != NULL) { + if (ms_card->segment) { for (i = 0; i < ms_card->segment_cnt; i++) { vfree(ms_card->segment[i].l2p_table); ms_card->segment[i].l2p_table = NULL; @@ -4313,7 +4302,7 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); rtsx_trace(chip); - goto GetEKBFinish; + goto free_buffer; } retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, @@ -4322,19 +4311,20 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); rtsx_clear_ms_error(chip); rtsx_trace(chip); - goto GetEKBFinish; + goto free_buffer; } if (check_ms_err(chip)) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); rtsx_clear_ms_error(chip); rtsx_trace(chip); - return STATUS_FAIL; + retval = STATUS_FAIL; + goto free_buffer; } bufflen = min_t(int, 1052, scsi_bufflen(srb)); rtsx_stor_set_xfer_buf(buf, bufflen, srb); -GetEKBFinish: +free_buffer: kfree(buf); return retval; } @@ -4566,7 +4556,7 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); - goto GetICVFinish; + goto free_buffer; } retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, @@ -4575,19 +4565,20 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_clear_ms_error(chip); rtsx_trace(chip); - goto GetICVFinish; + goto free_buffer; } if (check_ms_err(chip)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_clear_ms_error(chip); rtsx_trace(chip); - return STATUS_FAIL; + retval = STATUS_FAIL; + goto free_buffer; } bufflen = min_t(int, 1028, scsi_bufflen(srb)); rtsx_stor_set_xfer_buf(buf, bufflen, srb); -GetICVFinish: +free_buffer: kfree(buf); return retval; } @@ -4657,8 +4648,8 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_send_cmd_no_wait(chip); - retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i*512, - 512, 0, DMA_TO_DEVICE, 3000); + retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i * 512, + 512, 0, DMA_TO_DEVICE, 3000); if ((retval < 0) || check_ms_err(chip)) { rtsx_clear_ms_error(chip); if (ms_card->mg_auth == 0) { @@ -4705,7 +4696,7 @@ SetICVFinish: void ms_cleanup_work(struct rtsx_chip *chip) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; if (CHK_MSPRO(ms_card)) { if (ms_card->seq_mode) { @@ -4770,7 +4761,7 @@ int ms_power_off_card3v3(struct rtsx_chip *chip) int release_ms_card(struct rtsx_chip *chip) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; int retval; #ifdef MS_DELAY_WRITE diff --git a/drivers/staging/rts5208/ms.h b/drivers/staging/rts5208/ms.h index d919170f2720..d7686399df97 100644 --- a/drivers/staging/rts5208/ms.h +++ b/drivers/staging/rts5208/ms.h @@ -125,7 +125,6 @@ #define Pro_CatagoryReg 0x06 #define Pro_ClassReg 0x07 - #define Pro_SystemParm 0x10 #define Pro_DataCount1 0x11 #define Pro_DataCount0 0x12 diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 25d095a5ade7..5d65a5cdc748 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -34,27 +34,27 @@ MODULE_DESCRIPTION("Realtek PCI-Express card reader rts5208/rts5288 driver"); MODULE_LICENSE("GPL"); static unsigned int delay_use = 1; -module_param(delay_use, uint, S_IRUGO | S_IWUSR); +module_param(delay_use, uint, 0644); MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); static int ss_en; -module_param(ss_en, int, S_IRUGO | S_IWUSR); +module_param(ss_en, int, 0644); MODULE_PARM_DESC(ss_en, "enable selective suspend"); static int ss_interval = 50; -module_param(ss_interval, int, S_IRUGO | S_IWUSR); +module_param(ss_interval, int, 0644); MODULE_PARM_DESC(ss_interval, "Interval to enter ss state in seconds"); static int auto_delink_en; -module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); +module_param(auto_delink_en, int, 0644); MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); static unsigned char aspm_l0s_l1_en; -module_param(aspm_l0s_l1_en, byte, S_IRUGO | S_IWUSR); +module_param(aspm_l0s_l1_en, byte, 0644); MODULE_PARM_DESC(aspm_l0s_l1_en, "enable device aspm"); static int msi_en; -module_param(msi_en, int, S_IRUGO | S_IWUSR); +module_param(msi_en, int, 0644); MODULE_PARM_DESC(msi_en, "enable msi"); static irqreturn_t rtsx_interrupt(int irq, void *dev_id); @@ -81,14 +81,16 @@ static int slave_alloc(struct scsi_device *sdev) static int slave_configure(struct scsi_device *sdev) { - /* Scatter-gather buffers (all but the last) must have a length + /* + * Scatter-gather buffers (all but the last) must have a length * divisible by the bulk maxpacket size. Otherwise a data packet * would end up being short, causing a premature end to the data * transfer. Since high-speed bulk pipes have a maxpacket size * of 512, we'll use that as the scsi device queue's DMA alignment * mask. Guaranteeing proper alignment of the first buffer will * have the desired effect because, except at the beginning and - * the end, scatter-gather buffers follow page boundaries. */ + * the end, scatter-gather buffers follow page boundaries. + */ blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); /* Set the SCSI level to at least 2. We'll leave it at 3 if that's @@ -111,7 +113,6 @@ static int slave_configure(struct scsi_device *sdev) return 0; } - /*********************************************************************** * /proc/scsi/ functions ***********************************************************************/ @@ -130,7 +131,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb, struct rtsx_chip *chip = dev->chip; /* check for state-transition errors */ - if (chip->srb != NULL) { + if (chip->srb) { dev_err(&dev->pci->dev, "Error: chip->srb = %p\n", chip->srb); return SCSI_MLQUEUE_HOST_BUSY; @@ -186,8 +187,10 @@ static int command_abort(struct scsi_cmnd *srb) return SUCCESS; } -/* This invokes the transport reset mechanism to reset the state of the - * device */ +/* + * This invokes the transport reset mechanism to reset the state of the + * device + */ static int device_reset(struct scsi_cmnd *srb) { int result = 0; @@ -209,7 +212,6 @@ static int bus_reset(struct scsi_cmnd *srb) return result < 0 ? FAILED : SUCCESS; } - /* * this defines our host template, with which we'll allocate hosts */ @@ -259,7 +261,6 @@ static struct scsi_host_template rtsx_host_template = { .module = THIS_MODULE }; - static int rtsx_acquire_irq(struct rtsx_dev *dev) { struct rtsx_chip *chip = dev->chip; @@ -282,7 +283,6 @@ static int rtsx_acquire_irq(struct rtsx_dev *dev) return 0; } - int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val) { struct pci_dev *pdev; @@ -515,7 +515,6 @@ SkipForAbort: complete_and_exit(&dev->control_exit, 0); } - static int rtsx_polling_thread(void *__dev) { struct rtsx_dev *dev = __dev; @@ -625,7 +624,6 @@ Exit: return IRQ_HANDLED; } - /* Release all our dynamic resources */ static void rtsx_release_resources(struct rtsx_dev *dev) { @@ -660,15 +658,19 @@ static void rtsx_release_resources(struct rtsx_dev *dev) kfree(dev->chip); } -/* First stage of disconnect processing: stop all commands and remove - * the host */ +/* + * First stage of disconnect processing: stop all commands and remove + * the host + */ static void quiesce_and_remove_host(struct rtsx_dev *dev) { struct Scsi_Host *host = rtsx_to_host(dev); struct rtsx_chip *chip = dev->chip; - /* Prevent new transfers, stop the current command, and - * interrupt a SCSI-scan or device-reset delay */ + /* + * Prevent new transfers, stop the current command, and + * interrupt a SCSI-scan or device-reset delay + */ mutex_lock(&dev->dev_mutex); scsi_lock(host); rtsx_set_stat(chip, RTSX_STAT_DISCONNECT); @@ -680,9 +682,11 @@ static void quiesce_and_remove_host(struct rtsx_dev *dev) /* Wait some time to let other threads exist */ wait_timeout(100); - /* queuecommand won't accept any new commands and the control + /* + * queuecommand won't accept any new commands and the control * thread won't execute a previously-queued command. If there - * is such a command pending, complete it with an error. */ + * is such a command pending, complete it with an error. + */ mutex_lock(&dev->dev_mutex); if (chip->srb) { chip->srb->result = DID_NO_CONNECT << 16; @@ -702,8 +706,10 @@ static void release_everything(struct rtsx_dev *dev) { rtsx_release_resources(dev); - /* Drop our reference to the host; the SCSI core will free it - * when the refcount becomes 0. */ + /* + * Drop our reference to the host; the SCSI core will free it + * when the refcount becomes 0. + */ scsi_host_put(rtsx_to_host(dev)); } @@ -942,8 +948,10 @@ static int rtsx_probe(struct pci_dev *pci, rtsx_init_chip(dev->chip); - /* set the supported max_lun and max_id for the scsi host - * NOTE: the minimal value of max_id is 1 */ + /* + * set the supported max_lun and max_id for the scsi host + * NOTE: the minimal value of max_id is 1 + */ host->max_id = 1; host->max_lun = dev->chip->max_lun; @@ -994,7 +1002,6 @@ errout: return err; } - static void rtsx_remove(struct pci_dev *pci) { struct rtsx_dev *dev = pci_get_drvdata(pci); diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index 1396263e13e6..e725b10ed087 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -70,14 +70,13 @@ #define rtsx_write_config_byte(chip, where, val) \ pci_write_config_byte((chip)->rtsx->pci, where, val) -#define wait_timeout_x(task_state, msecs) \ -do { \ - set_current_state((task_state)); \ - schedule_timeout((msecs) * HZ / 1000); \ +#define wait_timeout_x(task_state, msecs) \ +do { \ + set_current_state((task_state)); \ + schedule_timeout((msecs) * HZ / 1000); \ } while (0) #define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs)) - #define STATE_TRANS_NONE 0 #define STATE_TRANS_CMD 1 #define STATE_TRANS_BUF 2 @@ -89,8 +88,6 @@ do { \ #define SCSI_LUN(srb) ((srb)->device->lun) -typedef unsigned long DELAY_PARA_T; - struct rtsx_chip; struct rtsx_dev { @@ -131,16 +128,15 @@ struct rtsx_dev { struct rtsx_chip *chip; }; -typedef struct rtsx_dev rtsx_dev_t; - /* Convert between rtsx_dev and the corresponding Scsi_Host */ static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev) { - return container_of((void *) dev, struct Scsi_Host, hostdata); + return container_of((void *)dev, struct Scsi_Host, hostdata); } + static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host) { - return (struct rtsx_dev *) host->hostdata; + return (struct rtsx_dev *)host->hostdata; } static inline void get_current_time(u8 *timeval_buf, int buf_len) @@ -165,8 +161,10 @@ static inline void get_current_time(u8 *timeval_buf, int buf_len) timeval_buf[7] = (u8)(tv_usec); } -/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the - * single queue element srb for write access */ +/* + * The scsi_lock() and scsi_unlock() macros protect the sm_state and the + * single queue element srb for write access + */ #define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock) diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index 231833a3045e..97717744962d 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -631,21 +631,21 @@ void rtsx_init_cards(struct rtsx_chip *chip) int switch_ssc_clock(struct rtsx_chip *chip, int clk) { int retval; - u8 N = (u8)(clk - 2), min_N, max_N; + u8 n = (u8)(clk - 2), min_n, max_n; u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask; int sd_vpclk_phase_reset = 0; if (chip->cur_clk == clk) return STATUS_SUCCESS; - min_N = 60; - max_N = 120; + min_n = 60; + max_n = 120; max_div = CLK_DIV_4; dev_dbg(rtsx_dev(chip), "Switch SSC clock to %dMHz (cur_clk = %d)\n", clk, chip->cur_clk); - if ((clk <= 2) || (N > max_N)) { + if ((clk <= 2) || (n > max_n)) { rtsx_trace(chip); return STATUS_FAIL; } @@ -655,15 +655,15 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) mcu_cnt = 7; div = CLK_DIV_1; - while ((N < min_N) && (div < max_div)) { - N = (N + 2) * 2 - 2; + while ((n < min_n) && (div < max_div)) { + n = (n + 2) * 2 - 2; div++; } - dev_dbg(rtsx_dev(chip), "N = %d, div = %d\n", N, div); + dev_dbg(rtsx_dev(chip), "n = %d, div = %d\n", n, div); if (chip->ssc_en) { ssc_depth = 0x01; - N -= 2; + n -= 2; } else { ssc_depth = 0; } @@ -677,7 +677,7 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth); - rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N); + rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); if (sd_vpclk_phase_reset) { rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, @@ -1027,26 +1027,26 @@ int card_share_mode(struct rtsx_chip *chip, int card) if (CHECK_PID(chip, 0x5208)) { mask = CARD_SHARE_MASK; - if (card == SD_CARD) + if (card == SD_CARD) { value = CARD_SHARE_48_SD; - else if (card == MS_CARD) + } else if (card == MS_CARD) { value = CARD_SHARE_48_MS; - else if (card == XD_CARD) + } else if (card == XD_CARD) { value = CARD_SHARE_48_XD; - else { + } else { rtsx_trace(chip); return STATUS_FAIL; } } else if (CHECK_PID(chip, 0x5288)) { mask = 0x03; - if (card == SD_CARD) + if (card == SD_CARD) { value = CARD_SHARE_BAROSSA_SD; - else if (card == MS_CARD) + } else if (card == MS_CARD) { value = CARD_SHARE_BAROSSA_MS; - else if (card == XD_CARD) + } else if (card == XD_CARD) { value = CARD_SHARE_BAROSSA_XD; - else { + } else { rtsx_trace(chip); return STATUS_FAIL; } @@ -1065,7 +1065,6 @@ int card_share_mode(struct rtsx_chip *chip, int card) return STATUS_SUCCESS; } - int select_card(struct rtsx_chip *chip, int card) { int retval; @@ -1073,15 +1072,15 @@ int select_card(struct rtsx_chip *chip, int card) if (chip->cur_card != card) { u8 mod; - if (card == SD_CARD) + if (card == SD_CARD) { mod = SD_MOD_SEL; - else if (card == MS_CARD) + } else if (card == MS_CARD) { mod = MS_MOD_SEL; - else if (card == XD_CARD) + } else if (card == XD_CARD) { mod = XD_MOD_SEL; - else if (card == SPI_CARD) + } else if (card == SPI_CARD) { mod = SPI_MOD_SEL; - else { + } else { rtsx_trace(chip); return STATUS_FAIL; } diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c index bcc4b666d79f..a10dd6220a7b 100644 --- a/drivers/staging/rts5208/rtsx_chip.c +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -743,7 +743,7 @@ static inline int check_sd_speed_prior(u32 sd_speed_prior) int i; for (i = 0; i < 4; i++) { - u8 tmp = (u8)(sd_speed_prior >> (i*8)); + u8 tmp = (u8)(sd_speed_prior >> (i * 8)); if ((tmp < 0x01) || (tmp > 0x04)) { fake_para = true; @@ -760,7 +760,7 @@ static inline int check_sd_current_prior(u32 sd_current_prior) int i; for (i = 0; i < 4; i++) { - u8 tmp = (u8)(sd_current_prior >> (i*8)); + u8 tmp = (u8)(sd_current_prior >> (i * 8)); if (tmp > 0x03) { fake_para = true; @@ -2288,7 +2288,7 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) ptr = buf; reg_addr = PPBUF_BASE2; - for (i = 0; i < buf_len/256; i++) { + for (i = 0; i < buf_len / 256; i++) { rtsx_init_cmd(chip); for (j = 0; j < 256; j++) @@ -2304,10 +2304,10 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) ptr += 256; } - if (buf_len%256) { + if (buf_len % 256) { rtsx_init_cmd(chip); - for (j = 0; j < buf_len%256; j++) + for (j = 0; j < buf_len % 256; j++) rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0); retval = rtsx_send_cmd(chip, 0, 250); @@ -2317,7 +2317,7 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) } } - memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256); + memcpy(ptr, rtsx_get_cmd_data(chip), buf_len % 256); return STATUS_SUCCESS; } @@ -2336,7 +2336,7 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) ptr = buf; reg_addr = PPBUF_BASE2; - for (i = 0; i < buf_len/256; i++) { + for (i = 0; i < buf_len / 256; i++) { rtsx_init_cmd(chip); for (j = 0; j < 256; j++) { @@ -2352,10 +2352,10 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) } } - if (buf_len%256) { + if (buf_len % 256) { rtsx_init_cmd(chip); - for (j = 0; j < buf_len%256; j++) { + for (j = 0; j < buf_len % 256; j++) { rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, *ptr); ptr++; diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index c08164f3247e..f36642817c6e 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -44,8 +44,10 @@ #define MG_SET_ICV_SLOW /* HW may miss ERR/CMDNK signal when sampling INT status. */ #define MS_SAMPLE_INT_ERR - /* HW DO NOT support Wait_INT function during READ_BYTES - * transfer mode */ + /* + * HW DO NOT support Wait_INT function + * during READ_BYTES transfer mode + */ #define READ_BYTES_WAIT_INT #endif @@ -101,18 +103,17 @@ #define TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */ #define TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */ - -/*----------------------------------- - Start-Stop-Unit ------------------------------------*/ +/* + * Start-Stop-Unit + */ #define STOP_MEDIUM 0x00 /* access disable */ #define MAKE_MEDIUM_READY 0x01 /* access enable */ #define UNLOAD_MEDIUM 0x02 /* unload */ #define LOAD_MEDIUM 0x03 /* load */ -/*----------------------------------- - STANDARD_INQUIRY ------------------------------------*/ +/* + * STANDARD_INQUIRY + */ #define QULIFIRE 0x00 #define AENC_FNC 0x00 #define TRML_IOP 0x00 @@ -129,17 +130,15 @@ #define PRDCT_REV_LEN 4 /* Product LOT Length */ /* Dynamic flag definitions: used in set_bit() etc. */ -#define RTSX_FLIDX_TRANS_ACTIVE 18 /* 0x00040000 transfer is active */ -#define RTSX_FLIDX_ABORTING 20 /* 0x00100000 abort is in - * progress */ -#define RTSX_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect - * in progress */ +#define RTSX_FLIDX_TRANS_ACTIVE 18 /* 0x00040000 transfer is active */ +#define RTSX_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */ +#define RTSX_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */ + #define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \ (1UL << US_FLIDX_DISCONNECTING)) -#define RTSX_FLIDX_RESETTING 22 /* 0x00400000 device reset - * in progress */ -#define RTSX_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI - * midlayer timed out */ + +#define RTSX_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */ +#define RTSX_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI midlayer timed out */ #define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */ #define RMB_DISC 0x80 /* The Device is Removable */ @@ -174,9 +173,9 @@ #define FIRST_RESET 0x01 #define USED_EXIST 0x02 -/*----------------------------------- - SENSE_DATA ------------------------------------*/ +/* + * SENSE_DATA + */ /*---- valid ----*/ #define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */ #define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */ @@ -228,7 +227,6 @@ #define ASCQ_LOAD_EJCT_ERR 0x00 #define ASCQ_WRITE_PROTECT 0x00 - struct sense_data_t { unsigned char err_code; /* error code */ /* bit7 : valid */ @@ -268,22 +266,22 @@ struct sense_data_t { #define TRIG_DMA (0x01 << 31) /* Bus interrupt pending register */ -#define CMD_DONE_INT (1 << 31) -#define DATA_DONE_INT (1 << 30) -#define TRANS_OK_INT (1 << 29) -#define TRANS_FAIL_INT (1 << 28) -#define XD_INT (1 << 27) -#define MS_INT (1 << 26) -#define SD_INT (1 << 25) -#define GPIO0_INT (1 << 24) -#define OC_INT (1 << 23) -#define SD_WRITE_PROTECT (1 << 19) -#define XD_EXIST (1 << 18) -#define MS_EXIST (1 << 17) -#define SD_EXIST (1 << 16) +#define CMD_DONE_INT BIT(31) +#define DATA_DONE_INT BIT(30) +#define TRANS_OK_INT BIT(29) +#define TRANS_FAIL_INT BIT(28) +#define XD_INT BIT(27) +#define MS_INT BIT(26) +#define SD_INT BIT(25) +#define GPIO0_INT BIT(24) +#define OC_INT BIT(23) +#define SD_WRITE_PROTECT BIT(19) +#define XD_EXIST BIT(18) +#define MS_EXIST BIT(17) +#define SD_EXIST BIT(16) #define DELINK_INT GPIO0_INT -#define MS_OC_INT (1 << 23) -#define SD_OC_INT (1 << 22) +#define MS_OC_INT BIT(23) +#define SD_OC_INT BIT(22) #define CARD_INT (XD_INT | MS_INT | SD_INT) #define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT) @@ -305,7 +303,6 @@ struct sense_data_t { #define MS_OC_INT_EN (1 << 23) #define SD_OC_INT_EN (1 << 22) - #define READ_REG_CMD 0 #define WRITE_REG_CMD 1 #define CHECK_REG_CMD 2 @@ -313,7 +310,6 @@ struct sense_data_t { #define HOST_TO_DEVICE 0 #define DEVICE_TO_HOST 1 - #define RTSX_RESV_BUF_LEN 4096 #define HOST_CMDS_BUF_LEN 1024 #define HOST_SG_TBL_BUF_LEN (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN) @@ -332,7 +328,6 @@ struct sense_data_t { #define XD_FREE_TABLE_CNT 1200 #define MS_FREE_TABLE_CNT 512 - /* Bit Operation */ #define SET_BIT(data, idx) ((data) |= 1 << (idx)) #define CLR_BIT(data, idx) ((data) &= ~(1 << (idx))) @@ -618,7 +613,6 @@ struct spi_info { int spi_clock; }; - #ifdef _MSG_TRACE struct trace_msg_t { u16 line; @@ -689,7 +683,7 @@ struct trace_msg_t { #define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= ~SDIO_IGNORED) struct rtsx_chip { - rtsx_dev_t *rtsx; + struct rtsx_dev *rtsx; u32 int_reg; /* Bus interrupt pending register */ char max_lun; @@ -712,9 +706,9 @@ struct rtsx_chip { int cur_card; unsigned long need_release; /* need release bit map */ - unsigned long need_reset; /* need reset - * bit map */ - /* Flag to indicate that this card is just resumed from SS state, + unsigned long need_reset; /* need reset bit map */ + /* + * Flag to indicate that this card is just resumed from SS state, * and need released before being resetted */ unsigned long need_reinit; @@ -732,8 +726,10 @@ struct rtsx_chip { u8 card_ejected; /* card ejected bit map */ u8 card_wp; /* card write protected bit map */ - u8 lun_mc; /* flag to indicate whether to answer - * MediaChange */ + u8 lun_mc; /* + * flag to indicate whether to answer + * MediaChange + */ #ifndef LED_AUTO_BLINK int led_toggle_counter; diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index d2031044ea34..becb4bba166c 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -484,14 +484,14 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) u8 card = get_lun_card(chip, lun); bool pro_formatter_flag = false; unsigned char inquiry_buf[] = { - QULIFIRE|DRCT_ACCESS_DEV, - RMB_DISC|0x0D, + QULIFIRE | DRCT_ACCESS_DEV, + RMB_DISC | 0x0D, 0x00, 0x01, 0x1f, 0x02, 0, - REL_ADR|WBUS_32|WBUS_16|SYNC|LINKED|CMD_QUE|SFT_RE, + REL_ADR | WBUS_32 | WBUS_16 | SYNC | LINKED | CMD_QUE | SFT_RE, }; if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { @@ -558,7 +558,6 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_GOOD; } - static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip) { unsigned int lun = SCSI_LUN(srb); @@ -594,7 +593,6 @@ static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_ERROR; } - static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip) { int prevent; @@ -613,7 +611,6 @@ static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_GOOD; } - static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) { struct sense_data_t *sense; @@ -1400,7 +1397,7 @@ static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf_len = 4 + ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT); - if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) { + if ((scsi_bufflen(srb) < buf_len) || !scsi_sglist(srb)) { set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); @@ -1521,7 +1518,7 @@ static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip) static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - unsigned lun = SCSI_LUN(srb); + unsigned int lun = SCSI_LUN(srb); if (srb->cmnd[3] == 1) { /* Variable Clock */ @@ -1989,8 +1986,8 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_FAILED; } - buf[2*i] = (u8)(val >> 8); - buf[2*i+1] = (u8)val; + buf[2 * i] = (u8)(val >> 8); + buf[2 * i + 1] = (u8)val; } len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), @@ -2048,7 +2045,7 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) } for (i = 0; i < len / 2; i++) { - val = ((u16)buf[2*i] << 8) | buf[2*i+1]; + val = ((u16)buf[2 * i] << 8) | buf[2 * i + 1]; retval = rtsx_write_phy_register(chip, addr + i, val); if (retval != STATUS_SUCCESS) { vfree(buf); @@ -2604,7 +2601,6 @@ static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) return result; } - static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) { u8 rtsx_status[16]; @@ -3071,18 +3067,18 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf[i++] = 0x80; if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) { /* System Information */ - memcpy(buf+i, ms_card->raw_sys_info, 96); + memcpy(buf + i, ms_card->raw_sys_info, 96); } else { /* Model Name */ - memcpy(buf+i, ms_card->raw_model_name, 48); + memcpy(buf + i, ms_card->raw_model_name, 48); } rtsx_stor_set_xfer_buf(buf, buf_len, srb); if (dev_info_id == 0x15) - scsi_set_resid(srb, scsi_bufflen(srb)-0x3C); + scsi_set_resid(srb, scsi_bufflen(srb) - 0x3C); else - scsi_set_resid(srb, scsi_bufflen(srb)-0x6C); + scsi_set_resid(srb, scsi_bufflen(srb) - 0x6C); kfree(buf); return STATUS_SUCCESS; diff --git a/drivers/staging/rts5208/rtsx_sys.h b/drivers/staging/rts5208/rtsx_sys.h index 0b6b4d4f1fea..f49bed9ec76a 100644 --- a/drivers/staging/rts5208/rtsx_sys.h +++ b/drivers/staging/rts5208/rtsx_sys.h @@ -28,8 +28,6 @@ #include "rtsx_chip.h" #include "rtsx_card.h" -typedef dma_addr_t ULONG_PTR; - static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip) { struct rtsx_dev *dev = chip->rtsx; diff --git a/drivers/staging/rts5208/rtsx_transport.h b/drivers/staging/rts5208/rtsx_transport.h index 899bc2079dbe..479137398c3d 100644 --- a/drivers/staging/rts5208/rtsx_transport.h +++ b/drivers/staging/rts5208/rtsx_transport.h @@ -38,7 +38,6 @@ void rtsx_stor_get_xfer_buf(unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb); void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip); - #define rtsx_init_cmd(chip) ((chip)->ci = 0) void rtsx_add_cmd(struct rtsx_chip *chip, diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index 6219e047557e..b0bbb36f8988 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -1428,7 +1428,6 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) continue; } - if (func_to_switch) break; @@ -1437,9 +1436,9 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) func_to_switch); #ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_SDR_RST) - && (DDR50_SUPPORT == func_to_switch) - && (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) { + if ((sd_card->sd_lock_status & SD_SDR_RST) && + (func_to_switch == DDR50_SUPPORT) && + (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) { func_to_switch = SDR50_SUPPORT; dev_dbg(rtsx_dev(chip), "Using SDR50 instead of DDR50 for SD Lock\n"); } @@ -2589,16 +2588,12 @@ Switch_Fail: #endif retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_dummy_clock(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) { int rty_cnt = 0; @@ -2606,8 +2601,7 @@ Switch_Fail: for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) { if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { sd_set_err_code(chip, SD_NO_CARD); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, @@ -2619,8 +2613,7 @@ Switch_Fail: dev_dbg(rtsx_dev(chip), "SD_IO card (Function number: %d)!\n", func_num); chip->sd_io = 1; - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } break; @@ -2638,10 +2631,8 @@ Switch_Fail: RTY_SD_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; wait_timeout(20); @@ -2659,10 +2650,8 @@ RTY_SD_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; wait_timeout(20); } @@ -2673,39 +2662,32 @@ RTY_SD_RST: if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { sd_set_err_code(chip, SD_NO_CARD); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } j++; - if (j < 3) { + if (j < 3) goto RTY_SD_RST; - } else { - rtsx_trace(chip); - return STATUS_FAIL; - } + else + goto Status_Fail; } retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, SD_RSP_TYPE_R3, rsp, 5); if (retval != STATUS_SUCCESS) { k++; - if (k < 3) { + if (k < 3) goto RTY_SD_RST; - } else { - rtsx_trace(chip); - return STATUS_FAIL; - } + else + goto Status_Fail; } i++; wait_timeout(20); } while (!(rsp[1] & 0x80) && (i < 255)); - if (i == 255) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (i == 255) + goto Status_Fail; if (hi_cap_flow) { if (rsp[1] & 0x40) @@ -2722,26 +2704,20 @@ RTY_SD_RST: if (support_1v8) { retval = sd_voltage_switch(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; } retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; for (i = 0; i < 3; i++) { retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; sd_card->sd_addr = (u32)rsp[1] << 24; sd_card->sd_addr += (u32)rsp[2] << 16; @@ -2751,24 +2727,18 @@ RTY_SD_RST: } retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; #ifdef SUPPORT_SD_LOCK SD_UNLOCK_ENTRY: retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (sd_card->sd_lock_status & SD_LOCKED) { sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST); @@ -2780,32 +2750,24 @@ SD_UNLOCK_ENTRY: retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; switch_bus_width = SD_BUS_WIDTH_4; } else { @@ -2814,16 +2776,12 @@ SD_UNLOCK_ENTRY: retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (!(sd_card->raw_csd[4] & 0x40)) sd_dont_switch = true; @@ -2862,17 +2820,13 @@ SD_UNLOCK_ENTRY: if (!support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; } #ifdef SUPPORT_SD_LOCK @@ -2890,10 +2844,8 @@ SD_UNLOCK_ENTRY: } retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (CHK_SD_DDR50(sd_card)) retval = sd_ddr_tuning(chip); @@ -2902,14 +2854,11 @@ SD_UNLOCK_ENTRY: if (retval != STATUS_SUCCESS) { if (sd20_mode) { - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } else { retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; try_sdio = false; sd20_mode = true; @@ -2930,14 +2879,11 @@ SD_UNLOCK_ENTRY: retval = sd_read_lba0(chip); if (retval != STATUS_SUCCESS) { if (sd20_mode) { - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } else { retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; try_sdio = false; sd20_mode = true; @@ -2948,10 +2894,8 @@ SD_UNLOCK_ENTRY: } retval = sd_check_wp_state(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; @@ -2973,8 +2917,11 @@ SD_UNLOCK_ENTRY: #endif return STATUS_SUCCESS; -} +Status_Fail: + rtsx_trace(chip); + return STATUS_FAIL; +} static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) { @@ -3105,7 +3052,6 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) return SWITCH_FAIL; } - static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) { struct sd_info *sd_card = &(chip->sd_card); @@ -3230,7 +3176,6 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) return STATUS_SUCCESS; } - static int reset_mmc(struct rtsx_chip *chip) { struct sd_info *sd_card = &(chip->sd_card); diff --git a/drivers/staging/rts5208/spi.c b/drivers/staging/rts5208/spi.c index 26eb2a184f91..13c539c83838 100644 --- a/drivers/staging/rts5208/spi.c +++ b/drivers/staging/rts5208/spi.c @@ -39,7 +39,8 @@ static int spi_init(struct rtsx_chip *chip) int retval; retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF, - CS_POLARITY_LOW | DTO_MSB_FIRST | SPI_MASTER | SPI_MODE0 | SPI_AUTO); + CS_POLARITY_LOW | DTO_MSB_FIRST + | SPI_MASTER | SPI_MODE0 | SPI_AUTO); if (retval) { rtsx_trace(chip); return retval; diff --git a/drivers/staging/rts5208/spi.h b/drivers/staging/rts5208/spi.h index fc824b5d8d59..c8d2beacd9e5 100644 --- a/drivers/staging/rts5208/spi.h +++ b/drivers/staging/rts5208/spi.h @@ -61,5 +61,4 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip); - #endif /* __REALTEK_RTSX_SPI_H */ diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index fc1dfe0991d4..1de02bb98839 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -834,7 +834,6 @@ static int xd_check_data_blank(u8 *redunt) != (XD_ECC1_ALL1 | XD_ECC2_ALL1)) return 0; - for (i = 0; i < 4; i++) { if (redunt[RESERVED0 + i] != 0xFF) return 0; @@ -938,7 +937,7 @@ static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) dev_dbg(rtsx_dev(chip), "Set unused block to index %d\n", zone->set_index); - zone->free_table[zone->set_index++] = (u16) (phy_blk & 0x3ff); + zone->free_table[zone->set_index++] = (u16)(phy_blk & 0x3ff); if (zone->set_index >= XD_FREE_TABLE_CNT) zone->set_index = 0; zone->unused_blk_cnt++; @@ -1402,7 +1401,6 @@ static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk) return STATUS_FAIL; } - static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) { struct xd_info *xd_card = &(chip->xd_card); @@ -1624,10 +1622,8 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, u8 reg_val, page_cnt; int zone_no, retval, i; - if (start_page > end_page) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (start_page > end_page) + goto Status_Fail; page_cnt = end_page - start_page; zone_no = (int)(log_blk / 1000); @@ -1643,8 +1639,7 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { xd_set_err_code(chip, XD_NO_CARD); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } } } @@ -1679,8 +1674,7 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, if (retval == -ETIMEDOUT) { xd_set_err_code(chip, XD_TO_ERROR); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } else { rtsx_trace(chip); goto Fail; @@ -1713,8 +1707,7 @@ Fail: if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { xd_set_err_code(chip, XD_NO_CARD); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } xd_set_err_code(chip, XD_ECC_ERROR); @@ -1722,8 +1715,7 @@ Fail: new_blk = xd_get_unused_block(chip, zone_no); if (new_blk == NO_NEW_BLK) { XD_CLR_BAD_OLDBLK(xd_card); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } retval = xd_copy_page(chip, phy_blk, new_blk, 0, @@ -1737,8 +1729,7 @@ Fail: XD_CLR_BAD_NEWBLK(xd_card); } XD_CLR_BAD_OLDBLK(xd_card); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); xd_erase_block(chip, phy_blk); @@ -1746,6 +1737,7 @@ Fail: XD_CLR_BAD_OLDBLK(xd_card); } +Status_Fail: rtsx_trace(chip); return STATUS_FAIL; } @@ -1830,7 +1822,6 @@ static int xd_prepare_write(struct rtsx_chip *chip, return STATUS_SUCCESS; } - static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, u32 log_blk, u8 start_page, u8 end_page, u8 *buf, unsigned int *index, @@ -1845,10 +1836,8 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n", __func__, old_blk, new_blk, log_blk); - if (start_page > end_page) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (start_page > end_page) + goto Status_Fail; page_cnt = end_page - start_page; zone_no = (int)(log_blk / 1000); @@ -1857,10 +1846,8 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, page_addr = (new_blk << xd_card->block_shift) + start_page; retval = xd_send_cmd(chip, READ1_1); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; rtsx_init_cmd(chip); @@ -1895,8 +1882,7 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, if (retval == -ETIMEDOUT) { xd_set_err_code(chip, XD_TO_ERROR); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } else { rtsx_trace(chip); goto Fail; @@ -1936,6 +1922,7 @@ Fail: xd_mark_bad_block(chip, new_blk); } +Status_Fail: rtsx_trace(chip); return STATUS_FAIL; } @@ -2000,7 +1987,6 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, return STATUS_FAIL; } - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { chip->card_fail |= XD_CARD; set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index cc0afeeb68c1..420546d43002 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -92,6 +92,7 @@ struct slic_rcvbuf_info { u32 lasttime; u32 lastid; }; + /* * SLIC Handle structure. Used to restrict handle values to * 32 bits by using an index rather than an address. @@ -223,8 +224,8 @@ struct mcast_address { struct slic_iface_stats { /* - * Stats - */ + * Stats + */ u64 xmt_bytes; u64 xmt_ucast; u64 xmt_mcast; @@ -351,10 +352,35 @@ struct base_driver { uint cardnuminuse[SLIC_MAX_CARDS]; }; -struct slic_shmem { - volatile u32 isr; - volatile u32 linkstatus; - volatile struct slic_stats inicstats; +struct slic_stats { + /* xmit stats */ + u64 xmit_tcp_bytes; + u64 xmit_tcp_segs; + u64 xmit_bytes; + u64 xmit_collisions; + u64 xmit_unicasts; + u64 xmit_other_error; + u64 xmit_excess_collisions; + /* rcv stats */ + u64 rcv_tcp_bytes; + u64 rcv_tcp_segs; + u64 rcv_bytes; + u64 rcv_unicasts; + u64 rcv_other_error; + u64 rcv_drops; +}; + +struct slic_shmem_data { + u32 isr; + u32 lnkstatus; + struct slic_stats stats; +}; + +struct slic_shmemory { + dma_addr_t isr_phaddr; + dma_addr_t lnkstatus_phaddr; + dma_addr_t stats_phaddr; + struct slic_shmem_data __iomem *shmem_data; }; struct slic_upr { @@ -414,10 +440,9 @@ struct adapter { u32 intrregistered; uint isp_initialized; uint gennumber; - struct slic_shmem *pshmem; + struct slic_shmemory shmem; dma_addr_t phys_shmem; - u32 isrcopy; - __iomem struct slic_regs *slic_regs; + void __iomem *regs; unsigned char state; unsigned char linkstate; unsigned char linkspeed; @@ -444,8 +469,8 @@ struct adapter { struct slic_cmdqueue cmdq_all; struct slic_cmdqmem cmdqmem; /* - * SLIC Handles - */ + * SLIC Handles + */ /* Object handles*/ struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS + 1]; /* Free object handles*/ @@ -487,6 +512,34 @@ struct adapter { struct slicnet_stats slic_stats; }; +static inline u32 slic_read32(struct adapter *adapter, unsigned int reg) +{ + return ioread32(adapter->regs + reg); +} + +static inline void slic_write32(struct adapter *adapter, unsigned int reg, + u32 val) +{ + iowrite32(val, adapter->regs + reg); +} + +static inline void slic_write64(struct adapter *adapter, unsigned int reg, + u32 val, u32 hiaddr) +{ + unsigned long flags; + + spin_lock_irqsave(&adapter->bit64reglock, flags); + slic_write32(adapter, SLIC_REG_ADDR_UPPER, hiaddr); + slic_write32(adapter, reg, val); + mmiowb(); + spin_unlock_irqrestore(&adapter->bit64reglock, flags); +} + +static inline void slic_flush_write(struct adapter *adapter) +{ + ioread32(adapter->regs + SLIC_REG_HOSTID); +} + #define UPDATE_STATS(largestat, newstat, oldstat) \ { \ if ((newstat) < (oldstat)) \ diff --git a/drivers/staging/slicoss/slichw.h b/drivers/staging/slicoss/slichw.h index 9723b4a104f7..49cb91aa02bb 100644 --- a/drivers/staging/slicoss/slichw.h +++ b/drivers/staging/slicoss/slichw.h @@ -289,224 +289,118 @@ struct slic_rspbuf { u32 pad2[4]; }; -struct slic_regs { - u32 slic_reset; /* Reset Register */ - u32 pad0; +/* Reset Register */ +#define SLIC_REG_RESET 0x0000 +/* Interrupt Control Register */ +#define SLIC_REG_ICR 0x0008 +/* Interrupt status pointer */ +#define SLIC_REG_ISP 0x0010 +/* Interrupt status */ +#define SLIC_REG_ISR 0x0018 +/* + * Header buffer address reg + * 31-8 - phy addr of set of contiguous hdr buffers + * 7-0 - number of buffers passed + * Buffers are 256 bytes long on 256-byte boundaries. + */ +#define SLIC_REG_HBAR 0x0020 +/* + * Data buffer handle & address reg + * 4 sets of registers; Buffers are 2K bytes long 2 per 4K page. + */ +#define SLIC_REG_DBAR 0x0028 +/* + * Xmt Cmd buf addr regs. + * 1 per XMT interface + * 31-5 - phy addr of host command buffer + * 4-0 - length of cmd in multiples of 32 bytes + * Buffers are 32 bytes up to 512 bytes long + */ +#define SLIC_REG_CBAR 0x0030 +/* Write control store */ +#define SLIC_REG_WCS 0x0034 +/* + * Response buffer address reg. + * 31-8 - phy addr of set of contiguous response buffers + * 7-0 - number of buffers passed + * Buffers are 32 bytes long on 32-byte boundaries. + */ +#define SLIC_REG_RBAR 0x0038 +/* Read statistics (UPR) */ +#define SLIC_REG_RSTAT 0x0040 +/* Read link status */ +#define SLIC_REG_LSTAT 0x0048 +/* Write Mac Config */ +#define SLIC_REG_WMCFG 0x0050 +/* Write phy register */ +#define SLIC_REG_WPHY 0x0058 +/* Rcv Cmd buf addr reg */ +#define SLIC_REG_RCBAR 0x0060 +/* Read SLIC Config*/ +#define SLIC_REG_RCONFIG 0x0068 +/* Interrupt aggregation time */ +#define SLIC_REG_INTAGG 0x0070 +/* Write XMIT config reg */ +#define SLIC_REG_WXCFG 0x0078 +/* Write RCV config reg */ +#define SLIC_REG_WRCFG 0x0080 +/* Write rcv addr a low */ +#define SLIC_REG_WRADDRAL 0x0088 +/* Write rcv addr a high */ +#define SLIC_REG_WRADDRAH 0x0090 +/* Write rcv addr b low */ +#define SLIC_REG_WRADDRBL 0x0098 +/* Write rcv addr b high */ +#define SLIC_REG_WRADDRBH 0x00a0 +/* Low bits of mcast mask */ +#define SLIC_REG_MCASTLOW 0x00a8 +/* High bits of mcast mask */ +#define SLIC_REG_MCASTHIGH 0x00b0 +/* Ping the card */ +#define SLIC_REG_PING 0x00b8 +/* Dump command */ +#define SLIC_REG_DUMP_CMD 0x00c0 +/* Dump data pointer */ +#define SLIC_REG_DUMP_DATA 0x00c8 +/* Read card's pci_status register */ +#define SLIC_REG_PCISTATUS 0x00d0 +/* Write hostid field */ +#define SLIC_REG_WRHOSTID 0x00d8 +/* Put card in a low power state */ +#define SLIC_REG_LOW_POWER 0x00e0 +/* Force slic into quiescent state before soft reset */ +#define SLIC_REG_QUIESCE 0x00e8 +/* Reset interface queues */ +#define SLIC_REG_RESET_IFACE 0x00f0 +/* + * Register is only written when it has changed. + * Bits 63-32 for host i/f addrs. + */ +#define SLIC_REG_ADDR_UPPER 0x00f8 +/* 64 bit Header buffer address reg */ +#define SLIC_REG_HBAR64 0x0100 +/* 64 bit Data buffer handle & address reg */ +#define SLIC_REG_DBAR64 0x0108 +/* 64 bit Xmt Cmd buf addr regs. */ +#define SLIC_REG_CBAR64 0x0110 +/* 64 bit Response buffer address reg.*/ +#define SLIC_REG_RBAR64 0x0118 +/* 64 bit Rcv Cmd buf addr reg*/ +#define SLIC_REG_RCBAR64 0x0120 +/* Read statistics (64 bit UPR) */ +#define SLIC_REG_RSTAT64 0x0128 +/* Download Gigabit RCV sequencer ucode */ +#define SLIC_REG_RCV_WCS 0x0130 +/* Write VlanId field */ +#define SLIC_REG_WRVLANID 0x0138 +/* Read Transformer info */ +#define SLIC_REG_READ_XF_INFO 0x0140 +/* Write Transformer info */ +#define SLIC_REG_WRITE_XF_INFO 0x0148 +/* Write card ticks per second */ +#define SLIC_REG_TICKS_PER_SEC 0x0170 - u32 slic_icr; /* Interrupt Control Register */ - u32 pad2; -#define SLIC_ICR 0x0008 - - u32 slic_isp; /* Interrupt status pointer */ - u32 pad1; -#define SLIC_ISP 0x0010 - - u32 slic_isr; /* Interrupt status */ - u32 pad3; -#define SLIC_ISR 0x0018 - - u32 slic_hbar; /* Header buffer address reg */ - u32 pad4; - /* - * 31-8 - phy addr of set of contiguous hdr buffers - * 7-0 - number of buffers passed - * Buffers are 256 bytes long on 256-byte boundaries. - */ -#define SLIC_HBAR 0x0020 -#define SLIC_HBAR_CNT_MSK 0x000000FF - - u32 slic_dbar; /* Data buffer handle & address reg */ - u32 pad5; - - /* 4 sets of registers; Buffers are 2K bytes long 2 per 4K page. */ -#define SLIC_DBAR 0x0028 -#define SLIC_DBAR_SIZE 2048 - - u32 slic_cbar; /* Xmt Cmd buf addr regs.*/ - /* - * 1 per XMT interface - * 31-5 - phy addr of host command buffer - * 4-0 - length of cmd in multiples of 32 bytes - * Buffers are 32 bytes up to 512 bytes long - */ -#define SLIC_CBAR 0x0030 -#define SLIC_CBAR_LEN_MSK 0x0000001F -#define SLIC_CBAR_ALIGN 0x00000020 - - u32 slic_wcs; /* write control store*/ -#define SLIC_WCS 0x0034 -#define SLIC_WCS_START 0x80000000 /*Start the SLIC (Jump to WCS)*/ -#define SLIC_WCS_COMPARE 0x40000000 /* Compare with value in WCS*/ - - u32 slic_rbar; /* Response buffer address reg.*/ - u32 pad7; - /* - * 31-8 - phy addr of set of contiguous response buffers - * 7-0 - number of buffers passed - * Buffers are 32 bytes long on 32-byte boundaries. - */ -#define SLIC_RBAR 0x0038 -#define SLIC_RBAR_CNT_MSK 0x000000FF -#define SLIC_RBAR_SIZE 32 - - u32 slic_stats; /* read statistics (UPR) */ - u32 pad8; -#define SLIC_RSTAT 0x0040 - - u32 slic_rlsr; /* read link status */ - u32 pad9; -#define SLIC_LSTAT 0x0048 - - u32 slic_wmcfg; /* Write Mac Config */ - u32 pad10; -#define SLIC_WMCFG 0x0050 - - u32 slic_wphy; /* Write phy register */ - u32 pad11; -#define SLIC_WPHY 0x0058 - - u32 slic_rcbar; /* Rcv Cmd buf addr reg */ - u32 pad12; -#define SLIC_RCBAR 0x0060 - - u32 slic_rconfig; /* Read SLIC Config*/ - u32 pad13; -#define SLIC_RCONFIG 0x0068 - - u32 slic_intagg; /* Interrupt aggregation time */ - u32 pad14; -#define SLIC_INTAGG 0x0070 - - u32 slic_wxcfg; /* Write XMIT config reg*/ - u32 pad16; -#define SLIC_WXCFG 0x0078 - - u32 slic_wrcfg; /* Write RCV config reg*/ - u32 pad17; -#define SLIC_WRCFG 0x0080 - - u32 slic_wraddral; /* Write rcv addr a low*/ - u32 pad18; -#define SLIC_WRADDRAL 0x0088 - - u32 slic_wraddrah; /* Write rcv addr a high*/ - u32 pad19; -#define SLIC_WRADDRAH 0x0090 - - u32 slic_wraddrbl; /* Write rcv addr b low*/ - u32 pad20; -#define SLIC_WRADDRBL 0x0098 - - u32 slic_wraddrbh; /* Write rcv addr b high*/ - u32 pad21; -#define SLIC_WRADDRBH 0x00a0 - - u32 slic_mcastlow; /* Low bits of mcast mask*/ - u32 pad22; -#define SLIC_MCASTLOW 0x00a8 - - u32 slic_mcasthigh; /* High bits of mcast mask*/ - u32 pad23; -#define SLIC_MCASTHIGH 0x00b0 - - u32 slic_ping; /* Ping the card*/ - u32 pad24; -#define SLIC_PING 0x00b8 - - u32 slic_dump_cmd; /* Dump command */ - u32 pad25; -#define SLIC_DUMP_CMD 0x00c0 - - u32 slic_dump_data; /* Dump data pointer */ - u32 pad26; -#define SLIC_DUMP_DATA 0x00c8 - - u32 slic_pcistatus; /* Read card's pci_status register */ - u32 pad27; -#define SLIC_PCISTATUS 0x00d0 - - u32 slic_wrhostid; /* Write hostid field */ - u32 pad28; -#define SLIC_WRHOSTID 0x00d8 -#define SLIC_RDHOSTID_1GB 0x1554 -#define SLIC_RDHOSTID_2GB 0x1554 - - u32 slic_low_power; /* Put card in a low power state */ - u32 pad29; -#define SLIC_LOW_POWER 0x00e0 - - u32 slic_quiesce; /* force slic into quiescent state - * before soft reset - */ - u32 pad30; -#define SLIC_QUIESCE 0x00e8 - - u32 slic_reset_iface;/* reset interface queues */ - u32 pad31; -#define SLIC_RESET_IFACE 0x00f0 - - u32 slic_addr_upper;/* Bits 63-32 for host i/f addrs */ - u32 pad32; -#define SLIC_ADDR_UPPER 0x00f8 /*Register is only written when it has changed*/ - - u32 slic_hbar64; /* 64 bit Header buffer address reg */ - u32 pad33; -#define SLIC_HBAR64 0x0100 - - u32 slic_dbar64; /* 64 bit Data buffer handle & address reg */ - u32 pad34; -#define SLIC_DBAR64 0x0108 - - u32 slic_cbar64; /* 64 bit Xmt Cmd buf addr regs. */ - u32 pad35; -#define SLIC_CBAR64 0x0110 - - u32 slic_rbar64; /* 64 bit Response buffer address reg.*/ - u32 pad36; -#define SLIC_RBAR64 0x0118 - - u32 slic_rcbar64; /* 64 bit Rcv Cmd buf addr reg*/ - u32 pad37; -#define SLIC_RCBAR64 0x0120 - - u32 slic_stats64; /* read statistics (64 bit UPR) */ - u32 pad38; -#define SLIC_RSTAT64 0x0128 - - u32 slic_rcv_wcs; /*Download Gigabit RCV sequencer ucode*/ - u32 pad39; -#define SLIC_RCV_WCS 0x0130 -#define SLIC_RCVWCS_BEGIN 0x40000000 -#define SLIC_RCVWCS_FINISH 0x80000000 - - u32 slic_wrvlanid; /* Write VlanId field */ - u32 pad40; -#define SLIC_WRVLANID 0x0138 - - u32 slic_read_xf_info; /* Read Transformer info */ - u32 pad41; -#define SLIC_READ_XF_INFO 0x0140 - - u32 slic_write_xf_info; /* Write Transformer info */ - u32 pad42; -#define SLIC_WRITE_XF_INFO 0x0148 - - u32 RSVD1; /* TOE Only */ - u32 pad43; - - u32 RSVD2; /* TOE Only */ - u32 pad44; - - u32 RSVD3; /* TOE Only */ - u32 pad45; - - u32 RSVD4; /* TOE Only */ - u32 pad46; - - u32 slic_ticks_per_sec; /* Write card ticks per second */ - u32 pad47; -#define SLIC_TICKS_PER_SEC 0x0170 -}; +#define SLIC_REG_HOSTID 0x1554 enum UPR_REQUEST { SLIC_UPR_STATS, @@ -565,85 +459,6 @@ struct slic_pnp_capabilities { struct slicpm_wakeup_capabilities wakeup_capabilities; }; -struct xmt_stats { - u32 xmit_tcp_bytes; - u32 xmit_tcp_segs; - u32 xmit_bytes; - u32 xmit_collisions; - u32 xmit_unicasts; - u32 xmit_other_error; - u32 xmit_excess_collisions; -}; - -struct rcv_stats { - u32 rcv_tcp_bytes; - u32 rcv_tcp_segs; - u32 rcv_bytes; - u32 rcv_unicasts; - u32 rcv_other_error; - u32 rcv_drops; -}; - -struct xmt_statsgb { - u64 xmit_tcp_bytes; - u64 xmit_tcp_segs; - u64 xmit_bytes; - u64 xmit_collisions; - u64 xmit_unicasts; - u64 xmit_other_error; - u64 xmit_excess_collisions; -}; - -struct rcv_statsgb { - u64 rcv_tcp_bytes; - u64 rcv_tcp_segs; - u64 rcv_bytes; - u64 rcv_unicasts; - u64 rcv_other_error; - u64 rcv_drops; -}; - -struct slic_stats { - union { - struct { - struct xmt_stats xmt100; - struct rcv_stats rcv100; - } stats_100; - struct { - struct xmt_statsgb xmtGB; - struct rcv_statsgb rcvGB; - } stats_GB; - } u; -}; - -#define xmit_tcp_segs100 u.stats_100.xmt100.xmit_tcp_segs -#define xmit_tcp_bytes100 u.stats_100.xmt100.xmit_tcp_bytes -#define xmit_bytes100 u.stats_100.xmt100.xmit_bytes -#define xmit_collisions100 u.stats_100.xmt100.xmit_collisions -#define xmit_unicasts100 u.stats_100.xmt100.xmit_unicasts -#define xmit_other_error100 u.stats_100.xmt100.xmit_other_error -#define xmit_excess_collisions100 u.stats_100.xmt100.xmit_excess_collisions -#define rcv_tcp_segs100 u.stats_100.rcv100.rcv_tcp_segs -#define rcv_tcp_bytes100 u.stats_100.rcv100.rcv_tcp_bytes -#define rcv_bytes100 u.stats_100.rcv100.rcv_bytes -#define rcv_unicasts100 u.stats_100.rcv100.rcv_unicasts -#define rcv_other_error100 u.stats_100.rcv100.rcv_other_error -#define rcv_drops100 u.stats_100.rcv100.rcv_drops -#define xmit_tcp_segs_gb u.stats_GB.xmtGB.xmit_tcp_segs -#define xmit_tcp_bytes_gb u.stats_GB.xmtGB.xmit_tcp_bytes -#define xmit_bytes_gb u.stats_GB.xmtGB.xmit_bytes -#define xmit_collisions_gb u.stats_GB.xmtGB.xmit_collisions -#define xmit_unicasts_gb u.stats_GB.xmtGB.xmit_unicasts -#define xmit_other_error_gb u.stats_GB.xmtGB.xmit_other_error -#define xmit_excess_collisions_gb u.stats_GB.xmtGB.xmit_excess_collisions - -#define rcv_tcp_segs_gb u.stats_GB.rcvGB.rcv_tcp_segs -#define rcv_tcp_bytes_gb u.stats_GB.rcvGB.rcv_tcp_bytes -#define rcv_bytes_gb u.stats_GB.rcvGB.rcv_bytes -#define rcv_unicasts_gb u.stats_GB.rcvGB.rcv_unicasts -#define rcv_other_error_gb u.stats_GB.rcvGB.rcv_other_error -#define rcv_drops_gb u.stats_GB.rcvGB.rcv_drops - struct slic_config_mac { u8 macaddrA[6]; }; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index ac126d4f3117..062307ad7fed 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -124,31 +124,10 @@ static const struct pci_device_id slic_pci_tbl[] = { { 0 } }; -static struct ethtool_ops slic_ethtool_ops; +static const struct ethtool_ops slic_ethtool_ops; MODULE_DEVICE_TABLE(pci, slic_pci_tbl); -static inline void slic_reg32_write(void __iomem *reg, u32 value, bool flush) -{ - writel(value, reg); - if (flush) - mb(); -} - -static inline void slic_reg64_write(struct adapter *adapter, void __iomem *reg, - u32 value, void __iomem *regh, u32 paddrh, - bool flush) -{ - unsigned long flags; - - spin_lock_irqsave(&adapter->bit64reglock, flags); - writel(paddrh, regh); - writel(value, reg); - if (flush) - mb(); - spin_unlock_irqrestore(&adapter->bit64reglock, flags); -} - static void slic_mcast_set_bit(struct adapter *adapter, char *address) { unsigned char crcpoly; @@ -172,8 +151,6 @@ static void slic_mcast_set_bit(struct adapter *adapter, char *address) static void slic_mcast_set_mask(struct adapter *adapter) { - __iomem struct slic_regs *slic_regs = adapter->slic_regs; - if (adapter->macopts & (MAC_ALLMCAST | MAC_PROMISC)) { /* * Turn on all multicast addresses. We have to do this for @@ -181,18 +158,17 @@ static void slic_mcast_set_mask(struct adapter *adapter) * Microcode from having to keep state about the MAC * configuration. */ - slic_reg32_write(&slic_regs->slic_mcastlow, 0xFFFFFFFF, FLUSH); - slic_reg32_write(&slic_regs->slic_mcasthigh, 0xFFFFFFFF, - FLUSH); + slic_write32(adapter, SLIC_REG_MCASTLOW, 0xFFFFFFFF); + slic_write32(adapter, SLIC_REG_MCASTHIGH, 0xFFFFFFFF); } else { /* * Commit our multicast mast to the SLIC by writing to the * multicast address mask registers */ - slic_reg32_write(&slic_regs->slic_mcastlow, - (u32)(adapter->mcastmask & 0xFFFFFFFF), FLUSH); - slic_reg32_write(&slic_regs->slic_mcasthigh, - (u32)((adapter->mcastmask >> 32) & 0xFFFFFFFF), FLUSH); + slic_write32(adapter, SLIC_REG_MCASTLOW, + (u32)(adapter->mcastmask & 0xFFFFFFFF)); + slic_write32(adapter, SLIC_REG_MCASTHIGH, + (u32)((adapter->mcastmask >> 32) & 0xFFFFFFFF)); } } @@ -208,13 +184,6 @@ static void slic_timer_ping(ulong dev) add_timer(&adapter->pingtimer); } -static void slic_unmap_mmio_space(struct adapter *adapter) -{ - if (adapter->slic_regs) - iounmap(adapter->slic_regs); - adapter->slic_regs = NULL; -} - /* * slic_link_config * @@ -224,7 +193,6 @@ static void slic_unmap_mmio_space(struct adapter *adapter) static void slic_link_config(struct adapter *adapter, u32 linkspeed, u32 linkduplex) { - u32 __iomem *wphy; u32 speed; u32 duplex; u32 phy_config; @@ -239,8 +207,6 @@ static void slic_link_config(struct adapter *adapter, if (linkduplex > LINK_AUTOD) linkduplex = LINK_AUTOD; - wphy = &adapter->slic_regs->slic_wphy; - if ((linkspeed == LINK_AUTOSPEED) || (linkspeed == LINK_1000MB)) { if (adapter->flags & ADAPT_FLAGS_FIBERMEDIA) { /* @@ -252,7 +218,7 @@ static void slic_link_config(struct adapter *adapter, phy_advreg = (MIICR_REG_4 | (PAR_ADV1000XFD)); /* enable PAUSE frames */ phy_advreg |= PAR_ASYMPAUSE_FIBER; - slic_reg32_write(wphy, phy_advreg, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_advreg); if (linkspeed == LINK_AUTOSPEED) { /* reset phy, enable auto-neg */ @@ -260,14 +226,17 @@ static void slic_link_config(struct adapter *adapter, (MIICR_REG_PCR | (PCR_RESET | PCR_AUTONEG | PCR_AUTONEG_RST)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); } else { /* forced 1000 Mb FD*/ /* * power down phy to break link * this may not work) */ phy_config = (MIICR_REG_PCR | PCR_POWERDOWN); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); + slic_flush_write(adapter); /* * wait, Marvell says 1 sec, * try to get away with 10 ms @@ -282,7 +251,8 @@ static void slic_link_config(struct adapter *adapter, (MIICR_REG_PCR | (PCR_RESET | PCR_SPEED_1000 | PCR_DUPLEX_FULL)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); } } else { /* copper gigabit */ @@ -309,10 +279,10 @@ static void slic_link_config(struct adapter *adapter, phy_advreg |= PAR_ASYMPAUSE; /* required by the Cicada PHY */ phy_advreg |= PAR_802_3; - slic_reg32_write(wphy, phy_advreg, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_advreg); /* advertise FD only @1000 Mb */ phy_gctlreg = (MIICR_REG_9 | (PGC_ADV1000FD)); - slic_reg32_write(wphy, phy_gctlreg, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_gctlreg); if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) { /* @@ -321,20 +291,23 @@ static void slic_link_config(struct adapter *adapter, */ phy_config = (MIICR_REG_16 | (MRV_REG16_XOVERON)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); /* reset phy, enable auto-neg */ phy_config = (MIICR_REG_PCR | (PCR_RESET | PCR_AUTONEG | PCR_AUTONEG_RST)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); } else { /* it's a Cicada PHY */ /* enable and restart auto-neg (don't reset) */ phy_config = (MIICR_REG_PCR | (PCR_AUTONEG | PCR_AUTONEG_RST)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); } } } else { @@ -354,13 +327,13 @@ static void slic_link_config(struct adapter *adapter, * disable auto crossover */ phy_config = (MIICR_REG_16 | (MRV_REG16_XOVEROFF)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); } /* power down phy to break link (this may not work) */ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN | speed | duplex)); - slic_reg32_write(wphy, phy_config, FLUSH); - + slic_write32(adapter, SLIC_REG_WPHY, phy_config); + slic_flush_write(adapter); /* wait, Marvell says 1 sec, try to get away with 10 ms */ mdelay(10); @@ -372,11 +345,11 @@ static void slic_link_config(struct adapter *adapter, */ phy_config = (MIICR_REG_PCR | (PCR_RESET | speed | duplex)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); } else { /* it's a Cicada PHY */ /* disable auto-neg, set speed, powerup */ phy_config = (MIICR_REG_PCR | (speed | duplex)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); } } } @@ -386,7 +359,6 @@ static int slic_card_download_gbrcv(struct adapter *adapter) const struct firmware *fw; const char *file = ""; int ret; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; u32 codeaddr; u32 instruction; int index = 0; @@ -427,27 +399,28 @@ static int slic_card_download_gbrcv(struct adapter *adapter) break; } /* start download */ - slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_BEGIN, FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, SLIC_RCVWCS_BEGIN); /* download the rcv sequencer ucode */ for (codeaddr = 0; codeaddr < rcvucodelen; codeaddr++) { /* write out instruction address */ - slic_reg32_write(&slic_regs->slic_rcv_wcs, codeaddr, FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, codeaddr); instruction = *(u32 *)(fw->data + index); index += 4; /* write out the instruction data low addr */ - slic_reg32_write(&slic_regs->slic_rcv_wcs, instruction, FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, instruction); instruction = *(u8 *)(fw->data + index); index++; /* write out the instruction data high addr */ - slic_reg32_write(&slic_regs->slic_rcv_wcs, (u8)instruction, - FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, instruction); } /* download finished */ release_firmware(fw); - slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_FINISH, FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, SLIC_RCVWCS_FINISH); + slic_flush_write(adapter); + return 0; } @@ -462,7 +435,6 @@ static int slic_card_download(struct adapter *adapter) u32 section; int thissectionsize; int codeaddr; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; u32 instruction; u32 baseaddress; u32 i; @@ -506,17 +478,17 @@ static int slic_card_download(struct adapter *adapter) for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) { /* Write out instruction address */ - slic_reg32_write(&slic_regs->slic_wcs, - baseaddress + codeaddr, FLUSH); + slic_write32(adapter, SLIC_REG_WCS, + baseaddress + codeaddr); /* Write out instruction to low addr */ - slic_reg32_write(&slic_regs->slic_wcs, - instruction, FLUSH); + slic_write32(adapter, SLIC_REG_WCS, + instruction); instruction = *(u32 *)(fw->data + index); index += 4; /* Write out instruction to high addr */ - slic_reg32_write(&slic_regs->slic_wcs, - instruction, FLUSH); + slic_write32(adapter, SLIC_REG_WCS, + instruction); instruction = *(u32 *)(fw->data + index); index += 4; } @@ -531,27 +503,25 @@ static int slic_card_download(struct adapter *adapter) for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) { /* Write out instruction address */ - slic_reg32_write(&slic_regs->slic_wcs, - SLIC_WCS_COMPARE | (baseaddress + codeaddr), - FLUSH); + slic_write32(adapter, SLIC_REG_WCS, + SLIC_WCS_COMPARE | (baseaddress + + codeaddr)); /* Write out instruction to low addr */ - slic_reg32_write(&slic_regs->slic_wcs, instruction, - FLUSH); + slic_write32(adapter, SLIC_REG_WCS, instruction); instruction = *(u32 *)(fw->data + index); index += 4; /* Write out instruction to high addr */ - slic_reg32_write(&slic_regs->slic_wcs, instruction, - FLUSH); + slic_write32(adapter, SLIC_REG_WCS, instruction); instruction = *(u32 *)(fw->data + index); index += 4; - } } release_firmware(fw); /* Everything OK, kick off the card */ mdelay(10); - slic_reg32_write(&slic_regs->slic_wcs, SLIC_WCS_START, FLUSH); + slic_write32(adapter, SLIC_REG_WCS, SLIC_WCS_START); + slic_flush_write(adapter); /* * stall for 20 ms, long enough for ucode to init card * and reach mainloop @@ -583,19 +553,21 @@ static void slic_adapter_set_hwaddr(struct adapter *adapter) static void slic_intagg_set(struct adapter *adapter, u32 value) { - slic_reg32_write(&adapter->slic_regs->slic_intagg, value, FLUSH); + slic_write32(adapter, SLIC_REG_INTAGG, value); adapter->card->loadlevel_current = value; } static void slic_soft_reset(struct adapter *adapter) { if (adapter->card->state == CARD_UP) { - slic_reg32_write(&adapter->slic_regs->slic_quiesce, 0, FLUSH); + slic_write32(adapter, SLIC_REG_QUIESCE, 0); + slic_flush_write(adapter); mdelay(1); } - slic_reg32_write(&adapter->slic_regs->slic_reset, SLIC_RESET_MAGIC, - FLUSH); + slic_write32(adapter, SLIC_REG_RESET, SLIC_RESET_MAGIC); + slic_flush_write(adapter); + mdelay(1); } @@ -603,17 +575,16 @@ static void slic_mac_address_config(struct adapter *adapter) { u32 value; u32 value2; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; value = ntohl(*(__be32 *)&adapter->currmacaddr[2]); - slic_reg32_write(&slic_regs->slic_wraddral, value, FLUSH); - slic_reg32_write(&slic_regs->slic_wraddrbl, value, FLUSH); + slic_write32(adapter, SLIC_REG_WRADDRAL, value); + slic_write32(adapter, SLIC_REG_WRADDRBL, value); value2 = (u32)((adapter->currmacaddr[0] << 8 | adapter->currmacaddr[1]) & 0xFFFF); - slic_reg32_write(&slic_regs->slic_wraddrah, value2, FLUSH); - slic_reg32_write(&slic_regs->slic_wraddrbh, value2, FLUSH); + slic_write32(adapter, SLIC_REG_WRADDRAH, value2); + slic_write32(adapter, SLIC_REG_WRADDRBH, value2); /* * Write our multicast mask out to the card. This is done @@ -626,7 +597,6 @@ static void slic_mac_address_config(struct adapter *adapter) static void slic_mac_config(struct adapter *adapter) { u32 value; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; /* Setup GMAC gaps */ if (adapter->linkspeed == LINK_1000MB) { @@ -650,7 +620,7 @@ static void slic_mac_config(struct adapter *adapter) } /* write mac config */ - slic_reg32_write(&slic_regs->slic_wmcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WMCFG, value); /* setup mac addresses */ slic_mac_address_config(adapter); @@ -660,7 +630,6 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) { u32 value; u32 RcrReset; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; if (linkchange) { /* Setup MAC */ @@ -677,7 +646,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) GXCR_XMTEN | /* Enable transmit */ GXCR_PAUSEEN); /* Enable pause */ - slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WXCFG, value); /* Setup rcvcfg last */ value = (RcrReset | /* Reset, if linkchange */ @@ -690,7 +659,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) value = (GXCR_RESET | /* Always reset */ GXCR_XMTEN); /* Enable transmit */ - slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WXCFG, value); /* Setup rcvcfg last */ value = (RcrReset | /* Reset, if linkchange */ @@ -707,7 +676,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) if (adapter->macopts & MAC_PROMISC) value |= GRCR_RCVALL; - slic_reg32_write(&slic_regs->slic_wrcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WRCFG, value); } /* @@ -717,24 +686,23 @@ static void slic_config_clear(struct adapter *adapter) { u32 value; u32 phy_config; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; /* Setup xmtcfg */ value = (GXCR_RESET | /* Always reset */ GXCR_PAUSEEN); /* Enable pause */ - slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WXCFG, value); value = (GRCR_RESET | /* Always reset */ GRCR_CTLEN | /* Enable CTL frames */ GRCR_ADDRAEN | /* Address A enable */ (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT)); - slic_reg32_write(&slic_regs->slic_wrcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WRCFG, value); /* power down phy */ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN)); - slic_reg32_write(&slic_regs->slic_wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); } static bool slic_mac_filter(struct adapter *adapter, @@ -810,13 +778,11 @@ static void slic_timer_load_check(ulong cardaddr) { struct sliccard *card = (struct sliccard *)cardaddr; struct adapter *adapter = card->master; - u32 __iomem *intagg; u32 load = card->events; u32 level = 0; if ((adapter) && (adapter->state == ADAPT_UP) && (card->state == CARD_UP) && (slic_global.dynamic_intagg)) { - intagg = &adapter->slic_regs->slic_intagg; if (adapter->devid == SLIC_1GB_DEVICE_ID) { if (adapter->linkspeed == LINK_1000MB) level = 100; @@ -836,7 +802,7 @@ static void slic_timer_load_check(ulong cardaddr) } if (card->loadlevel_current != level) { card->loadlevel_current = level; - slic_reg32_write(intagg, level, FLUSH); + slic_write32(adapter, SLIC_REG_INTAGG, level); } } else { if (load > SLIC_LOAD_5) @@ -853,7 +819,7 @@ static void slic_timer_load_check(ulong cardaddr) level = SLIC_INTAGG_0; if (card->loadlevel_current != level) { card->loadlevel_current = level; - slic_reg32_write(intagg, level, FLUSH); + slic_write32(adapter, SLIC_REG_INTAGG, level); } } } @@ -897,7 +863,6 @@ static int slic_upr_queue_request(struct adapter *adapter, static void slic_upr_start(struct adapter *adapter) { struct slic_upr *upr; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; upr = adapter->upr_list; if (!upr) @@ -909,31 +874,27 @@ static void slic_upr_start(struct adapter *adapter) switch (upr->upr_request) { case SLIC_UPR_STATS: if (upr->upr_data_h == 0) { - slic_reg32_write(&slic_regs->slic_stats, upr->upr_data, - FLUSH); + slic_write32(adapter, SLIC_REG_RSTAT, upr->upr_data); } else { - slic_reg64_write(adapter, &slic_regs->slic_stats64, - upr->upr_data, - &slic_regs->slic_addr_upper, - upr->upr_data_h, FLUSH); + slic_write64(adapter, SLIC_REG_RSTAT64, upr->upr_data, + upr->upr_data_h); } break; case SLIC_UPR_RLSR: - slic_reg64_write(adapter, &slic_regs->slic_rlsr, upr->upr_data, - &slic_regs->slic_addr_upper, upr->upr_data_h, - FLUSH); + slic_write64(adapter, SLIC_REG_LSTAT, upr->upr_data, + upr->upr_data_h); break; case SLIC_UPR_RCONFIG: - slic_reg64_write(adapter, &slic_regs->slic_rconfig, - upr->upr_data, &slic_regs->slic_addr_upper, - upr->upr_data_h, FLUSH); + slic_write64(adapter, SLIC_REG_RCONFIG, upr->upr_data, + upr->upr_data_h); break; case SLIC_UPR_PING: - slic_reg32_write(&slic_regs->slic_ping, 1, FLUSH); + slic_write32(adapter, SLIC_REG_PING, 1); break; } + slic_flush_write(adapter); } static int slic_upr_request(struct adapter *adapter, @@ -961,42 +922,34 @@ err_unlock_irq: static void slic_link_upr_complete(struct adapter *adapter, u32 isr) { - u32 linkstatus = adapter->pshmem->linkstatus; + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; + u32 lst = sm_data->lnkstatus; uint linkup; unsigned char linkspeed; unsigned char linkduplex; if ((isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) { - struct slic_shmem *pshmem; + dma_addr_t phaddr = sm->lnkstatus_phaddr; - pshmem = (struct slic_shmem *)(unsigned long) - adapter->phys_shmem; -#if BITS_PER_LONG == 64 - slic_upr_queue_request(adapter, - SLIC_UPR_RLSR, - SLIC_GET_ADDR_LOW(&pshmem->linkstatus), - SLIC_GET_ADDR_HIGH(&pshmem->linkstatus), + slic_upr_queue_request(adapter, SLIC_UPR_RLSR, + cpu_to_le32(lower_32_bits(phaddr)), + cpu_to_le32(upper_32_bits(phaddr)), 0, 0); -#else - slic_upr_queue_request(adapter, - SLIC_UPR_RLSR, - (u32)&pshmem->linkstatus, - SLIC_GET_ADDR_HIGH(pshmem), 0, 0); -#endif return; } if (adapter->state != ADAPT_UP) return; - linkup = linkstatus & GIG_LINKUP ? LINK_UP : LINK_DOWN; - if (linkstatus & GIG_SPEED_1000) + linkup = lst & GIG_LINKUP ? LINK_UP : LINK_DOWN; + if (lst & GIG_SPEED_1000) linkspeed = LINK_1000MB; - else if (linkstatus & GIG_SPEED_100) + else if (lst & GIG_SPEED_100) linkspeed = LINK_100MB; else linkspeed = LINK_10MB; - if (linkstatus & GIG_FULLDUPLEX) + if (lst & GIG_FULLDUPLEX) linkduplex = LINK_FULLD; else linkduplex = LINK_HALFD; @@ -1016,6 +969,7 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr) /* link has gone from up to down */ if (linkup == LINK_DOWN) { adapter->linkstate = LINK_DOWN; + netif_carrier_off(adapter->netdev); return; } @@ -1027,7 +981,7 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr) /* setup the mac */ slic_config_set(adapter, true); adapter->linkstate = LINK_UP; - netif_start_queue(adapter->netdev); + netif_carrier_on(adapter->netdev); } } @@ -1047,81 +1001,65 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr) upr->next = NULL; adapter->upr_busy = 0; switch (upr->upr_request) { - case SLIC_UPR_STATS: - { - struct slic_stats *slicstats = - (struct slic_stats *)&adapter->pshmem->inicstats; - struct slic_stats *newstats = slicstats; - struct slic_stats *old = &adapter->inicstats_prev; - struct slicnet_stats *stst = &adapter->slic_stats; + case SLIC_UPR_STATS: { + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; + struct slic_stats *stats = &sm_data->stats; + struct slic_stats *old = &adapter->inicstats_prev; + struct slicnet_stats *stst = &adapter->slic_stats; - if (isr & ISR_UPCERR) { - dev_err(&adapter->netdev->dev, - "SLIC_UPR_STATS command failed isr[%x]\n", - isr); - - break; - } - UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs, - newstats->xmit_tcp_segs_gb, - old->xmit_tcp_segs_gb); - - UPDATE_STATS_GB(stst->tcp.xmit_tcp_bytes, - newstats->xmit_tcp_bytes_gb, - old->xmit_tcp_bytes_gb); - - UPDATE_STATS_GB(stst->tcp.rcv_tcp_segs, - newstats->rcv_tcp_segs_gb, - old->rcv_tcp_segs_gb); - - UPDATE_STATS_GB(stst->tcp.rcv_tcp_bytes, - newstats->rcv_tcp_bytes_gb, - old->rcv_tcp_bytes_gb); - - UPDATE_STATS_GB(stst->iface.xmt_bytes, - newstats->xmit_bytes_gb, - old->xmit_bytes_gb); - - UPDATE_STATS_GB(stst->iface.xmt_ucast, - newstats->xmit_unicasts_gb, - old->xmit_unicasts_gb); - - UPDATE_STATS_GB(stst->iface.rcv_bytes, - newstats->rcv_bytes_gb, - old->rcv_bytes_gb); - - UPDATE_STATS_GB(stst->iface.rcv_ucast, - newstats->rcv_unicasts_gb, - old->rcv_unicasts_gb); - - UPDATE_STATS_GB(stst->iface.xmt_errors, - newstats->xmit_collisions_gb, - old->xmit_collisions_gb); - - UPDATE_STATS_GB(stst->iface.xmt_errors, - newstats->xmit_excess_collisions_gb, - old->xmit_excess_collisions_gb); - - UPDATE_STATS_GB(stst->iface.xmt_errors, - newstats->xmit_other_error_gb, - old->xmit_other_error_gb); - - UPDATE_STATS_GB(stst->iface.rcv_errors, - newstats->rcv_other_error_gb, - old->rcv_other_error_gb); - - UPDATE_STATS_GB(stst->iface.rcv_discards, - newstats->rcv_drops_gb, - old->rcv_drops_gb); - - if (newstats->rcv_drops_gb > old->rcv_drops_gb) { - adapter->rcv_drops += - (newstats->rcv_drops_gb - - old->rcv_drops_gb); - } - memcpy(old, newstats, sizeof(struct slic_stats)); + if (isr & ISR_UPCERR) { + dev_err(&adapter->netdev->dev, + "SLIC_UPR_STATS command failed isr[%x]\n", isr); break; } + + UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs, stats->xmit_tcp_segs, + old->xmit_tcp_segs); + + UPDATE_STATS_GB(stst->tcp.xmit_tcp_bytes, stats->xmit_tcp_bytes, + old->xmit_tcp_bytes); + + UPDATE_STATS_GB(stst->tcp.rcv_tcp_segs, stats->rcv_tcp_segs, + old->rcv_tcp_segs); + + UPDATE_STATS_GB(stst->tcp.rcv_tcp_bytes, stats->rcv_tcp_bytes, + old->rcv_tcp_bytes); + + UPDATE_STATS_GB(stst->iface.xmt_bytes, stats->xmit_bytes, + old->xmit_bytes); + + UPDATE_STATS_GB(stst->iface.xmt_ucast, stats->xmit_unicasts, + old->xmit_unicasts); + + UPDATE_STATS_GB(stst->iface.rcv_bytes, stats->rcv_bytes, + old->rcv_bytes); + + UPDATE_STATS_GB(stst->iface.rcv_ucast, stats->rcv_unicasts, + old->rcv_unicasts); + + UPDATE_STATS_GB(stst->iface.xmt_errors, stats->xmit_collisions, + old->xmit_collisions); + + UPDATE_STATS_GB(stst->iface.xmt_errors, + stats->xmit_excess_collisions, + old->xmit_excess_collisions); + + UPDATE_STATS_GB(stst->iface.xmt_errors, stats->xmit_other_error, + old->xmit_other_error); + + UPDATE_STATS_GB(stst->iface.rcv_errors, stats->rcv_other_error, + old->rcv_other_error); + + UPDATE_STATS_GB(stst->iface.rcv_discards, stats->rcv_drops, + old->rcv_drops); + + if (stats->rcv_drops > old->rcv_drops) + adapter->rcv_drops += (stats->rcv_drops - + old->rcv_drops); + memcpy_fromio(old, stats, sizeof(*stats)); + break; + } case SLIC_UPR_RLSR: slic_link_upr_complete(adapter, isr); break; @@ -1186,7 +1124,6 @@ static int slic_rspqueue_init(struct adapter *adapter) { int i; struct slic_rspqueue *rspq = &adapter->rspqueue; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; u32 paddrh = 0; memset(rspq, 0, sizeof(struct slic_rspqueue)); @@ -1205,14 +1142,12 @@ static int slic_rspqueue_init(struct adapter *adapter) } if (paddrh == 0) { - slic_reg32_write(&slic_regs->slic_rbar, - (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE), - DONT_FLUSH); + slic_write32(adapter, SLIC_REG_RBAR, + rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE); } else { - slic_reg64_write(adapter, &slic_regs->slic_rbar64, - (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE), - &slic_regs->slic_addr_upper, - paddrh, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_RBAR64, + rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE, + paddrh); } } rspq->offset = 0; @@ -1233,9 +1168,9 @@ static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter) if (++rspq->offset < SLIC_RSPQ_BUFSINPAGE) { rspq->rspbuf++; } else { - slic_reg64_write(adapter, &adapter->slic_regs->slic_rbar64, - (rspq->paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE), - &adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_RBAR64, + rspq->paddr[rspq->pageindex] | + SLIC_RSPQ_BUFSINPAGE, 0); rspq->pageindex = (rspq->pageindex + 1) % rspq->num_pages; rspq->offset = 0; rspq->rspbuf = (struct slic_rspbuf *) @@ -1569,14 +1504,11 @@ retry_rcvqfill: } #endif if (paddrh == 0) { - slic_reg32_write(&adapter->slic_regs->slic_hbar, - (u32)paddrl, DONT_FLUSH); + slic_write32(adapter, SLIC_REG_HBAR, + (u32)paddrl); } else { - slic_reg64_write(adapter, - &adapter->slic_regs->slic_hbar64, - paddrl, - &adapter->slic_regs->slic_addr_upper, - paddrh, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_HBAR64, paddrl, + paddrh); } if (rcvq->head) rcvq->tail->next = skb; @@ -1698,14 +1630,10 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb) dev_err(dev, " rcvq->tail[%p]\n", rcvq->tail); dev_err(dev, " rcvq->count[%x]\n", rcvq->count); } - if (paddrh == 0) { - slic_reg32_write(&adapter->slic_regs->slic_hbar, (u32)paddrl, - DONT_FLUSH); - } else { - slic_reg64_write(adapter, &adapter->slic_regs->slic_hbar64, - paddrl, &adapter->slic_regs->slic_addr_upper, - paddrh, DONT_FLUSH); - } + if (paddrh == 0) + slic_write32(adapter, SLIC_REG_HBAR, (u32)paddrl); + else + slic_write64(adapter, SLIC_REG_HBAR64, paddrl, paddrh); if (rcvq->head) rcvq->tail->next = skb; else @@ -1728,26 +1656,17 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb) static int slic_link_event_handler(struct adapter *adapter) { int status; - struct slic_shmem *pshmem; + struct slic_shmemory *sm = &adapter->shmem; + dma_addr_t phaddr = sm->lnkstatus_phaddr; if (adapter->state != ADAPT_UP) { /* Adapter is not operational. Ignore. */ return -ENODEV; } - - pshmem = (struct slic_shmem *)(unsigned long)adapter->phys_shmem; - -#if BITS_PER_LONG == 64 - status = slic_upr_request(adapter, - SLIC_UPR_RLSR, - SLIC_GET_ADDR_LOW(&pshmem->linkstatus), - SLIC_GET_ADDR_HIGH(&pshmem->linkstatus), - 0, 0); -#else + /* no 4GB wrap guaranteed */ status = slic_upr_request(adapter, SLIC_UPR_RLSR, - (u32)&pshmem->linkstatus, /* no 4GB wrap guaranteed */ - 0, 0, 0); -#endif + cpu_to_le32(lower_32_bits(phaddr)), + cpu_to_le32(upper_32_bits(phaddr)), 0, 0); return status; } @@ -1757,12 +1676,13 @@ static void slic_init_cleanup(struct adapter *adapter) adapter->intrregistered = 0; free_irq(adapter->netdev->irq, adapter->netdev); } - if (adapter->pshmem) { - pci_free_consistent(adapter->pcidev, - sizeof(struct slic_shmem), - adapter->pshmem, adapter->phys_shmem); - adapter->pshmem = NULL; - adapter->phys_shmem = (dma_addr_t)(unsigned long)NULL; + + if (adapter->shmem.shmem_data) { + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; + + pci_free_consistent(adapter->pcidev, sizeof(*sm_data), sm_data, + sm->isr_phaddr); } if (adapter->pingtimerset) { @@ -2147,13 +2067,16 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct adapter *adapter = netdev_priv(dev); + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; u32 isr; - if ((adapter->pshmem) && (adapter->pshmem->isr)) { - slic_reg32_write(&adapter->slic_regs->slic_icr, - ICR_INT_MASK, FLUSH); - isr = adapter->isrcopy = adapter->pshmem->isr; - adapter->pshmem->isr = 0; + if (sm_data->isr) { + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_MASK); + slic_flush_write(adapter); + + isr = sm_data->isr; + sm_data->isr = 0; adapter->num_isrs++; switch (adapter->card->state) { case CARD_UP: @@ -2169,10 +2092,9 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) break; } - adapter->isrcopy = 0; adapter->all_reg_writes += 2; adapter->isr_reg_writes++; - slic_reg32_write(&adapter->slic_regs->slic_isr, 0, FLUSH); + slic_write32(adapter, SLIC_REG_ISR, 0); } else { adapter->false_interrupts++; } @@ -2224,13 +2146,11 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev) } #endif if (hcmd->paddrh == 0) { - slic_reg32_write(&adapter->slic_regs->slic_cbar, - (hcmd->paddrl | hcmd->cmdsize), DONT_FLUSH); + slic_write32(adapter, SLIC_REG_CBAR, (hcmd->paddrl | + hcmd->cmdsize)); } else { - slic_reg64_write(adapter, &adapter->slic_regs->slic_cbar64, - (hcmd->paddrl | hcmd->cmdsize), - &adapter->slic_regs->slic_addr_upper, - hcmd->paddrh, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_CBAR64, + hcmd->paddrl | hcmd->cmdsize, hcmd->paddrh); } xmit_done: return NETDEV_TX_OK; @@ -2290,8 +2210,8 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) { struct sliccard *card = adapter->card; struct net_device *dev = adapter->netdev; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; - struct slic_shmem *pshmem; + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; int rc; /* adapter should be down at this point */ @@ -2335,28 +2255,20 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) adapter->queues_initialized = 1; } - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); + slic_flush_write(adapter); mdelay(1); if (!adapter->isp_initialized) { unsigned long flags; - pshmem = (struct slic_shmem *)(unsigned long) - adapter->phys_shmem; - spin_lock_irqsave(&adapter->bit64reglock, flags); - -#if BITS_PER_LONG == 64 - slic_reg32_write(&slic_regs->slic_addr_upper, - SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH); - slic_reg32_write(&slic_regs->slic_isp, - SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH); -#else - slic_reg32_write(&slic_regs->slic_addr_upper, 0, DONT_FLUSH); - slic_reg32_write(&slic_regs->slic_isp, (u32)&pshmem->isr, - FLUSH); -#endif + slic_write32(adapter, SLIC_REG_ADDR_UPPER, + cpu_to_le32(upper_32_bits(sm->isr_phaddr))); + slic_write32(adapter, SLIC_REG_ISP, + cpu_to_le32(lower_32_bits(sm->isr_phaddr))); spin_unlock_irqrestore(&adapter->bit64reglock, flags); + adapter->isp_initialized = 1; } @@ -2383,17 +2295,20 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) /* * clear any pending events, then enable interrupts */ - adapter->isrcopy = 0; - adapter->pshmem->isr = 0; - slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH); - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_ON, FLUSH); + sm_data->isr = 0; + slic_write32(adapter, SLIC_REG_ISR, 0); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_ON); slic_link_config(adapter, LINK_AUTOSPEED, LINK_AUTOD); + slic_flush_write(adapter); + rc = slic_link_event_handler(adapter); if (rc) { /* disable interrupts then clear pending events */ - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); - slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); + slic_write32(adapter, SLIC_REG_ISR, 0); + slic_flush_write(adapter); + if (adapter->pingtimerset) { del_timer(&adapter->pingtimer); adapter->pingtimerset = 0; @@ -2417,7 +2332,7 @@ static int slic_entry_open(struct net_device *dev) unsigned long flags; int status; - netif_stop_queue(adapter->netdev); + netif_carrier_off(dev); spin_lock_irqsave(&slic_global.driver_lock, flags); if (!adapter->activated) { @@ -2440,6 +2355,9 @@ static int slic_entry_open(struct net_device *dev) spin_unlock: spin_unlock_irqrestore(&slic_global.driver_lock, flags); + + netif_start_queue(adapter->netdev); + return status; } @@ -2463,7 +2381,7 @@ static void slic_entry_remove(struct pci_dev *pcidev) unregister_netdev(dev); slic_adapter_freeresources(adapter); - slic_unmap_mmio_space(adapter); + iounmap(adapter->regs); /* free multicast addresses */ mlist = adapter->mcastaddrs; @@ -2497,7 +2415,6 @@ static int slic_entry_halt(struct net_device *dev) { struct adapter *adapter = netdev_priv(dev); struct sliccard *card = adapter->card; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; unsigned long flags; spin_lock_irqsave(&slic_global.driver_lock, flags); @@ -2507,7 +2424,7 @@ static int slic_entry_halt(struct net_device *dev) adapter->upr_list = NULL; adapter->upr_busy = 0; adapter->devflags_prev = 0; - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); adapter->all_reg_writes++; adapter->icr_reg_writes++; slic_config_clear(adapter); @@ -2517,8 +2434,10 @@ static int slic_entry_halt(struct net_device *dev) adapter->activated = 0; } #ifdef AUTOMATIC_RESET - slic_reg32_write(&slic_regs->slic_reset_iface, 0, FLUSH); + slic_write32(adapter, SLIC_REG_RESET_IFACE, 0); #endif + slic_flush_write(adapter); + /* * Reset the adapter's cmd queues */ @@ -2530,6 +2449,9 @@ static int slic_entry_halt(struct net_device *dev) #endif spin_unlock_irqrestore(&slic_global.driver_lock, flags); + + netif_carrier_off(dev); + return 0; } @@ -2661,14 +2583,14 @@ static void slic_config_pci(struct pci_dev *pcidev) static int slic_card_init(struct sliccard *card, struct adapter *adapter) { - __iomem struct slic_regs *slic_regs = adapter->slic_regs; + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; struct slic_eeprom *peeprom; struct oslic_eeprom *pOeeprom; dma_addr_t phys_config; u32 phys_configh; u32 phys_configl; u32 i = 0; - struct slic_shmem *pshmem; int status; uint macaddrs = card->card_size; ushort eecodesize; @@ -2695,27 +2617,26 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) sizeof(struct slic_eeprom), &phys_config); - phys_configl = SLIC_GET_ADDR_LOW(phys_config); - phys_configh = SLIC_GET_ADDR_HIGH(phys_config); - if (!peeprom) { dev_err(&adapter->pcidev->dev, "Failed to allocate DMA memory for EEPROM.\n"); return -ENOMEM; } + phys_configl = SLIC_GET_ADDR_LOW(phys_config); + phys_configh = SLIC_GET_ADDR_HIGH(phys_config); + memset(peeprom, 0, sizeof(struct slic_eeprom)); - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); + slic_flush_write(adapter); mdelay(1); - pshmem = (struct slic_shmem *)(unsigned long) - adapter->phys_shmem; spin_lock_irqsave(&adapter->bit64reglock, flags); - slic_reg32_write(&slic_regs->slic_addr_upper, - SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH); - slic_reg32_write(&slic_regs->slic_isp, - SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH); + slic_write32(adapter, SLIC_REG_ADDR_UPPER, + cpu_to_le32(upper_32_bits(sm->isr_phaddr))); + slic_write32(adapter, SLIC_REG_ISP, + cpu_to_le32(lower_32_bits(sm->isr_phaddr))); spin_unlock_irqrestore(&adapter->bit64reglock, flags); status = slic_config_get(adapter, phys_configl, phys_configh); @@ -2726,33 +2647,31 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) } for (;;) { - if (adapter->pshmem->isr) { - if (adapter->pshmem->isr & ISR_UPC) { - adapter->pshmem->isr = 0; - slic_reg64_write(adapter, - &slic_regs->slic_isp, 0, - &slic_regs->slic_addr_upper, - 0, FLUSH); - slic_reg32_write(&slic_regs->slic_isr, - 0, FLUSH); + if (sm_data->isr) { + if (sm_data->isr & ISR_UPC) { + sm_data->isr = 0; + slic_write64(adapter, SLIC_REG_ISP, 0, + 0); + slic_write32(adapter, SLIC_REG_ISR, 0); + slic_flush_write(adapter); slic_upr_request_complete(adapter, 0); break; } - adapter->pshmem->isr = 0; - slic_reg32_write(&slic_regs->slic_isr, - 0, FLUSH); + sm_data->isr = 0; + slic_write32(adapter, SLIC_REG_ISR, 0); + slic_flush_write(adapter); } else { mdelay(1); i++; if (i > 5000) { dev_err(&adapter->pcidev->dev, "Fetch of config data timed out.\n"); - slic_reg64_write(adapter, - &slic_regs->slic_isp, 0, - &slic_regs->slic_addr_upper, - 0, FLUSH); + slic_write64(adapter, SLIC_REG_ISP, + 0, 0); + slic_flush_write(adapter); + status = -EINVAL; goto card_init_err; } @@ -2796,7 +2715,6 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) /* see if the EEPROM is valid by checking it's checksum */ if ((eecodesize <= MAX_EECODE_SIZE) && (eecodesize >= MIN_EECODE_SIZE)) { - ee_chksum = *(u16 *)((char *)peeprom + (eecodesize - 2)); /* @@ -2830,9 +2748,8 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) peeprom, phys_config); if (!card->config.EepromValid) { - slic_reg64_write(adapter, &slic_regs->slic_isp, 0, - &slic_regs->slic_addr_upper, - 0, FLUSH); + slic_write64(adapter, SLIC_REG_ISP, 0, 0); + slic_flush_write(adapter); dev_err(&adapter->pcidev->dev, "EEPROM invalid.\n"); return -EINVAL; } @@ -2896,14 +2813,17 @@ static void slic_init_driver(void) } } -static void slic_init_adapter(struct net_device *netdev, - struct pci_dev *pcidev, - const struct pci_device_id *pci_tbl_entry, - void __iomem *memaddr, int chip_idx) +static int slic_init_adapter(struct net_device *netdev, + struct pci_dev *pcidev, + const struct pci_device_id *pci_tbl_entry, + void __iomem *memaddr, int chip_idx) { ushort index; struct slic_handle *pslic_handle; struct adapter *adapter = netdev_priv(netdev); + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data; + dma_addr_t phaddr; /* adapter->pcidev = pcidev;*/ adapter->vendid = pci_tbl_entry->vendor; @@ -2912,7 +2832,7 @@ static void slic_init_adapter(struct net_device *netdev, adapter->busnumber = pcidev->bus->number; adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F); adapter->functionnumber = (pcidev->devfn & 0x7); - adapter->slic_regs = memaddr; + adapter->regs = memaddr; adapter->irq = pcidev->irq; adapter->chipid = chip_idx; adapter->port = 0; @@ -2932,19 +2852,23 @@ static void slic_init_adapter(struct net_device *netdev, */ for (index = 1, pslic_handle = &adapter->slic_handles[1]; index < SLIC_CMDQ_MAXCMDS; index++, pslic_handle++) { - pslic_handle->token.handle_index = index; pslic_handle->type = SLIC_HANDLE_FREE; pslic_handle->next = adapter->pfree_slic_handles; adapter->pfree_slic_handles = pslic_handle; } - adapter->pshmem = (struct slic_shmem *) - pci_alloc_consistent(adapter->pcidev, - sizeof(struct slic_shmem), - &adapter-> - phys_shmem); - if (adapter->pshmem) - memset(adapter->pshmem, 0, sizeof(struct slic_shmem)); + sm_data = pci_zalloc_consistent(adapter->pcidev, sizeof(*sm_data), + &phaddr); + if (!sm_data) + return -ENOMEM; + + sm->shmem_data = sm_data; + sm->isr_phaddr = phaddr; + sm->lnkstatus_phaddr = phaddr + offsetof(struct slic_shmem_data, + lnkstatus); + sm->stats_phaddr = phaddr + offsetof(struct slic_shmem_data, stats); + + return 0; } static const struct net_device_ops slic_netdev_ops = { @@ -2964,27 +2888,9 @@ static u32 slic_card_locate(struct adapter *adapter) struct sliccard *card = slic_global.slic_card; struct physcard *physcard = slic_global.phys_card; ushort card_hostid; - u16 __iomem *hostid_reg; uint i; - uint rdhostid_offset = 0; - switch (adapter->devid) { - case SLIC_2GB_DEVICE_ID: - rdhostid_offset = SLIC_RDHOSTID_2GB; - break; - case SLIC_1GB_DEVICE_ID: - rdhostid_offset = SLIC_RDHOSTID_1GB; - break; - default: - return -ENODEV; - } - - hostid_reg = - (u16 __iomem *)(((u8 __iomem *)(adapter->slic_regs)) + - rdhostid_offset); - - /* read the 16 bit hostid from SRAM */ - card_hostid = (ushort)readw(hostid_reg); + card_hostid = slic_read32(adapter, SLIC_REG_HOSTID); /* Initialize a new card structure if need be */ if (card_hostid == SLIC_HOSTID_DEFAULT) { @@ -3130,7 +3036,7 @@ static int slic_entry_probe(struct pci_dev *pcidev, mmio_start = pci_resource_start(pcidev, 0); mmio_len = pci_resource_len(pcidev, 0); - memmapped_ioaddr = ioremap(mmio_start, mmio_len); + memmapped_ioaddr = ioremap_nocache(mmio_start, mmio_len); if (!memmapped_ioaddr) { dev_err(&pcidev->dev, "cannot remap MMIO region %lx @ %lx\n", mmio_len, mmio_start); @@ -3142,13 +3048,17 @@ static int slic_entry_probe(struct pci_dev *pcidev, slic_init_driver(); - slic_init_adapter(netdev, - pcidev, pci_tbl_entry, memmapped_ioaddr, cards_found); + err = slic_init_adapter(netdev, pcidev, pci_tbl_entry, memmapped_ioaddr, + cards_found); + if (err) { + dev_err(&pcidev->dev, "failed to init adapter: %i\n", err); + goto err_out_unmap; + } err = slic_card_locate(adapter); if (err) { dev_err(&pcidev->dev, "cannot locate card\n"); - goto err_out_unmap; + goto err_clean_init; } card = adapter->card; @@ -3160,7 +3070,7 @@ static int slic_entry_probe(struct pci_dev *pcidev, err = slic_card_init(card, adapter); if (err) - goto err_out_unmap; + goto err_clean_init; slic_adapter_set_hwaddr(adapter); @@ -3168,17 +3078,21 @@ static int slic_entry_probe(struct pci_dev *pcidev, netdev->irq = adapter->irq; netdev->netdev_ops = &slic_netdev_ops; + netif_carrier_off(netdev); + strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) { dev_err(&pcidev->dev, "Cannot register net device, aborting.\n"); - goto err_out_unmap; + goto err_clean_init; } cards_found++; return 0; +err_clean_init: + slic_init_cleanup(adapter); err_out_unmap: iounmap(memmapped_ioaddr); err_out_free_netdev: @@ -3209,7 +3123,7 @@ static void __exit slic_module_cleanup(void) pci_unregister_driver(&slic_driver); } -static struct ethtool_ops slic_ethtool_ops = { +static const struct ethtool_ops slic_ethtool_ops = { .get_coalesce = slic_get_coalesce, .set_coalesce = slic_set_coalesce }; diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index f80ee776677f..839d6730bde9 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -6,11 +6,9 @@ #include "ddk750_chip.h" #include "ddk750_power.h" -/* n / d + 1 / 2 = (2n + d) / 2d */ -#define roundedDiv(num, denom) ((2 * (num) + (denom)) / (2 * (denom))) #define MHz(x) ((x) * 1000000) -logical_chip_type_t getChipType(void) +logical_chip_type_t sm750_get_chip_type(void) { unsigned short physicalID; char physicalRev; @@ -37,7 +35,7 @@ static unsigned int get_mxclk_freq(void) unsigned int pll_reg; unsigned int M, N, OD, POD; - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return MHz(130); pll_reg = PEEK32(MXCLK_PLL_CTRL); @@ -60,7 +58,7 @@ static void setChipClock(unsigned int frequency) unsigned int ulActualMxClk; /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */ - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return; if (frequency) { @@ -71,9 +69,10 @@ static void setChipClock(unsigned int frequency) pll.clockType = MXCLK_PLL; /* - * Call calcPllValue() to fill up the other fields for PLL structure. - * Sometime, the chip cannot set up the exact clock required by User. - * Return value from calcPllValue() gives the actual possible clock. + * Call calcPllValue() to fill the other fields of PLL structure. + * Sometime, the chip cannot set up the exact clock + * required by the User. + * Return value of calcPllValue gives the actual possible clock. */ ulActualMxClk = calcPllValue(frequency, &pll); @@ -86,18 +85,22 @@ static void setMemoryClock(unsigned int frequency) { unsigned int reg, divisor; - /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ - if (getChipType() == SM750LE) + /* Cheok_0509: For SM750LE, the memory clock is fixed. + * Nothing to set. + */ + if (sm750_get_chip_type() == SM750LE) return; if (frequency) { - /* Set the frequency to the maximum frequency that the DDR Memory can take - which is 336MHz. */ + /* + * Set the frequency to the maximum frequency + * that the DDR Memory can take which is 336MHz. + */ if (frequency > MHz(336)) frequency = MHz(336); /* Calculate the divisor */ - divisor = roundedDiv(get_mxclk_freq(), frequency); + divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK; @@ -133,18 +136,21 @@ static void setMasterClock(unsigned int frequency) { unsigned int reg, divisor; - /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ - if (getChipType() == SM750LE) + /* Cheok_0509: For SM750LE, the memory clock is fixed. + * Nothing to set. + */ + if (sm750_get_chip_type() == SM750LE) return; if (frequency) { - /* Set the frequency to the maximum frequency that the SM750 engine can - run, which is about 190 MHz. */ + /* Set the frequency to the maximum frequency + * that the SM750 engine can run, which is about 190 MHz. + */ if (frequency > MHz(190)) frequency = MHz(190); /* Calculate the divisor */ - divisor = roundedDiv(get_mxclk_freq(), frequency); + divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK; @@ -174,7 +180,7 @@ unsigned int ddk750_getVMSize(void) unsigned int data; /* sm750le only use 64 mb memory*/ - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return SZ_64M; /* for 750,always use power mode0*/ @@ -213,7 +219,7 @@ int ddk750_initHw(initchip_param_t *pInitParam) reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM); setCurrentGate(reg); - if (getChipType() != SM750LE) { + if (sm750_get_chip_type() != SM750LE) { /* set panel pll and graphic mode via mmio_88 */ reg = PEEK32(VGA_CONFIGURATION); reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE); @@ -236,9 +242,10 @@ int ddk750_initHw(initchip_param_t *pInitParam) setMasterClock(MHz(pInitParam->masterClock)); - /* Reset the memory controller. If the memory controller is not reset in SM750, - the system might hang when sw accesses the memory. - The memory should be resetted after changing the MXCLK. + /* Reset the memory controller. + * If the memory controller is not reset in SM750, + * the system might hang when sw accesses the memory. + * The memory should be resetted after changing the MXCLK. */ if (pInitParam->resetMemory == 1) { reg = PEEK32(MISC_CTRL); @@ -282,24 +289,27 @@ int ddk750_initHw(initchip_param_t *pInitParam) } /* - monk liu @ 4/6/2011: - re-write the calculatePLL function of ddk750. - the original version function does not use some mathematics tricks and shortcut - when it doing the calculation of the best N,M,D combination - I think this version gives a little upgrade in speed - - 750 pll clock formular: - Request Clock = (Input Clock * M )/(N * X) - - Input Clock = 14318181 hz - X = 2 power D - D ={0,1,2,3,4,5,6} - M = {1,...,255} - N = {2,...,15} -*/ + * monk liu @ 4/6/2011: + * re-write the calculatePLL function of ddk750. + * the original version function does not use + * some mathematics tricks and shortcut + * when it doing the calculation of the best N,M,D combination + * I think this version gives a little upgrade in speed + * + * 750 pll clock formular: + * Request Clock = (Input Clock * M )/(N * X) + * + * Input Clock = 14318181 hz + * X = 2 power D + * D ={0,1,2,3,4,5,6} + * M = {1,...,255} + * N = {2,...,15} + */ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) { - /* as sm750 register definition, N located in 2,15 and M located in 1,255 */ + /* as sm750 register definition, + * N located in 2,15 and M located in 1,255 + */ int N, M, X, d; int mini_diff; unsigned int RN, quo, rem, fl_quo; @@ -308,9 +318,11 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) const int max_OD = 3; int max_d = 6; - if (getChipType() == SM750LE) { - /* SM750LE don't have prgrammable PLL and M/N values to work on. - Just return the requested clock. */ + if (sm750_get_chip_type() == SM750LE) { + /* SM750LE don't have + * programmable PLL and M/N values to work on. + * Just return the requested clock. + */ return request_orig; } @@ -319,19 +331,23 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) request = request_orig / 1000; input = pll->inputFreq / 1000; - /* for MXCLK register , no POD provided, so need be treated differently */ + /* for MXCLK register, + * no POD provided, so need be treated differently + */ if (pll->clockType == MXCLK_PLL) max_d = 3; for (N = 15; N > 1; N--) { - /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */ + /* RN will not exceed maximum long + * if @request <= 285 MHZ (for 32bit cpu) + */ RN = N * request; quo = RN / input; rem = RN % input;/* rem always small than 14318181 */ fl_quo = (rem * 10000 / input); for (d = max_d; d >= 0; d--) { - X = (1 << d); + X = BIT(d); M = quo * X; M += fl_quo * X / 10000; /* round step */ diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h index 0891384ef3e5..14357fd1cc6b 100644 --- a/drivers/staging/sm750fb/ddk750_chip.h +++ b/drivers/staging/sm750fb/ddk750_chip.h @@ -69,7 +69,7 @@ typedef struct _initchip_param_t { } initchip_param_t; -logical_chip_type_t getChipType(void); +logical_chip_type_t sm750_get_chip_type(void); unsigned int calcPllValue(unsigned int request, pll_value_t *pll); unsigned int formatPllReg(pll_value_t *pPLL); void ddk750_set_mmio(void __iomem *, unsigned short, char); diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index ca4973ee49e4..4023c476b9e4 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -68,8 +68,10 @@ static void waitNextVerticalSync(int ctrl, int delay) if (!ctrl) { /* primary controller */ - /* Do not wait when the Primary PLL is off or display control is already off. - This will prevent the software to wait forever. */ + /* + * Do not wait when the Primary PLL is off or display control is + * already off. This will prevent the software to wait forever. + */ if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || !(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { return; @@ -88,9 +90,10 @@ static void waitNextVerticalSync(int ctrl, int delay) } } else { - - /* Do not wait when the Primary PLL is off or display control is already off. - This will prevent the software to wait forever. */ + /* + * Do not wait when the Primary PLL is off or display control is + * already off. This will prevent the software to wait forever. + */ if (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) || !(PEEK32(CRT_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { return; @@ -134,7 +137,6 @@ static void swPanelPowerSequence(int disp, int delay) reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); POKE32(PANEL_DISPLAY_CTRL, reg); primaryWaitVerticalSync(delay); - } void ddk750_setLogicalDispOut(disp_output_t output) @@ -159,7 +161,6 @@ void ddk750_setLogicalDispOut(disp_output_t output) /*se blank off */ reg &= ~CRT_DISPLAY_CTRL_BLANK; POKE32(CRT_DISPLAY_CTRL, reg); - } if (output & PRI_TP_USAGE) { diff --git a/drivers/staging/sm750fb/ddk750_display.h b/drivers/staging/sm750fb/ddk750_display.h index ca35aa1df9d7..e3fde428c52b 100644 --- a/drivers/staging/sm750fb/ddk750_display.h +++ b/drivers/staging/sm750fb/ddk750_display.h @@ -2,100 +2,98 @@ #define DDK750_DISPLAY_H__ /* panel path select - 80000[29:28] -*/ + * 80000[29:28] + */ #define PNL_2_OFFSET 0 #define PNL_2_MASK (3 << PNL_2_OFFSET) #define PNL_2_USAGE (PNL_2_MASK << 16) -#define PNL_2_PRI ((0 << PNL_2_OFFSET)|PNL_2_USAGE) -#define PNL_2_SEC ((2 << PNL_2_OFFSET)|PNL_2_USAGE) +#define PNL_2_PRI ((0 << PNL_2_OFFSET) | PNL_2_USAGE) +#define PNL_2_SEC ((2 << PNL_2_OFFSET) | PNL_2_USAGE) /* primary timing & plane enable bit - 1: 80000[8] & 80000[2] on - 0: both off -*/ + * 1: 80000[8] & 80000[2] on + * 0: both off + */ #define PRI_TP_OFFSET 4 #define PRI_TP_MASK BIT(PRI_TP_OFFSET) #define PRI_TP_USAGE (PRI_TP_MASK << 16) -#define PRI_TP_ON ((0x1 << PRI_TP_OFFSET)|PRI_TP_USAGE) -#define PRI_TP_OFF ((0x0 << PRI_TP_OFFSET)|PRI_TP_USAGE) +#define PRI_TP_ON ((0x1 << PRI_TP_OFFSET) | PRI_TP_USAGE) +#define PRI_TP_OFF ((0x0 << PRI_TP_OFFSET) | PRI_TP_USAGE) /* panel sequency status - 80000[27:24] -*/ + * 80000[27:24] + */ #define PNL_SEQ_OFFSET 6 #define PNL_SEQ_MASK BIT(PNL_SEQ_OFFSET) #define PNL_SEQ_USAGE (PNL_SEQ_MASK << 16) -#define PNL_SEQ_ON (BIT(PNL_SEQ_OFFSET)|PNL_SEQ_USAGE) -#define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET)|PNL_SEQ_USAGE) +#define PNL_SEQ_ON (BIT(PNL_SEQ_OFFSET) | PNL_SEQ_USAGE) +#define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET) | PNL_SEQ_USAGE) /* dual digital output - 80000[19] -*/ + * 80000[19] + */ #define DUAL_TFT_OFFSET 8 #define DUAL_TFT_MASK BIT(DUAL_TFT_OFFSET) #define DUAL_TFT_USAGE (DUAL_TFT_MASK << 16) -#define DUAL_TFT_ON (BIT(DUAL_TFT_OFFSET)|DUAL_TFT_USAGE) -#define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET)|DUAL_TFT_USAGE) +#define DUAL_TFT_ON (BIT(DUAL_TFT_OFFSET) | DUAL_TFT_USAGE) +#define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET) | DUAL_TFT_USAGE) /* secondary timing & plane enable bit - 1:80200[8] & 80200[2] on - 0: both off -*/ + * 1:80200[8] & 80200[2] on + * 0: both off + */ #define SEC_TP_OFFSET 5 #define SEC_TP_MASK BIT(SEC_TP_OFFSET) #define SEC_TP_USAGE (SEC_TP_MASK << 16) -#define SEC_TP_ON ((0x1 << SEC_TP_OFFSET)|SEC_TP_USAGE) -#define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET)|SEC_TP_USAGE) +#define SEC_TP_ON ((0x1 << SEC_TP_OFFSET) | SEC_TP_USAGE) +#define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET) | SEC_TP_USAGE) /* crt path select - 80200[19:18] -*/ + * 80200[19:18] + */ #define CRT_2_OFFSET 2 #define CRT_2_MASK (3 << CRT_2_OFFSET) #define CRT_2_USAGE (CRT_2_MASK << 16) -#define CRT_2_PRI ((0x0 << CRT_2_OFFSET)|CRT_2_USAGE) -#define CRT_2_SEC ((0x2 << CRT_2_OFFSET)|CRT_2_USAGE) +#define CRT_2_PRI ((0x0 << CRT_2_OFFSET) | CRT_2_USAGE) +#define CRT_2_SEC ((0x2 << CRT_2_OFFSET) | CRT_2_USAGE) /* DAC affect both DVI and DSUB - 4[20] -*/ + * 4[20] + */ #define DAC_OFFSET 7 #define DAC_MASK BIT(DAC_OFFSET) #define DAC_USAGE (DAC_MASK << 16) -#define DAC_ON ((0x0 << DAC_OFFSET)|DAC_USAGE) -#define DAC_OFF ((0x1 << DAC_OFFSET)|DAC_USAGE) +#define DAC_ON ((0x0 << DAC_OFFSET) | DAC_USAGE) +#define DAC_OFF ((0x1 << DAC_OFFSET) | DAC_USAGE) /* DPMS only affect D-SUB head - 0[31:30] -*/ + * 0[31:30] + */ #define DPMS_OFFSET 9 #define DPMS_MASK (3 << DPMS_OFFSET) #define DPMS_USAGE (DPMS_MASK << 16) -#define DPMS_OFF ((3 << DPMS_OFFSET)|DPMS_USAGE) -#define DPMS_ON ((0 << DPMS_OFFSET)|DPMS_USAGE) +#define DPMS_OFF ((3 << DPMS_OFFSET) | DPMS_USAGE) +#define DPMS_ON ((0 << DPMS_OFFSET) | DPMS_USAGE) -/* - LCD1 means panel path TFT1 & panel path DVI (so enable DAC) - CRT means crt path DSUB -*/ +/* LCD1 means panel path TFT1 & panel path DVI (so enable DAC) + * CRT means crt path DSUB + */ typedef enum _disp_output_t { - do_LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON, - do_LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON, - do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON, - do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON, - /* - do_DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON, - do_DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON, - */ - do_CRT_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON, - do_CRT_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON, + do_LCD1_PRI = PNL_2_PRI | PRI_TP_ON | PNL_SEQ_ON | DAC_ON, + do_LCD1_SEC = PNL_2_SEC | SEC_TP_ON | PNL_SEQ_ON | DAC_ON, + do_LCD2_PRI = CRT_2_PRI | PRI_TP_ON | DUAL_TFT_ON, + do_LCD2_SEC = CRT_2_SEC | SEC_TP_ON | DUAL_TFT_ON, + /* do_DSUB_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON|DAC_ON, + * do_DSUB_SEC = CRT_2_SEC | SEC_TP_ON | DPMS_ON|DAC_ON, + */ + do_CRT_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON | DAC_ON, + do_CRT_SEC = CRT_2_SEC | SEC_TP_ON | DPMS_ON | DAC_ON, } disp_output_t; diff --git a/drivers/staging/sm750fb/ddk750_dvi.c b/drivers/staging/sm750fb/ddk750_dvi.c index a4a255007c8d..8252f771ef9e 100644 --- a/drivers/staging/sm750fb/ddk750_dvi.c +++ b/drivers/staging/sm750fb/ddk750_dvi.c @@ -6,9 +6,11 @@ #include "ddk750_sii164.h" -/* This global variable contains all the supported driver and its corresponding - function API. Please set the function pointer to NULL whenever the function - is not supported. */ +/* + * This global variable contains all the supported driver and its corresponding + * function API. Please set the function pointer to NULL whenever the function + * is not supported. + */ static dvi_ctrl_device_t g_dcftSupportedDviController[] = { #ifdef DVI_CTRL_SII164 { diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index 39c3e1cdbc0c..d391c127ead7 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -21,7 +21,7 @@ unsigned char bus_speed_mode POKE32(GPIO_MUX, value); /* Enable Hardware I2C power. - TODO: Check if we need to enable GPIO power? + * TODO: Check if we need to enable GPIO power? */ enableI2C(1); diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index ccb4e067661a..05b83646c2d5 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -4,15 +4,14 @@ #include "ddk750_mode.h" #include "ddk750_chip.h" -/* - SM750LE only: - This function takes care extra registers and bit fields required to set - up a mode in SM750LE - - Explanation about Display Control register: - HW only supports 7 predefined pixel clocks, and clock select is - in bit 29:27 of Display Control register. -*/ +/* SM750LE only: + * This function takes care extra registers and bit fields required to set + * up a mode in SM750LE + * + * Explanation about Display Control register: + * HW only supports 7 predefined pixel clocks, and clock select is + * in bit 29:27 of Display Control register. + */ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl) { unsigned long x, y; @@ -21,9 +20,9 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, y = pModeParam->vertical_display_end; /* SM750LE has to set up the top-left and bottom-right - registers as well. - Note that normal SM750/SM718 only use those two register for - auto-centering mode. + * registers as well. + * Note that normal SM750/SM718 only use those two register for + * auto-centering mode. */ POKE32(CRT_AUTO_CENTERING_TL, 0); @@ -33,8 +32,8 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, ((x - 1) & CRT_AUTO_CENTERING_BR_RIGHT_MASK)); /* Assume common fields in dispControl have been properly set before - calling this function. - This function only sets the extra fields in dispControl. + * calling this function. + * This function only sets the extra fields in dispControl. */ /* Clear bit 29:27 of display control register */ @@ -63,7 +62,7 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT); /* Set bit 14 of display controller */ - dispControl = DISPLAY_CTRL_CLOCK_PHASE; + dispControl |= DISPLAY_CTRL_CLOCK_PHASE; POKE32(CRT_DISPLAY_CTRL, dispControl); @@ -117,7 +116,7 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) if (pModeParam->horizontal_sync_polarity) tmp |= DISPLAY_CTRL_HSYNC_PHASE; - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { displayControlAdjust_SM750LE(pModeParam, tmp); } else { reg = PEEK32(CRT_DISPLAY_CTRL) & @@ -209,7 +208,7 @@ int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock) pll.clockType = clock; uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll); - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { /* set graphic mode via IO method */ outb_p(0x88, 0x3d4); outb_p(0x06, 0x3d5); diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index b3c3791b95bd..7cc6169f884e 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -6,7 +6,7 @@ void ddk750_setDPMS(DPMS_t state) { unsigned int value; - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { value = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_DPMS_MASK; value |= (state << CRT_DISPLAY_CTRL_DPMS_SHIFT); POKE32(CRT_DISPLAY_CTRL, value); @@ -19,7 +19,7 @@ void ddk750_setDPMS(DPMS_t state) static unsigned int getPowerMode(void) { - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return 0; return PEEK32(POWER_MODE_CTRL) & POWER_MODE_CTRL_MODE_MASK; } @@ -35,7 +35,7 @@ void setPowerMode(unsigned int powerMode) control_value = PEEK32(POWER_MODE_CTRL) & ~POWER_MODE_CTRL_MODE_MASK; - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return; switch (powerMode) { diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c index 67f36e71da7e..99a8683e6383 100644 --- a/drivers/staging/sm750fb/ddk750_sii164.c +++ b/drivers/staging/sm750fb/ddk750_sii164.c @@ -174,8 +174,8 @@ long sii164InitChip( i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config); /* De-skew enabled with default 111b value. - This will fix some artifacts problem in some mode on board 2.2. - Somehow this fix does not affect board 2.1. + * This fixes some artifacts problem in some mode on board 2.2. + * Somehow this fix does not affect board 2.1. */ if (deskewEnable == 0) config = SII164_DESKEW_DISABLE; @@ -344,7 +344,8 @@ void sii164EnableHotPlugDetection( detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT); /* Depending on each DVI controller, need to enable the hot plug based on each - individual chip design. */ + * individual chip design. + */ if (enableHotPlug != 0) sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI); else diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c index 8d644a7cba52..72a42330e7a1 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.c +++ b/drivers/staging/sm750fb/ddk750_swi2c.c @@ -89,12 +89,12 @@ static void sw_i2c_wait(void) * always be non-zero,which makes the while loop * never finish. * use non-ultimate for loop below is safe - * */ + */ /* Change wait algorithm to use PCI bus clock, - it's more reliable than counter loop .. - write 0x61 to 0x3ce and read from 0x3cf - */ + * it's more reliable than counter loop .. + * write 0x61 to 0x3ce and read from 0x3cf + */ int i, tmp; for (i = 0; i < 600; i++) { @@ -403,7 +403,7 @@ long sm750_sw_i2c_init( if ((clk_gpio > 31) || (data_gpio > 31)) return -1; - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return sm750le_i2c_init(clk_gpio, data_gpio); /* Initialize the GPIO pin for the i2c Clock Register */ @@ -501,8 +501,8 @@ long sm750_sw_i2c_write_reg( sw_i2c_start(); /* Send the device address and read the data. All should return success - in order for the writing processed to be successful - */ + * in order for the writing processed to be successful + */ if ((sw_i2c_write_byte(addr) != 0) || (sw_i2c_write_byte(reg) != 0) || (sw_i2c_write_byte(data) != 0)) { diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 6ed004e40855..7d90e250142c 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1176,7 +1176,7 @@ static int __init lynxfb_setup(char *options) else { strcat(tmp, opt); tmp += strlen(opt); - if (options != NULL) + if (options) *tmp++ = ':'; else *tmp++ = 0; diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h index 8e70ce0d6da4..ff31c5c9cc6f 100644 --- a/drivers/staging/sm750fb/sm750.h +++ b/drivers/staging/sm750fb/sm750.h @@ -147,17 +147,17 @@ struct lynxfb_output { int dpms; int paths; /* which paths(s) this output stands for,for sm750: - paths=1:means output for panel paths - paths=2:means output for crt paths - paths=3:means output for both panel and crt paths - */ + * paths=1:means output for panel paths + * paths=2:means output for crt paths + * paths=3:means output for both panel and crt paths + */ int *channel; /* which channel these outputs linked with,for sm750: - *channel=0 means primary channel - *channel=1 means secondary channel - output->channel ==> &crtc->channel - */ + * *channel=0 means primary channel + * *channel=1 means secondary channel + * output->channel ==> &crtc->channel + */ void *priv; int (*proc_setBLANK)(struct lynxfb_output*, int); diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c index 9aa4066ac86d..38adae6b5d83 100644 --- a/drivers/staging/sm750fb/sm750_accel.c +++ b/drivers/staging/sm750fb/sm750_accel.c @@ -67,7 +67,8 @@ void hw_de_init(struct lynx_accel *accel) /* set2dformat only be called from setmode functions * but if you need dual framebuffer driver,need call set2dformat - * every time you use 2d function */ + * every time you use 2d function + */ void hw_set2dformat(struct lynx_accel *accel, int fmt) { @@ -90,7 +91,8 @@ int hw_fillrect(struct lynx_accel *accel, if (accel->de_wait() != 0) { /* int time wait and always busy,seems hardware - * got something error */ + * got something error + */ pr_debug("De engine always busy\n"); return -1; } @@ -152,24 +154,26 @@ unsigned int rop2) /* ROP value */ /* Determine direction of operation */ if (sy < dy) { /* +----------+ - |S | - | +----------+ - | | | | - | | | | - +---|------+ | - | D| - +----------+ */ + * |S | + * | +----------+ + * | | | | + * | | | | + * +---|------+ | + * | D| + * +----------+ + */ nDirection = BOTTOM_TO_TOP; } else if (sy > dy) { /* +----------+ - |D | - | +----------+ - | | | | - | | | | - +---|------+ | - | S| - +----------+ */ + * |D | + * | +----------+ + * | | | | + * | | | | + * +---|------+ | + * | S| + * +----------+ + */ nDirection = TOP_TO_BOTTOM; } else { @@ -177,22 +181,24 @@ unsigned int rop2) /* ROP value */ if (sx <= dx) { /* +------+---+------+ - |S | | D| - | | | | - | | | | - | | | | - +------+---+------+ */ + * |S | | D| + * | | | | + * | | | | + * | | | | + * +------+---+------+ + */ nDirection = RIGHT_TO_LEFT; } else { /* sx > dx */ /* +------+---+------+ - |D | | S| - | | | | - | | | | - | | | | - +------+---+------+ */ + * |D | | S| + * | | | | + * | | | | + * | | | | + * +------+---+------+ + */ nDirection = LEFT_TO_RIGHT; } @@ -208,32 +214,36 @@ unsigned int rop2) /* ROP value */ } /* Note: - DE_FOREGROUND are DE_BACKGROUND are don't care. - DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency(). + * DE_FOREGROUND are DE_BACKGROUND are don't care. + * DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS + * are set by set deSetTransparency(). */ /* 2D Source Base. - It is an address offset (128 bit aligned) from the beginning of frame buffer. + * It is an address offset (128 bit aligned) + * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */ /* 2D Destination Base. - It is an address offset (128 bit aligned) from the beginning of frame buffer. + * It is an address offset (128 bit aligned) + * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */ /* Program pitch (distance between the 1st points of two adjacent lines). - Note that input pitch is BYTE value, but the 2D Pitch register uses - pixel values. Need Byte to pixel conversion. - */ + * Note that input pitch is BYTE value, but the 2D Pitch register uses + * pixel values. Need Byte to pixel conversion. + */ write_dpr(accel, DE_PITCH, ((dPitch / Bpp << DE_PITCH_DESTINATION_SHIFT) & DE_PITCH_DESTINATION_MASK) | (sPitch / Bpp & DE_PITCH_SOURCE_MASK)); /* dpr10 */ /* Screen Window width in Pixels. - 2D engine uses this value to calculate the linear address in frame buffer for a given point. - */ + * 2D engine uses this value to calculate the linear address in frame buffer + * for a given point. + */ write_dpr(accel, DE_WINDOW_WIDTH, ((dPitch / Bpp << DE_WINDOW_WIDTH_DST_SHIFT) & DE_WINDOW_WIDTH_DST_MASK) | @@ -307,33 +317,37 @@ int hw_imageblit(struct lynx_accel *accel, return -1; /* 2D Source Base. - Use 0 for HOST Blt. + * Use 0 for HOST Blt. */ write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0); /* 2D Destination Base. - It is an address offset (128 bit aligned) from the beginning of frame buffer. + * It is an address offset (128 bit aligned) + * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* Program pitch (distance between the 1st points of two adjacent lines). - Note that input pitch is BYTE value, but the 2D Pitch register uses - pixel values. Need Byte to pixel conversion. - */ + * Note that input pitch is BYTE value, but the 2D Pitch register uses + * pixel values. Need Byte to pixel conversion. + */ write_dpr(accel, DE_PITCH, ((dPitch / bytePerPixel << DE_PITCH_DESTINATION_SHIFT) & DE_PITCH_DESTINATION_MASK) | (dPitch / bytePerPixel & DE_PITCH_SOURCE_MASK)); /* dpr10 */ /* Screen Window width in Pixels. - 2D engine uses this value to calculate the linear address in frame buffer for a given point. + * 2D engine uses this value to calculate the linear address + * in frame buffer for a given point. */ write_dpr(accel, DE_WINDOW_WIDTH, ((dPitch / bytePerPixel << DE_WINDOW_WIDTH_DST_SHIFT) & DE_WINDOW_WIDTH_DST_MASK) | (dPitch / bytePerPixel & DE_WINDOW_WIDTH_SRC_MASK)); - /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used. - For mono bitmap, use startBit for X_K1. */ + /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, + * and Y_K2 field is not used. + * For mono bitmap, use startBit for X_K1. + */ write_dpr(accel, DE_SOURCE, (startBit << DE_SOURCE_X_K1_SHIFT) & DE_SOURCE_X_K1_MONO_MASK); /* dpr00 */ diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 2daeedd88c30..7dd208caa5eb 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -35,17 +35,17 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start); /* reserve the vidreg space of smi adaptor - * if you do this, u need to add release region code + * if you do this, you need to add release region code * in lynxfb_remove, or memory will not be mapped again * successfully - * */ + */ ret = pci_request_region(pdev, 1, "sm750fb"); if (ret) { pr_err("Can not request PCI regions.\n"); goto exit; } - /* now map mmio and vidmem*/ + /* now map mmio and vidmem */ sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start, sm750_dev->vidreg_size); if (!sm750_dev->pvReg) { @@ -56,7 +56,6 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg); } - sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1; sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1; @@ -64,10 +63,10 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) sm750_dev->vidmem_start = pci_resource_start(pdev, 0); /* don't use pdev_resource[x].end - resource[x].start to - * calculate the resource size,its only the maximum available - * size but not the actual size,use + * calculate the resource size, it's only the maximum available + * size but not the actual size, using * @ddk750_getVMSize function can be safe. - * */ + */ sm750_dev->vidmem_size = ddk750_getVMSize(); pr_info("video memory phyAddr = %lx, size = %u bytes\n", sm750_dev->vidmem_start, sm750_dev->vidmem_size); @@ -86,33 +85,31 @@ exit: return ret; } - - int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) { struct init_status *parm; parm = &sm750_dev->initParm; if (parm->chip_clk == 0) - parm->chip_clk = (getChipType() == SM750LE) ? + parm->chip_clk = (sm750_get_chip_type() == SM750LE) ? DEFAULT_SM750LE_CHIP_CLOCK : DEFAULT_SM750_CHIP_CLOCK; if (parm->mem_clk == 0) parm->mem_clk = parm->chip_clk; if (parm->master_clk == 0) - parm->master_clk = parm->chip_clk/3; + parm->master_clk = parm->chip_clk / 3; ddk750_initHw((initchip_param_t *)&sm750_dev->initParm); - /* for sm718,open pci burst */ + /* for sm718, open pci burst */ if (sm750_dev->devid == 0x718) { POKE32(SYSTEM_CTRL, PEEK32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST); } - if (getChipType() != SM750LE) { + if (sm750_get_chip_type() != SM750LE) { unsigned int val; - /* does user need CRT ?*/ + /* does user need CRT? */ if (sm750_dev->nocrt) { POKE32(MISC_CTRL, PEEK32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF); @@ -144,19 +141,21 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) } POKE32(PANEL_DISPLAY_CTRL, val); } else { - /* for 750LE ,no DVI chip initialization makes Monitor no signal */ - /* Set up GPIO for software I2C to program DVI chip in the - Xilinx SP605 board, in order to have video signal. + /* for 750LE, no DVI chip initialization + * makes Monitor no signal + * + * Set up GPIO for software I2C to program DVI chip in the + * Xilinx SP605 board, in order to have video signal. */ sm750_sw_i2c_init(0, 1); /* Customer may NOT use CH7301 DVI chip, which has to be - initialized differently. - */ + * initialized differently. + */ if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) { /* The following register values for CH7301 are from - Chrontel app note and our experiment. - */ + * Chrontel app note and our experiment. + */ pr_info("yes,CH7301 DVI chip found\n"); sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16); sm750_sw_i2c_write_reg(0xec, 0x21, 0x9); @@ -173,7 +172,8 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) } int hw_sm750_output_setMode(struct lynxfb_output *output, - struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix) + struct fb_var_screeninfo *var, + struct fb_fix_screeninfo *fix) { int ret; disp_output_t dispSet; @@ -183,8 +183,7 @@ int hw_sm750_output_setMode(struct lynxfb_output *output, dispSet = 0; channel = *output->channel; - - if (getChipType() != SM750LE) { + if (sm750_get_chip_type() != SM750LE) { if (channel == sm750_primary) { pr_info("primary channel\n"); if (output->paths & sm750_panel) @@ -198,11 +197,10 @@ int hw_sm750_output_setMode(struct lynxfb_output *output, dispSet |= do_LCD1_SEC; if (output->paths & sm750_crt) dispSet |= do_CRT_SEC; - } ddk750_setLogicalDispOut(dispSet); } else { - /* just open DISPLAY_CONTROL_750LE register bit 3:0*/ + /* just open DISPLAY_CONTROL_750LE register bit 3:0 */ u32 reg; reg = PEEK32(DISPLAY_CONTROL_750LE); @@ -214,7 +212,8 @@ int hw_sm750_output_setMode(struct lynxfb_output *output, return ret; } -int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var) +int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, + struct fb_var_screeninfo *var) { struct sm750_dev *sm750_dev; struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc); @@ -233,19 +232,15 @@ int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo * break; default: return -EINVAL; - } return 0; } - -/* - set the controller's mode for @crtc charged with @var and @fix parameters -*/ +/* set the controller's mode for @crtc charged with @var and @fix parameters */ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, - struct fb_var_screeninfo *var, - struct fb_fix_screeninfo *fix) + struct fb_var_screeninfo *var, + struct fb_fix_screeninfo *fix) { int ret, fmt; u32 reg; @@ -254,7 +249,6 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, struct sm750_dev *sm750_dev; struct lynxfb_par *par; - ret = 0; par = container_of(crtc, struct lynxfb_par, crtc); sm750_dev = par->dev; @@ -278,17 +272,22 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, /* set timing */ modparm.pixel_clock = ps_to_hz(var->pixclock); - modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG; - modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG; - modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS:NEG; + modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) + ? POS : NEG; + modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) + ? POS : NEG; + modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) + ? POS : NEG; modparm.horizontal_display_end = var->xres; modparm.horizontal_sync_width = var->hsync_len; modparm.horizontal_sync_start = var->xres + var->right_margin; - modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len; + modparm.horizontal_total = var->xres + var->left_margin + + var->right_margin + var->hsync_len; modparm.vertical_display_end = var->yres; modparm.vertical_sync_height = var->vsync_len; modparm.vertical_sync_start = var->yres + var->lower_margin; - modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; + modparm.vertical_total = var->yres + var->upper_margin + + var->lower_margin + var->vsync_len; /* choose pll */ if (crtc->channel != sm750_secondary) @@ -304,12 +303,14 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, } if (crtc->channel != sm750_secondary) { - /* set pitch, offset ,width,start address ,etc... */ + /* set pitch, offset, width, start address, etc... */ POKE32(PANEL_FB_ADDRESS, crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK); reg = var->xres * (var->bits_per_pixel >> 3); - /* crtc->channel is not equal to par->index on numeric,be aware of that */ + /* crtc->channel is not equal to par->index on numeric, + * be aware of that + */ reg = ALIGN(reg, crtc->line_pad); reg = (reg << PANEL_FB_WIDTH_WIDTH_SHIFT) & PANEL_FB_WIDTH_WIDTH_MASK; @@ -321,8 +322,8 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, reg |= (var->xoffset & PANEL_WINDOW_WIDTH_X_MASK); POKE32(PANEL_WINDOW_WIDTH, reg); - reg = ((var->yres_virtual - 1) << - PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT); + reg = (var->yres_virtual - 1) << + PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT; reg &= PANEL_WINDOW_HEIGHT_HEIGHT_MASK; reg |= (var->yoffset & PANEL_WINDOW_HEIGHT_Y_MASK); POKE32(PANEL_WINDOW_HEIGHT, reg); @@ -341,7 +342,9 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, /* not implemented now */ POKE32(CRT_FB_ADDRESS, crtc->oScreen); reg = var->xres * (var->bits_per_pixel >> 3); - /* crtc->channel is not equal to par->index on numeric,be aware of that */ + /* crtc->channel is not equal to par->index on numeric, + * be aware of that + */ reg = ALIGN(reg, crtc->line_pad) << CRT_FB_WIDTH_WIDTH_SHIFT; reg &= CRT_FB_WIDTH_WIDTH_MASK; reg |= (fix->line_length & CRT_FB_WIDTH_OFFSET_MASK); @@ -352,20 +355,19 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, reg |= ((var->bits_per_pixel >> 4) & CRT_DISPLAY_CTRL_FORMAT_MASK); POKE32(CRT_DISPLAY_CTRL, reg); - } - exit: return ret; } int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index, - ushort red, ushort green, ushort blue) + ushort red, ushort green, ushort blue) { static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM}; - POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue); + POKE32(add[crtc->channel] + index * 4, + (red << 16) | (green << 8) | blue); return 0; } @@ -414,7 +416,9 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) { unsigned int dpms, pps, crtdb; - dpms = pps = crtdb = 0; + dpms = 0; + pps = 0; + crtdb = 0; switch (blank) { case FB_BLANK_UNBLANK: @@ -461,14 +465,13 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) return 0; } - void hw_sm750_initAccel(struct sm750_dev *sm750_dev) { u32 reg; enable2DEngine(1); - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { reg = PEEK32(DE_STATE1); reg |= DE_STATE1_DE_ABORT; POKE32(DE_STATE1, reg); @@ -509,7 +512,6 @@ int hw_sm750le_deWait(void) return -1; } - int hw_sm750_deWait(void) { int i = 0x10000000; @@ -529,10 +531,10 @@ int hw_sm750_deWait(void) } int hw_sm750_pan_display(struct lynxfb_crtc *crtc, - const struct fb_var_screeninfo *var, - const struct fb_info *info) + const struct fb_var_screeninfo *var, + const struct fb_info *info) { - uint32_t total; + u32 total; /* check params */ if ((var->xoffset + var->xres > var->xres_virtual) || (var->yoffset + var->yres > var->yres_virtual)) { diff --git a/drivers/staging/speakup/devsynth.c b/drivers/staging/speakup/devsynth.c index 84989711ae67..58abd1d85105 100644 --- a/drivers/staging/speakup/devsynth.c +++ b/drivers/staging/speakup/devsynth.c @@ -34,7 +34,7 @@ static ssize_t speakup_file_write(struct file *fp, const char __user *buffer, synth_write(buf, bytes); spin_unlock_irqrestore(&speakup_info.spinlock, flags); } - return (ssize_t) nbytes; + return (ssize_t)nbytes; } static ssize_t speakup_file_read(struct file *fp, char __user *buf, diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index 528cbdce4227..e744aa9730ff 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -251,7 +251,7 @@ static ssize_t keymap_show(struct kobject *kobj, struct kobj_attribute *attr, } cp += sprintf(cp, "0, %d\n", KEY_MAP_VER); spin_unlock_irqrestore(&speakup_info.spinlock, flags); - return (int)(cp-buf); + return (int)(cp - buf); } /* @@ -288,8 +288,8 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr, cp = spk_s2uchar(cp, cp1); cp1++; } - i = (int)cp1[-2]+1; - i *= (int)cp1[-1]+1; + i = (int)cp1[-2] + 1; + i *= (int)cp1[-1] + 1; i += 2; /* 0 and last map ver */ if (cp1[-3] != KEY_MAP_VER || cp1[-1] > 10 || i+SHIFT_TBL_SIZE+4 >= sizeof(spk_key_buf)) { @@ -350,9 +350,9 @@ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr, } else { shut = 0; } - if (ch&4) + if (ch & 4) shut |= 0x40; - if (ch&1) + if (ch & 1) spk_shut_up |= shut; else spk_shut_up &= ~shut; @@ -411,11 +411,13 @@ static ssize_t synth_direct_store(struct kobject *kobj, int len; int bytes; const char *ptr = buf; + unsigned long flags; if (!synth) return -EPERM; len = strlen(buf); + spin_lock_irqsave(&speakup_info.spinlock, flags); while (len > 0) { bytes = min_t(size_t, len, 250); strncpy(tmp, ptr, bytes); @@ -425,6 +427,7 @@ static ssize_t synth_direct_store(struct kobject *kobj, ptr += bytes; len -= bytes; } + spin_unlock_irqrestore(&speakup_info.spinlock, flags); return count; } @@ -973,11 +976,11 @@ static struct attribute *i18n_attrs[] = { * created for the attributes with the directory being the name of the * attribute group. */ -static struct attribute_group main_attr_group = { +static const struct attribute_group main_attr_group = { .attrs = main_attrs, }; -static struct attribute_group i18n_attr_group = { +static const struct attribute_group i18n_attr_group = { .attrs = i18n_attrs, .name = "i18n", }; diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index 4f462c35fdd9..54b2f3918628 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -18,7 +18,7 @@ #include "serialio.h" #define MAXSYNTHS 16 /* Max number of synths in array. */ -static struct spk_synth *synths[MAXSYNTHS]; +static struct spk_synth *synths[MAXSYNTHS + 1]; struct spk_synth *synth; char spk_pitch_buff[32] = ""; static int module_status; @@ -407,7 +407,7 @@ static int do_synth_init(struct spk_synth *in_synth) if (!spk_quiet_boot) synth_printf("%s found\n", synth->long_name); if (synth->attributes.name - && sysfs_create_group(speakup_kobj, &(synth->attributes)) < 0) + && sysfs_create_group(speakup_kobj, &synth->attributes) < 0) return -ENOMEM; synth_flags = synth->flags; wake_up_interruptible_all(&speakup_event); @@ -429,7 +429,7 @@ void synth_release(void) del_timer(&thread_timer); spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (synth->attributes.name) - sysfs_remove_group(speakup_kobj, &(synth->attributes)); + sysfs_remove_group(speakup_kobj, &synth->attributes); for (var = synth->vars; var->var_id != MAXVARS; var++) speakup_unregister_var(var->var_id); spk_stop_serial_interrupt(); diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c index e1393d2a2b0f..21186e3dc7ad 100644 --- a/drivers/staging/speakup/varhandlers.c +++ b/drivers/staging/speakup/varhandlers.c @@ -276,7 +276,7 @@ int spk_set_mask_bits(const char *input, const int which, const int how) u_char *cp; short mask = spk_punc_info[which].mask; - if (how&1) { + if (how & 1) { for (cp = (u_char *)spk_punc_info[3].value; *cp; cp++) spk_chartab[*cp] &= ~mask; } @@ -290,14 +290,14 @@ int spk_set_mask_bits(const char *input, const int which, const int how) if (mask < PUNC) { if (!(spk_chartab[*cp] & PUNC)) break; - } else if (spk_chartab[*cp]&B_NUM) + } else if (spk_chartab[*cp] & B_NUM) break; } if (*cp) return -EINVAL; cp = (u_char *)input; } - if (how&2) { + if (how & 2) { for (; *cp; cp++) if (*cp > SPACE) spk_chartab[*cp] |= mask; diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index db4e6b28755b..259ef6487959 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -75,28 +75,6 @@ enum channel_clientstate { /* access channel anytime */ }; -static inline const u8 * -ULTRA_CHANNELCLI_STRING(u32 state) -{ - switch (state) { - case CHANNELCLI_DETACHED: - return (const u8 *)("DETACHED"); - case CHANNELCLI_DISABLED: - return (const u8 *)("DISABLED"); - case CHANNELCLI_ATTACHING: - return (const u8 *)("ATTACHING"); - case CHANNELCLI_ATTACHED: - return (const u8 *)("ATTACHED"); - case CHANNELCLI_BUSY: - return (const u8 *)("BUSY"); - case CHANNELCLI_OWNED: - return (const u8 *)("OWNED"); - default: - break; - } - return (const u8 *)("?"); -} - #define SPAR_CHANNEL_SERVER_READY(ch) \ (readl(&(ch)->srv_state) == CHANNELSRV_READY) @@ -132,22 +110,6 @@ ULTRA_CHANNELCLI_STRING(u32 state) /* throttling invalid boot channel statetransition error due to busy channel */ #define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04 -/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */ -/* throttling invalid guest OS channel statetransition error due to - * client disabled - */ -#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED 0x01 - -/* throttling invalid guest OS channel statetransition error due to - * client not attached - */ -#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED 0x02 - -/* throttling invalid guest OS channel statetransition error due to - * busy channel - */ -#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY 0x04 - /* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so * that windows guest can look at the FeatureFlags in the io channel, * and configure the windows driver to use interrupts or not based on @@ -347,148 +309,6 @@ static inline int spar_check_channel_server(uuid_le typeuuid, char *name, return 1; } -/* Given a file pathname (with '/' or '\' separating directory nodes), - * returns a pointer to the beginning of a node within that pathname such - * that the number of nodes from that pointer to the end of the string is - * NOT more than . Note that if the pathname has less than nodes - * in it, the return pointer will be to the beginning of the string. - */ -static inline u8 * -pathname_last_n_nodes(u8 *s, unsigned int n) -{ - u8 *p = s; - unsigned int node_count = 0; - - while (*p != '\0') { - if ((*p == '/') || (*p == '\\')) - node_count++; - p++; - } - if (node_count <= n) - return s; - while (n > 0) { - p--; - if (p == s) - break; /* should never happen, unless someone - * is changing the string while we are - * looking at it!! - */ - if ((*p == '/') || (*p == '\\')) - n--; - } - return p + 1; -} - -static inline int -spar_channel_client_acquire_os(void __iomem *ch, u8 *id) -{ - struct channel_header __iomem *hdr = ch; - - if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_DISABLED, - &hdr->cli_error_os); - /* throttle until acquire successful */ - - pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n", - id); - } - return 0; - } - if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) && - (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) { - /* Our competitor is DISABLED, so we can transition to OWNED */ - pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n", - id, "cli_state_os", - ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os), - ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED), - CHANNELCLI_OWNED); - writel(CHANNELCLI_OWNED, &hdr->cli_state_os); - mb(); /* required for channel synch */ - } - if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) { - if (readb(&hdr->cli_error_os)) { - /* we are in an error msg throttling state; - * come out of it - */ - pr_info("%s Channel OS client acquire now successful\n", - id); - writeb(0, &hdr->cli_error_os); - } - return 1; - } - - /* We have to do it the "hard way". We transition to BUSY, - * and can use the channel iff our competitor has not also - * transitioned to BUSY. - */ - if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED, - &hdr->cli_error_os); - /* throttle until acquire successful */ - pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n", - id, ULTRA_CHANNELCLI_STRING( - readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os)); - } - return 0; - } - writel(CHANNELCLI_BUSY, &hdr->cli_state_os); - mb(); /* required for channel synch */ - if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_BUSY, - &hdr->cli_error_os); - /* throttle until acquire successful */ - pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n", - id); - } - /* reset busy */ - writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); - mb(); /* required for channel synch */ - return 0; - } - if (readb(&hdr->cli_error_os)) { - /* we are in an error msg throttling state; come out of it */ - pr_info("%s Channel OS client acquire now successful\n", id); - writeb(0, &hdr->cli_error_os); - } - return 1; -} - -static inline void -spar_channel_client_release_os(void __iomem *ch, u8 *id) -{ - struct channel_header __iomem *hdr = ch; - - if (readb(&hdr->cli_error_os)) { - /* we are in an error msg throttling state; come out of it */ - pr_info("%s Channel OS client error state cleared\n", id); - writeb(0, &hdr->cli_error_os); - } - if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) - return; - if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) { - pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n", - id, ULTRA_CHANNELCLI_STRING( - readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os)); - /* return; */ - } - writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* release busy */ -} - /* * Routine Description: * Tries to insert the prebuilt signal pointed to by pSignal into the nth @@ -569,4 +389,45 @@ unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, u32 queue); +/* + * CHANNEL Guids + */ + +/* {414815ed-c58c-11da-95a9-00e08161165f} */ +#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x414815ed, 0xc58c, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) +static const uuid_le spar_vhba_channel_protocol_uuid = + SPAR_VHBA_CHANNEL_PROTOCOL_UUID; +#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \ + "414815ed-c58c-11da-95a9-00e08161165f" + +/* {8cd5994d-c58e-11da-95a9-00e08161165f} */ +#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) +static const uuid_le spar_vnic_channel_protocol_uuid = + SPAR_VNIC_CHANNEL_PROTOCOL_UUID; +#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \ + "8cd5994d-c58e-11da-95a9-00e08161165f" + +/* {72120008-4AAB-11DC-8530-444553544200} */ +#define SPAR_SIOVM_UUID \ + UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ + 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) +static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; + +/* {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} */ +#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ + 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) + +static const uuid_le spar_controldirector_channel_protocol_uuid = + SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; + +/* {b4e79625-aede-4eAA-9e11-D3eddcd4504c} */ +#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ + 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) + #endif diff --git a/drivers/staging/unisys/include/channel_guid.h b/drivers/staging/unisys/include/channel_guid.h deleted file mode 100644 index 17cb499cb53c..000000000000 --- a/drivers/staging/unisys/include/channel_guid.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * CHANNEL Guids - */ - -/* {414815ed-c58c-11da-95a9-00e08161165f} */ -#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x414815ed, 0xc58c, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le spar_vhba_channel_protocol_uuid = - SPAR_VHBA_CHANNEL_PROTOCOL_UUID; -#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \ - "414815ed-c58c-11da-95a9-00e08161165f" - -/* {8cd5994d-c58e-11da-95a9-00e08161165f} */ -#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le spar_vnic_channel_protocol_uuid = - SPAR_VNIC_CHANNEL_PROTOCOL_UUID; -#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \ - "8cd5994d-c58e-11da-95a9-00e08161165f" - -/* {72120008-4AAB-11DC-8530-444553544200} */ -#define SPAR_SIOVM_UUID \ - UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ - 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) -static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; - -/* {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} */ -#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ - 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) - -static const uuid_le spar_controldirector_channel_protocol_uuid = - SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; - -/* {b4e79625-aede-4eAA-9e11-D3eddcd4504c} */ -#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ - 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) diff --git a/drivers/staging/unisys/include/diagchannel.h b/drivers/staging/unisys/include/diagchannel.h deleted file mode 100644 index 6e813c77b97e..000000000000 --- a/drivers/staging/unisys/include/diagchannel.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef _DIAG_CHANNEL_H_ -#define _DIAG_CHANNEL_H_ - -/* Levels of severity for diagnostic events, in order from lowest severity to - * highest (i.e. fatal errors are the most severe, and should always be logged, - * but info events rarely need to be logged except during debugging). The - * values DIAG_SEVERITY_ENUM_BEGIN and DIAG_SEVERITY_ENUM_END are not valid - * severity values. They exist merely to dilineate the list, so that future - * additions won't require changes to the driver (i.e. when checking for - * out-of-range severities in SetSeverity). The values DIAG_SEVERITY_OVERRIDE - * and DIAG_SEVERITY_SHUTOFF are not valid severity values for logging events - * but they are valid for controlling the amount of event data. Changes made - * to the enum, need to be reflected in s-Par. - */ -enum diag_severity { - DIAG_SEVERITY_VERBOSE = 0, - DIAG_SEVERITY_INFO = 1, - DIAG_SEVERITY_WARNING = 2, - DIAG_SEVERITY_ERR = 3, - DIAG_SEVERITY_PRINT = 4, -}; - -#endif diff --git a/drivers/staging/unisys/include/guestlinuxdebug.h b/drivers/staging/unisys/include/guestlinuxdebug.h deleted file mode 100644 index b81287f5e2c3..000000000000 --- a/drivers/staging/unisys/include/guestlinuxdebug.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __GUESTLINUXDEBUG_H__ -#define __GUESTLINUXDEBUG_H__ - -/* - * This file contains supporting interface for "vmcallinterface.h", particularly - * regarding adding additional structure and functionality to linux - * ISSUE_IO_VMCALL_POSTCODE_SEVERITY - */ - -/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/ -enum driver_pc { /* POSTCODE driver identifier tuples */ - /* visorchipset driver files */ - VISOR_CHIPSET_PC = 0xA0, - VISOR_CHIPSET_PC_controlvm_c = 0xA1, - VISOR_CHIPSET_PC_controlvm_cm2 = 0xA2, - VISOR_CHIPSET_PC_controlvm_direct_c = 0xA3, - VISOR_CHIPSET_PC_file_c = 0xA4, - VISOR_CHIPSET_PC_parser_c = 0xA5, - VISOR_CHIPSET_PC_testing_c = 0xA6, - VISOR_CHIPSET_PC_visorchipset_main_c = 0xA7, - VISOR_CHIPSET_PC_visorswitchbus_c = 0xA8, - /* visorbus driver files */ - VISOR_BUS_PC = 0xB0, - VISOR_BUS_PC_businst_attr_c = 0xB1, - VISOR_BUS_PC_channel_attr_c = 0xB2, - VISOR_BUS_PC_devmajorminor_attr_c = 0xB3, - VISOR_BUS_PC_visorbus_main_c = 0xB4, - /* visorclientbus driver files */ - VISOR_CLIENT_BUS_PC = 0xC0, - VISOR_CLIENT_BUS_PC_visorclientbus_main_c = 0xC1, - /* virt hba driver files */ - VIRT_HBA_PC = 0xC2, - VIRT_HBA_PC_virthba_c = 0xC3, - /* virtpci driver files */ - VIRT_PCI_PC = 0xC4, - VIRT_PCI_PC_virtpci_c = 0xC5, - /* virtnic driver files */ - VIRT_NIC_PC = 0xC6, - VIRT_NIC_P_virtnic_c = 0xC7, - /* uislib driver files */ - UISLIB_PC = 0xD0, - UISLIB_PC_uislib_c = 0xD1, - UISLIB_PC_uisqueue_c = 0xD2, - UISLIB_PC_uisthread_c = 0xD3, - UISLIB_PC_uisutils_c = 0xD4, -}; - -enum event_pc { /* POSTCODE event identifier tuples */ - ATTACH_PORT_ENTRY_PC = 0x001, - ATTACH_PORT_FAILURE_PC = 0x002, - ATTACH_PORT_SUCCESS_PC = 0x003, - BUS_FAILURE_PC = 0x004, - BUS_CREATE_ENTRY_PC = 0x005, - BUS_CREATE_FAILURE_PC = 0x006, - BUS_CREATE_EXIT_PC = 0x007, - BUS_CONFIGURE_ENTRY_PC = 0x008, - BUS_CONFIGURE_FAILURE_PC = 0x009, - BUS_CONFIGURE_EXIT_PC = 0x00A, - CHIPSET_INIT_ENTRY_PC = 0x00B, - CHIPSET_INIT_SUCCESS_PC = 0x00C, - CHIPSET_INIT_FAILURE_PC = 0x00D, - CHIPSET_INIT_EXIT_PC = 0x00E, - CREATE_WORKQUEUE_PC = 0x00F, - CREATE_WORKQUEUE_FAILED_PC = 0x0A0, - CONTROLVM_INIT_FAILURE_PC = 0x0A1, - DEVICE_CREATE_ENTRY_PC = 0x0A2, - DEVICE_CREATE_FAILURE_PC = 0x0A3, - DEVICE_CREATE_SUCCESS_PC = 0x0A4, - DEVICE_CREATE_EXIT_PC = 0x0A5, - DEVICE_ADD_PC = 0x0A6, - DEVICE_REGISTER_FAILURE_PC = 0x0A7, - DEVICE_CHANGESTATE_ENTRY_PC = 0x0A8, - DEVICE_CHANGESTATE_FAILURE_PC = 0x0A9, - DEVICE_CHANGESTATE_EXIT_PC = 0x0AA, - DRIVER_ENTRY_PC = 0x0AB, - DRIVER_EXIT_PC = 0x0AC, - MALLOC_FAILURE_PC = 0x0AD, - QUEUE_DELAYED_WORK_PC = 0x0AE, - UISLIB_THREAD_FAILURE_PC = 0x0B7, - VBUS_CHANNEL_ENTRY_PC = 0x0B8, - VBUS_CHANNEL_FAILURE_PC = 0x0B9, - VBUS_CHANNEL_EXIT_PC = 0x0BA, - VHBA_CREATE_ENTRY_PC = 0x0BB, - VHBA_CREATE_FAILURE_PC = 0x0BC, - VHBA_CREATE_EXIT_PC = 0x0BD, - VHBA_CREATE_SUCCESS_PC = 0x0BE, - VHBA_COMMAND_HANDLER_PC = 0x0BF, - VHBA_PROBE_ENTRY_PC = 0x0C0, - VHBA_PROBE_FAILURE_PC = 0x0C1, - VHBA_PROBE_EXIT_PC = 0x0C2, - VNIC_CREATE_ENTRY_PC = 0x0C3, - VNIC_CREATE_FAILURE_PC = 0x0C4, - VNIC_CREATE_SUCCESS_PC = 0x0C5, - VNIC_PROBE_ENTRY_PC = 0x0C6, - VNIC_PROBE_FAILURE_PC = 0x0C7, - VNIC_PROBE_EXIT_PC = 0x0C8, - VPCI_CREATE_ENTRY_PC = 0x0C9, - VPCI_CREATE_FAILURE_PC = 0x0CA, - VPCI_CREATE_EXIT_PC = 0x0CB, - VPCI_PROBE_ENTRY_PC = 0x0CC, - VPCI_PROBE_FAILURE_PC = 0x0CD, - VPCI_PROBE_EXIT_PC = 0x0CE, - CRASH_DEV_ENTRY_PC = 0x0CF, - CRASH_DEV_EXIT_PC = 0x0D0, - CRASH_DEV_HADDR_NULL = 0x0D1, - CRASH_DEV_CONTROLVM_NULL = 0x0D2, - CRASH_DEV_RD_BUS_FAIULRE_PC = 0x0D3, - CRASH_DEV_RD_DEV_FAIULRE_PC = 0x0D4, - CRASH_DEV_BUS_NULL_FAILURE_PC = 0x0D5, - CRASH_DEV_DEV_NULL_FAILURE_PC = 0x0D6, - CRASH_DEV_CTRL_RD_FAILURE_PC = 0x0D7, - CRASH_DEV_COUNT_FAILURE_PC = 0x0D8, - SAVE_MSG_BUS_FAILURE_PC = 0x0D9, - SAVE_MSG_DEV_FAILURE_PC = 0x0DA, - CALLHOME_INIT_FAILURE_PC = 0x0DB -}; - -#ifdef __GNUC__ - -#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR -#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING -/* TODO-> Info currently doesn't show, so we set info=warning */ -#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT - -/* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR); - * Please also note that the resulting postcode is in hex, so if you are - * searching for the __LINE__ number, convert it first to decimal. The line - * number combined with driver and type of call, will allow you to track down - * exactly what line an error occurred on, or where the last driver - * entered/exited from. - */ - -/* BASE FUNCTIONS */ -#define POSTCODE_LINUX_A(DRIVER_PC, EVENT_PC, pc32bit, severity) \ -do { \ - unsigned long long post_code_temp; \ - post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ - ((((u64)__LINE__) & 0xFFF) << 32) | \ - (((u64)pc32bit) & 0xFFFFFFFF); \ - ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ -} while (0) - -#define POSTCODE_LINUX_B(DRIVER_PC, EVENT_PC, pc16bit1, pc16bit2, severity) \ -do { \ - unsigned long long post_code_temp; \ - post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ - ((((u64)__LINE__) & 0xFFF) << 32) | \ - ((((u64)pc16bit1) & 0xFFFF) << 16) | \ - (((u64)pc16bit2) & 0xFFFF); \ - ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ -} while (0) - -/* MOST COMMON */ -#define POSTCODE_LINUX_2(EVENT_PC, severity) \ - POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, 0x0000, severity) - -#define POSTCODE_LINUX_3(EVENT_PC, pc32bit, severity) \ - POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, pc32bit, severity) - -#define POSTCODE_LINUX_4(EVENT_PC, pc16bit1, pc16bit2, severity) \ - POSTCODE_LINUX_B(CURRENT_FILE_PC, EVENT_PC, pc16bit1, \ - pc16bit2, severity) - -#endif -#endif diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index 5ccf81485d72..cba4433bcd51 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -33,7 +33,6 @@ #include #include "channel.h" -#include "channel_guid.h" #define ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE #define ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE diff --git a/drivers/staging/unisys/include/periodic_work.h b/drivers/staging/unisys/include/periodic_work.h deleted file mode 100644 index 0b3335a4b206..000000000000 --- a/drivers/staging/unisys/include/periodic_work.h +++ /dev/null @@ -1,40 +0,0 @@ -/* periodic_work.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __PERIODIC_WORK_H__ -#define __PERIODIC_WORK_H__ - -#include -#include - -/* PERIODIC_WORK an opaque structure to users. - * Fields are declared only in the implementation .c files. - */ -struct periodic_work; - -struct periodic_work * -visor_periodic_work_create(ulong jiffy_interval, - struct workqueue_struct *workqueue, - void (*workfunc)(void *), - void *workfuncarg, - const char *devnam); -void visor_periodic_work_destroy(struct periodic_work *pw); -bool visor_periodic_work_nextperiod(struct periodic_work *pw); -bool visor_periodic_work_start(struct periodic_work *pw); -bool visor_periodic_work_stop(struct periodic_work *pw); - -#endif diff --git a/drivers/staging/unisys/include/vbushelper.h b/drivers/staging/unisys/include/vbushelper.h deleted file mode 100644 index f1b6aacb79d7..000000000000 --- a/drivers/staging/unisys/include/vbushelper.h +++ /dev/null @@ -1,46 +0,0 @@ -/* vbushelper.h - * - * Copyright (C) 2011 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VBUSHELPER_H__ -#define __VBUSHELPER_H__ - -/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the - * command line - */ - -#define TARGET_HOSTNAME "linuxguest" - -static inline void bus_device_info_init( - struct ultra_vbus_deviceinfo *bus_device_info_ptr, - const char *dev_type, const char *drv_name, - const char *ver, const char *ver_tag) -{ - memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); - snprintf(bus_device_info_ptr->devtype, - sizeof(bus_device_info_ptr->devtype), - "%s", (dev_type) ? dev_type : "unknownType"); - snprintf(bus_device_info_ptr->drvname, - sizeof(bus_device_info_ptr->drvname), - "%s", (drv_name) ? drv_name : "unknownDriver"); - snprintf(bus_device_info_ptr->infostrs, - sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s", - (ver) ? ver : "unknownVer", - (ver_tag) ? ver_tag : "unknownVerTag", - TARGET_HOSTNAME); -} - -#endif diff --git a/drivers/staging/unisys/include/version.h b/drivers/staging/unisys/include/version.h deleted file mode 100644 index 83d1da7a2f81..000000000000 --- a/drivers/staging/unisys/include/version.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* version.h */ - -/* Common version/release info needed by all components goes here. - * (This file must compile cleanly in all environments.) - * Ultimately, this will be combined with defines generated dynamically as - * part of the sysgen, and some of the defines below may in fact end up - * being replaced with dynamically generated ones. - */ -#ifndef __VERSION_H__ -#define __VERSION_H__ - -#define SPARVER1 "1" -#define SPARVER2 "0" -#define SPARVER3 "0" -#define SPARVER4 "0" - -#define VERSION SPARVER1 "." SPARVER2 "." SPARVER3 "." SPARVER4 - -/* Here are various version forms needed in Windows environments. - */ -#define VISOR_PRODUCTVERSION SPARVERCOMMA -#define VISOR_PRODUCTVERSION_STR SPARVER1 "." SPARVER2 "." SPARVER3 "." \ - SPARVER4 -#define VISOR_OBJECTVERSION_STR SPARVER1 "," SPARVER2 "," SPARVER3 "," \ - SPARVER4 - -#define COPYRIGHT "Unisys Corporation" -#define COPYRIGHTDATE "2010 - 2013" - -#endif diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 9baf1ec70d01..677627c72c4c 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -34,8 +34,9 @@ #include #include #include +#include +#include -#include "periodic_work.h" #include "channel.h" struct visor_driver; @@ -65,8 +66,6 @@ struct visor_channeltype_descriptor { * struct visor_driver - Information provided by each visor driver when it * registers with the visorbus driver. * @name: Name of the visor driver. - * @version: The numbered version of the driver (x.x.xxx). - * @vertag: A human readable version string. * @owner: The module owner. * @channel_types: Types of channels handled by this driver, ending with * a zero GUID. Our specialized BUS.match() method knows @@ -93,12 +92,9 @@ struct visor_channeltype_descriptor { * @resume: Behaves similar to pause. * @driver: Private reference to the device driver. For use by bus * driver only. - * @version_attr: Private version field. For use by bus driver only. */ struct visor_driver { const char *name; - const char *version; - const char *vertag; struct module *owner; struct visor_channeltype_descriptor *channel_types; int (*probe)(struct visor_device *dev); @@ -111,7 +107,6 @@ struct visor_driver { /* These fields are for private use by the bus driver only. */ struct device_driver driver; - struct driver_attribute version_attr; }; #define to_visor_driver(x) ((x) ? \ @@ -120,33 +115,33 @@ struct visor_driver { /** * struct visor_device - A device type for things "plugged" into the visorbus * bus - * visorchannel: Points to the channel that the device is + * @visorchannel: Points to the channel that the device is * associated with. - * channel_type_guid: Identifies the channel type to the bus driver. - * device: Device struct meant for use by the bus driver + * @channel_type_guid: Identifies the channel type to the bus driver. + * @device: Device struct meant for use by the bus driver * only. - * list_all: Used by the bus driver to enumerate devices. - * periodic_work: Device work queue. Private use by bus driver - * only. - * being_removed: Indicates that the device is being removed from + * @list_all: Used by the bus driver to enumerate devices. + * @timer: Timer fired periodically to do interrupt-type + * activity. + * @being_removed: Indicates that the device is being removed from * the bus. Private bus driver use only. - * visordriver_callback_lock: Used by the bus driver to lock when handling + * @visordriver_callback_lock: Used by the bus driver to lock when handling * channel events. - * pausing: Indicates that a change towards a paused state. + * @pausing: Indicates that a change towards a paused state. * is in progress. Only modified by the bus driver. - * resuming: Indicates that a change towards a running state + * @resuming: Indicates that a change towards a running state * is in progress. Only modified by the bus driver. - * chipset_bus_no: Private field used by the bus driver. - * chipset_dev_no: Private field used the bus driver. - * state: Used to indicate the current state of the + * @chipset_bus_no: Private field used by the bus driver. + * @chipset_dev_no: Private field used the bus driver. + * @state: Used to indicate the current state of the * device. - * inst: Unique GUID for this instance of the device. - * name: Name of the device. - * pending_msg_hdr: For private use by bus driver to respond to + * @inst: Unique GUID for this instance of the device. + * @name: Name of the device. + * @pending_msg_hdr: For private use by bus driver to respond to * hypervisor requests. - * vbus_hdr_info: A pointer to header info. Private use by bus + * @vbus_hdr_info: A pointer to header info. Private use by bus * driver. - * partition_uuid: Indicates client partion id. This should be the + * @partition_uuid: Indicates client partion id. This should be the * same across all visor_devices in the current * guest. Private use by bus driver only. */ @@ -157,9 +152,10 @@ struct visor_device { /* These fields are for private use by the bus driver only. */ struct device device; struct list_head list_all; - struct periodic_work *periodic_work; + struct timer_list timer; + bool timer_active; bool being_removed; - struct semaphore visordriver_callback_lock; + struct mutex visordriver_callback_lock; bool pausing; bool resuming; u32 chipset_bus_no; @@ -174,7 +170,6 @@ struct visor_device { #define to_visor_device(x) container_of(x, struct visor_device, device) -#ifndef STANDALONE_CLIENT int visorbus_register_visor_driver(struct visor_driver *); void visorbus_unregister_visor_driver(struct visor_driver *); int visorbus_read_channel(struct visor_device *dev, @@ -183,50 +178,34 @@ int visorbus_read_channel(struct visor_device *dev, int visorbus_write_channel(struct visor_device *dev, unsigned long offset, void *src, unsigned long nbytes); -int visorbus_clear_channel(struct visor_device *dev, - unsigned long offset, u8 ch, unsigned long nbytes); void visorbus_enable_channel_interrupts(struct visor_device *dev); void visorbus_disable_channel_interrupts(struct visor_device *dev); -#endif -/* Note that for visorchannel_create() - * and arguments may be 0 if we are a channel CLIENT. - * In this case, the values can simply be read from the channel header. +/* Levels of severity for diagnostic events, in order from lowest severity to + * highest (i.e. fatal errors are the most severe, and should always be logged, + * but info events rarely need to be logged except during debugging). The + * values DIAG_SEVERITY_ENUM_BEGIN and DIAG_SEVERITY_ENUM_END are not valid + * severity values. They exist merely to dilineate the list, so that future + * additions won't require changes to the driver (i.e. when checking for + * out-of-range severities in SetSeverity). The values DIAG_SEVERITY_OVERRIDE + * and DIAG_SEVERITY_SHUTOFF are not valid severity values for logging events + * but they are valid for controlling the amount of event data. Changes made + * to the enum, need to be reflected in s-Par. */ -struct visorchannel *visorchannel_create(u64 physaddr, - unsigned long channel_bytes, - gfp_t gfp, uuid_le guid); -struct visorchannel *visorchannel_create_with_lock(u64 physaddr, - unsigned long channel_bytes, - gfp_t gfp, uuid_le guid); -void visorchannel_destroy(struct visorchannel *channel); -int visorchannel_read(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes); -int visorchannel_write(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes); -int visorchannel_clear(struct visorchannel *channel, ulong offset, - u8 ch, ulong nbytes); -bool visorchannel_signalremove(struct visorchannel *channel, u32 queue, - void *msg); -bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue, - void *msg); -bool visorchannel_signalempty(struct visorchannel *channel, u32 queue); +enum diag_severity { + DIAG_SEVERITY_VERBOSE = 0, + DIAG_SEVERITY_INFO = 1, + DIAG_SEVERITY_WARNING = 2, + DIAG_SEVERITY_ERR = 3, + DIAG_SEVERITY_PRINT = 4, +}; -int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, - u32 queue); -int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); -u64 visorchannel_get_physaddr(struct visorchannel *channel); -ulong visorchannel_get_nbytes(struct visorchannel *channel); -char *visorchannel_id(struct visorchannel *channel, char *s); -char *visorchannel_zoneid(struct visorchannel *channel, char *s); -u64 visorchannel_get_clientpartition(struct visorchannel *channel); -int visorchannel_set_clientpartition(struct visorchannel *channel, - u64 partition_handle); +int visorchannel_signalremove(struct visorchannel *channel, u32 queue, + void *msg); +int visorchannel_signalinsert(struct visorchannel *channel, u32 queue, + void *msg); +bool visorchannel_signalempty(struct visorchannel *channel, u32 queue); uuid_le visorchannel_get_uuid(struct visorchannel *channel); -char *visorchannel_uuid_id(uuid_le *guid, char *s); -void visorchannel_debug(struct visorchannel *channel, int num_queues, - struct seq_file *seq, u32 off); -void __iomem *visorchannel_get_header(struct visorchannel *channel); #define BUS_ROOT_DEVICE UINT_MAX struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, diff --git a/drivers/staging/unisys/visorbus/Makefile b/drivers/staging/unisys/visorbus/Makefile index fc790e7592fc..f3730d8c953e 100644 --- a/drivers/staging/unisys/visorbus/Makefile +++ b/drivers/staging/unisys/visorbus/Makefile @@ -7,6 +7,5 @@ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus.o visorbus-y := visorbus_main.o visorbus-y += visorchannel.o visorbus-y += visorchipset.o -visorbus-y += periodic_work.o ccflags-y += -Idrivers/staging/unisys/include diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index 03e36fb6a5a0..f0bfc4ded892 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -482,4 +482,80 @@ struct spar_controlvm_parameters_header { u32 reserved; /* Natural alignment */ }; +/* General Errors------------------------------------------------------[0-99] */ +#define CONTROLVM_RESP_SUCCESS 0 +#define CONTROLVM_RESP_ERROR_ALREADY_DONE 1 +#define CONTROLVM_RESP_ERROR_IOREMAP_FAILED 2 +#define CONTROLVM_RESP_ERROR_KMALLOC_FAILED 3 +#define CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN 4 +#define CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT 5 + +/* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */ +#define CONTROLVM_RESP_ERROR_CLIENT_SWITCHCOUNT_NONZERO 100 +#define CONTROLVM_RESP_ERROR_EXPECTED_CHIPSET_INIT 101 + +/* Maximum Limit----------------------------------------------------[200-299] */ +#define CONTROLVM_RESP_ERROR_MAX_BUSES 201 /* BUS_CREATE */ +#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 /* DEVICE_CREATE */ +/* Payload and Parameter Related------------------------------------[400-499] */ +#define CONTROLVM_RESP_ERROR_PAYLOAD_INVALID 400 /* SWITCH_ATTACHEXTPORT, + * DEVICE_CONFIGURE + */ +#define CONTROLVM_RESP_ERROR_INITIATOR_PARAMETER_INVALID 401 /* Multiple */ +#define CONTROLVM_RESP_ERROR_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */ +#define CONTROLVM_RESP_ERROR_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */ +/* Specified[Packet Structure] Value-------------------------------[500-599] */ +#define CONTROLVM_RESP_ERROR_BUS_INVALID 500 /* SWITCH_ATTACHINTPORT, + * BUS_CONFIGURE, + * DEVICE_CREATE, + * DEVICE_CONFIG + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_ERROR_DEVICE_INVALID 501 /* SWITCH_ATTACHINTPORT */ + /* DEVICE_CREATE, + * DEVICE_CONFIGURE, + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_ERROR_CHANNEL_INVALID 502 /* DEVICE_CREATE, + * DEVICE_CONFIGURE + */ +/* Partition Driver Callback Interface----------------------[600-699] */ +#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE 604 /* BUS_CREATE, + * BUS_DESTROY, + * DEVICE_CREATE, + * DEVICE_DESTROY + */ +/* Unable to invoke VIRTPCI callback */ +#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR 605 + /* BUS_CREATE, + * BUS_DESTROY, + * DEVICE_CREATE, + * DEVICE_DESTROY + */ +/* VIRTPCI Callback returned error */ +#define CONTROLVM_RESP_ERROR_GENERIC_DRIVER_CALLBACK_ERROR 606 + /* SWITCH_ATTACHEXTPORT, + * SWITCH_DETACHEXTPORT + * DEVICE_CONFIGURE + */ + +/* generic device callback returned error */ +/* Bus Related------------------------------------------------------[700-799] */ +#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 /* BUS_DESTROY */ +/* Channel Related--------------------------------------------------[800-899] */ +#define CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN 800 /* GET_CHANNELINFO, + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL 801 /* DEVICE_CREATE */ +/* Chipset Shutdown Related---------------------------------------[1000-1099] */ +#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_FAILED 1000 +#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001 + +/* Chipset Stop Related-------------------------------------------[1100-1199] */ +#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS 1100 +#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_SWITCH 1101 + +/* Device Related-------------------------------------------------[1400-1499] */ +#define CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT 1400 + #endif /* __CONTROLVMCHANNEL_H__ */ diff --git a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h b/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h deleted file mode 100644 index 23ad0ea6c9fc..000000000000 --- a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h +++ /dev/null @@ -1,101 +0,0 @@ -/* controlvmcompletionstatus.c - * - * Copyright (C) 2010 - 2015 UNISYS CORPORATION - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* Defines for all valid values returned in the response message header - * completionStatus field. See controlvmchannel.h for description of - * the header: _CONTROLVM_MESSAGE_HEADER. - */ - -#ifndef __CONTROLVMCOMPLETIONSTATUS_H__ -#define __CONTROLVMCOMPLETIONSTATUS_H__ - -/* General Errors------------------------------------------------------[0-99] */ -#define CONTROLVM_RESP_SUCCESS 0 -#define CONTROLVM_RESP_ERROR_ALREADY_DONE 1 -#define CONTROLVM_RESP_ERROR_IOREMAP_FAILED 2 -#define CONTROLVM_RESP_ERROR_KMALLOC_FAILED 3 -#define CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN 4 -#define CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT 5 - -/* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */ -#define CONTROLVM_RESP_ERROR_CLIENT_SWITCHCOUNT_NONZERO 100 -#define CONTROLVM_RESP_ERROR_EXPECTED_CHIPSET_INIT 101 - -/* Maximum Limit----------------------------------------------------[200-299] */ -#define CONTROLVM_RESP_ERROR_MAX_BUSES 201 /* BUS_CREATE */ -#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 /* DEVICE_CREATE */ -/* Payload and Parameter Related------------------------------------[400-499] */ -#define CONTROLVM_RESP_ERROR_PAYLOAD_INVALID 400 /* SWITCH_ATTACHEXTPORT, - * DEVICE_CONFIGURE - */ -#define CONTROLVM_RESP_ERROR_INITIATOR_PARAMETER_INVALID 401 /* Multiple */ -#define CONTROLVM_RESP_ERROR_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */ -#define CONTROLVM_RESP_ERROR_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */ -/* Specified[Packet Structure] Value-------------------------------[500-599] */ -#define CONTROLVM_RESP_ERROR_BUS_INVALID 500 /* SWITCH_ATTACHINTPORT, - * BUS_CONFIGURE, - * DEVICE_CREATE, - * DEVICE_CONFIG - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_ERROR_DEVICE_INVALID 501 /* SWITCH_ATTACHINTPORT */ - /* DEVICE_CREATE, - * DEVICE_CONFIGURE, - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_ERROR_CHANNEL_INVALID 502 /* DEVICE_CREATE, - * DEVICE_CONFIGURE - */ -/* Partition Driver Callback Interface----------------------[600-699] */ -#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE 604 /* BUS_CREATE, - * BUS_DESTROY, - * DEVICE_CREATE, - * DEVICE_DESTROY - */ -/* Unable to invoke VIRTPCI callback */ -#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR 605 - /* BUS_CREATE, - * BUS_DESTROY, - * DEVICE_CREATE, - * DEVICE_DESTROY - */ -/* VIRTPCI Callback returned error */ -#define CONTROLVM_RESP_ERROR_GENERIC_DRIVER_CALLBACK_ERROR 606 - /* SWITCH_ATTACHEXTPORT, - * SWITCH_DETACHEXTPORT - * DEVICE_CONFIGURE - */ - -/* generic device callback returned error */ -/* Bus Related------------------------------------------------------[700-799] */ -#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 /* BUS_DESTROY */ -/* Channel Related--------------------------------------------------[800-899] */ -#define CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN 800 /* GET_CHANNELINFO, - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL 801 /* DEVICE_CREATE */ -/* Chipset Shutdown Related---------------------------------------[1000-1099] */ -#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_FAILED 1000 -#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001 - -/* Chipset Stop Related-------------------------------------------[1100-1199] */ -#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS 1100 -#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_SWITCH 1101 - -/* Device Related-------------------------------------------------[1400-1499] */ -#define CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT 1400 - -#endif /* __CONTROLVMCOMPLETIONSTATUS_H__ not defined */ diff --git a/drivers/staging/unisys/visorbus/iovmcall_gnuc.h b/drivers/staging/unisys/visorbus/iovmcall_gnuc.h deleted file mode 100644 index 98ea7f381a3c..000000000000 --- a/drivers/staging/unisys/visorbus/iovmcall_gnuc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2010 - 2015 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* Linux GCC Version (32-bit and 64-bit) */ -static inline unsigned long -__unisys_vmcall_gnuc(unsigned long tuple, unsigned long reg_ebx, - unsigned long reg_ecx) -{ - unsigned long result = 0; - unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; - - cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); - if (!(cpuid_ecx & 0x80000000)) - return -EPERM; - - __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : - "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); - return result; -} - -static inline unsigned long -__unisys_extended_vmcall_gnuc(unsigned long long tuple, - unsigned long long reg_ebx, - unsigned long long reg_ecx, - unsigned long long reg_edx) -{ - unsigned long result = 0; - unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; - - cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); - if (!(cpuid_ecx & 0x80000000)) - return -EPERM; - - __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : - "a"(tuple), "b"(reg_ebx), "c"(reg_ecx), "d"(reg_edx)); - return result; -} diff --git a/drivers/staging/unisys/visorbus/periodic_work.c b/drivers/staging/unisys/visorbus/periodic_work.c deleted file mode 100644 index 00b152764f84..000000000000 --- a/drivers/staging/unisys/visorbus/periodic_work.c +++ /dev/null @@ -1,204 +0,0 @@ -/* periodic_work.c - * - * Copyright (C) 2010 - 2015 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * Helper functions to schedule periodic work in Linux kernel mode. - */ -#include - -#include "periodic_work.h" - -#define MYDRVNAME "periodic_work" - -struct periodic_work { - rwlock_t lock; - struct delayed_work work; - void (*workfunc)(void *); - void *workfuncarg; - bool is_scheduled; - bool want_to_stop; - ulong jiffy_interval; - struct workqueue_struct *workqueue; - const char *devnam; -}; - -static void periodic_work_func(struct work_struct *work) -{ - struct periodic_work *pw; - - pw = container_of(work, struct periodic_work, work.work); - (*pw->workfunc)(pw->workfuncarg); -} - -struct periodic_work -*visor_periodic_work_create(ulong jiffy_interval, - struct workqueue_struct *workqueue, - void (*workfunc)(void *), - void *workfuncarg, - const char *devnam) -{ - struct periodic_work *pw; - - pw = kzalloc(sizeof(*pw), GFP_KERNEL | __GFP_NORETRY); - if (!pw) - return NULL; - - rwlock_init(&pw->lock); - pw->jiffy_interval = jiffy_interval; - pw->workqueue = workqueue; - pw->workfunc = workfunc; - pw->workfuncarg = workfuncarg; - pw->devnam = devnam; - return pw; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_create); - -void visor_periodic_work_destroy(struct periodic_work *pw) -{ - kfree(pw); -} -EXPORT_SYMBOL_GPL(visor_periodic_work_destroy); - -/** Call this from your periodic work worker function to schedule the next - * call. - * If this function returns false, there was a failure and the - * periodic work is no longer scheduled - */ -bool visor_periodic_work_nextperiod(struct periodic_work *pw) -{ - bool rc = false; - - write_lock(&pw->lock); - if (pw->want_to_stop) { - pw->is_scheduled = false; - pw->want_to_stop = false; - rc = true; /* yes, true; see visor_periodic_work_stop() */ - goto unlock; - } else if (!queue_delayed_work(pw->workqueue, &pw->work, - pw->jiffy_interval)) { - pw->is_scheduled = false; - rc = false; - goto unlock; - } - rc = true; -unlock: - write_unlock(&pw->lock); - return rc; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_nextperiod); - -/** This function returns true iff new periodic work was actually started. - * If this function returns false, then no work was started - * (either because it was already started, or because of a failure). - */ -bool visor_periodic_work_start(struct periodic_work *pw) -{ - bool rc = false; - - write_lock(&pw->lock); - if (pw->is_scheduled) { - rc = false; - goto unlock; - } - if (pw->want_to_stop) { - rc = false; - goto unlock; - } - INIT_DELAYED_WORK(&pw->work, &periodic_work_func); - if (!queue_delayed_work(pw->workqueue, &pw->work, - pw->jiffy_interval)) { - rc = false; - goto unlock; - } - pw->is_scheduled = true; - rc = true; -unlock: - write_unlock(&pw->lock); - return rc; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_start); - -/** This function returns true iff your call actually stopped the periodic - * work. - * - * -- PAY ATTENTION... this is important -- - * - * NO NO #1 - * - * Do NOT call this function from some function that is running on the - * same workqueue as the work you are trying to stop might be running - * on! If you violate this rule, visor_periodic_work_stop() MIGHT work, - * but it also MIGHT get hung up in an infinite loop saying - * "waiting for delayed work...". This will happen if the delayed work - * you are trying to cancel has been put in the workqueue list, but can't - * run yet because we are running that same workqueue thread right now. - * - * Bottom line: If you need to call visor_periodic_work_stop() from a - * workitem, be sure the workitem is on a DIFFERENT workqueue than the - * workitem that you are trying to cancel. - * - * If I could figure out some way to check for this "no no" condition in - * the code, I would. It would have saved me the trouble of writing this - * long comment. And also, don't think this is some "theoretical" race - * condition. It is REAL, as I have spent the day chasing it. - * - * NO NO #2 - * - * Take close note of the locks that you own when you call this function. - * You must NOT own any locks that are needed by the periodic work - * function that is currently installed. If you DO, a deadlock may result, - * because stopping the periodic work often involves waiting for the last - * iteration of the periodic work function to complete. Again, if you hit - * this deadlock, you will get hung up in an infinite loop saying - * "waiting for delayed work...". - */ -bool visor_periodic_work_stop(struct periodic_work *pw) -{ - bool stopped_something = false; - - write_lock(&pw->lock); - stopped_something = pw->is_scheduled && (!pw->want_to_stop); - while (pw->is_scheduled) { - pw->want_to_stop = true; - if (cancel_delayed_work(&pw->work)) { - /* We get here if the delayed work was pending as - * delayed work, but was NOT run. - */ - WARN_ON(!pw->is_scheduled); - pw->is_scheduled = false; - } else { - /* If we get here, either the delayed work: - * - was run, OR, - * - is running RIGHT NOW on another processor, OR, - * - wasn't even scheduled (there is a miniscule - * timing window where this could be the case) - * flush_workqueue() would make sure it is finished - * executing, but that still isn't very useful, which - * explains the loop... - */ - } - if (pw->is_scheduled) { - write_unlock(&pw->lock); - schedule_timeout_interruptible(msecs_to_jiffies(10)); - write_lock(&pw->lock); - } else { - pw->want_to_stop = false; - } - } - write_unlock(&pw->lock); - return stopped_something; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_stop); diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index 90fa12e62f26..e97917522f6a 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -23,7 +23,6 @@ * the client devices and client drivers for the server end to see. */ #include -#include "vbusdeviceinfo.h" #include "channel.h" /* {193b331b-c58f-11da-95a9-00e08161165f} */ @@ -58,6 +57,216 @@ static const uuid_le spar_vbus_channel_protocol_uuid = actual_bytes)) #pragma pack(push, 1) /* both GCC and VC now allow this pragma */ + +/* + * An array of this struct is present in the channel area for each vbus. + * (See vbuschannel.h.) + * It is filled in by the client side to provide info about the device + * and driver from the client's perspective. + */ +struct ultra_vbus_deviceinfo { + u8 devtype[16]; /* short string identifying the device type */ + u8 drvname[16]; /* driver .sys file name */ + u8 infostrs[96]; /* kernel version */ + u8 reserved[128]; /* pad size to 256 bytes */ +}; + +/** + * vbuschannel_sanitize_buffer() - remove non-printable chars from buffer + * @p: destination buffer where chars are written to + * @remain: number of bytes that can be written starting at #p + * @src: pointer to source buffer + * @srcmax: number of valid characters at #src + * + * Reads chars from the buffer at @src for @srcmax bytes, and writes to + * the buffer at @p, which is @remain bytes long, ensuring never to + * overflow the buffer at @p, using the following rules: + * - printable characters are simply copied from the buffer at @src to the + * buffer at @p + * - intervening streaks of non-printable characters in the buffer at @src + * are replaced with a single space in the buffer at @p + * Note that we pay no attention to '\0'-termination. + * + * Pass @p == NULL and @remain == 0 for this special behavior -- In this + * case, we simply return the number of bytes that WOULD HAVE been written + * to a buffer at @p, had it been infinitely big. + * + * Return: the number of bytes written to @p (or WOULD HAVE been written to + * @p, as described in the previous paragraph) + */ +static inline int +vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) +{ + int chars = 0; + int nonprintable_streak = 0; + + while (srcmax > 0) { + if ((*src >= ' ') && (*src < 0x7f)) { + if (nonprintable_streak) { + if (remain > 0) { + *p = ' '; + p++; + remain--; + chars++; + } else if (!p) { + chars++; + } + nonprintable_streak = 0; + } + if (remain > 0) { + *p = *src; + p++; + remain--; + chars++; + } else if (!p) { + chars++; + } + } else { + nonprintable_streak = 1; + } + src++; + srcmax--; + } + return chars; +} + +#define VBUSCHANNEL_ADDACHAR(ch, p, remain, chars) \ + do { \ + if (remain <= 0) \ + break; \ + *p = ch; \ + p++; chars++; remain--; \ + } while (0) + +/** + * vbuschannel_itoa() - convert non-negative int to string + * @p: destination string + * @remain: max number of bytes that can be written to @p + * @num: input int to convert + * + * Converts the non-negative value at @num to an ascii decimal string + * at @p, writing at most @remain bytes. Note there is NO '\0' termination + * written to @p. + * + * Return: number of bytes written to @p + * + */ +static inline int +vbuschannel_itoa(char *p, int remain, int num) +{ + int digits = 0; + char s[32]; + int i; + + if (num == 0) { + /* '0' is a special case */ + if (remain <= 0) + return 0; + *p = '0'; + return 1; + } + /* form a backwards decimal ascii string in */ + while (num > 0) { + if (digits >= (int)sizeof(s)) + return 0; + s[digits++] = (num % 10) + '0'; + num = num / 10; + } + if (remain < digits) { + /* not enough room left at

to hold number, so fill with + * '?' + */ + for (i = 0; i < remain; i++, p++) + *p = '?'; + return remain; + } + /* plug in the decimal ascii string representing the number, by */ + /* reversing the string we just built in */ + i = digits; + while (i > 0) { + i--; + *p = s[i]; + p++; + } + return digits; +} + +/** + * vbuschannel_devinfo_to_string() - format a struct ultra_vbus_deviceinfo + * to a printable string + * @devinfo: the struct ultra_vbus_deviceinfo to format + * @p: destination string area + * @remain: size of destination string area in bytes + * @devix: the device index to be included in the output data, or -1 if no + * device index is to be included + * + * Reads @devInfo, and converts its contents to a printable string at @p, + * writing at most @remain bytes. Note there is NO '\0' termination + * written to @p. + * + * Return: number of bytes written to @p + */ +static inline int +vbuschannel_devinfo_to_string(struct ultra_vbus_deviceinfo *devinfo, + char *p, int remain, int devix) +{ + char *psrc; + int nsrc, x, i, pad; + int chars = 0; + + psrc = &devinfo->devtype[0]; + nsrc = sizeof(devinfo->devtype); + if (vbuschannel_sanitize_buffer(NULL, 0, psrc, nsrc) <= 0) + return 0; + + /* emit device index */ + if (devix >= 0) { + VBUSCHANNEL_ADDACHAR('[', p, remain, chars); + x = vbuschannel_itoa(p, remain, devix); + p += x; + remain -= x; + chars += x; + VBUSCHANNEL_ADDACHAR(']', p, remain, chars); + } else { + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + } + + /* emit device type */ + x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); + p += x; + remain -= x; + chars += x; + pad = 15 - x; /* pad device type to be exactly 15 chars */ + for (i = 0; i < pad; i++) + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + + /* emit driver name */ + psrc = &devinfo->drvname[0]; + nsrc = sizeof(devinfo->drvname); + x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); + p += x; + remain -= x; + chars += x; + pad = 15 - x; /* pad driver name to be exactly 15 chars */ + for (i = 0; i < pad; i++) + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + + /* emit strings */ + psrc = &devinfo->infostrs[0]; + nsrc = sizeof(devinfo->infostrs); + x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); + p += x; + remain -= x; + chars += x; + VBUSCHANNEL_ADDACHAR('\n', p, remain, chars); + + return chars; +} + struct spar_vbus_headerinfo { u32 struct_bytes; /* size of this struct in bytes */ u32 device_info_struct_bytes; /* sizeof(ULTRA_VBUS_DEVICEINFO) */ diff --git a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h deleted file mode 100644 index abdab4ad0b36..000000000000 --- a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (C) 2010 - 2015 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VBUSDEVICEINFO_H__ -#define __VBUSDEVICEINFO_H__ - -#include - -#pragma pack(push, 1) /* both GCC and VC now allow this pragma */ - -/* An array of this struct is present in the channel area for each vbus. - * (See vbuschannel.h.) - * It is filled in by the client side to provide info about the device - * and driver from the client's perspective. - */ -struct ultra_vbus_deviceinfo { - u8 devtype[16]; /* short string identifying the device type */ - u8 drvname[16]; /* driver .sys file name */ - u8 infostrs[96]; /* sequence of tab-delimited id strings: */ - /* */ - u8 reserved[128]; /* pad size to 256 bytes */ -}; - -#pragma pack(pop) - -/* Reads chars from the buffer at for bytes, and writes to - * the buffer at

, which is bytes long, ensuring never to - * overflow the buffer at

, using the following rules: - * - printable characters are simply copied from the buffer at to the - * buffer at

- * - intervening streaks of non-printable characters in the buffer at - * are replaced with a single space in the buffer at

- * Note that we pay no attention to '\0'-termination. - * Returns the number of bytes written to

. - * - * Pass

== NULL and == 0 for this special behavior. In this - * case, we simply return the number of bytes that WOULD HAVE been written - * to a buffer at

, had it been infinitely big. - */ -static inline int -vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) -{ - int chars = 0; - int nonprintable_streak = 0; - - while (srcmax > 0) { - if ((*src >= ' ') && (*src < 0x7f)) { - if (nonprintable_streak) { - if (remain > 0) { - *p = ' '; - p++; - remain--; - chars++; - } else if (!p) { - chars++; - } - nonprintable_streak = 0; - } - if (remain > 0) { - *p = *src; - p++; - remain--; - chars++; - } else if (!p) { - chars++; - } - } else { - nonprintable_streak = 1; - } - src++; - srcmax--; - } - return chars; -} - -#define VBUSCHANNEL_ADDACHAR(ch, p, remain, chars) \ - do { \ - if (remain <= 0) \ - break; \ - *p = ch; \ - p++; chars++; remain--; \ - } while (0) - -/* Converts the non-negative value at to an ascii decimal string - * at

, writing at most bytes. Note there is NO '\0' termination - * written to

. - * - * Returns the number of bytes written to

. - * - * Note that we create this function because we need to do this operation in - * an environment-independent way (since we are in a common header file). - */ -static inline int -vbuschannel_itoa(char *p, int remain, int num) -{ - int digits = 0; - char s[32]; - int i; - - if (num == 0) { - /* '0' is a special case */ - if (remain <= 0) - return 0; - *p = '0'; - return 1; - } - /* form a backwards decimal ascii string in */ - while (num > 0) { - if (digits >= (int)sizeof(s)) - return 0; - s[digits++] = (num % 10) + '0'; - num = num / 10; - } - if (remain < digits) { - /* not enough room left at

to hold number, so fill with - * '?' - */ - for (i = 0; i < remain; i++, p++) - *p = '?'; - return remain; - } - /* plug in the decimal ascii string representing the number, by */ - /* reversing the string we just built in */ - i = digits; - while (i > 0) { - i--; - *p = s[i]; - p++; - } - return digits; -} - -/* Reads , and converts its contents to a printable string at

, - * writing at most bytes. Note there is NO '\0' termination - * written to

. - * - * Pass >= 0 if you want a device index presented. - * - * Returns the number of bytes written to

. - */ -static inline int -vbuschannel_devinfo_to_string(struct ultra_vbus_deviceinfo *devinfo, - char *p, int remain, int devix) -{ - char *psrc; - int nsrc, x, i, pad; - int chars = 0; - - psrc = &devinfo->devtype[0]; - nsrc = sizeof(devinfo->devtype); - if (vbuschannel_sanitize_buffer(NULL, 0, psrc, nsrc) <= 0) - return 0; - - /* emit device index */ - if (devix >= 0) { - VBUSCHANNEL_ADDACHAR('[', p, remain, chars); - x = vbuschannel_itoa(p, remain, devix); - p += x; - remain -= x; - chars += x; - VBUSCHANNEL_ADDACHAR(']', p, remain, chars); - } else { - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - } - - /* emit device type */ - x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); - p += x; - remain -= x; - chars += x; - pad = 15 - x; /* pad device type to be exactly 15 chars */ - for (i = 0; i < pad; i++) - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - - /* emit driver name */ - psrc = &devinfo->drvname[0]; - nsrc = sizeof(devinfo->drvname); - x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); - p += x; - remain -= x; - chars += x; - pad = 15 - x; /* pad driver name to be exactly 15 chars */ - for (i = 0; i < pad; i++) - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - - /* emit strings */ - psrc = &devinfo->infostrs[0]; - nsrc = sizeof(devinfo->infostrs); - x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); - p += x; - remain -= x; - chars += x; - VBUSCHANNEL_ADDACHAR('\n', p, remain, chars); - - return chars; -} - -#endif diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index d32b8980a1cf..fec0a54916fe 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -18,62 +18,22 @@ #include "visorbus.h" #include "visorbus_private.h" -#include "version.h" -#include "periodic_work.h" -#include "vbuschannel.h" -#include "guestlinuxdebug.h" #include "vmcallinterface.h" #define MYDRVNAME "visorbus" /* module parameters */ -static int visorbus_debug; static int visorbus_forcematch; static int visorbus_forcenomatch; -static int visorbus_debugref; -#define SERIALLOOPBACKCHANADDR (100 * 1024 * 1024) /* Display string that is guaranteed to be no longer the 99 characters*/ #define LINESIZE 99 #define CURRENT_FILE_PC VISOR_BUS_PC_visorbus_main_c -#define POLLJIFFIES_TESTWORK 100 #define POLLJIFFIES_NORMALCHANNEL 10 static int busreg_rc = -ENODEV; /* stores the result from bus registration */ -static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env); -static int visorbus_match(struct device *xdev, struct device_driver *xdrv); -static void fix_vbus_dev_info(struct visor_device *visordev); - -/* BUS type attributes - * - * define & implement display of bus attributes under - * /sys/bus/visorbus. - * - */ - -static ssize_t version_show(struct bus_type *bus, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", VERSION); -} - -static BUS_ATTR_RO(version); - -static struct attribute *visorbus_bus_attrs[] = { - &bus_attr_version.attr, - NULL, -}; - -static const struct attribute_group visorbus_bus_group = { - .attrs = visorbus_bus_attrs, -}; - -static const struct attribute_group *visorbus_bus_groups[] = { - &visorbus_bus_group, - NULL, -}; - /* * DEVICE type attributes * @@ -106,61 +66,14 @@ static const struct attribute_group *visorbus_dev_groups[] = { NULL, }; -/** This describes the TYPE of bus. - * (Don't confuse this with an INSTANCE of the bus.) - */ -struct bus_type visorbus_type = { - .name = "visorbus", - .match = visorbus_match, - .uevent = visorbus_uevent, - .dev_groups = visorbus_dev_groups, - .bus_groups = visorbus_bus_groups, -}; - -static struct delayed_work periodic_work; - -/* YES, we need 2 workqueues. - * The reason is, workitems on the test queue may need to cancel - * workitems on the other queue. You will be in for trouble if you try to - * do this with workitems queued on the same workqueue. - */ -static struct workqueue_struct *periodic_test_workqueue; -static struct workqueue_struct *periodic_dev_workqueue; -static long long bus_count; /** number of bus instances */ - /** ever-increasing */ - -static void chipset_bus_create(struct visor_device *bus_info); -static void chipset_bus_destroy(struct visor_device *bus_info); -static void chipset_device_create(struct visor_device *dev_info); -static void chipset_device_destroy(struct visor_device *dev_info); -static void chipset_device_pause(struct visor_device *dev_info); -static void chipset_device_resume(struct visor_device *dev_info); - -/** These functions are implemented herein, and are called by the chipset - * driver to notify us about specific events. - */ -static struct visorchipset_busdev_notifiers chipset_notifiers = { - .bus_create = chipset_bus_create, - .bus_destroy = chipset_bus_destroy, - .device_create = chipset_device_create, - .device_destroy = chipset_device_destroy, - .device_pause = chipset_device_pause, - .device_resume = chipset_device_resume, -}; - -/** These functions are implemented in the chipset driver, and we call them - * herein when we want to acknowledge a specific event. - */ -static struct visorchipset_busdev_responders chipset_responders; - /* filled in with info about parent chipset driver when we register with it */ static struct ultra_vbus_deviceinfo chipset_driverinfo; /* filled in with info about this driver, wrt it servicing client busses */ static struct ultra_vbus_deviceinfo clientbus_driverinfo; -/** list of visor_device structs, linked via .list_all */ +/* list of visor_device structs, linked via .list_all */ static LIST_HEAD(list_all_bus_instances); -/** list of visor_device structs, linked via .list_all */ +/* list of visor_device structs, linked via .list_all */ static LIST_HEAD(list_all_device_instances); static int @@ -177,9 +90,14 @@ visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env) return 0; } -/* This is called automatically upon adding a visor_device (device_add), or - * adding a visor_driver (visorbus_register_visor_driver), and returns 1 iff the - * provided driver can control the specified device. +/** + * visorbus_match() - called automatically upon adding a visor_device + * (device_add), or adding a visor_driver + * (visorbus_register_visor_driver) + * @xdev: struct device for the device being matched + * @xdrv: struct device_driver for driver to match device against + * + * Return: 1 iff the provided driver can control the specified device */ static int visorbus_match(struct device *xdev, struct device_driver *xdrv) @@ -211,9 +129,22 @@ visorbus_match(struct device *xdev, struct device_driver *xdrv) return 0; } -/** This is called when device_unregister() is called for the bus device - * instance, after all other tasks involved with destroying the device - * are complete. +/* + * This describes the TYPE of bus. + * (Don't confuse this with an INSTANCE of the bus.) + */ +struct bus_type visorbus_type = { + .name = "visorbus", + .match = visorbus_match, + .uevent = visorbus_uevent, + .dev_groups = visorbus_dev_groups, +}; + +/** + * visorbus_releae_busdevice() - called when device_unregister() is called for + * the bus device instance, after all other tasks + * involved with destroying the dev are complete + * @xdev: struct device for the bus being released */ static void visorbus_release_busdevice(struct device *xdev) @@ -223,18 +154,16 @@ visorbus_release_busdevice(struct device *xdev) kfree(dev); } -/** This is called when device_unregister() is called for each child - * device instance. +/** + * visorbus_release_device() - called when device_unregister() is called for + * each child device instance + * @xdev: struct device for the visor device being released */ static void visorbus_release_device(struct device *xdev) { struct visor_device *dev = to_visor_device(xdev); - if (dev->periodic_work) { - visor_periodic_work_destroy(dev->periodic_work); - dev->periodic_work = NULL; - } if (dev->visorchannel) { visorchannel_destroy(dev->visorchannel); dev->visorchannel = NULL; @@ -242,9 +171,11 @@ visorbus_release_device(struct device *xdev) kfree(dev); } -/* begin implementation of specific channel attributes to appear under -* /sys/bus/visorbus/dev/channel -*/ +/* + * begin implementation of specific channel attributes to appear under + * /sys/bus/visorbus/dev/channel + */ + static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -349,15 +280,11 @@ static const struct attribute_group *visorbus_channel_groups[] = { /* end implementation of specific channel attributes */ -/* BUS instance attributes +/* + * BUS instance attributes * * define & implement display of bus attributes under - * /sys/bus/visorbus/busses/visorbus. - * - * This is a bit hoaky because the kernel does not yet have the infrastructure - * to separate bus INSTANCE attributes from bus TYPE attributes... - * so we roll our own. See businst.c / businst.h. - * + * /sys/bus/visorbus/devices/visorbus. */ static ssize_t partition_handle_show(struct device *dev, @@ -434,8 +361,8 @@ static ssize_t client_bus_info_show(struct device *dev, if (vdev->name) partition_name = vdev->name; shift = snprintf(pos, remain, - "Client device / client driver info for %s eartition (vbus #%d):\n", - partition_name, vdev->chipset_dev_no); + "Client device / client driver info for %s partition (vbus #%u):\n", + partition_name, vdev->chipset_bus_no); pos += shift; remain -= shift; shift = visorchannel_read(channel, @@ -508,103 +435,48 @@ static const struct attribute_group *visorbus_groups[] = { NULL }; -/* DRIVER attributes - * - * define & implement display of driver attributes under - * /sys/bus/visorbus/drivers/. - * - */ - -static ssize_t -DRIVER_ATTR_version(struct device_driver *xdrv, char *buf) -{ - struct visor_driver *drv = to_visor_driver(xdrv); - - return snprintf(buf, PAGE_SIZE, "%s\n", drv->version); -} - -static int -register_driver_attributes(struct visor_driver *drv) -{ - struct driver_attribute version = - __ATTR(version, S_IRUGO, DRIVER_ATTR_version, NULL); - drv->version_attr = version; - return driver_create_file(&drv->driver, &drv->version_attr); -} - static void -unregister_driver_attributes(struct visor_driver *drv) +dev_periodic_work(unsigned long __opaque) { - driver_remove_file(&drv->driver, &drv->version_attr); -} - -static void -dev_periodic_work(void *xdev) -{ - struct visor_device *dev = xdev; + struct visor_device *dev = (struct visor_device *)__opaque; struct visor_driver *drv = to_visor_driver(dev->device.driver); - down(&dev->visordriver_callback_lock); if (drv->channel_interrupt) drv->channel_interrupt(dev); - up(&dev->visordriver_callback_lock); - if (!visor_periodic_work_nextperiod(dev->periodic_work)) - put_device(&dev->device); + mod_timer(&dev->timer, jiffies + POLLJIFFIES_NORMALCHANNEL); } static void dev_start_periodic_work(struct visor_device *dev) { - if (dev->being_removed) + if (dev->being_removed || dev->timer_active) return; /* now up by at least 2 */ get_device(&dev->device); - if (!visor_periodic_work_start(dev->periodic_work)) - put_device(&dev->device); + dev->timer.expires = jiffies + POLLJIFFIES_NORMALCHANNEL; + add_timer(&dev->timer); + dev->timer_active = true; } static void dev_stop_periodic_work(struct visor_device *dev) { - if (visor_periodic_work_stop(dev->periodic_work)) - put_device(&dev->device); + if (!dev->timer_active) + return; + del_timer_sync(&dev->timer); + dev->timer_active = false; + put_device(&dev->device); } -/** This is called automatically upon adding a visor_device (device_add), or - * adding a visor_driver (visorbus_register_visor_driver), but only after - * visorbus_match has returned 1 to indicate a successful match between - * driver and device. - */ -static int -visordriver_probe_device(struct device *xdev) -{ - int res; - struct visor_driver *drv; - struct visor_device *dev; - - drv = to_visor_driver(xdev->driver); - dev = to_visor_device(xdev); - - if (!drv->probe) - return -ENODEV; - - down(&dev->visordriver_callback_lock); - dev->being_removed = false; - - res = drv->probe(dev); - if (res >= 0) { - /* success: reference kept via unmatched get_device() */ - get_device(&dev->device); - fix_vbus_dev_info(dev); - } - - up(&dev->visordriver_callback_lock); - return res; -} - -/** This is called when device_unregister() is called for each child device - * instance, to notify the appropriate visorbus_driver that the device is - * going away, and to decrease the reference count of the device. +/** + * visordriver_remove_device() - handle visor device going away + * @xdev: struct device for the visor device being removed + * + * This is called when device_unregister() is called for each child device + * instance, to notify the appropriate visorbus function driver that the device + * is going away, and to decrease the reference count of the device. + * + * Return: 0 iff successful */ static int visordriver_remove_device(struct device *xdev) @@ -614,105 +486,44 @@ visordriver_remove_device(struct device *xdev) dev = to_visor_device(xdev); drv = to_visor_driver(xdev->driver); - down(&dev->visordriver_callback_lock); + mutex_lock(&dev->visordriver_callback_lock); dev->being_removed = true; if (drv->remove) drv->remove(dev); - up(&dev->visordriver_callback_lock); + mutex_unlock(&dev->visordriver_callback_lock); dev_stop_periodic_work(dev); put_device(&dev->device); return 0; } -/** A particular type of visor driver calls this function to register - * the driver. The caller MUST fill in the following fields within the - * #drv structure: - * name, version, owner, channel_types, probe, remove +/** + * visorbus_unregister_visor_driver() - unregisters the provided driver + * @drv: the driver to unregister * - * Here's how the whole Linux bus / driver / device model works. - * - * At system start-up, the visorbus kernel module is loaded, which registers - * visorbus_type as a bus type, using bus_register(). - * - * All kernel modules that support particular device types on a - * visorbus bus are loaded. Each of these kernel modules calls - * visorbus_register_visor_driver() in their init functions, passing a - * visor_driver struct. visorbus_register_visor_driver() in turn calls - * register_driver(&visor_driver.driver). This .driver member is - * initialized with generic methods (like probe), whose sole responsibility - * is to act as a broker for the real methods, which are within the - * visor_driver struct. (This is the way the subclass behavior is - * implemented, since visor_driver is essentially a subclass of the - * generic driver.) Whenever a driver_register() happens, core bus code in - * the kernel does (see device_attach() in drivers/base/dd.c): - * - * for each dev associated with the bus (the bus that driver is on) that - * does not yet have a driver - * if bus.match(dev,newdriver) == yes_matched ** .match specified - * ** during bus_register(). - * newdriver.probe(dev) ** for visor drivers, this will call - * ** the generic driver.probe implemented in visorbus.c, - * ** which in turn calls the probe specified within the - * ** struct visor_driver (which was specified by the - * ** actual device driver as part of - * ** visorbus_register_visor_driver()). - * - * The above dance also happens when a new device appears. - * So the question is, how are devices created within the system? - * Basically, just call device_add(dev). See pci_bus_add_devices(). - * pci_scan_device() shows an example of how to build a device struct. It - * returns the newly-created struct to pci_scan_single_device(), who adds it - * to the list of devices at PCIBUS.devices. That list of devices is what - * is traversed by pci_bus_add_devices(). - * - */ -int visorbus_register_visor_driver(struct visor_driver *drv) -{ - int rc = 0; - - if (busreg_rc < 0) - return -ENODEV; /*can't register on a nonexistent bus*/ - - drv->driver.name = drv->name; - drv->driver.bus = &visorbus_type; - drv->driver.probe = visordriver_probe_device; - drv->driver.remove = visordriver_remove_device; - drv->driver.owner = drv->owner; - - /* driver_register does this: - * bus_add_driver(drv) - * ->if (drv.bus) ** (bus_type) ** - * driver_attach(drv) - * for each dev with bus type of drv.bus - * if (!dev.drv) ** no driver assigned yet ** - * if (bus.match(dev,drv)) [visorbus_match] - * dev.drv = drv - * if (!drv.probe(dev)) [visordriver_probe_device] - * dev.drv = NULL - */ - - rc = driver_register(&drv->driver); - if (rc < 0) - return rc; - rc = register_driver_attributes(drv); - if (rc < 0) - driver_unregister(&drv->driver); - return rc; -} -EXPORT_SYMBOL_GPL(visorbus_register_visor_driver); - -/** A particular type of visor driver calls this function to unregister - * the driver, i.e., within its module_exit function. + * A visor function driver calls this function to unregister the driver, + * i.e., within its module_exit function. */ void visorbus_unregister_visor_driver(struct visor_driver *drv) { - unregister_driver_attributes(drv); driver_unregister(&drv->driver); } EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver); +/** + * visorbus_read_channel() - reads from the designated channel into + * the provided buffer + * @dev: the device whose channel is read from + * @offset: the offset into the channel at which reading starts + * @dest: the destination buffer that is written into from the channel + * @nbytes: the number of bytes to read from the channel + * + * If receiving a message, use the visorchannel_signalremove() + * function instead. + * + * Return: integer indicating success (zero) or failure (non-zero) + */ int visorbus_read_channel(struct visor_device *dev, unsigned long offset, void *dest, unsigned long nbytes) @@ -721,6 +532,19 @@ visorbus_read_channel(struct visor_device *dev, unsigned long offset, } EXPORT_SYMBOL_GPL(visorbus_read_channel); +/** + * visorbus_write_channel() - writes the provided buffer into the designated + * channel + * @dev: the device whose channel is written to + * @offset: the offset into the channel at which writing starts + * @src: the source buffer that is written into the channel + * @nbytes: the number of bytes to write into the channel + * + * If sending a message, use the visorchannel_signalinsert() + * function instead. + * + * Return: integer indicating success (zero) or failure (non-zero) + */ int visorbus_write_channel(struct visor_device *dev, unsigned long offset, void *src, unsigned long nbytes) @@ -729,16 +553,13 @@ visorbus_write_channel(struct visor_device *dev, unsigned long offset, } EXPORT_SYMBOL_GPL(visorbus_write_channel); -int -visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch, - unsigned long nbytes) -{ - return visorchannel_clear(dev->visorchannel, offset, ch, nbytes); -} -EXPORT_SYMBOL_GPL(visorbus_clear_channel); - -/** We don't really have a real interrupt, so for now we just call the - * interrupt function periodically... +/** + * visorbus_enable_channel_interrupts() - enables interrupts on the + * designated device + * @dev: the device on which to enable interrupts + * + * Currently we don't yet have a real interrupt, so for now we just call the + * interrupt function periodically via a timer. */ void visorbus_enable_channel_interrupts(struct visor_device *dev) @@ -747,6 +568,11 @@ visorbus_enable_channel_interrupts(struct visor_device *dev) } EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts); +/** + * visorbus_disable_channel_interrupts() - disables interrupts on the + * designated device + * @dev: the device on which to disable interrupts + */ void visorbus_disable_channel_interrupts(struct visor_device *dev) { @@ -754,19 +580,28 @@ visorbus_disable_channel_interrupts(struct visor_device *dev) } EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts); -/** This is how everything starts from the device end. - * This function is called when a channel first appears via a ControlVM - * message. In response, this function allocates a visor_device to - * correspond to the new channel, and attempts to connect it the appropriate - * driver. If the appropriate driver is found, the visor_driver.probe() - * function for that driver will be called, and will be passed the new - * visor_device that we just created. +/** + * create_visor_device() - create visor device as a result of receiving the + * controlvm device_create message for a new device + * @dev: a freshly-zeroed struct visor_device, containing only filled-in values + * for chipset_bus_no and chipset_dev_no, that will be initialized * - * It's ok if the appropriate driver is not yet loaded, because in that case - * the new device struct will just stick around in the bus' list of devices. - * When the appropriate driver calls visorbus_register_visor_driver(), the - * visor_driver.probe() for the new driver will be called with the new - * device. + * This is how everything starts from the device end. + * This function is called when a channel first appears via a ControlVM + * message. In response, this function allocates a visor_device to + * correspond to the new channel, and attempts to connect it the appropriate + * driver. If the appropriate driver is found, the visor_driver.probe() + * function for that driver will be called, and will be passed the new + * visor_device that we just created. + * + * It's ok if the appropriate driver is not yet loaded, because in that case + * the new device struct will just stick around in the bus' list of devices. + * When the appropriate driver calls visorbus_register_visor_driver(), the + * visor_driver.probe() for the new driver will be called with the new + * device. + * + * Return: 0 if successful, otherwise the negative value returned by + * device_add() indicating the reason for failure */ static int create_visor_device(struct visor_device *dev) @@ -778,33 +613,27 @@ create_visor_device(struct visor_device *dev) POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, chipset_dev_no, chipset_bus_no, POSTCODE_SEVERITY_INFO); - sema_init(&dev->visordriver_callback_lock, 1); /* unlocked */ + mutex_init(&dev->visordriver_callback_lock); dev->device.bus = &visorbus_type; dev->device.groups = visorbus_channel_groups; device_initialize(&dev->device); dev->device.release = visorbus_release_device; /* keep a reference just for us (now 2) */ get_device(&dev->device); - dev->periodic_work = - visor_periodic_work_create(POLLJIFFIES_NORMALCHANNEL, - periodic_dev_workqueue, - dev_periodic_work, - dev, dev_name(&dev->device)); - if (!dev->periodic_work) { - POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no, - DIAG_SEVERITY_ERR); - err = -EINVAL; - goto err_put; - } + init_timer(&dev->timer); + dev->timer.data = (unsigned long)(dev); + dev->timer.function = dev_periodic_work; - /* bus_id must be a unique name with respect to this bus TYPE + /* + * bus_id must be a unique name with respect to this bus TYPE * (NOT bus instance). That's why we need to include the bus * number within the name. */ dev_set_name(&dev->device, "vbus%u:dev%u", chipset_bus_no, chipset_dev_no); - /* device_add does this: + /* + * device_add does this: * bus_add_device(dev) * ->device_attach(dev) * ->for each driver drv registered on the bus that dev is on @@ -864,11 +693,20 @@ get_vbus_header_info(struct visorchannel *chan, return 0; } -/* Write the contents of to the struct - * spar_vbus_channel_protocol.chp_info. +/** + * write_vbus_chp_info() - write the contents of to the struct + * spar_vbus_channel_protocol.chp_info + * @chan: indentifies the s-Par channel that will be updated + * @hdr_info: used to find appropriate channel offset to write data + * @info: contains the information to write + * + * Writes chipset info into the channel memory to be used for diagnostic + * purposes. + * + * Returns no value since this is debug information and not needed for + * device functionality. */ - -static int +static void write_vbus_chp_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, struct ultra_vbus_deviceinfo *info) @@ -876,18 +714,25 @@ write_vbus_chp_info(struct visorchannel *chan, int off = sizeof(struct channel_header) + hdr_info->chp_info_offset; if (hdr_info->chp_info_offset == 0) - return -EFAULT; + return; - if (visorchannel_write(chan, off, info, sizeof(*info)) < 0) - return -EFAULT; - return 0; + visorchannel_write(chan, off, info, sizeof(*info)); } -/* Write the contents of to the struct - * spar_vbus_channel_protocol.bus_info. +/** + * write_vbus_bus_info() - write the contents of to the struct + * spar_vbus_channel_protocol.bus_info + * @chan: indentifies the s-Par channel that will be updated + * @hdr_info: used to find appropriate channel offset to write data + * @info: contains the information to write + * + * Writes bus info into the channel memory to be used for diagnostic + * purposes. + * + * Returns no value since this is debug information and not needed for + * device functionality. */ - -static int +static void write_vbus_bus_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, struct ultra_vbus_deviceinfo *info) @@ -895,37 +740,46 @@ write_vbus_bus_info(struct visorchannel *chan, int off = sizeof(struct channel_header) + hdr_info->bus_info_offset; if (hdr_info->bus_info_offset == 0) - return -EFAULT; + return; - if (visorchannel_write(chan, off, info, sizeof(*info)) < 0) - return -EFAULT; - return 0; + visorchannel_write(chan, off, info, sizeof(*info)); } -/* Write the contents of to the - * struct spar_vbus_channel_protocol.dev_info[]. +/** + * write_vbus_dev_info() - write the contents of to the struct + * spar_vbus_channel_protocol.dev_info[] + * @chan: indentifies the s-Par channel that will be updated + * @hdr_info: used to find appropriate channel offset to write data + * @info: contains the information to write + * @devix: the relative device number (0..n-1) of the device on the bus + * + * Writes device info into the channel memory to be used for diagnostic + * purposes. + * + * Returns no value since this is debug information and not needed for + * device functionality. */ -static int +static void write_vbus_dev_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, - struct ultra_vbus_deviceinfo *info, int devix) + struct ultra_vbus_deviceinfo *info, unsigned int devix) { int off = (sizeof(struct channel_header) + hdr_info->dev_info_offset) + (hdr_info->device_info_struct_bytes * devix); if (hdr_info->dev_info_offset == 0) - return -EFAULT; + return; - if (visorchannel_write(chan, off, info, sizeof(*info)) < 0) - return -EFAULT; - return 0; + visorchannel_write(chan, off, info, sizeof(*info)); } -/* For a child device just created on a client bus, fill in - * information about the driver that is controlling this device into - * the the appropriate slot within the vbus channel of the bus - * instance. +/** + * fix_vbus_dev_info() - for a child device just created on a client bus, fill + * in information about the driver that is controlling + * this device into the the appropriate slot within the + * vbus channel of the bus instance + * @visordev: struct visor_device for the desired device */ static void fix_vbus_dev_info(struct visor_device *visordev) @@ -933,8 +787,8 @@ fix_vbus_dev_info(struct visor_device *visordev) int i; struct visor_device *bdev; struct visor_driver *visordrv; - int bus_no = visordev->chipset_bus_no; - int dev_no = visordev->chipset_dev_no; + u32 bus_no = visordev->chipset_bus_no; + u32 dev_no = visordev->chipset_dev_no; struct ultra_vbus_deviceinfo dev_info; const char *chan_type_name = NULL; struct spar_vbus_headerinfo *hdr_info; @@ -942,17 +796,16 @@ fix_vbus_dev_info(struct visor_device *visordev) if (!visordev->device.driver) return; - hdr_info = (struct spar_vbus_headerinfo *)visordev->vbus_hdr_info; - if (!hdr_info) - return; - bdev = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL); if (!bdev) return; - + hdr_info = (struct spar_vbus_headerinfo *)bdev->vbus_hdr_info; + if (!hdr_info) + return; visordrv = to_visor_driver(visordev->device.driver); - /* Within the list of device types (by GUID) that the driver + /* + * Within the list of device types (by GUID) that the driver * says it supports, find out which one of those types matches * the type of this device, so that we can include the device * type name @@ -966,20 +819,148 @@ fix_vbus_dev_info(struct visor_device *visordev) } } - bus_device_info_init(&dev_info, chan_type_name, - visordrv->name, visordrv->version, - visordrv->vertag); + bus_device_info_init(&dev_info, chan_type_name, visordrv->name); write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no); - /* Re-write bus+chipset info, because it is possible that this - * was previously written by our evil counterpart, virtpci. - */ + /* + * Re-write bus+chipset info, because it is possible that this + * was previously written by our evil counterpart, virtpci. + */ write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo); write_vbus_bus_info(bdev->visorchannel, hdr_info, &clientbus_driverinfo); } -/** Create a device instance for the visor bus itself. +/** + * visordriver_probe_device() - handle new visor device coming online + * @xdev: struct device for the visor device being probed + * + * This is called automatically upon adding a visor_device (device_add), or + * adding a visor_driver (visorbus_register_visor_driver), but only after + * visorbus_match() has returned 1 to indicate a successful match between + * driver and device. + * + * If successful, a reference to the device will be held onto via get_device(). + * + * Return: 0 if successful, meaning the function driver's probe() function + * was successful with this device, otherwise a negative errno + * value indicating failure reason + */ +static int +visordriver_probe_device(struct device *xdev) +{ + int res; + struct visor_driver *drv; + struct visor_device *dev; + + drv = to_visor_driver(xdev->driver); + dev = to_visor_device(xdev); + + if (!drv->probe) + return -ENODEV; + + mutex_lock(&dev->visordriver_callback_lock); + dev->being_removed = false; + + res = drv->probe(dev); + if (res >= 0) { + /* success: reference kept via unmatched get_device() */ + get_device(&dev->device); + fix_vbus_dev_info(dev); + } + + mutex_unlock(&dev->visordriver_callback_lock); + return res; +} + +/** + * visorbus_register_visor_driver() - registers the provided visor driver + * for handling one or more visor device + * types (channel_types) + * @drv: the driver to register + * + * A visor function driver calls this function to register + * the driver. The caller MUST fill in the following fields within the + * #drv structure: + * name, version, owner, channel_types, probe, remove + * + * Here's how the whole Linux bus / driver / device model works. + * + * At system start-up, the visorbus kernel module is loaded, which registers + * visorbus_type as a bus type, using bus_register(). + * + * All kernel modules that support particular device types on a + * visorbus bus are loaded. Each of these kernel modules calls + * visorbus_register_visor_driver() in their init functions, passing a + * visor_driver struct. visorbus_register_visor_driver() in turn calls + * register_driver(&visor_driver.driver). This .driver member is + * initialized with generic methods (like probe), whose sole responsibility + * is to act as a broker for the real methods, which are within the + * visor_driver struct. (This is the way the subclass behavior is + * implemented, since visor_driver is essentially a subclass of the + * generic driver.) Whenever a driver_register() happens, core bus code in + * the kernel does (see device_attach() in drivers/base/dd.c): + * + * for each dev associated with the bus (the bus that driver is on) that + * does not yet have a driver + * if bus.match(dev,newdriver) == yes_matched ** .match specified + * ** during bus_register(). + * newdriver.probe(dev) ** for visor drivers, this will call + * ** the generic driver.probe implemented in visorbus.c, + * ** which in turn calls the probe specified within the + * ** struct visor_driver (which was specified by the + * ** actual device driver as part of + * ** visorbus_register_visor_driver()). + * + * The above dance also happens when a new device appears. + * So the question is, how are devices created within the system? + * Basically, just call device_add(dev). See pci_bus_add_devices(). + * pci_scan_device() shows an example of how to build a device struct. It + * returns the newly-created struct to pci_scan_single_device(), who adds it + * to the list of devices at PCIBUS.devices. That list of devices is what + * is traversed by pci_bus_add_devices(). + * + * Return: integer indicating success (zero) or failure (non-zero) + */ +int visorbus_register_visor_driver(struct visor_driver *drv) +{ + int rc = 0; + + if (busreg_rc < 0) + return -ENODEV; /*can't register on a nonexistent bus*/ + + drv->driver.name = drv->name; + drv->driver.bus = &visorbus_type; + drv->driver.probe = visordriver_probe_device; + drv->driver.remove = visordriver_remove_device; + drv->driver.owner = drv->owner; + + /* + * driver_register does this: + * bus_add_driver(drv) + * ->if (drv.bus) ** (bus_type) ** + * driver_attach(drv) + * for each dev with bus type of drv.bus + * if (!dev.drv) ** no driver assigned yet ** + * if (bus.match(dev,drv)) [visorbus_match] + * dev.drv = drv + * if (!drv.probe(dev)) [visordriver_probe_device] + * dev.drv = NULL + */ + + rc = driver_register(&drv->driver); + if (rc < 0) + driver_unregister(&drv->driver); + return rc; +} +EXPORT_SYMBOL_GPL(visorbus_register_visor_driver); + +/** + * create_bus_instance() - create a device instance for the visor bus itself + * @dev: struct visor_device indicating the bus instance + * + * Return: 0 for success, otherwise negative errno value indicating reason for + * failure */ static int create_bus_instance(struct visor_device *dev) @@ -1014,25 +995,26 @@ create_bus_instance(struct visor_device *dev) } else { kfree(hdr_info); } - bus_count++; list_add_tail(&dev->list_all, &list_all_bus_instances); dev_set_drvdata(&dev->device, dev); return 0; } -/** Remove a device instance for the visor bus itself. +/** + * remove_bus_instance() - remove a device instance for the visor bus itself + * @dev: struct visor_device indentifying the bus to remove */ static void remove_bus_instance(struct visor_device *dev) { - /* Note that this will result in the release method for + /* + * Note that this will result in the release method for * dev->dev being called, which will call * visorbus_release_busdevice(). This has something to do with * the put_device() done in device_unregister(), but I have never * successfully been able to trace thru the code to see where/how * release() gets called. But I know it does. */ - bus_count--; if (dev->visorchannel) { visorchannel_destroy(dev->visorchannel); dev->visorchannel = NULL; @@ -1042,8 +1024,11 @@ remove_bus_instance(struct visor_device *dev) device_unregister(&dev->device); } -/** Create and register the one-and-only one instance of - * the visor bus type (visorbus_type). +/** + * create_bus_type() - create and register the one-and-only one instance of + * the visor bus type (visorbus_type) + * Return: 0 for success, otherwise negative errno value returned by + * bus_register() indicating the reason for failure */ static int create_bus_type(void) @@ -1052,7 +1037,9 @@ create_bus_type(void) return busreg_rc; } -/** Remove the one-and-only one instance of the visor bus type (visorbus_type). +/** + * remove_bus_type() - remove the one-and-only one instance of the visor bus + * type (visorbus_type) */ static void remove_bus_type(void) @@ -1060,7 +1047,8 @@ remove_bus_type(void) bus_unregister(&visorbus_type); } -/** Remove all child visor bus device instances. +/** + * remove_all_visor_devices() - remove all child visor bus device instances */ static void remove_all_visor_devices(void) @@ -1075,7 +1063,7 @@ remove_all_visor_devices(void) } } -static void +void chipset_bus_create(struct visor_device *dev) { int rc; @@ -1092,19 +1080,17 @@ chipset_bus_create(struct visor_device *dev) POSTCODE_LINUX_3(CHIPSET_INIT_SUCCESS_PC, bus_no, POSTCODE_SEVERITY_INFO); - if (chipset_responders.bus_create) - (*chipset_responders.bus_create) (dev, rc); + bus_create_response(dev, rc); } -static void +void chipset_bus_destroy(struct visor_device *dev) { remove_bus_instance(dev); - if (chipset_responders.bus_destroy) - (*chipset_responders.bus_destroy)(dev, 0); + bus_destroy_response(dev, 0); } -static void +void chipset_device_create(struct visor_device *dev_info) { int rc; @@ -1115,8 +1101,7 @@ chipset_device_create(struct visor_device *dev_info) POSTCODE_SEVERITY_INFO); rc = create_visor_device(dev_info); - if (chipset_responders.device_create) - chipset_responders.device_create(dev_info, rc); + device_create_response(dev_info, rc); if (rc < 0) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, @@ -1126,18 +1111,22 @@ chipset_device_create(struct visor_device *dev_info) POSTCODE_SEVERITY_INFO); } -static void +void chipset_device_destroy(struct visor_device *dev_info) { remove_visor_device(dev_info); - if (chipset_responders.device_destroy) - (*chipset_responders.device_destroy) (dev_info, 0); + device_destroy_response(dev_info, 0); } -/* This is the callback function specified for a function driver, to - * be called when a pending "pause device" operation has been - * completed. +/** + * pause_state_change_complete() - the callback function to be called by a + * visorbus function driver when a + * pending "pause device" operation has + * completed + * @dev: struct visor_device identifying the paused device + * @status: 0 iff the pause state change completed successfully, otherwise + * a negative errno value indicating the reason for failure */ static void pause_state_change_complete(struct visor_device *dev, int status) @@ -1146,19 +1135,18 @@ pause_state_change_complete(struct visor_device *dev, int status) return; dev->pausing = false; - if (!chipset_responders.device_pause) /* this can never happen! */ - return; - /* Notify the chipset driver that the pause is complete, which - * will presumably want to send some sort of response to the - * initiator. - */ - (*chipset_responders.device_pause) (dev, status); + device_pause_response(dev, status); } -/* This is the callback function specified for a function driver, to - * be called when a pending "resume device" operation has been - * completed. +/** + * resume_state_change_complete() - the callback function to be called by a + * visorbus function driver when a + * pending "resume device" operation has + * completed + * @dev: struct visor_device identifying the resumed device + * @status: 0 iff the resume state change completed successfully, otherwise + * a negative errno value indicating the reason for failure */ static void resume_state_change_complete(struct visor_device *dev, int status) @@ -1167,19 +1155,25 @@ resume_state_change_complete(struct visor_device *dev, int status) return; dev->resuming = false; - if (!chipset_responders.device_resume) /* this can never happen! */ - return; - /* Notify the chipset driver that the resume is complete, + /* + * Notify the chipset driver that the resume is complete, * which will presumably want to send some sort of response to * the initiator. */ - (*chipset_responders.device_resume) (dev, status); + device_resume_response(dev, status); } -/* Tell the subordinate function driver for a specific device to pause - * or resume that device. Result is returned asynchronously via a - * callback function. +/** + * initiate_chipset_device_pause_resume() - start a pause or resume operation + * for a visor device + * @dev: struct visor_device identifying the device being paused or resumed + * @is_pause: true to indicate pause operation, false to indicate resume + * + * Tell the subordinate function driver for a specific device to pause + * or resume that device. Success/failure result is returned asynchronously + * via a callback function; see pause_state_change_complete() and + * resume_state_change_complete(). */ static void initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) @@ -1189,9 +1183,9 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) void (*notify_func)(struct visor_device *dev, int response) = NULL; if (is_pause) - notify_func = chipset_responders.device_pause; + notify_func = device_pause_response; else - notify_func = chipset_responders.device_resume; + notify_func = device_resume_response; if (!notify_func) return; @@ -1206,7 +1200,8 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) return; } - /* Note that even though both drv->pause() and drv->resume + /* + * Note that even though both drv->pause() and drv->resume * specify a callback function, it is NOT necessary for us to * increment our local module usage count. Reason is, there * is already a linkage dependency between child function @@ -1246,33 +1241,41 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) } } -static void +/** + * chipset_device_pause() - start a pause operation for a visor device + * @dev_info: struct visor_device identifying the device being paused + * + * Tell the subordinate function driver for a specific device to pause + * that device. Success/failure result is returned asynchronously + * via a callback function; see pause_state_change_complete(). + */ +void chipset_device_pause(struct visor_device *dev_info) { initiate_chipset_device_pause_resume(dev_info, true); } -static void +/** + * chipset_device_resume() - start a resume operation for a visor device + * @dev_info: struct visor_device identifying the device being resumed + * + * Tell the subordinate function driver for a specific device to resume + * that device. Success/failure result is returned asynchronously + * via a callback function; see resume_state_change_complete(). + */ +void chipset_device_resume(struct visor_device *dev_info) { initiate_chipset_device_pause_resume(dev_info, false); } -struct channel_size_info { - uuid_le guid; - unsigned long min_size; - unsigned long max_size; -}; - int visorbus_init(void) { int err; POSTCODE_LINUX_3(DRIVER_ENTRY_PC, 0, POSTCODE_SEVERITY_INFO); - bus_device_info_init(&clientbus_driverinfo, - "clientbus", "visorbus", - VERSION, NULL); + bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus"); err = create_bus_type(); if (err < 0) { @@ -1280,19 +1283,7 @@ visorbus_init(void) goto error; } - periodic_dev_workqueue = create_singlethread_workqueue("visorbus_dev"); - if (!periodic_dev_workqueue) { - POSTCODE_LINUX_2(CREATE_WORKQUEUE_PC, DIAG_SEVERITY_ERR); - err = -ENOMEM; - goto error; - } - - /* This enables us to receive notifications when devices appear for - * which this service partition is to be a server for. - */ - visorchipset_register_busdev(&chipset_notifiers, - &chipset_responders, - &chipset_driverinfo); + bus_device_info_init(&chipset_driverinfo, "chipset", "visorchipset"); return 0; @@ -1306,20 +1297,8 @@ visorbus_exit(void) { struct list_head *listentry, *listtmp; - visorchipset_register_busdev(NULL, NULL, NULL); remove_all_visor_devices(); - flush_workqueue(periodic_dev_workqueue); /* better not be any work! */ - destroy_workqueue(periodic_dev_workqueue); - periodic_dev_workqueue = NULL; - - if (periodic_test_workqueue) { - cancel_delayed_work(&periodic_work); - flush_workqueue(periodic_test_workqueue); - destroy_workqueue(periodic_test_workqueue); - periodic_test_workqueue = NULL; - } - list_for_each_safe(listentry, listtmp, &list_all_bus_instances) { struct visor_device *dev = list_entry(listentry, struct visor_device, @@ -1329,9 +1308,6 @@ visorbus_exit(void) remove_bus_type(); } -module_param_named(debug, visorbus_debug, int, S_IRUGO); -MODULE_PARM_DESC(visorbus_debug, "1 to debug"); - module_param_named(forcematch, visorbus_forcematch, int, S_IRUGO); MODULE_PARM_DESC(visorbus_forcematch, "1 to force a successful dev <--> drv match"); @@ -1339,6 +1315,3 @@ MODULE_PARM_DESC(visorbus_forcematch, module_param_named(forcenomatch, visorbus_forcenomatch, int, S_IRUGO); MODULE_PARM_DESC(visorbus_forcenomatch, "1 to force an UNsuccessful dev <--> drv match"); - -module_param_named(debugref, visorbus_debugref, int, S_IRUGO); -MODULE_PARM_DESC(visorbus_debugref, "1 to debug reference counting"); diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 39edd2018453..15403fb52847 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -1,4 +1,4 @@ -/* visorchipset.h +/* visorbus_private.h * * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. @@ -14,55 +14,72 @@ * details. */ -#ifndef __VISORCHIPSET_H__ -#define __VISORCHIPSET_H__ +#ifndef __VISORBUS_PRIVATE_H__ +#define __VISORBUS_PRIVATE_H__ #include +#include #include "controlvmchannel.h" -#include "vbusdeviceinfo.h" -#include "vbushelper.h" +#include "vbuschannel.h" -/* These functions will be called from within visorchipset when certain - * events happen. (The implementation of these functions is outside of - * visorchipset.) +/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the + * command line */ -struct visorchipset_busdev_notifiers { - void (*bus_create)(struct visor_device *bus_info); - void (*bus_destroy)(struct visor_device *bus_info); - void (*device_create)(struct visor_device *bus_info); - void (*device_destroy)(struct visor_device *bus_info); - void (*device_pause)(struct visor_device *bus_info); - void (*device_resume)(struct visor_device *bus_info); -}; -/* These functions live inside visorchipset, and will be called to indicate - * responses to specific events (by code outside of visorchipset). - * For now, the value for each response is simply either: - * 0 = it worked - * -1 = it failed - */ -struct visorchipset_busdev_responders { - void (*bus_create)(struct visor_device *p, int response); - void (*bus_destroy)(struct visor_device *p, int response); - void (*device_create)(struct visor_device *p, int response); - void (*device_destroy)(struct visor_device *p, int response); - void (*device_pause)(struct visor_device *p, int response); - void (*device_resume)(struct visor_device *p, int response); -}; +static inline void bus_device_info_init( + struct ultra_vbus_deviceinfo *bus_device_info_ptr, + const char *dev_type, const char *drv_name) +{ + memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); + snprintf(bus_device_info_ptr->devtype, + sizeof(bus_device_info_ptr->devtype), + "%s", (dev_type) ? dev_type : "unknownType"); + snprintf(bus_device_info_ptr->drvname, + sizeof(bus_device_info_ptr->drvname), + "%s", (drv_name) ? drv_name : "unknownDriver"); + snprintf(bus_device_info_ptr->infostrs, + sizeof(bus_device_info_ptr->infostrs), "kernel ver. %s", + utsname()->release); +} -/** Register functions (in the bus driver) to get called by visorchipset - * whenever a bus or device appears for which this guest is to be the - * client for. visorchipset will fill in , to indicate - * functions the bus driver should call to indicate message responses. - */ -void -visorchipset_register_busdev( - struct visorchipset_busdev_notifiers *notifiers, - struct visorchipset_busdev_responders *responders, - struct ultra_vbus_deviceinfo *driver_info); +void chipset_bus_create(struct visor_device *bus_info); +void chipset_bus_destroy(struct visor_device *bus_info); +void chipset_device_create(struct visor_device *dev_info); +void chipset_device_destroy(struct visor_device *dev_info); +void chipset_device_pause(struct visor_device *dev_info); +void chipset_device_resume(struct visor_device *dev_info); + +void bus_create_response(struct visor_device *p, int response); +void bus_destroy_response(struct visor_device *p, int response); +void device_create_response(struct visor_device *p, int response); +void device_destroy_response(struct visor_device *p, int response); +void device_resume_response(struct visor_device *p, int response); +void device_pause_response(struct visor_device *p, int response); -/* visorbus init and exit functions */ int visorbus_init(void); void visorbus_exit(void); + +/* visorchannel access functions */ + +struct visorchannel *visorchannel_create(u64 physaddr, + unsigned long channel_bytes, + gfp_t gfp, uuid_le guid); +struct visorchannel *visorchannel_create_with_lock(u64 physaddr, + unsigned long channel_bytes, + gfp_t gfp, uuid_le guid); +void visorchannel_destroy(struct visorchannel *channel); +int visorchannel_read(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes); +int visorchannel_write(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes); +u64 visorchannel_get_physaddr(struct visorchannel *channel); +ulong visorchannel_get_nbytes(struct visorchannel *channel); +char *visorchannel_id(struct visorchannel *channel, char *s); +char *visorchannel_zoneid(struct visorchannel *channel, char *s); +u64 visorchannel_get_clientpartition(struct visorchannel *channel); +int visorchannel_set_clientpartition(struct visorchannel *channel, + u64 partition_handle); +char *visorchannel_uuid_id(uuid_le *guid, char *s); +void __iomem *visorchannel_get_header(struct visorchannel *channel); #endif diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 43373582cf1d..300a65dc5c6c 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -15,14 +15,13 @@ */ /* - * This provides Supervisor channel communication primitives, which are + * This provides s-Par channel communication primitives, which are * independent of the mechanism used to access the channel data. */ #include #include -#include "version.h" #include "visorbus.h" #include "controlvmchannel.h" @@ -55,13 +54,342 @@ struct visorchannel { uuid_le inst; }; -/* Creates the struct visorchannel abstraction for a data area in memory, - * but does NOT modify this data area. +void +visorchannel_destroy(struct visorchannel *channel) +{ + if (!channel) + return; + if (channel->mapped) { + memunmap(channel->mapped); + if (channel->requested) + release_mem_region(channel->physaddr, channel->nbytes); + } + kfree(channel); +} + +u64 +visorchannel_get_physaddr(struct visorchannel *channel) +{ + return channel->physaddr; +} + +ulong +visorchannel_get_nbytes(struct visorchannel *channel) +{ + return channel->nbytes; +} + +char * +visorchannel_uuid_id(uuid_le *guid, char *s) +{ + sprintf(s, "%pUL", guid); + return s; +} + +char * +visorchannel_id(struct visorchannel *channel, char *s) +{ + return visorchannel_uuid_id(&channel->guid, s); +} + +char * +visorchannel_zoneid(struct visorchannel *channel, char *s) +{ + return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s); +} + +u64 +visorchannel_get_clientpartition(struct visorchannel *channel) +{ + return channel->chan_hdr.partition_handle; +} + +int +visorchannel_set_clientpartition(struct visorchannel *channel, + u64 partition_handle) +{ + channel->chan_hdr.partition_handle = partition_handle; + return 0; +} + +/** + * visorchannel_get_uuid() - queries the UUID of the designated channel + * @channel: the channel to query + * + * Return: the UUID of the provided channel + */ +uuid_le +visorchannel_get_uuid(struct visorchannel *channel) +{ + return channel->guid; +} +EXPORT_SYMBOL_GPL(visorchannel_get_uuid); + +int +visorchannel_read(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes) +{ + if (offset + nbytes > channel->nbytes) + return -EIO; + + memcpy(local, channel->mapped + offset, nbytes); + + return 0; +} + +int +visorchannel_write(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes) +{ + size_t chdr_size = sizeof(struct channel_header); + size_t copy_size; + + if (offset + nbytes > channel->nbytes) + return -EIO; + + if (offset < chdr_size) { + copy_size = min(chdr_size - offset, nbytes); + memcpy(((char *)(&channel->chan_hdr)) + offset, + local, copy_size); + } + + memcpy(channel->mapped + offset, local, nbytes); + + return 0; +} + +void __iomem * +visorchannel_get_header(struct visorchannel *channel) +{ + return (void __iomem *)&channel->chan_hdr; +} + +/* + * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a + * channel header + */ +#define SIG_QUEUE_OFFSET(chan_hdr, q) \ + ((chan_hdr)->ch_space_offset + \ + ((q) * sizeof(struct signal_queue_header))) + +/* + * Return offset of a specific queue entry (data) from the beginning of a + * channel header + */ +#define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \ + (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \ + ((slot) * (sig_hdr)->signal_size)) + +/* + * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back + * into host memory + */ +#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ + visorchannel_write(channel, \ + SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\ + offsetof(struct signal_queue_header, FIELD), \ + &((sig_hdr)->FIELD), \ + sizeof((sig_hdr)->FIELD)) + +static int +sig_read_header(struct visorchannel *channel, u32 queue, + struct signal_queue_header *sig_hdr) +{ + if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header)) + return -EINVAL; + + /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */ + return visorchannel_read(channel, + SIG_QUEUE_OFFSET(&channel->chan_hdr, queue), + sig_hdr, sizeof(struct signal_queue_header)); +} + +static inline int +sig_read_data(struct visorchannel *channel, u32 queue, + struct signal_queue_header *sig_hdr, u32 slot, void *data) +{ + int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue, + sig_hdr, slot); + + return visorchannel_read(channel, signal_data_offset, + data, sig_hdr->signal_size); +} + +static inline int +sig_write_data(struct visorchannel *channel, u32 queue, + struct signal_queue_header *sig_hdr, u32 slot, void *data) +{ + int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue, + sig_hdr, slot); + + return visorchannel_write(channel, signal_data_offset, + data, sig_hdr->signal_size); +} + +static int +signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) +{ + struct signal_queue_header sig_hdr; + int error; + + error = sig_read_header(channel, queue, &sig_hdr); + if (error) + return error; + + if (sig_hdr.head == sig_hdr.tail) + return -EIO; /* no signals to remove */ + + sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; + + error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg); + if (error) + return error; + + sig_hdr.num_received++; + + /* + * For each data field in SIGNAL_QUEUE_HEADER that was modified, + * update host memory. + */ + mb(); /* required for channel synch */ + + error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail); + if (error) + return error; + error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received); + if (error) + return error; + + return 0; +} + +/** + * visorchannel_signalremove() - removes a message from the designated + * channel/queue + * @channel: the channel the message will be removed from + * @queue: the queue the message will be removed from + * @msg: the message to remove + * + * Return: integer error code indicating the status of the removal + */ +int +visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) +{ + int rc; + unsigned long flags; + + if (channel->needs_lock) { + spin_lock_irqsave(&channel->remove_lock, flags); + rc = signalremove_inner(channel, queue, msg); + spin_unlock_irqrestore(&channel->remove_lock, flags); + } else { + rc = signalremove_inner(channel, queue, msg); + } + + return rc; +} +EXPORT_SYMBOL_GPL(visorchannel_signalremove); + +/** + * visorchannel_signalempty() - checks if the designated channel/queue + * contains any messages + * @channel: the channel to query + * @queue: the queue in the channel to query + * + * Return: boolean indicating whether any messages in the designated + * channel/queue are present + */ +bool +visorchannel_signalempty(struct visorchannel *channel, u32 queue) +{ + unsigned long flags = 0; + struct signal_queue_header sig_hdr; + bool rc = false; + + if (channel->needs_lock) + spin_lock_irqsave(&channel->remove_lock, flags); + + if (sig_read_header(channel, queue, &sig_hdr)) + rc = true; + if (sig_hdr.head == sig_hdr.tail) + rc = true; + if (channel->needs_lock) + spin_unlock_irqrestore(&channel->remove_lock, flags); + + return rc; +} +EXPORT_SYMBOL_GPL(visorchannel_signalempty); + +static int +signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) +{ + struct signal_queue_header sig_hdr; + int error; + + error = sig_read_header(channel, queue, &sig_hdr); + if (error) + return error; + + sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots; + if (sig_hdr.head == sig_hdr.tail) { + sig_hdr.num_overflows++; + visorchannel_write(channel, + SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) + + offsetof(struct signal_queue_header, + num_overflows), + &sig_hdr.num_overflows, + sizeof(sig_hdr.num_overflows)); + return -EIO; + } + + error = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg); + if (error) + return error; + + sig_hdr.num_sent++; + + /* + * For each data field in SIGNAL_QUEUE_HEADER that was modified, + * update host memory. + */ + mb(); /* required for channel synch */ + + error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head); + if (error) + return error; + error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent); + if (error) + return error; + + return 0; +} + +/** + * visorchannel_create_guts() - creates the struct visorchannel abstraction + * for a data area in memory, but does NOT modify + * this data area + * @physaddr: physical address of start of channel + * @channel_bytes: size of the channel in bytes; this may 0 if the channel has + * already been initialized in memory (which is true for all + * channels provided to guest environments by the s-Par + * back-end), in which case the actual channel size will be + * read from the channel header in memory + * @gfp: gfp_t to use when allocating memory for the data struct + * @guid: uuid that identifies channel type; this may 0 if the channel + * has already been initialized in memory (which is true for all + * channels provided to guest environments by the s-Par + * back-end), in which case the actual channel guid will be + * read from the channel header in memory + * @needs_lock: must specify true if you have multiple threads of execution + * that will be calling visorchannel methods of this + * visorchannel at the same time + * + * Return: pointer to visorchannel that was created if successful, + * otherwise NULL */ static struct visorchannel * visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, - gfp_t gfp, unsigned long off, - uuid_le guid, bool needs_lock) + gfp_t gfp, uuid_le guid, bool needs_lock) { struct visorchannel *channel; int err; @@ -78,7 +406,8 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, spin_lock_init(&channel->insert_lock); spin_lock_init(&channel->remove_lock); - /* Video driver constains the efi framebuffer so it will get a + /* + * Video driver constains the efi framebuffer so it will get a * conflict resource when requesting its full mem region. Since * we are only using the efi framebuffer for video we can ignore * this. Remember that we haven't requested it so we don't try to @@ -145,352 +474,31 @@ struct visorchannel * visorchannel_create(u64 physaddr, unsigned long channel_bytes, gfp_t gfp, uuid_le guid) { - return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid, + return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid, false); } -EXPORT_SYMBOL_GPL(visorchannel_create); struct visorchannel * visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes, gfp_t gfp, uuid_le guid) { - return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid, + return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid, true); } -EXPORT_SYMBOL_GPL(visorchannel_create_with_lock); -void -visorchannel_destroy(struct visorchannel *channel) -{ - if (!channel) - return; - if (channel->mapped) { - memunmap(channel->mapped); - if (channel->requested) - release_mem_region(channel->physaddr, channel->nbytes); - } - kfree(channel); -} -EXPORT_SYMBOL_GPL(visorchannel_destroy); - -u64 -visorchannel_get_physaddr(struct visorchannel *channel) -{ - return channel->physaddr; -} -EXPORT_SYMBOL_GPL(visorchannel_get_physaddr); - -ulong -visorchannel_get_nbytes(struct visorchannel *channel) -{ - return channel->nbytes; -} -EXPORT_SYMBOL_GPL(visorchannel_get_nbytes); - -char * -visorchannel_uuid_id(uuid_le *guid, char *s) -{ - sprintf(s, "%pUL", guid); - return s; -} -EXPORT_SYMBOL_GPL(visorchannel_uuid_id); - -char * -visorchannel_id(struct visorchannel *channel, char *s) -{ - return visorchannel_uuid_id(&channel->guid, s); -} -EXPORT_SYMBOL_GPL(visorchannel_id); - -char * -visorchannel_zoneid(struct visorchannel *channel, char *s) -{ - return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s); -} -EXPORT_SYMBOL_GPL(visorchannel_zoneid); - -u64 -visorchannel_get_clientpartition(struct visorchannel *channel) -{ - return channel->chan_hdr.partition_handle; -} -EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition); - -int -visorchannel_set_clientpartition(struct visorchannel *channel, - u64 partition_handle) -{ - channel->chan_hdr.partition_handle = partition_handle; - return 0; -} -EXPORT_SYMBOL_GPL(visorchannel_set_clientpartition); - -uuid_le -visorchannel_get_uuid(struct visorchannel *channel) -{ - return channel->guid; -} -EXPORT_SYMBOL_GPL(visorchannel_get_uuid); - -int -visorchannel_read(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes) -{ - if (offset + nbytes > channel->nbytes) - return -EIO; - - memcpy(local, channel->mapped + offset, nbytes); - - return 0; -} -EXPORT_SYMBOL_GPL(visorchannel_read); - -int -visorchannel_write(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes) -{ - size_t chdr_size = sizeof(struct channel_header); - size_t copy_size; - - if (offset + nbytes > channel->nbytes) - return -EIO; - - if (offset < chdr_size) { - copy_size = min(chdr_size - offset, nbytes); - memcpy(((char *)(&channel->chan_hdr)) + offset, - local, copy_size); - } - - memcpy(channel->mapped + offset, local, nbytes); - - return 0; -} -EXPORT_SYMBOL_GPL(visorchannel_write); - -int -visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, - ulong nbytes) -{ - int err; - int bufsize = PAGE_SIZE; - int written = 0; - u8 *buf; - - buf = (u8 *)__get_free_page(GFP_KERNEL); - if (!buf) - return -ENOMEM; - - memset(buf, ch, bufsize); - - while (nbytes > 0) { - int thisbytes = bufsize; - - if (nbytes < thisbytes) - thisbytes = nbytes; - err = visorchannel_write(channel, offset + written, - buf, thisbytes); - if (err) - goto out_free_page; - - written += thisbytes; - nbytes -= thisbytes; - } - err = 0; - -out_free_page: - free_page((unsigned long)buf); - return err; -} -EXPORT_SYMBOL_GPL(visorchannel_clear); - -void __iomem * -visorchannel_get_header(struct visorchannel *channel) -{ - return (void __iomem *)&channel->chan_hdr; -} -EXPORT_SYMBOL_GPL(visorchannel_get_header); - -/** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a - * channel header +/** + * visorchannel_signalinsert() - inserts a message into the designated + * channel/queue + * @channel: the channel the message will be added to + * @queue: the queue the message will be added to + * @msg: the message to insert + * + * Return: integer error code indicating the status of the insertion */ -#define SIG_QUEUE_OFFSET(chan_hdr, q) \ - ((chan_hdr)->ch_space_offset + \ - ((q) * sizeof(struct signal_queue_header))) - -/** Return offset of a specific queue entry (data) from the beginning of a - * channel header - */ -#define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \ - (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \ - ((slot) * (sig_hdr)->signal_size)) - -/** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back - * into host memory - */ -#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ - (visorchannel_write(channel, \ - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\ - offsetof(struct signal_queue_header, FIELD), \ - &((sig_hdr)->FIELD), \ - sizeof((sig_hdr)->FIELD)) >= 0) - -static bool -sig_read_header(struct visorchannel *channel, u32 queue, - struct signal_queue_header *sig_hdr) -{ - int err; - - if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header)) - return false; - - /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */ - err = visorchannel_read(channel, - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue), - sig_hdr, sizeof(struct signal_queue_header)); - if (err) - return false; - - return true; -} - -static inline bool -sig_read_data(struct visorchannel *channel, u32 queue, - struct signal_queue_header *sig_hdr, u32 slot, void *data) -{ - int err; - int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue, - sig_hdr, slot); - - err = visorchannel_read(channel, signal_data_offset, - data, sig_hdr->signal_size); - if (err) - return false; - - return true; -} - -static inline bool -sig_write_data(struct visorchannel *channel, u32 queue, - struct signal_queue_header *sig_hdr, u32 slot, void *data) -{ - int err; - int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue, - sig_hdr, slot); - - err = visorchannel_write(channel, signal_data_offset, - data, sig_hdr->signal_size); - if (err) - return false; - - return true; -} - -static bool -signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) -{ - struct signal_queue_header sig_hdr; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return false; - if (sig_hdr.head == sig_hdr.tail) - return false; /* no signals to remove */ - - sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; - if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) - return false; - sig_hdr.num_received++; - - /* For each data field in SIGNAL_QUEUE_HEADER that was modified, - * update host memory. - */ - mb(); /* required for channel synch */ - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail)) - return false; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received)) - return false; - return true; -} - -bool -visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) -{ - bool rc; - unsigned long flags; - - if (channel->needs_lock) { - spin_lock_irqsave(&channel->remove_lock, flags); - rc = signalremove_inner(channel, queue, msg); - spin_unlock_irqrestore(&channel->remove_lock, flags); - } else { - rc = signalremove_inner(channel, queue, msg); - } - - return rc; -} -EXPORT_SYMBOL_GPL(visorchannel_signalremove); - -bool -visorchannel_signalempty(struct visorchannel *channel, u32 queue) -{ - unsigned long flags = 0; - struct signal_queue_header sig_hdr; - bool rc = false; - - if (channel->needs_lock) - spin_lock_irqsave(&channel->remove_lock, flags); - - if (!sig_read_header(channel, queue, &sig_hdr)) - rc = true; - if (sig_hdr.head == sig_hdr.tail) - rc = true; - if (channel->needs_lock) - spin_unlock_irqrestore(&channel->remove_lock, flags); - - return rc; -} -EXPORT_SYMBOL_GPL(visorchannel_signalempty); - -static bool -signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) -{ - struct signal_queue_header sig_hdr; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return false; - - sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots; - if (sig_hdr.head == sig_hdr.tail) { - sig_hdr.num_overflows++; - visorchannel_write(channel, - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) + - offsetof(struct signal_queue_header, - num_overflows), - &sig_hdr.num_overflows, - sizeof(sig_hdr.num_overflows)); - return false; - } - - if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg)) - return false; - - sig_hdr.num_sent++; - - /* For each data field in SIGNAL_QUEUE_HEADER that was modified, - * update host memory. - */ - mb(); /* required for channel synch */ - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head)) - return false; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) - return false; - - return true; -} - -bool +int visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) { - bool rc; + int rc; unsigned long flags; if (channel->needs_lock) { @@ -504,132 +512,3 @@ visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) return rc; } EXPORT_SYMBOL_GPL(visorchannel_signalinsert); - -int -visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) -{ - struct signal_queue_header sig_hdr; - u32 slots_avail, slots_used; - u32 head, tail; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return 0; - head = sig_hdr.head; - tail = sig_hdr.tail; - if (head < tail) - head = head + sig_hdr.max_slots; - slots_used = head - tail; - slots_avail = sig_hdr.max_signals - slots_used; - return (int)slots_avail; -} -EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail); - -int -visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue) -{ - struct signal_queue_header sig_hdr; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return 0; - return (int)sig_hdr.max_signals; -} -EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots); - -static void -sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq) -{ - seq_printf(seq, "Signal Queue #%d\n", which); - seq_printf(seq, " VersionId = %lu\n", (ulong)q->version); - seq_printf(seq, " Type = %lu\n", (ulong)q->chtype); - seq_printf(seq, " oSignalBase = %llu\n", - (long long)q->sig_base_offset); - seq_printf(seq, " SignalSize = %lu\n", (ulong)q->signal_size); - seq_printf(seq, " MaxSignalSlots = %lu\n", - (ulong)q->max_slots); - seq_printf(seq, " MaxSignals = %lu\n", (ulong)q->max_signals); - seq_printf(seq, " FeatureFlags = %-16.16Lx\n", - (long long)q->features); - seq_printf(seq, " NumSignalsSent = %llu\n", - (long long)q->num_sent); - seq_printf(seq, " NumSignalsReceived = %llu\n", - (long long)q->num_received); - seq_printf(seq, " NumOverflows = %llu\n", - (long long)q->num_overflows); - seq_printf(seq, " Head = %lu\n", (ulong)q->head); - seq_printf(seq, " Tail = %lu\n", (ulong)q->tail); -} - -void -visorchannel_debug(struct visorchannel *channel, int num_queues, - struct seq_file *seq, u32 off) -{ - u64 addr = 0; - ulong nbytes = 0, nbytes_region = 0; - struct channel_header hdr; - struct channel_header *phdr = &hdr; - int i = 0; - int errcode = 0; - - if (!channel) - return; - - addr = visorchannel_get_physaddr(channel); - nbytes_region = visorchannel_get_nbytes(channel); - errcode = visorchannel_read(channel, off, - phdr, sizeof(struct channel_header)); - if (errcode < 0) { - seq_printf(seq, - "Read of channel header failed with errcode=%d)\n", - errcode); - if (off == 0) { - phdr = &channel->chan_hdr; - seq_puts(seq, "(following data may be stale)\n"); - } else { - return; - } - } - nbytes = (ulong)(phdr->size); - seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n", - addr + off, nbytes, nbytes_region); - seq_printf(seq, "Type = %pUL\n", &phdr->chtype); - seq_printf(seq, "ZoneGuid = %pUL\n", &phdr->zone_uuid); - seq_printf(seq, "Signature = 0x%-16.16Lx\n", - (long long)phdr->signature); - seq_printf(seq, "LegacyState = %lu\n", (ulong)phdr->legacy_state); - seq_printf(seq, "SrvState = %lu\n", (ulong)phdr->srv_state); - seq_printf(seq, "CliStateBoot = %lu\n", (ulong)phdr->cli_state_boot); - seq_printf(seq, "CliStateOS = %lu\n", (ulong)phdr->cli_state_os); - seq_printf(seq, "HeaderSize = %lu\n", (ulong)phdr->header_size); - seq_printf(seq, "Size = %llu\n", (long long)phdr->size); - seq_printf(seq, "Features = 0x%-16.16llx\n", - (long long)phdr->features); - seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n", - (long long)phdr->partition_handle); - seq_printf(seq, "Handle = 0x%-16.16llx\n", - (long long)phdr->handle); - seq_printf(seq, "VersionId = %lu\n", (ulong)phdr->version_id); - seq_printf(seq, "oChannelSpace = %llu\n", - (long long)phdr->ch_space_offset); - if ((phdr->ch_space_offset == 0) || (errcode < 0)) - ; - else - for (i = 0; i < num_queues; i++) { - struct signal_queue_header q; - - errcode = visorchannel_read(channel, - off + - phdr->ch_space_offset + - (i * sizeof(q)), - &q, sizeof(q)); - if (errcode < 0) { - seq_printf(seq, - "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n", - i, addr, errcode); - continue; - } - sigqueue_debug(&q, i, seq); - } - seq_printf(seq, "--- End channel @0x%-16.16Lx for 0x%lx bytes ---\n", - addr + off, nbytes); -} -EXPORT_SYMBOL_GPL(visorchannel_debug); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index d248c946a13b..59871495ea85 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -25,21 +25,12 @@ #include #include -#include "channel_guid.h" -#include "controlvmchannel.h" -#include "controlvmcompletionstatus.h" -#include "guestlinuxdebug.h" -#include "periodic_work.h" -#include "version.h" #include "visorbus.h" #include "visorbus_private.h" #include "vmcallinterface.h" #define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c -#define MAX_NAME_SIZE 128 -#define MAX_IP_SIZE 50 -#define MAXOUTSTANDINGCHANNELCOMMAND 256 #define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 #define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 @@ -58,9 +49,6 @@ * Module parameters */ static int visorchipset_major; -static int visorchipset_visorbusregwait = 1; /* default is on */ -static unsigned long controlvm_payload_bytes_buffered; -static u32 dump_vhba_bus; static int visorchipset_open(struct inode *inode, struct file *file) @@ -79,15 +67,15 @@ visorchipset_release(struct inode *inode, struct file *file) return 0; } -/* When the controlvm channel is idle for at least MIN_IDLE_SECONDS, -* we switch to slow polling mode. As soon as we get a controlvm -* message, we switch back to fast polling mode. -*/ +/* + * When the controlvm channel is idle for at least MIN_IDLE_SECONDS, + * we switch to slow polling mode. As soon as we get a controlvm + * message, we switch back to fast polling mode. + */ #define MIN_IDLE_SECONDS 10 static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; /* when we got our last controlvm message */ static unsigned long most_recent_message_jiffies; -static int visorbusregistered; struct parser_context { unsigned long allocbytes; @@ -99,51 +87,36 @@ struct parser_context { }; static struct delayed_work periodic_controlvm_work; -static DEFINE_SEMAPHORE(notifier_lock); static struct cdev file_cdev; static struct visorchannel **file_controlvm_channel; -static struct controlvm_message_packet g_devicechangestate_packet; - -static LIST_HEAD(bus_info_list); -static LIST_HEAD(dev_info_list); static struct visorchannel *controlvm_channel; /* Manages the request payload in the controlvm channel */ struct visor_controlvm_payload_info { u8 *ptr; /* pointer to base address of payload pool */ - u64 offset; /* offset from beginning of controlvm + u64 offset; /* + * offset from beginning of controlvm * channel to beginning of payload * pool */ u32 bytes; /* number of bytes in payload pool */ }; static struct visor_controlvm_payload_info controlvm_payload_info; +static unsigned long controlvm_payload_bytes_buffered; -/* The following globals are used to handle the scenario where we are unable to - * offload the payload from a controlvm message due to memory requirements. In +/* + * The following globals are used to handle the scenario where we are unable to + * offload the payload from a controlvm message due to memory requirements. In * this scenario, we simply stash the controlvm message, then attempt to * process it again the next time controlvm_periodic_work() runs. */ static struct controlvm_message controlvm_pending_msg; static bool controlvm_pending_msg_valid; -/* This identifies a data buffer that has been received via a controlvm messages - * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation. - */ -struct putfile_buffer_entry { - struct list_head next; /* putfile_buffer_entry list */ - struct parser_context *parser_ctx; /* points to input data buffer */ -}; - -/* List of struct putfile_request *, via next_putfile_request member. - * Each entry in this list identifies an outstanding TRANSMIT_FILE - * conversation. - */ -static LIST_HEAD(putfile_request_list); - -/* This describes a buffer and its current state of transfer (e.g., how many +/* + * This describes a buffer and its current state of transfer (e.g., how many * bytes have already been supplied as putfile data, and how many bytes are * remaining) for a putfile_request. */ @@ -155,8 +128,9 @@ struct putfile_active_buffer { }; #define PUTFILE_REQUEST_SIG 0x0906101302281211 -/* This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE - * conversation. Structs of this type are dynamically linked into +/* + * This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE + * conversation. Structs of this type are dynamically linked into * . */ struct putfile_request { @@ -168,7 +142,8 @@ struct putfile_request { /* link to next struct putfile_request */ struct list_head next_putfile_request; - /* head of putfile_buffer_entry list, which describes the data to be + /* + * head of putfile_buffer_entry list, which describes the data to be * supplied as putfile data; * - this list is added to when controlvm messages come in that supply * file data @@ -184,11 +159,13 @@ struct putfile_request { /* data not yet read within current putfile_buffer_entry */ struct putfile_active_buffer active_buf; - /* <0 = failed, 0 = in-progress, >0 = successful; */ - /* note that this must be set with req_list_lock, and if you set <0, */ - /* it is your responsibility to also free up all of the other objects */ - /* in this struct (like input_buffer_list, active_buf.parser_ctx) */ - /* before releasing the lock */ + /* + * <0 = failed, 0 = in-progress, >0 = successful; + * note that this must be set with req_list_lock, and if you set <0, + * it is your responsibility to also free up all of the other objects + * in this struct (like input_buffer_list, active_buf.parser_ctx) + * before releasing the lock + */ int completion_status; }; @@ -199,193 +176,179 @@ struct parahotplug_request { struct controlvm_message msg; }; -static LIST_HEAD(parahotplug_request_list); -static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ -static void parahotplug_process_list(void); - -/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE / - * CONTROLVM_REPORTEVENT. - */ -static struct visorchipset_busdev_notifiers busdev_notifiers; - -static void bus_create_response(struct visor_device *p, int response); -static void bus_destroy_response(struct visor_device *p, int response); -static void device_create_response(struct visor_device *p, int response); -static void device_destroy_response(struct visor_device *p, int response); -static void device_resume_response(struct visor_device *p, int response); - -static void visorchipset_device_pause_response(struct visor_device *p, - int response); - -static struct visorchipset_busdev_responders busdev_responders = { - .bus_create = bus_create_response, - .bus_destroy = bus_destroy_response, - .device_create = device_create_response, - .device_destroy = device_destroy_response, - .device_pause = visorchipset_device_pause_response, - .device_resume = device_resume_response, -}; - /* info for /dev/visorchipset */ -static dev_t major_dev = -1; /**< indicates major num for device */ +static dev_t major_dev = -1; /*< indicates major num for device */ /* prototypes for attributes */ static ssize_t toolaction_show(struct device *dev, - struct device_attribute *attr, char *buf); + struct device_attribute *attr, + char *buf) +{ + u8 tool_action = 0; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), &tool_action, sizeof(u8)); + return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); +} + static ssize_t toolaction_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); + const char *buf, size_t count) +{ + u8 tool_action; + int ret; + + if (kstrtou8(buf, 10, &tool_action)) + return -EINVAL; + + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), + &tool_action, sizeof(u8)); + + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(toolaction); static ssize_t boottotool_show(struct device *dev, - struct device_attribute *attr, char *buf); + struct device_attribute *attr, + char *buf) +{ + struct efi_spar_indication efi_spar_indication; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), &efi_spar_indication, + sizeof(struct efi_spar_indication)); + return scnprintf(buf, PAGE_SIZE, "%u\n", + efi_spar_indication.boot_to_tool); +} + static ssize_t boottotool_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count); + struct device_attribute *attr, + const char *buf, size_t count) +{ + int val, ret; + struct efi_spar_indication efi_spar_indication; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + efi_spar_indication.boot_to_tool = val; + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), &(efi_spar_indication), + sizeof(struct efi_spar_indication)); + + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(boottotool); static ssize_t error_show(struct device *dev, struct device_attribute *attr, - char *buf); + char *buf) +{ + u32 error = 0; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); + return scnprintf(buf, PAGE_SIZE, "%i\n", error); +} + static ssize_t error_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); + const char *buf, size_t count) +{ + u32 error; + int ret; + + if (kstrtou32(buf, 10, &error)) + return -EINVAL; + + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(error); static ssize_t textid_show(struct device *dev, struct device_attribute *attr, - char *buf); + char *buf) +{ + u32 text_id = 0; + + visorchannel_read + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); + return scnprintf(buf, PAGE_SIZE, "%i\n", text_id); +} + static ssize_t textid_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); + const char *buf, size_t count) +{ + u32 text_id; + int ret; + + if (kstrtou32(buf, 10, &text_id)) + return -EINVAL; + + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(textid); static ssize_t remaining_steps_show(struct device *dev, - struct device_attribute *attr, char *buf); + struct device_attribute *attr, char *buf) +{ + u16 remaining_steps = 0; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); + return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps); +} + static ssize_t remaining_steps_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); + const char *buf, size_t count) +{ + u16 remaining_steps; + int ret; + + if (kstrtou16(buf, 10, &remaining_steps)) + return -EINVAL; + + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(remaining_steps); -static ssize_t devicedisabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_WO(devicedisabled); - -static ssize_t deviceenabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_WO(deviceenabled); - -static struct attribute *visorchipset_install_attrs[] = { - &dev_attr_toolaction.attr, - &dev_attr_boottotool.attr, - &dev_attr_error.attr, - &dev_attr_textid.attr, - &dev_attr_remaining_steps.attr, - NULL -}; - -static struct attribute_group visorchipset_install_group = { - .name = "install", - .attrs = visorchipset_install_attrs -}; - -static struct attribute *visorchipset_parahotplug_attrs[] = { - &dev_attr_devicedisabled.attr, - &dev_attr_deviceenabled.attr, - NULL -}; - -static struct attribute_group visorchipset_parahotplug_group = { - .name = "parahotplug", - .attrs = visorchipset_parahotplug_attrs -}; - -static const struct attribute_group *visorchipset_dev_groups[] = { - &visorchipset_install_group, - &visorchipset_parahotplug_group, - NULL -}; - -static void visorchipset_dev_release(struct device *dev) -{ -} - -/* /sys/devices/platform/visorchipset */ -static struct platform_device visorchipset_platform_device = { - .name = "visorchipset", - .id = -1, - .dev.groups = visorchipset_dev_groups, - .dev.release = visorchipset_dev_release, -}; - -/* Function prototypes */ -static void controlvm_respond(struct controlvm_message_header *msg_hdr, - int response); -static void controlvm_respond_chipset_init( - struct controlvm_message_header *msg_hdr, int response, - enum ultra_chipset_feature features); -static void controlvm_respond_physdev_changestate( - struct controlvm_message_header *msg_hdr, int response, - struct spar_segment_state state); - -static void parser_done(struct parser_context *ctx); - -static struct parser_context * -parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) -{ - int allocbytes = sizeof(struct parser_context) + bytes; - struct parser_context *ctx; - - if (retry) - *retry = false; - - /* - * alloc an 0 extra byte to ensure payload is - * '\0'-terminated - */ - allocbytes++; - if ((controlvm_payload_bytes_buffered + bytes) - > MAX_CONTROLVM_PAYLOAD_BYTES) { - if (retry) - *retry = true; - return NULL; - } - ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); - if (!ctx) { - if (retry) - *retry = true; - return NULL; - } - - ctx->allocbytes = allocbytes; - ctx->param_bytes = bytes; - ctx->curr = NULL; - ctx->bytes_remaining = 0; - ctx->byte_stream = false; - if (local) { - void *p; - - if (addr > virt_to_phys(high_memory - 1)) - goto err_finish_ctx; - p = __va((unsigned long)(addr)); - memcpy(ctx->data, p, bytes); - } else { - void *mapping = memremap(addr, bytes, MEMREMAP_WB); - - if (!mapping) - goto err_finish_ctx; - memcpy(ctx->data, mapping, bytes); - memunmap(mapping); - } - - ctx->byte_stream = true; - controlvm_payload_bytes_buffered += ctx->param_bytes; - - return ctx; - -err_finish_ctx: - parser_done(ctx); - return NULL; -} - static uuid_le parser_id_get(struct parser_context *ctx) { @@ -397,8 +360,9 @@ parser_id_get(struct parser_context *ctx) return phdr->id; } -/** Describes the state from the perspective of which controlvm messages have - * been received for a bus or device. +/* + * Describes the state from the perspective of which controlvm messages have + * been received for a bus or device. */ enum PARSER_WHICH_STRING { @@ -481,170 +445,6 @@ parser_string_get(struct parser_context *ctx) return value; } -static ssize_t toolaction_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - u8 tool_action = 0; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), &tool_action, sizeof(u8)); - return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); -} - -static ssize_t toolaction_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u8 tool_action; - int ret; - - if (kstrtou8(buf, 10, &tool_action)) - return -EINVAL; - - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), - &tool_action, sizeof(u8)); - - if (ret) - return ret; - return count; -} - -static ssize_t boottotool_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct efi_spar_indication efi_spar_indication; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &efi_spar_indication, - sizeof(struct efi_spar_indication)); - return scnprintf(buf, PAGE_SIZE, "%u\n", - efi_spar_indication.boot_to_tool); -} - -static ssize_t boottotool_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int val, ret; - struct efi_spar_indication efi_spar_indication; - - if (kstrtoint(buf, 10, &val)) - return -EINVAL; - - efi_spar_indication.boot_to_tool = val; - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &(efi_spar_indication), - sizeof(struct efi_spar_indication)); - - if (ret) - return ret; - return count; -} - -static ssize_t error_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u32 error = 0; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); - return scnprintf(buf, PAGE_SIZE, "%i\n", error); -} - -static ssize_t error_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - u32 error; - int ret; - - if (kstrtou32(buf, 10, &error)) - return -EINVAL; - - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); - if (ret) - return ret; - return count; -} - -static ssize_t textid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u32 text_id = 0; - - visorchannel_read - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); - return scnprintf(buf, PAGE_SIZE, "%i\n", text_id); -} - -static ssize_t textid_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - u32 text_id; - int ret; - - if (kstrtou32(buf, 10, &text_id)) - return -EINVAL; - - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); - if (ret) - return ret; - return count; -} - -static ssize_t remaining_steps_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u16 remaining_steps = 0; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); - return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps); -} - -static ssize_t remaining_steps_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u16 remaining_steps; - int ret; - - if (kstrtou16(buf, 10, &remaining_steps)) - return -EINVAL; - - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); - if (ret) - return ret; - return count; -} - struct visor_busdev { u32 bus_no; u32 dev_no; @@ -683,64 +483,6 @@ struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, vdev = to_visor_device(dev); return vdev; } -EXPORT_SYMBOL(visorbus_get_device_by_id); - -void -visorchipset_register_busdev( - struct visorchipset_busdev_notifiers *notifiers, - struct visorchipset_busdev_responders *responders, - struct ultra_vbus_deviceinfo *driver_info) -{ - down(¬ifier_lock); - if (!notifiers) { - memset(&busdev_notifiers, 0, - sizeof(busdev_notifiers)); - visorbusregistered = 0; /* clear flag */ - } else { - busdev_notifiers = *notifiers; - visorbusregistered = 1; /* set flag */ - } - if (responders) - *responders = busdev_responders; - if (driver_info) - bus_device_info_init(driver_info, "chipset", "visorchipset", - VERSION, NULL); - - up(¬ifier_lock); -} -EXPORT_SYMBOL_GPL(visorchipset_register_busdev); - -static void -chipset_init(struct controlvm_message *inmsg) -{ - static int chipset_inited; - enum ultra_chipset_feature features = 0; - int rc = CONTROLVM_RESP_SUCCESS; - - POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); - if (chipset_inited) { - rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto out_respond; - } - chipset_inited = 1; - POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); - - /* Set features to indicate we support parahotplug (if Command - * also supports it). - */ - features = - inmsg->cmd.init_chipset. - features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG; - - /* Set the "reply" bit so Command knows this is a - * features-aware driver. - */ - features |= ULTRA_CHIPSET_FEATURE_REPLY; - -out_respond: - if (inmsg->hdr.flags.response_expected) - controlvm_respond_chipset_init(&inmsg->hdr, rc, features); -} static void controlvm_init_response(struct controlvm_message *msg, @@ -757,21 +499,6 @@ controlvm_init_response(struct controlvm_message *msg, } } -static void -controlvm_respond(struct controlvm_message_header *msg_hdr, int response) -{ - struct controlvm_message outmsg; - - controlvm_init_response(&outmsg, msg_hdr, response); - if (outmsg.hdr.flags.test_message == 1) - return; - - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { - return; - } -} - static void controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr, int response, @@ -781,8 +508,57 @@ controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr, controlvm_init_response(&outmsg, msg_hdr, response); outmsg.cmd.init_chipset.features = features; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { + if (visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { + return; + } +} + +static void +chipset_init(struct controlvm_message *inmsg) +{ + static int chipset_inited; + enum ultra_chipset_feature features = 0; + int rc = CONTROLVM_RESP_SUCCESS; + + POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); + if (chipset_inited) { + rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; + goto out_respond; + } + chipset_inited = 1; + POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); + + /* + * Set features to indicate we support parahotplug (if Command + * also supports it). + */ + features = + inmsg->cmd.init_chipset. + features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG; + + /* + * Set the "reply" bit so Command knows this is a + * features-aware driver. + */ + features |= ULTRA_CHIPSET_FEATURE_REPLY; + +out_respond: + if (inmsg->hdr.flags.response_expected) + controlvm_respond_chipset_init(&inmsg->hdr, rc, features); +} + +static void +controlvm_respond(struct controlvm_message_header *msg_hdr, int response) +{ + struct controlvm_message outmsg; + + controlvm_init_response(&outmsg, msg_hdr, response); + if (outmsg.hdr.flags.test_message == 1) + return; + + if (visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { return; } } @@ -796,8 +572,8 @@ static void controlvm_respond_physdev_changestate( controlvm_init_response(&outmsg, msg_hdr, response); outmsg.cmd.device_change_state.state = state; outmsg.cmd.device_change_state.flags.phys_device = 1; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { + if (visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { return; } } @@ -894,8 +670,8 @@ device_changestate_responder(enum controlvm_id cmd_id, outmsg.cmd.device_change_state.dev_no = dev_no; outmsg.cmd.device_change_state.state = response_state; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) + if (visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) return; } @@ -920,20 +696,20 @@ bus_epilog(struct visor_device *bus_info, { struct controlvm_message_header *pmsg_hdr = NULL; - down(¬ifier_lock); - if (!bus_info) { - /* relying on a valid passed in response code */ - /* be lazy and re-use msg_hdr for this failure, is this ok?? */ + /* + * relying on a valid passed in response code + * be lazy and re-use msg_hdr for this failure, is this ok?? + */ pmsg_hdr = msg_hdr; - goto out_respond_and_unlock; + goto out_respond; } if (bus_info->pending_msg_hdr) { /* only non-NULL if dev is still waiting on a response */ response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; pmsg_hdr = bus_info->pending_msg_hdr; - goto out_respond_and_unlock; + goto out_respond; } if (need_response) { @@ -942,7 +718,7 @@ bus_epilog(struct visor_device *bus_info, POSTCODE_LINUX_4(MALLOC_FAILURE_PC, cmd, bus_info->chipset_bus_no, POSTCODE_SEVERITY_ERR); - goto out_unlock; + return; } memcpy(pmsg_hdr, msg_hdr, @@ -953,25 +729,16 @@ bus_epilog(struct visor_device *bus_info, if (response == CONTROLVM_RESP_SUCCESS) { switch (cmd) { case CONTROLVM_BUS_CREATE: - if (busdev_notifiers.bus_create) { - (*busdev_notifiers.bus_create) (bus_info); - goto out_unlock; - } + chipset_bus_create(bus_info); break; case CONTROLVM_BUS_DESTROY: - if (busdev_notifiers.bus_destroy) { - (*busdev_notifiers.bus_destroy) (bus_info); - goto out_unlock; - } + chipset_bus_destroy(bus_info); break; } } -out_respond_and_unlock: +out_respond: bus_responder(cmd, pmsg_hdr, response); - -out_unlock: - up(¬ifier_lock); } static void @@ -980,31 +747,29 @@ device_epilog(struct visor_device *dev_info, struct controlvm_message_header *msg_hdr, int response, bool need_response, bool for_visorbus) { - struct visorchipset_busdev_notifiers *notifiers; struct controlvm_message_header *pmsg_hdr = NULL; - notifiers = &busdev_notifiers; - - down(¬ifier_lock); if (!dev_info) { - /* relying on a valid passed in response code */ - /* be lazy and re-use msg_hdr for this failure, is this ok?? */ + /* + * relying on a valid passed in response code + * be lazy and re-use msg_hdr for this failure, is this ok?? + */ pmsg_hdr = msg_hdr; - goto out_respond_and_unlock; + goto out_respond; } if (dev_info->pending_msg_hdr) { /* only non-NULL if dev is still waiting on a response */ response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; pmsg_hdr = dev_info->pending_msg_hdr; - goto out_respond_and_unlock; + goto out_respond; } if (need_response) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto out_respond_and_unlock; + goto out_respond; } memcpy(pmsg_hdr, msg_hdr, @@ -1015,48 +780,34 @@ device_epilog(struct visor_device *dev_info, if (response >= 0) { switch (cmd) { case CONTROLVM_DEVICE_CREATE: - if (notifiers->device_create) { - (*notifiers->device_create) (dev_info); - goto out_unlock; - } + chipset_device_create(dev_info); break; case CONTROLVM_DEVICE_CHANGESTATE: /* ServerReady / ServerRunning / SegmentStateRunning */ if (state.alive == segment_state_running.alive && state.operating == segment_state_running.operating) { - if (notifiers->device_resume) { - (*notifiers->device_resume) (dev_info); - goto out_unlock; - } + chipset_device_resume(dev_info); } /* ServerNotReady / ServerLost / SegmentStateStandby */ else if (state.alive == segment_state_standby.alive && state.operating == segment_state_standby.operating) { - /* technically this is standby case + /* + * technically this is standby case * where server is lost */ - if (notifiers->device_pause) { - (*notifiers->device_pause) (dev_info); - goto out_unlock; - } + chipset_device_pause(dev_info); } break; case CONTROLVM_DEVICE_DESTROY: - if (notifiers->device_destroy) { - (*notifiers->device_destroy) (dev_info); - goto out_unlock; - } + chipset_device_destroy(dev_info); break; } } -out_respond_and_unlock: +out_respond: device_responder(cmd, pmsg_hdr, response); - -out_unlock: - up(¬ifier_lock); } static void @@ -1103,10 +854,8 @@ bus_create(struct controlvm_message *inmsg) goto out_bus_epilog; } bus_info->visorchannel = visorchannel; - if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) { - dump_vhba_bus = bus_no; + if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) save_crash_message(inmsg, CRASH_BUS); - } POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); @@ -1303,11 +1052,19 @@ my_device_destroy(struct controlvm_message *inmsg) inmsg->hdr.flags.response_expected == 1, 1); } -/* When provided with the physical address of the controlvm channel +/** + * initialize_controlvm_payload_info() - init controlvm_payload_info struct + * @phys_addr: the physical address of controlvm channel + * @offset: the offset to payload + * @bytes: the size of the payload in bytes + * @info: the returning valid struct + * + * When provided with the physical address of the controlvm channel * (phys_addr), the offset to the payload area we need to manage * (offset), and the size of this payload area (bytes), fills in the - * controlvm_payload_info struct. Returns true for success or false - * for failure. + * controlvm_payload_info struct. + * + * Return: CONTROLVM_RESP_SUCCESS for success or a negative for failure */ static int initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes, @@ -1371,8 +1128,315 @@ initialize_controlvm_payload(void) &controlvm_payload_info); } -/* Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset. - * Returns CONTROLVM_RESP_xxx code. +/* + * The general parahotplug flow works as follows. The visorchipset + * driver receives a DEVICE_CHANGESTATE message from Command + * specifying a physical device to enable or disable. The CONTROLVM + * message handler calls parahotplug_process_message, which then adds + * the message to a global list and kicks off a udev event which + * causes a user level script to enable or disable the specified + * device. The udev script then writes to + * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write + * to get called, at which point the appropriate CONTROLVM message is + * retrieved from the list and responded to. + */ + +#define PARAHOTPLUG_TIMEOUT_MS 2000 + +/** + * parahotplug_next_id() - generate unique int to match an outstanding CONTROLVM + * message with a udev script /proc response + * + * Return: a unique integer value + */ +static int +parahotplug_next_id(void) +{ + static atomic_t id = ATOMIC_INIT(0); + + return atomic_inc_return(&id); +} + +/** + * parahotplug_next_expiration() - returns the time (in jiffies) when a + * CONTROLVM message on the list should expire + * -- PARAHOTPLUG_TIMEOUT_MS in the future + * + * Return: expected expiration time (in jiffies) + */ +static unsigned long +parahotplug_next_expiration(void) +{ + return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); +} + +/** + * parahotplug_request_create() - create a parahotplug_request, which is + * basically a wrapper for a CONTROLVM_MESSAGE + * that we can stick on a list + * @msg: the message to insert in the request + * + * Return: the request containing the provided message + */ +static struct parahotplug_request * +parahotplug_request_create(struct controlvm_message *msg) +{ + struct parahotplug_request *req; + + req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY); + if (!req) + return NULL; + + req->id = parahotplug_next_id(); + req->expiration = parahotplug_next_expiration(); + req->msg = *msg; + + return req; +} + +/** + * parahotplug_request_destroy() - free a parahotplug_request + * @req: the request to deallocate + */ +static void +parahotplug_request_destroy(struct parahotplug_request *req) +{ + kfree(req); +} + +static LIST_HEAD(parahotplug_request_list); +static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ + +/** + * parahotplug_request_complete() - mark request as complete + * @id: the id of the request + * @active: indicates whether the request is assigned to active partition + * + * Called from the /proc handler, which means the user script has + * finished the enable/disable. Find the matching identifier, and + * respond to the CONTROLVM message with success. + * + * Return: 0 on success or -EINVAL on failure + */ +static int +parahotplug_request_complete(int id, u16 active) +{ + struct list_head *pos; + struct list_head *tmp; + + spin_lock(¶hotplug_request_list_lock); + + /* Look for a request matching "id". */ + list_for_each_safe(pos, tmp, ¶hotplug_request_list) { + struct parahotplug_request *req = + list_entry(pos, struct parahotplug_request, list); + if (req->id == id) { + /* + * Found a match. Remove it from the list and + * respond. + */ + list_del(pos); + spin_unlock(¶hotplug_request_list_lock); + req->msg.cmd.device_change_state.state.active = active; + if (req->msg.hdr.flags.response_expected) + controlvm_respond_physdev_changestate( + &req->msg.hdr, CONTROLVM_RESP_SUCCESS, + req->msg.cmd.device_change_state.state); + parahotplug_request_destroy(req); + return 0; + } + } + + spin_unlock(¶hotplug_request_list_lock); + return -EINVAL; +} + +/** + * devicedisabled_store() - disables the hotplug device + * @dev: sysfs interface variable not utilized in this function + * @attr: sysfs interface variable not utilized in this function + * @buf: buffer containing the device id + * @count: the size of the buffer + * + * The parahotplug/devicedisabled interface gets called by our support script + * when an SR-IOV device has been shut down. The ID is passed to the script + * and then passed back when the device has been removed. + * + * Return: the size of the buffer for success or negative for error + */ +static ssize_t devicedisabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int id; + int err; + + if (kstrtouint(buf, 10, &id)) + return -EINVAL; + + err = parahotplug_request_complete(id, 0); + if (err < 0) + return err; + return count; +} +static DEVICE_ATTR_WO(devicedisabled); + +/** + * deviceenabled_store() - enables the hotplug device + * @dev: sysfs interface variable not utilized in this function + * @attr: sysfs interface variable not utilized in this function + * @buf: buffer containing the device id + * @count: the size of the buffer + * + * The parahotplug/deviceenabled interface gets called by our support script + * when an SR-IOV device has been recovered. The ID is passed to the script + * and then passed back when the device has been brought back up. + * + * Return: the size of the buffer for success or negative for error + */ +static ssize_t deviceenabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int id; + + if (kstrtouint(buf, 10, &id)) + return -EINVAL; + + parahotplug_request_complete(id, 1); + return count; +} +static DEVICE_ATTR_WO(deviceenabled); + +static struct attribute *visorchipset_install_attrs[] = { + &dev_attr_toolaction.attr, + &dev_attr_boottotool.attr, + &dev_attr_error.attr, + &dev_attr_textid.attr, + &dev_attr_remaining_steps.attr, + NULL +}; + +static struct attribute_group visorchipset_install_group = { + .name = "install", + .attrs = visorchipset_install_attrs +}; + +static struct attribute *visorchipset_parahotplug_attrs[] = { + &dev_attr_devicedisabled.attr, + &dev_attr_deviceenabled.attr, + NULL +}; + +static struct attribute_group visorchipset_parahotplug_group = { + .name = "parahotplug", + .attrs = visorchipset_parahotplug_attrs +}; + +static const struct attribute_group *visorchipset_dev_groups[] = { + &visorchipset_install_group, + &visorchipset_parahotplug_group, + NULL +}; + +static void visorchipset_dev_release(struct device *dev) +{ +} + +/* /sys/devices/platform/visorchipset */ +static struct platform_device visorchipset_platform_device = { + .name = "visorchipset", + .id = -1, + .dev.groups = visorchipset_dev_groups, + .dev.release = visorchipset_dev_release, +}; + +/** + * parahotplug_request_kickoff() - initiate parahotplug request + * @req: the request to initiate + * + * Cause uevent to run the user level script to do the disable/enable specified + * in the parahotplug_request. + */ +static void +parahotplug_request_kickoff(struct parahotplug_request *req) +{ + struct controlvm_message_packet *cmd = &req->msg.cmd; + char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40], + env_func[40]; + char *envp[] = { + env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL + }; + + sprintf(env_cmd, "SPAR_PARAHOTPLUG=1"); + sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id); + sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d", + cmd->device_change_state.state.active); + sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d", + cmd->device_change_state.bus_no); + sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d", + cmd->device_change_state.dev_no >> 3); + sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d", + cmd->device_change_state.dev_no & 0x7); + + kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, + envp); +} + +/** + * parahotplug_process_message() - enables or disables a PCI device by kicking + * off a udev script + * @inmsg: the message indicating whether to enable or disable + */ +static void +parahotplug_process_message(struct controlvm_message *inmsg) +{ + struct parahotplug_request *req; + + req = parahotplug_request_create(inmsg); + + if (!req) + return; + + if (inmsg->cmd.device_change_state.state.active) { + /* + * For enable messages, just respond with success + * right away. This is a bit of a hack, but there are + * issues with the early enable messages we get (with + * either the udev script not detecting that the device + * is up, or not getting called at all). Fortunately + * the messages that get lost don't matter anyway, as + * + * devices are automatically enabled at + * initialization. + */ + parahotplug_request_kickoff(req); + controlvm_respond_physdev_changestate + (&inmsg->hdr, + CONTROLVM_RESP_SUCCESS, + inmsg->cmd.device_change_state.state); + parahotplug_request_destroy(req); + } else { + /* + * For disable messages, add the request to the + * request list before kicking off the udev script. It + * won't get responded to until the script has + * indicated it's done. + */ + spin_lock(¶hotplug_request_list_lock); + list_add_tail(&req->list, ¶hotplug_request_list); + spin_unlock(¶hotplug_request_list_lock); + + parahotplug_request_kickoff(req); + } +} + +/** + * visorchipset_chipset_ready() - sends chipset_ready action + * + * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset. + * + * Return: CONTROLVM_RESP_SUCCESS */ static int visorchipset_chipset_ready(void) @@ -1393,8 +1457,12 @@ visorchipset_chipset_selftest(void) return CONTROLVM_RESP_SUCCESS; } -/* Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset. - * Returns CONTROLVM_RESP_xxx code. +/** + * visorchipset_chipset_notready() - sends chipset_notready action + * + * Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset. + * + * Return: CONTROLVM_RESP_SUCCESS */ static int visorchipset_chipset_notready(void) @@ -1436,338 +1504,6 @@ chipset_notready(struct controlvm_message_header *msg_hdr) controlvm_respond(msg_hdr, rc); } -/* This is your "one-stop" shop for grabbing the next message from the - * CONTROLVM_QUEUE_EVENT queue in the controlvm channel. - */ -static bool -read_controlvm_event(struct controlvm_message *msg) -{ - if (visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_EVENT, msg)) { - /* got a message */ - if (msg->hdr.flags.test_message == 1) - return false; - return true; - } - return false; -} - -/* - * The general parahotplug flow works as follows. The visorchipset - * driver receives a DEVICE_CHANGESTATE message from Command - * specifying a physical device to enable or disable. The CONTROLVM - * message handler calls parahotplug_process_message, which then adds - * the message to a global list and kicks off a udev event which - * causes a user level script to enable or disable the specified - * device. The udev script then writes to - * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write - * to get called, at which point the appropriate CONTROLVM message is - * retrieved from the list and responded to. - */ - -#define PARAHOTPLUG_TIMEOUT_MS 2000 - -/* - * Generate unique int to match an outstanding CONTROLVM message with a - * udev script /proc response - */ -static int -parahotplug_next_id(void) -{ - static atomic_t id = ATOMIC_INIT(0); - - return atomic_inc_return(&id); -} - -/* - * Returns the time (in jiffies) when a CONTROLVM message on the list - * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future - */ -static unsigned long -parahotplug_next_expiration(void) -{ - return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); -} - -/* - * Create a parahotplug_request, which is basically a wrapper for a - * CONTROLVM_MESSAGE that we can stick on a list - */ -static struct parahotplug_request * -parahotplug_request_create(struct controlvm_message *msg) -{ - struct parahotplug_request *req; - - req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY); - if (!req) - return NULL; - - req->id = parahotplug_next_id(); - req->expiration = parahotplug_next_expiration(); - req->msg = *msg; - - return req; -} - -/* - * Free a parahotplug_request. - */ -static void -parahotplug_request_destroy(struct parahotplug_request *req) -{ - kfree(req); -} - -/* - * Cause uevent to run the user level script to do the disable/enable - * specified in (the CONTROLVM message in) the specified - * parahotplug_request - */ -static void -parahotplug_request_kickoff(struct parahotplug_request *req) -{ - struct controlvm_message_packet *cmd = &req->msg.cmd; - char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40], - env_func[40]; - char *envp[] = { - env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL - }; - - sprintf(env_cmd, "SPAR_PARAHOTPLUG=1"); - sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id); - sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d", - cmd->device_change_state.state.active); - sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d", - cmd->device_change_state.bus_no); - sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d", - cmd->device_change_state.dev_no >> 3); - sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d", - cmd->device_change_state.dev_no & 0x7); - - kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, - envp); -} - -/* - * Remove any request from the list that's been on there too long and - * respond with an error. - */ -static void -parahotplug_process_list(void) -{ - struct list_head *pos; - struct list_head *tmp; - - spin_lock(¶hotplug_request_list_lock); - - list_for_each_safe(pos, tmp, ¶hotplug_request_list) { - struct parahotplug_request *req = - list_entry(pos, struct parahotplug_request, list); - - if (!time_after_eq(jiffies, req->expiration)) - continue; - - list_del(pos); - if (req->msg.hdr.flags.response_expected) - controlvm_respond_physdev_changestate( - &req->msg.hdr, - CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT, - req->msg.cmd.device_change_state.state); - parahotplug_request_destroy(req); - } - - spin_unlock(¶hotplug_request_list_lock); -} - -/* - * Called from the /proc handler, which means the user script has - * finished the enable/disable. Find the matching identifier, and - * respond to the CONTROLVM message with success. - */ -static int -parahotplug_request_complete(int id, u16 active) -{ - struct list_head *pos; - struct list_head *tmp; - - spin_lock(¶hotplug_request_list_lock); - - /* Look for a request matching "id". */ - list_for_each_safe(pos, tmp, ¶hotplug_request_list) { - struct parahotplug_request *req = - list_entry(pos, struct parahotplug_request, list); - if (req->id == id) { - /* Found a match. Remove it from the list and - * respond. - */ - list_del(pos); - spin_unlock(¶hotplug_request_list_lock); - req->msg.cmd.device_change_state.state.active = active; - if (req->msg.hdr.flags.response_expected) - controlvm_respond_physdev_changestate( - &req->msg.hdr, CONTROLVM_RESP_SUCCESS, - req->msg.cmd.device_change_state.state); - parahotplug_request_destroy(req); - return 0; - } - } - - spin_unlock(¶hotplug_request_list_lock); - return -EINVAL; -} - -/* - * Enables or disables a PCI device by kicking off a udev script - */ -static void -parahotplug_process_message(struct controlvm_message *inmsg) -{ - struct parahotplug_request *req; - - req = parahotplug_request_create(inmsg); - - if (!req) - return; - - if (inmsg->cmd.device_change_state.state.active) { - /* For enable messages, just respond with success - * right away. This is a bit of a hack, but there are - * issues with the early enable messages we get (with - * either the udev script not detecting that the device - * is up, or not getting called at all). Fortunately - * the messages that get lost don't matter anyway, as - * devices are automatically enabled at - * initialization. - */ - parahotplug_request_kickoff(req); - controlvm_respond_physdev_changestate - (&inmsg->hdr, - CONTROLVM_RESP_SUCCESS, - inmsg->cmd.device_change_state.state); - parahotplug_request_destroy(req); - } else { - /* For disable messages, add the request to the - * request list before kicking off the udev script. It - * won't get responded to until the script has - * indicated it's done. - */ - spin_lock(¶hotplug_request_list_lock); - list_add_tail(&req->list, ¶hotplug_request_list); - spin_unlock(¶hotplug_request_list_lock); - - parahotplug_request_kickoff(req); - } -} - -/* Process a controlvm message. - * Return result: - * false - this function will return false only in the case where the - * controlvm message was NOT processed, but processing must be - * retried before reading the next controlvm message; a - * scenario where this can occur is when we need to throttle - * the allocation of memory in which to copy out controlvm - * payload data - * true - processing of the controlvm message completed, - * either successfully or with an error. - */ -static bool -handle_command(struct controlvm_message inmsg, u64 channel_addr) -{ - struct controlvm_message_packet *cmd = &inmsg.cmd; - u64 parm_addr; - u32 parm_bytes; - struct parser_context *parser_ctx = NULL; - bool local_addr; - struct controlvm_message ackmsg; - - /* create parsing context if necessary */ - local_addr = (inmsg.hdr.flags.test_message == 1); - if (channel_addr == 0) - return true; - parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; - parm_bytes = inmsg.hdr.payload_bytes; - - /* Parameter and channel addresses within test messages actually lie - * within our OS-controlled memory. We need to know that, because it - * makes a difference in how we compute the virtual address. - */ - if (parm_addr && parm_bytes) { - bool retry = false; - - parser_ctx = - parser_init_byte_stream(parm_addr, parm_bytes, - local_addr, &retry); - if (!parser_ctx && retry) - return false; - } - - if (!local_addr) { - controlvm_init_response(&ackmsg, &inmsg.hdr, - CONTROLVM_RESP_SUCCESS); - if (controlvm_channel) - visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_ACK, - &ackmsg); - } - switch (inmsg.hdr.id) { - case CONTROLVM_CHIPSET_INIT: - chipset_init(&inmsg); - break; - case CONTROLVM_BUS_CREATE: - bus_create(&inmsg); - break; - case CONTROLVM_BUS_DESTROY: - bus_destroy(&inmsg); - break; - case CONTROLVM_BUS_CONFIGURE: - bus_configure(&inmsg, parser_ctx); - break; - case CONTROLVM_DEVICE_CREATE: - my_device_create(&inmsg); - break; - case CONTROLVM_DEVICE_CHANGESTATE: - if (cmd->device_change_state.flags.phys_device) { - parahotplug_process_message(&inmsg); - } else { - /* save the hdr and cmd structures for later use */ - /* when sending back the response to Command */ - my_device_changestate(&inmsg); - g_devicechangestate_packet = inmsg.cmd; - break; - } - break; - case CONTROLVM_DEVICE_DESTROY: - my_device_destroy(&inmsg); - break; - case CONTROLVM_DEVICE_CONFIGURE: - /* no op for now, just send a respond that we passed */ - if (inmsg.hdr.flags.response_expected) - controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS); - break; - case CONTROLVM_CHIPSET_READY: - chipset_ready(&inmsg.hdr); - break; - case CONTROLVM_CHIPSET_SELFTEST: - chipset_selftest(&inmsg.hdr); - break; - case CONTROLVM_CHIPSET_STOP: - chipset_notready(&inmsg.hdr); - break; - default: - if (inmsg.hdr.flags.response_expected) - controlvm_respond - (&inmsg.hdr, - -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); - break; - } - - if (parser_ctx) { - parser_done(parser_ctx); - parser_ctx = NULL; - } - return true; -} - static inline unsigned int issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes) { @@ -1795,76 +1531,6 @@ static u64 controlvm_get_channel_address(void) return addr; } -static void -controlvm_periodic_work(struct work_struct *work) -{ - struct controlvm_message inmsg; - bool got_command = false; - bool handle_command_failed = false; - - /* make sure visorbus server is registered for controlvm callbacks */ - if (visorchipset_visorbusregwait && !visorbusregistered) - goto cleanup; - - while (visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_RESPONSE, - &inmsg)) - ; - if (!got_command) { - if (controlvm_pending_msg_valid) { - /* we throttled processing of a prior - * msg, so try to process it again - * rather than reading a new one - */ - inmsg = controlvm_pending_msg; - controlvm_pending_msg_valid = false; - got_command = true; - } else { - got_command = read_controlvm_event(&inmsg); - } - } - - handle_command_failed = false; - while (got_command && (!handle_command_failed)) { - most_recent_message_jiffies = jiffies; - if (handle_command(inmsg, - visorchannel_get_physaddr - (controlvm_channel))) - got_command = read_controlvm_event(&inmsg); - else { - /* this is a scenario where throttling - * is required, but probably NOT an - * error...; we stash the current - * controlvm msg so we will attempt to - * reprocess it on our next loop - */ - handle_command_failed = true; - controlvm_pending_msg = inmsg; - controlvm_pending_msg_valid = true; - } - } - - /* parahotplug_worker */ - parahotplug_process_list(); - -cleanup: - - if (time_after(jiffies, - most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { - /* it's been longer than MIN_IDLE_SECONDS since we - * processed our last controlvm message; slow down the - * polling - */ - if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - } else { - if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - } - - schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); -} - static void setup_crash_devices_work_queue(struct work_struct *work) { @@ -1874,13 +1540,6 @@ setup_crash_devices_work_queue(struct work_struct *work) u32 local_crash_msg_offset; u16 local_crash_msg_count; - /* make sure visorbus is registered for controlvm callbacks */ - if (visorchipset_visorbusregwait && !visorbusregistered) { - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); - return; - } - POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO); /* send init chipset msg */ @@ -1958,7 +1617,7 @@ setup_crash_devices_work_queue(struct work_struct *work) POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO); } -static void +void bus_create_response(struct visor_device *bus_info, int response) { if (response >= 0) @@ -1971,7 +1630,7 @@ bus_create_response(struct visor_device *bus_info, int response) bus_info->pending_msg_hdr = NULL; } -static void +void bus_destroy_response(struct visor_device *bus_info, int response) { bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr, @@ -1981,7 +1640,7 @@ bus_destroy_response(struct visor_device *bus_info, int response) bus_info->pending_msg_hdr = NULL; } -static void +void device_create_response(struct visor_device *dev_info, int response) { if (response >= 0) @@ -1994,7 +1653,7 @@ device_create_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -static void +void device_destroy_response(struct visor_device *dev_info, int response) { device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr, @@ -2004,9 +1663,9 @@ device_destroy_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -static void -visorchipset_device_pause_response(struct visor_device *dev_info, - int response) +void +device_pause_response(struct visor_device *dev_info, + int response) { device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, dev_info, response, @@ -2016,7 +1675,7 @@ visorchipset_device_pause_response(struct visor_device *dev_info, dev_info->pending_msg_hdr = NULL; } -static void +void device_resume_response(struct visor_device *dev_info, int response) { device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, @@ -2027,40 +1686,6 @@ device_resume_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -/* The parahotplug/devicedisabled interface gets called by our support script - * when an SR-IOV device has been shut down. The ID is passed to the script - * and then passed back when the device has been removed. - */ -static ssize_t devicedisabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int id; - - if (kstrtouint(buf, 10, &id)) - return -EINVAL; - - parahotplug_request_complete(id, 0); - return count; -} - -/* The parahotplug/deviceenabled interface gets called by our support script - * when an SR-IOV device has been recovered. The ID is passed to the script - * and then passed back when the device has been brought back up. - */ -static ssize_t deviceenabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int id; - - if (kstrtouint(buf, 10, &id)) - return -EINVAL; - - parahotplug_request_complete(id, 1); - return count; -} - static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma) { @@ -2191,6 +1816,298 @@ visorchipset_file_cleanup(dev_t major_dev) unregister_chrdev_region(major_dev, 1); } +static struct parser_context * +parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) +{ + int allocbytes = sizeof(struct parser_context) + bytes; + struct parser_context *ctx; + + if (retry) + *retry = false; + + /* + * alloc an 0 extra byte to ensure payload is + * '\0'-terminated + */ + allocbytes++; + if ((controlvm_payload_bytes_buffered + bytes) + > MAX_CONTROLVM_PAYLOAD_BYTES) { + if (retry) + *retry = true; + return NULL; + } + ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); + if (!ctx) { + if (retry) + *retry = true; + return NULL; + } + + ctx->allocbytes = allocbytes; + ctx->param_bytes = bytes; + ctx->curr = NULL; + ctx->bytes_remaining = 0; + ctx->byte_stream = false; + if (local) { + void *p; + + if (addr > virt_to_phys(high_memory - 1)) + goto err_finish_ctx; + p = __va((unsigned long)(addr)); + memcpy(ctx->data, p, bytes); + } else { + void *mapping = memremap(addr, bytes, MEMREMAP_WB); + + if (!mapping) + goto err_finish_ctx; + memcpy(ctx->data, mapping, bytes); + memunmap(mapping); + } + + ctx->byte_stream = true; + controlvm_payload_bytes_buffered += ctx->param_bytes; + + return ctx; + +err_finish_ctx: + parser_done(ctx); + return NULL; +} + +/** + * handle_command() - process a controlvm message + * @inmsg: the message to process + * @channel_addr: address of the controlvm channel + * + * Return: + * false - this function will return false only in the case where the + * controlvm message was NOT processed, but processing must be + * retried before reading the next controlvm message; a + * scenario where this can occur is when we need to throttle + * the allocation of memory in which to copy out controlvm + * payload data + * true - processing of the controlvm message completed, + * either successfully or with an error + */ +static bool +handle_command(struct controlvm_message inmsg, u64 channel_addr) +{ + struct controlvm_message_packet *cmd = &inmsg.cmd; + u64 parm_addr; + u32 parm_bytes; + struct parser_context *parser_ctx = NULL; + bool local_addr; + struct controlvm_message ackmsg; + + /* create parsing context if necessary */ + local_addr = (inmsg.hdr.flags.test_message == 1); + if (channel_addr == 0) + return true; + parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; + parm_bytes = inmsg.hdr.payload_bytes; + + /* + * Parameter and channel addresses within test messages actually lie + * within our OS-controlled memory. We need to know that, because it + * makes a difference in how we compute the virtual address. + */ + if (parm_addr && parm_bytes) { + bool retry = false; + + parser_ctx = + parser_init_byte_stream(parm_addr, parm_bytes, + local_addr, &retry); + if (!parser_ctx && retry) + return false; + } + + if (!local_addr) { + controlvm_init_response(&ackmsg, &inmsg.hdr, + CONTROLVM_RESP_SUCCESS); + if (controlvm_channel) + visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_ACK, + &ackmsg); + } + switch (inmsg.hdr.id) { + case CONTROLVM_CHIPSET_INIT: + chipset_init(&inmsg); + break; + case CONTROLVM_BUS_CREATE: + bus_create(&inmsg); + break; + case CONTROLVM_BUS_DESTROY: + bus_destroy(&inmsg); + break; + case CONTROLVM_BUS_CONFIGURE: + bus_configure(&inmsg, parser_ctx); + break; + case CONTROLVM_DEVICE_CREATE: + my_device_create(&inmsg); + break; + case CONTROLVM_DEVICE_CHANGESTATE: + if (cmd->device_change_state.flags.phys_device) { + parahotplug_process_message(&inmsg); + } else { + /* + * save the hdr and cmd structures for later use + * when sending back the response to Command + */ + my_device_changestate(&inmsg); + break; + } + break; + case CONTROLVM_DEVICE_DESTROY: + my_device_destroy(&inmsg); + break; + case CONTROLVM_DEVICE_CONFIGURE: + /* no op for now, just send a respond that we passed */ + if (inmsg.hdr.flags.response_expected) + controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS); + break; + case CONTROLVM_CHIPSET_READY: + chipset_ready(&inmsg.hdr); + break; + case CONTROLVM_CHIPSET_SELFTEST: + chipset_selftest(&inmsg.hdr); + break; + case CONTROLVM_CHIPSET_STOP: + chipset_notready(&inmsg.hdr); + break; + default: + if (inmsg.hdr.flags.response_expected) + controlvm_respond + (&inmsg.hdr, + -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); + break; + } + + if (parser_ctx) { + parser_done(parser_ctx); + parser_ctx = NULL; + } + return true; +} + +/** + * read_controlvm_event() - retreives the next message from the + * CONTROLVM_QUEUE_EVENT queue in the controlvm + * channel + * @msg: pointer to the retrieved message + * + * Return: true if a valid message was retrieved or false otherwise + */ +static bool +read_controlvm_event(struct controlvm_message *msg) +{ + if (!visorchannel_signalremove(controlvm_channel, + CONTROLVM_QUEUE_EVENT, msg)) { + /* got a message */ + if (msg->hdr.flags.test_message == 1) + return false; + return true; + } + return false; +} + +/** + * parahotplug_process_list() - remove any request from the list that's been on + * there too long and respond with an error + */ +static void +parahotplug_process_list(void) +{ + struct list_head *pos; + struct list_head *tmp; + + spin_lock(¶hotplug_request_list_lock); + + list_for_each_safe(pos, tmp, ¶hotplug_request_list) { + struct parahotplug_request *req = + list_entry(pos, struct parahotplug_request, list); + + if (!time_after_eq(jiffies, req->expiration)) + continue; + + list_del(pos); + if (req->msg.hdr.flags.response_expected) + controlvm_respond_physdev_changestate( + &req->msg.hdr, + CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT, + req->msg.cmd.device_change_state.state); + parahotplug_request_destroy(req); + } + + spin_unlock(¶hotplug_request_list_lock); +} + +static void +controlvm_periodic_work(struct work_struct *work) +{ + struct controlvm_message inmsg; + bool got_command = false; + bool handle_command_failed = false; + + while (!visorchannel_signalremove(controlvm_channel, + CONTROLVM_QUEUE_RESPONSE, + &inmsg)) + ; + if (!got_command) { + if (controlvm_pending_msg_valid) { + /* + * we throttled processing of a prior + * msg, so try to process it again + * rather than reading a new one + */ + inmsg = controlvm_pending_msg; + controlvm_pending_msg_valid = false; + got_command = true; + } else { + got_command = read_controlvm_event(&inmsg); + } + } + + handle_command_failed = false; + while (got_command && (!handle_command_failed)) { + most_recent_message_jiffies = jiffies; + if (handle_command(inmsg, + visorchannel_get_physaddr + (controlvm_channel))) + got_command = read_controlvm_event(&inmsg); + else { + /* + * this is a scenario where throttling + * is required, but probably NOT an + * error...; we stash the current + * controlvm msg so we will attempt to + * reprocess it on our next loop + */ + handle_command_failed = true; + controlvm_pending_msg = inmsg; + controlvm_pending_msg_valid = true; + } + } + + /* parahotplug_worker */ + parahotplug_process_list(); + + if (time_after(jiffies, + most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { + /* + * it's been longer than MIN_IDLE_SECONDS since we + * processed our last controlvm message; slow down the + * polling + */ + if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; + } else { + if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; + } + + schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); +} + static int visorchipset_init(struct acpi_device *acpi_device) { @@ -2202,7 +2119,6 @@ visorchipset_init(struct acpi_device *acpi_device) if (!addr) goto error; - memset(&busdev_notifiers, 0, sizeof(busdev_notifiers)); memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info)); controlvm_channel = visorchannel_create_with_lock(addr, 0, @@ -2341,15 +2257,10 @@ static void exit_unisys(void) module_param_named(major, visorchipset_major, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_major, "major device number to use for the device node"); -module_param_named(visorbusregwait, visorchipset_visorbusregwait, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_visorbusregwait, - "1 to have the module wait for the visor bus to register"); module_init(init_unisys); module_exit(exit_unisys); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver " - VERSION); -MODULE_VERSION(VERSION); +MODULE_DESCRIPTION("s-Par visorbus driver for virtual device buses"); diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h index c043fa41ceda..86e695d5a441 100644 --- a/drivers/staging/unisys/visorbus/vmcallinterface.h +++ b/drivers/staging/unisys/visorbus/vmcallinterface.h @@ -20,11 +20,39 @@ * Virtualization. The VMCALLs are provided by Monitor and used by IO code * running on IO Partitions. */ +static inline unsigned long +__unisys_vmcall_gnuc(unsigned long tuple, unsigned long reg_ebx, + unsigned long reg_ecx) +{ + unsigned long result = 0; + unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; -#ifdef __GNUC__ -#include "iovmcall_gnuc.h" -#endif /* */ -#include "diagchannel.h" + cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); + if (!(cpuid_ecx & 0x80000000)) + return -EPERM; + + __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : + "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); + return result; +} + +static inline unsigned long +__unisys_extended_vmcall_gnuc(unsigned long long tuple, + unsigned long long reg_ebx, + unsigned long long reg_ecx, + unsigned long long reg_edx) +{ + unsigned long result = 0; + unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; + + cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); + if (!(cpuid_ecx & 0x80000000)) + return -EPERM; + + __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : + "a"(tuple), "b"(reg_ebx), "c"(reg_ecx), "d"(reg_edx)); + return result; +} #ifdef VMCALL_IO_CONTROLVM_ADDR #undef VMCALL_IO_CONTROLVM_ADDR @@ -57,7 +85,6 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */ #define VMCALL_SUCCESS 0 #define VMCALL_SUCCESSFUL(result) (result == 0) -#ifdef __GNUC__ #define unisys_vmcall(tuple, reg_ebx, reg_ecx) \ __unisys_vmcall_gnuc(tuple, reg_ebx, reg_ecx) #define unisys_extended_vmcall(tuple, reg_ebx, reg_ecx, reg_edx) \ @@ -74,7 +101,6 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */ #define ISSUE_IO_VMCALL_POSTCODE_SEVERITY(postcode, severity) \ ISSUE_IO_EXTENDED_VMCALL(VMCALL_POST_CODE_LOGEVENT, severity, \ MDS_APPOS, postcode) -#endif /* Structures for IO VMCALLs */ @@ -89,4 +115,156 @@ struct vmcall_io_controlvm_addr_params { u8 unused[4]; /* Unused Bytes in the 64-Bit Aligned Struct */ } __packed; +/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/ +enum driver_pc { /* POSTCODE driver identifier tuples */ + /* visorchipset driver files */ + VISOR_CHIPSET_PC = 0xA0, + VISOR_CHIPSET_PC_controlvm_c = 0xA1, + VISOR_CHIPSET_PC_controlvm_cm2 = 0xA2, + VISOR_CHIPSET_PC_controlvm_direct_c = 0xA3, + VISOR_CHIPSET_PC_file_c = 0xA4, + VISOR_CHIPSET_PC_parser_c = 0xA5, + VISOR_CHIPSET_PC_testing_c = 0xA6, + VISOR_CHIPSET_PC_visorchipset_main_c = 0xA7, + VISOR_CHIPSET_PC_visorswitchbus_c = 0xA8, + /* visorbus driver files */ + VISOR_BUS_PC = 0xB0, + VISOR_BUS_PC_businst_attr_c = 0xB1, + VISOR_BUS_PC_channel_attr_c = 0xB2, + VISOR_BUS_PC_devmajorminor_attr_c = 0xB3, + VISOR_BUS_PC_visorbus_main_c = 0xB4, + /* visorclientbus driver files */ + VISOR_CLIENT_BUS_PC = 0xC0, + VISOR_CLIENT_BUS_PC_visorclientbus_main_c = 0xC1, + /* virt hba driver files */ + VIRT_HBA_PC = 0xC2, + VIRT_HBA_PC_virthba_c = 0xC3, + /* virtpci driver files */ + VIRT_PCI_PC = 0xC4, + VIRT_PCI_PC_virtpci_c = 0xC5, + /* virtnic driver files */ + VIRT_NIC_PC = 0xC6, + VIRT_NIC_P_virtnic_c = 0xC7, + /* uislib driver files */ + UISLIB_PC = 0xD0, + UISLIB_PC_uislib_c = 0xD1, + UISLIB_PC_uisqueue_c = 0xD2, + /* 0xD3 RESERVED */ + UISLIB_PC_uisutils_c = 0xD4, +}; + +enum event_pc { /* POSTCODE event identifier tuples */ + ATTACH_PORT_ENTRY_PC = 0x001, + ATTACH_PORT_FAILURE_PC = 0x002, + ATTACH_PORT_SUCCESS_PC = 0x003, + BUS_FAILURE_PC = 0x004, + BUS_CREATE_ENTRY_PC = 0x005, + BUS_CREATE_FAILURE_PC = 0x006, + BUS_CREATE_EXIT_PC = 0x007, + BUS_CONFIGURE_ENTRY_PC = 0x008, + BUS_CONFIGURE_FAILURE_PC = 0x009, + BUS_CONFIGURE_EXIT_PC = 0x00A, + CHIPSET_INIT_ENTRY_PC = 0x00B, + CHIPSET_INIT_SUCCESS_PC = 0x00C, + CHIPSET_INIT_FAILURE_PC = 0x00D, + CHIPSET_INIT_EXIT_PC = 0x00E, + CREATE_WORKQUEUE_PC = 0x00F, + CREATE_WORKQUEUE_FAILED_PC = 0x0A0, + CONTROLVM_INIT_FAILURE_PC = 0x0A1, + DEVICE_CREATE_ENTRY_PC = 0x0A2, + DEVICE_CREATE_FAILURE_PC = 0x0A3, + DEVICE_CREATE_SUCCESS_PC = 0x0A4, + DEVICE_CREATE_EXIT_PC = 0x0A5, + DEVICE_ADD_PC = 0x0A6, + DEVICE_REGISTER_FAILURE_PC = 0x0A7, + DEVICE_CHANGESTATE_ENTRY_PC = 0x0A8, + DEVICE_CHANGESTATE_FAILURE_PC = 0x0A9, + DEVICE_CHANGESTATE_EXIT_PC = 0x0AA, + DRIVER_ENTRY_PC = 0x0AB, + DRIVER_EXIT_PC = 0x0AC, + MALLOC_FAILURE_PC = 0x0AD, + QUEUE_DELAYED_WORK_PC = 0x0AE, + /* 0x0B7 RESERVED */ + VBUS_CHANNEL_ENTRY_PC = 0x0B8, + VBUS_CHANNEL_FAILURE_PC = 0x0B9, + VBUS_CHANNEL_EXIT_PC = 0x0BA, + VHBA_CREATE_ENTRY_PC = 0x0BB, + VHBA_CREATE_FAILURE_PC = 0x0BC, + VHBA_CREATE_EXIT_PC = 0x0BD, + VHBA_CREATE_SUCCESS_PC = 0x0BE, + VHBA_COMMAND_HANDLER_PC = 0x0BF, + VHBA_PROBE_ENTRY_PC = 0x0C0, + VHBA_PROBE_FAILURE_PC = 0x0C1, + VHBA_PROBE_EXIT_PC = 0x0C2, + VNIC_CREATE_ENTRY_PC = 0x0C3, + VNIC_CREATE_FAILURE_PC = 0x0C4, + VNIC_CREATE_SUCCESS_PC = 0x0C5, + VNIC_PROBE_ENTRY_PC = 0x0C6, + VNIC_PROBE_FAILURE_PC = 0x0C7, + VNIC_PROBE_EXIT_PC = 0x0C8, + VPCI_CREATE_ENTRY_PC = 0x0C9, + VPCI_CREATE_FAILURE_PC = 0x0CA, + VPCI_CREATE_EXIT_PC = 0x0CB, + VPCI_PROBE_ENTRY_PC = 0x0CC, + VPCI_PROBE_FAILURE_PC = 0x0CD, + VPCI_PROBE_EXIT_PC = 0x0CE, + CRASH_DEV_ENTRY_PC = 0x0CF, + CRASH_DEV_EXIT_PC = 0x0D0, + CRASH_DEV_HADDR_NULL = 0x0D1, + CRASH_DEV_CONTROLVM_NULL = 0x0D2, + CRASH_DEV_RD_BUS_FAIULRE_PC = 0x0D3, + CRASH_DEV_RD_DEV_FAIULRE_PC = 0x0D4, + CRASH_DEV_BUS_NULL_FAILURE_PC = 0x0D5, + CRASH_DEV_DEV_NULL_FAILURE_PC = 0x0D6, + CRASH_DEV_CTRL_RD_FAILURE_PC = 0x0D7, + CRASH_DEV_COUNT_FAILURE_PC = 0x0D8, + SAVE_MSG_BUS_FAILURE_PC = 0x0D9, + SAVE_MSG_DEV_FAILURE_PC = 0x0DA, + CALLHOME_INIT_FAILURE_PC = 0x0DB +}; + +#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR +#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING +/* TODO-> Info currently doesn't show, so we set info=warning */ +#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT + +/* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR); + * Please also note that the resulting postcode is in hex, so if you are + * searching for the __LINE__ number, convert it first to decimal. The line + * number combined with driver and type of call, will allow you to track down + * exactly what line an error occurred on, or where the last driver + * entered/exited from. + */ + +/* BASE FUNCTIONS */ +#define POSTCODE_LINUX_A(DRIVER_PC, EVENT_PC, pc32bit, severity) \ +do { \ + unsigned long long post_code_temp; \ + post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ + ((((u64)__LINE__) & 0xFFF) << 32) | \ + (((u64)pc32bit) & 0xFFFFFFFF); \ + ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ +} while (0) + +#define POSTCODE_LINUX_B(DRIVER_PC, EVENT_PC, pc16bit1, pc16bit2, severity) \ +do { \ + unsigned long long post_code_temp; \ + post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ + ((((u64)__LINE__) & 0xFFF) << 32) | \ + ((((u64)pc16bit1) & 0xFFFF) << 16) | \ + (((u64)pc16bit2) & 0xFFFF); \ + ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ +} while (0) + +/* MOST COMMON */ +#define POSTCODE_LINUX_2(EVENT_PC, severity) \ + POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, 0x0000, severity) + +#define POSTCODE_LINUX_3(EVENT_PC, pc32bit, severity) \ + POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, pc32bit, severity) + +#define POSTCODE_LINUX_4(EVENT_PC, pc16bit1, pc16bit2, severity) \ + POSTCODE_LINUX_B(CURRENT_FILE_PC, EVENT_PC, pc16bit1, \ + pc16bit2, severity) + #endif /* __IOMONINTF_H__ */ diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 120ba2097e02..5a7a87efed27 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -36,21 +36,6 @@ #define MAX_PENDING_REQUESTS (MIN_NUMSIGNALS * 2) #define VISORHBA_ERROR_COUNT 30 -static int visorhba_queue_command_lck(struct scsi_cmnd *scsicmd, - void (*visorhba_cmnd_done) - (struct scsi_cmnd *)); -#ifdef DEF_SCSI_QCMD -static DEF_SCSI_QCMD(visorhba_queue_command) -#else -#define visorhba_queue_command visorhba_queue_command_lck -#endif -static int visorhba_probe(struct visor_device *dev); -static void visorhba_remove(struct visor_device *dev); -static int visorhba_pause(struct visor_device *dev, - visorbus_state_complete_func complete_func); -static int visorhba_resume(struct visor_device *dev, - visorbus_state_complete_func complete_func); - static struct dentry *visorhba_debugfs_dir; /* GUIDS for HBA channel type supported by this driver */ @@ -62,20 +47,6 @@ static struct visor_channeltype_descriptor visorhba_channel_types[] = { { NULL_UUID_LE, NULL } }; -/* This is used to tell the visor bus driver which types of visor devices - * we support, and what functions to call when a visor device that we support - * is attached or removed. - */ -static struct visor_driver visorhba_driver = { - .name = "visorhba", - .owner = THIS_MODULE, - .channel_types = visorhba_channel_types, - .probe = visorhba_probe, - .remove = visorhba_remove, - .pause = visorhba_pause, - .resume = visorhba_resume, - .channel_interrupt = NULL, -}; MODULE_DEVICE_TABLE(visorbus, visorhba_channel_types); MODULE_ALIAS("visorbus:" SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR); @@ -364,9 +335,9 @@ static int forward_taskmgmt_command(enum task_mgmt_types tasktype, dev_dbg(&scsidev->sdev_gendev, "visorhba: initiating type=%d taskmgmt command\n", tasktype); - if (!visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - cmdrsp)) + if (visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, + cmdrsp)) goto err_del_scsipending_ent; /* It can take the Service Partition up to 35 seconds to complete @@ -567,9 +538,9 @@ visorhba_queue_command_lck(struct scsi_cmnd *scsicmd, } cmdrsp->scsi.guest_phys_entries = scsi_sg_count(scsicmd); - if (!visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - cmdrsp)) + if (visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, + cmdrsp)) /* queue must be full and we aren't going to wait */ goto err_del_scsipending_ent; @@ -580,6 +551,12 @@ err_del_scsipending_ent: return SCSI_MLQUEUE_DEVICE_BUSY; } +#ifdef DEF_SCSI_QCMD +static DEF_SCSI_QCMD(visorhba_queue_command) +#else +#define visorhba_queue_command visorhba_queue_command_lck +#endif + /** * visorhba_slave_alloc - called when new disk is discovered * @scsidev: New disk @@ -950,9 +927,9 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visorhba_devdata *devdata) struct scsi_cmnd *scsicmd; while (1) { - if (!visorchannel_signalremove(devdata->dev->visorchannel, - IOCHAN_FROM_IOPART, - cmdrsp)) + if (visorchannel_signalremove(devdata->dev->visorchannel, + IOCHAN_FROM_IOPART, + cmdrsp)) break; /* queue empty */ if (cmdrsp->cmdtype == CMD_SCSI_TYPE) { @@ -1186,6 +1163,21 @@ static void visorhba_remove(struct visor_device *dev) debugfs_remove_recursive(devdata->debugfs_dir); } +/* This is used to tell the visor bus driver which types of visor devices + * we support, and what functions to call when a visor device that we support + * is attached or removed. + */ +static struct visor_driver visorhba_driver = { + .name = "visorhba", + .owner = THIS_MODULE, + .channel_types = visorhba_channel_types, + .probe = visorhba_probe, + .remove = visorhba_remove, + .pause = visorhba_pause, + .resume = visorhba_resume, + .channel_interrupt = NULL, +}; + /** * visorhba_init - driver init routine * @@ -1228,4 +1220,4 @@ module_exit(visorhba_exit); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("s-Par hba driver"); +MODULE_DESCRIPTION("s-Par HBA driver for virtual SCSI host busses"); diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h index 1bc3d2064080..53dde7c53809 100644 --- a/drivers/staging/unisys/visorinput/ultrainputreport.h +++ b/drivers/staging/unisys/visorinput/ultrainputreport.h @@ -17,8 +17,6 @@ #include -#include "ultrainputreport.h" - /* Identifies mouse and keyboard activity which is specified by the firmware to * the host using the cmsimpleinput protocol. @ingroup coretypes */ diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index d67cd76327c0..6f94b646f7c5 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -29,9 +29,7 @@ #include #include -#include "version.h" #include "visorbus.h" -#include "channel.h" #include "ultrainputreport.h" /* Keyboard channel {c73416d0-b0b8-44af-b304-9d2ae99f1b3d} */ @@ -63,9 +61,10 @@ enum visorinput_device_type { */ struct visorinput_devdata { struct visor_device *dev; - struct rw_semaphore lock_visor_dev; /* lock for dev */ + struct mutex lock_visor_dev; /* lock for dev */ struct input_dev *visorinput_dev; bool paused; + bool interrupts_enabled; unsigned int keycode_table_bytes; /* size of following array */ /* for keyboard devices: visorkbd_keycode[] + visorkbd_ext_keycode[] */ unsigned char keycode_table[0]; @@ -228,7 +227,21 @@ static int visorinput_open(struct input_dev *visorinput_dev) return -EINVAL; } dev_dbg(&visorinput_dev->dev, "%s opened\n", __func__); + + /* + * If we're not paused, really enable interrupts. + * Regardless of whether we are paused, set a flag indicating + * interrupts should be enabled so when we resume, interrupts + * will really be enabled. + */ + mutex_lock(&devdata->lock_visor_dev); + devdata->interrupts_enabled = true; + if (devdata->paused) + goto out_unlock; visorbus_enable_channel_interrupts(devdata->dev); + +out_unlock: + mutex_unlock(&devdata->lock_visor_dev); return 0; } @@ -243,20 +256,35 @@ static void visorinput_close(struct input_dev *visorinput_dev) return; } dev_dbg(&visorinput_dev->dev, "%s closed\n", __func__); + + /* + * If we're not paused, really disable interrupts. + * Regardless of whether we are paused, set a flag indicating + * interrupts should be disabled so when we resume we will + * not re-enable them. + */ + + mutex_lock(&devdata->lock_visor_dev); + devdata->interrupts_enabled = false; + if (devdata->paused) + goto out_unlock; visorbus_disable_channel_interrupts(devdata->dev); + +out_unlock: + mutex_unlock(&devdata->lock_visor_dev); } /* - * register_client_keyboard() initializes and returns a Linux input node that + * setup_client_keyboard() initializes and returns a Linux input node that * we can use to deliver keyboard inputs to Linux. We of course do this when * we see keyboard inputs coming in on a keyboard channel. */ static struct input_dev * -register_client_keyboard(void *devdata, /* opaque on purpose */ - unsigned char *keycode_table) +setup_client_keyboard(void *devdata, /* opaque on purpose */ + unsigned char *keycode_table) { - int i, error; + int i; struct input_dev *visorinput_dev; visorinput_dev = input_allocate_device(); @@ -290,18 +318,12 @@ register_client_keyboard(void *devdata, /* opaque on purpose */ visorinput_dev->close = visorinput_close; input_set_drvdata(visorinput_dev, devdata); /* pre input_register! */ - error = input_register_device(visorinput_dev); - if (error) { - input_free_device(visorinput_dev); - return NULL; - } return visorinput_dev; } static struct input_dev * -register_client_mouse(void *devdata /* opaque on purpose */) +setup_client_mouse(void *devdata /* opaque on purpose */) { - int error; struct input_dev *visorinput_dev = NULL; int xres, yres; struct fb_info *fb0; @@ -336,13 +358,6 @@ register_client_mouse(void *devdata /* opaque on purpose */) visorinput_dev->open = visorinput_open; visorinput_dev->close = visorinput_close; input_set_drvdata(visorinput_dev, devdata); /* pre input_register! */ - - error = input_register_device(visorinput_dev); - if (error) { - input_free_device(visorinput_dev); - return NULL; - } - input_set_capability(visorinput_dev, EV_REL, REL_WHEEL); return visorinput_dev; @@ -360,8 +375,18 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) devdata = kzalloc(sizeof(*devdata) + extra_bytes, GFP_KERNEL); if (!devdata) return NULL; + mutex_init(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); devdata->dev = dev; + /* + * visorinput_open() can be called as soon as input_register_device() + * happens, and that will enable channel interrupts. Setting paused + * prevents us from getting into visorinput_channel_interrupt() prior + * to the device structure being totally initialized. + */ + devdata->paused = true; + /* * This is an input device in a client guest partition, * so we need to create whatever input nodes are necessary to @@ -374,23 +399,49 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) KEYCODE_TABLE_BYTES); memcpy(devdata->keycode_table + KEYCODE_TABLE_BYTES, visorkbd_ext_keycode, KEYCODE_TABLE_BYTES); - devdata->visorinput_dev = register_client_keyboard + devdata->visorinput_dev = setup_client_keyboard (devdata, devdata->keycode_table); if (!devdata->visorinput_dev) goto cleanups_register; break; case visorinput_mouse: - devdata->visorinput_dev = register_client_mouse(devdata); + devdata->visorinput_dev = setup_client_mouse(devdata); if (!devdata->visorinput_dev) goto cleanups_register; break; } - init_rwsem(&devdata->lock_visor_dev); + dev_set_drvdata(&dev->device, devdata); + mutex_unlock(&devdata->lock_visor_dev); + + /* + * Device struct is completely set up now, with the exception of + * visorinput_dev being registered. + * We need to unlock before we register the device, because this + * can cause an on-stack call of visorinput_open(), which would + * deadlock if we had the lock. + */ + if (input_register_device(devdata->visorinput_dev)) { + input_free_device(devdata->visorinput_dev); + goto err_kfree_devdata; + } + + mutex_lock(&devdata->lock_visor_dev); + /* + * Establish calls to visorinput_channel_interrupt() if that is + * the desired state that we've kept track of in interrupts_enabled + * while the device was being created. + */ + devdata->paused = false; + if (devdata->interrupts_enabled) + visorbus_enable_channel_interrupts(dev); + mutex_unlock(&devdata->lock_visor_dev); return devdata; cleanups_register: + mutex_unlock(&devdata->lock_visor_dev); +err_kfree_devdata: kfree(devdata); return NULL; } @@ -398,7 +449,6 @@ cleanups_register: static int visorinput_probe(struct visor_device *dev) { - struct visorinput_devdata *devdata = NULL; uuid_le guid; enum visorinput_device_type devtype; @@ -409,10 +459,9 @@ visorinput_probe(struct visor_device *dev) devtype = visorinput_keyboard; else return -ENODEV; - devdata = devdata_create(dev, devtype); - if (!devdata) + visorbus_disable_channel_interrupts(dev); + if (!devdata_create(dev, devtype)) return -ENOMEM; - dev_set_drvdata(&dev->device, devdata); return 0; } @@ -431,6 +480,7 @@ visorinput_remove(struct visor_device *dev) if (!devdata) return; + mutex_lock(&devdata->lock_visor_dev); visorbus_disable_channel_interrupts(dev); /* @@ -438,10 +488,10 @@ visorinput_remove(struct visor_device *dev) * in visorinput_channel_interrupt() */ - down_write(&devdata->lock_visor_dev); dev_set_drvdata(&dev->device, NULL); + mutex_unlock(&devdata->lock_visor_dev); + unregister_client_input(devdata->visorinput_dev); - up_write(&devdata->lock_visor_dev); kfree(devdata); } @@ -529,15 +579,9 @@ visorinput_channel_interrupt(struct visor_device *dev) if (!devdata) return; - down_write(&devdata->lock_visor_dev); - if (devdata->paused) /* don't touch device/channel when paused */ - goto out_locked; - visorinput_dev = devdata->visorinput_dev; - if (!visorinput_dev) - goto out_locked; - while (visorchannel_signalremove(dev->visorchannel, 0, &r)) { + while (!visorchannel_signalremove(dev->visorchannel, 0, &r)) { scancode = r.activity.arg1; keycode = scancode_to_keycode(scancode); switch (r.activity.action) { @@ -611,8 +655,6 @@ visorinput_channel_interrupt(struct visor_device *dev) break; } } -out_locked: - up_write(&devdata->lock_visor_dev); } static int @@ -627,16 +669,24 @@ visorinput_pause(struct visor_device *dev, goto out; } - down_write(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); if (devdata->paused) { rc = -EBUSY; goto out_locked; } + if (devdata->interrupts_enabled) + visorbus_disable_channel_interrupts(dev); + + /* + * due to above, at this time no thread of execution will be + * in visorinput_channel_interrupt() + */ + devdata->paused = true; complete_func(dev, 0); rc = 0; out_locked: - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); out: return rc; } @@ -652,16 +702,25 @@ visorinput_resume(struct visor_device *dev, rc = -ENODEV; goto out; } - down_write(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); if (!devdata->paused) { rc = -EBUSY; goto out_locked; } devdata->paused = false; complete_func(dev, 0); + + /* + * Re-establish calls to visorinput_channel_interrupt() if that is + * the desired state that we've kept track of in interrupts_enabled + * while the device was paused. + */ + if (devdata->interrupts_enabled) + visorbus_enable_channel_interrupts(dev); + rc = 0; out_locked: - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); out: return rc; } @@ -675,7 +734,6 @@ static struct visor_channeltype_descriptor visorinput_channel_types[] = { static struct visor_driver visorinput_driver = { .name = "visorinput", - .vertag = NULL, .owner = THIS_MODULE, .channel_types = visorinput_channel_types, .probe = visorinput_probe, @@ -704,8 +762,7 @@ MODULE_DEVICE_TABLE(visorbus, visorinput_channel_types); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("s-Par human input driver for guest Linux"); -MODULE_VERSION(VERSION); +MODULE_DESCRIPTION("s-Par human input driver for virtual keyboard/mouse"); MODULE_ALIAS("visorbus:" SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR); MODULE_ALIAS("visorbus:" SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR); diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index a28388d3ddc2..136700756485 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -29,8 +29,6 @@ #include "iochannel.h" #define VISORNIC_INFINITE_RSP_WAIT 0 -#define VISORNICSOPENMAX 32 -#define MAXDEVICES 16384 /* MAX_BUF = 64 lines x 32 MAXVNIC x 80 characters * = 163840 bytes @@ -38,27 +36,6 @@ #define MAX_BUF 163840 #define NAPI_WEIGHT 64 -static int visornic_probe(struct visor_device *dev); -static void visornic_remove(struct visor_device *dev); -static int visornic_pause(struct visor_device *dev, - visorbus_state_complete_func complete_func); -static int visornic_resume(struct visor_device *dev, - visorbus_state_complete_func complete_func); - -/* DEBUGFS declarations */ -static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); -static ssize_t enable_ints_write(struct file *file, const char __user *buf, - size_t len, loff_t *ppos); -static struct dentry *visornic_debugfs_dir; -static const struct file_operations debugfs_info_fops = { - .read = info_debugfs_read, -}; - -static const struct file_operations debugfs_enable_ints_fops = { - .write = enable_ints_write, -}; - /* GUIDS for director channel type supported by this driver. */ static struct visor_channeltype_descriptor visornic_channel_types[] = { /* Note that the only channel type we expect to be reported by the @@ -77,23 +54,6 @@ MODULE_DEVICE_TABLE(visorbus, visornic_channel_types); */ MODULE_ALIAS("visorbus:" SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR); -/* This is used to tell the visor bus driver which types of visor devices - * we support, and what functions to call when a visor device that we support - * is attached or removed. - */ -static struct visor_driver visornic_driver = { - .name = "visornic", - .version = "1.0.0.0", - .vertag = NULL, - .owner = THIS_MODULE, - .channel_types = visornic_channel_types, - .probe = visornic_probe, - .remove = visornic_remove, - .pause = visornic_pause, - .resume = visornic_resume, - .channel_interrupt = NULL, -}; - struct chanstat { unsigned long got_rcv; unsigned long got_enbdisack; @@ -181,9 +141,6 @@ struct visornic_devdata { struct uiscmdrsp cmdrsp[SIZEOF_CMDRSP]; }; -static int visornic_poll(struct napi_struct *napi, int budget); -static void poll_for_irq(unsigned long v); - /** * visor_copy_fragsinfo_from_skb( * @skb_in: skbuff that we are pulling the frags from @@ -289,6 +246,10 @@ static ssize_t enable_ints_write(struct file *file, return count; } +static const struct file_operations debugfs_enable_ints_fops = { + .write = enable_ints_write, +}; + /** * visornic_serverdown_complete - IOPART went down, pause device * @work: Work queue it was scheduled on @@ -425,9 +386,9 @@ post_skb(struct uiscmdrsp *cmdrsp, if ((cmdrsp->net.rcvpost.frag.pi_off + skb->len) <= PI_PAGE_SIZE) { cmdrsp->net.type = NET_RCV_POST; cmdrsp->cmdtype = CMD_NET_TYPE; - if (visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - cmdrsp)) { + if (!visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, + cmdrsp)) { atomic_inc(&devdata->num_rcvbuf_in_iovm); devdata->chstat.sent_post++; } else { @@ -454,9 +415,9 @@ send_enbdis(struct net_device *netdev, int state, devdata->cmdrsp_rcv->net.enbdis.context = netdev; devdata->cmdrsp_rcv->net.type = NET_RCV_ENBDIS; devdata->cmdrsp_rcv->cmdtype = CMD_NET_TYPE; - if (visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - devdata->cmdrsp_rcv)) + if (!visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, + devdata->cmdrsp_rcv)) devdata->chstat.sent_enbdis++; } @@ -920,8 +881,8 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } - if (!visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, cmdrsp)) { + if (visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, cmdrsp)) { netif_stop_queue(netdev); spin_unlock_irqrestore(&devdata->priv_lock, flags); devdata->busy_cnt++; @@ -1522,6 +1483,11 @@ static ssize_t info_debugfs_read(struct file *file, char __user *buf, return bytes_read; } +static struct dentry *visornic_debugfs_dir; +static const struct file_operations debugfs_info_fops = { + .read = info_debugfs_read, +}; + /** * send_rcv_posts_if_needed * @devdata: visornic device @@ -1573,9 +1539,9 @@ send_rcv_posts_if_needed(struct visornic_devdata *devdata) static void drain_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) { - while (visorchannel_signalremove(devdata->dev->visorchannel, - IOCHAN_FROM_IOPART, - cmdrsp)) + while (!visorchannel_signalremove(devdata->dev->visorchannel, + IOCHAN_FROM_IOPART, + cmdrsp)) ; } @@ -1586,7 +1552,7 @@ drain_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) * * Drain the respones queue of any responses from the IO partition. * Process the responses as we get them. - * Returns when response queue is empty or when the threadd stops. + * Returns when response queue is empty or when the thread stops. */ static void service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, @@ -1599,9 +1565,9 @@ service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, /* TODO: CLIENT ACQUIRE -- Don't really need this at the * moment */ - if (!visorchannel_signalremove(devdata->dev->visorchannel, - IOCHAN_FROM_IOPART, - cmdrsp)) + if (visorchannel_signalremove(devdata->dev->visorchannel, + IOCHAN_FROM_IOPART, + cmdrsp)) break; /* queue empty */ switch (cmdrsp->net.type) { @@ -2061,6 +2027,21 @@ static int visornic_resume(struct visor_device *dev, return 0; } +/* This is used to tell the visor bus driver which types of visor devices + * we support, and what functions to call when a visor device that we support + * is attached or removed. + */ +static struct visor_driver visornic_driver = { + .name = "visornic", + .owner = THIS_MODULE, + .channel_types = visornic_channel_types, + .probe = visornic_probe, + .remove = visornic_remove, + .pause = visornic_pause, + .resume = visornic_resume, + .channel_interrupt = NULL, +}; + /** * visornic_init - Init function * @@ -2115,5 +2096,4 @@ module_exit(visornic_cleanup); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("sPAR nic driver for sparlinux: ver 1.0.0.0"); -MODULE_VERSION("1.0.0.0"); +MODULE_DESCRIPTION("s-Par NIC driver for virtual network devices"); diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig new file mode 100644 index 000000000000..9676fb29075a --- /dev/null +++ b/drivers/staging/vc04_services/Kconfig @@ -0,0 +1,9 @@ +config BCM2708_VCHIQ + tristate "Videocore VCHIQ" + depends on RASPBERRYPI_FIRMWARE && BROKEN + default y + help + Kernel to VideoCore communication interface for the + BCM2708 family of products. + Defaults to Y when the Broadcom Videocore services + are included in the build, N otherwise. diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile new file mode 100644 index 000000000000..90ab4781df2c --- /dev/null +++ b/drivers/staging/vc04_services/Makefile @@ -0,0 +1,14 @@ +obj-$(CONFIG_BCM2708_VCHIQ) += vchiq.o + +vchiq-objs := \ + interface/vchiq_arm/vchiq_core.o \ + interface/vchiq_arm/vchiq_arm.o \ + interface/vchiq_arm/vchiq_kern_lib.o \ + interface/vchiq_arm/vchiq_2835_arm.o \ + interface/vchiq_arm/vchiq_debugfs.o \ + interface/vchiq_arm/vchiq_shim.o \ + interface/vchiq_arm/vchiq_util.o \ + interface/vchiq_arm/vchiq_connected.o \ + +ccflags-y += -DVCOS_VERIFY_BKPTS=1 -Idrivers/staging/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 + diff --git a/drivers/staging/vc04_services/interface/vchi/connections/connection.h b/drivers/staging/vc04_services/interface/vchi/connections/connection.h new file mode 100644 index 000000000000..fef6ac34c6d2 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/connections/connection.h @@ -0,0 +1,328 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CONNECTION_H_ +#define CONNECTION_H_ + +#include +#include +#include + +#include "interface/vchi/vchi_cfg_internal.h" +#include "interface/vchi/vchi_common.h" +#include "interface/vchi/message_drivers/message.h" + +/****************************************************************************** + Global defs + *****************************************************************************/ + +// Opaque handle for a connection / service pair +typedef struct opaque_vchi_connection_connected_service_handle_t *VCHI_CONNECTION_SERVICE_HANDLE_T; + +// opaque handle to the connection state information +typedef struct opaque_vchi_connection_info_t VCHI_CONNECTION_STATE_T; + +typedef struct vchi_connection_t VCHI_CONNECTION_T; + + +/****************************************************************************** + API + *****************************************************************************/ + +// Routine to init a connection with a particular low level driver +typedef VCHI_CONNECTION_STATE_T * (*VCHI_CONNECTION_INIT_T)( struct vchi_connection_t * connection, + const VCHI_MESSAGE_DRIVER_T * driver ); + +// Routine to control CRC enabling at a connection level +typedef int32_t (*VCHI_CONNECTION_CRC_CONTROL_T)( VCHI_CONNECTION_STATE_T *state_handle, + VCHI_CRC_CONTROL_T control ); + +// Routine to create a service +typedef int32_t (*VCHI_CONNECTION_SERVICE_CONNECT_T)( VCHI_CONNECTION_STATE_T *state_handle, + int32_t service_id, + uint32_t rx_fifo_size, + uint32_t tx_fifo_size, + int server, + VCHI_CALLBACK_T callback, + void *callback_param, + int32_t want_crc, + int32_t want_unaligned_bulk_rx, + int32_t want_unaligned_bulk_tx, + VCHI_CONNECTION_SERVICE_HANDLE_T *service_handle ); + +// Routine to close a service +typedef int32_t (*VCHI_CONNECTION_SERVICE_DISCONNECT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle ); + +// Routine to queue a message +typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + const void *data, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// scatter-gather (vector) message queueing +typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + VCHI_MSG_VECTOR_T *vector, + uint32_t count, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// Routine to dequeue a message +typedef int32_t (*VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void *data, + uint32_t max_data_size_to_read, + uint32_t *actual_msg_size, + VCHI_FLAGS_T flags ); + +// Routine to peek at a message +typedef int32_t (*VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags ); + +// Routine to hold a message +typedef int32_t (*VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags, + void **message_handle ); + +// Routine to initialise a received message iterator +typedef int32_t (*VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + VCHI_MSG_ITER_T *iter, + VCHI_FLAGS_T flags ); + +// Routine to release a held message +typedef int32_t (*VCHI_CONNECTION_HELD_MSG_RELEASE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void *message_handle ); + +// Routine to get info on a held message +typedef int32_t (*VCHI_CONNECTION_HELD_MSG_INFO_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void *message_handle, + void **data, + int32_t *msg_size, + uint32_t *tx_timestamp, + uint32_t *rx_timestamp ); + +// Routine to check whether the iterator has a next message +typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, + const VCHI_MSG_ITER_T *iter ); + +// Routine to advance the iterator +typedef int32_t (*VCHI_CONNECTION_MSG_ITER_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, + VCHI_MSG_ITER_T *iter, + void **data, + uint32_t *msg_size ); + +// Routine to remove the last message returned by the iterator +typedef int32_t (*VCHI_CONNECTION_MSG_ITER_REMOVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, + VCHI_MSG_ITER_T *iter ); + +// Routine to hold the last message returned by the iterator +typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HOLD_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, + VCHI_MSG_ITER_T *iter, + void **msg_handle ); + +// Routine to transmit bulk data +typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + const void *data_src, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *bulk_handle ); + +// Routine to receive data +typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void *data_dst, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *bulk_handle ); + +// Routine to report if a server is available +typedef int32_t (*VCHI_CONNECTION_SERVER_PRESENT)( VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t peer_flags ); + +// Routine to report the number of RX slots available +typedef int (*VCHI_CONNECTION_RX_SLOTS_AVAILABLE)( const VCHI_CONNECTION_STATE_T *state ); + +// Routine to report the RX slot size +typedef uint32_t (*VCHI_CONNECTION_RX_SLOT_SIZE)( const VCHI_CONNECTION_STATE_T *state ); + +// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO +typedef void (*VCHI_CONNECTION_RX_BULK_BUFFER_ADDED)(VCHI_CONNECTION_STATE_T *state, + int32_t service, + uint32_t length, + MESSAGE_TX_CHANNEL_T channel, + uint32_t channel_params, + uint32_t data_length, + uint32_t data_offset); + +// Callback to inform a service that a Xon or Xoff message has been received +typedef void (*VCHI_CONNECTION_FLOW_CONTROL)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t xoff); + +// Callback to inform a service that a server available reply message has been received +typedef void (*VCHI_CONNECTION_SERVER_AVAILABLE_REPLY)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, uint32_t flags); + +// Callback to indicate that bulk auxiliary messages have arrived +typedef void (*VCHI_CONNECTION_BULK_AUX_RECEIVED)(VCHI_CONNECTION_STATE_T *state); + +// Callback to indicate that bulk auxiliary messages have arrived +typedef void (*VCHI_CONNECTION_BULK_AUX_TRANSMITTED)(VCHI_CONNECTION_STATE_T *state, void *handle); + +// Callback with all the connection info you require +typedef void (*VCHI_CONNECTION_INFO)(VCHI_CONNECTION_STATE_T *state, uint32_t protocol_version, uint32_t slot_size, uint32_t num_slots, uint32_t min_bulk_size); + +// Callback to inform of a disconnect +typedef void (*VCHI_CONNECTION_DISCONNECT)(VCHI_CONNECTION_STATE_T *state, uint32_t flags); + +// Callback to inform of a power control request +typedef void (*VCHI_CONNECTION_POWER_CONTROL)(VCHI_CONNECTION_STATE_T *state, MESSAGE_TX_CHANNEL_T channel, int32_t enable); + +// allocate memory suitably aligned for this connection +typedef void * (*VCHI_BUFFER_ALLOCATE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, uint32_t * length); + +// free memory allocated by buffer_allocate +typedef void (*VCHI_BUFFER_FREE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, void * address); + + +/****************************************************************************** + System driver struct + *****************************************************************************/ + +struct opaque_vchi_connection_api_t +{ + // Routine to init the connection + VCHI_CONNECTION_INIT_T init; + + // Connection-level CRC control + VCHI_CONNECTION_CRC_CONTROL_T crc_control; + + // Routine to connect to or create service + VCHI_CONNECTION_SERVICE_CONNECT_T service_connect; + + // Routine to disconnect from a service + VCHI_CONNECTION_SERVICE_DISCONNECT_T service_disconnect; + + // Routine to queue a message + VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T service_queue_msg; + + // scatter-gather (vector) message queue + VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T service_queue_msgv; + + // Routine to dequeue a message + VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T service_dequeue_msg; + + // Routine to peek at a message + VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T service_peek_msg; + + // Routine to hold a message + VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T service_hold_msg; + + // Routine to initialise a received message iterator + VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T service_look_ahead_msg; + + // Routine to release a message + VCHI_CONNECTION_HELD_MSG_RELEASE_T held_msg_release; + + // Routine to get information on a held message + VCHI_CONNECTION_HELD_MSG_INFO_T held_msg_info; + + // Routine to check for next message on iterator + VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T msg_iter_has_next; + + // Routine to get next message on iterator + VCHI_CONNECTION_MSG_ITER_NEXT_T msg_iter_next; + + // Routine to remove the last message returned by iterator + VCHI_CONNECTION_MSG_ITER_REMOVE_T msg_iter_remove; + + // Routine to hold the last message returned by iterator + VCHI_CONNECTION_MSG_ITER_HOLD_T msg_iter_hold; + + // Routine to transmit bulk data + VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T bulk_queue_transmit; + + // Routine to receive data + VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T bulk_queue_receive; + + // Routine to report the available servers + VCHI_CONNECTION_SERVER_PRESENT server_present; + + // Routine to report the number of RX slots available + VCHI_CONNECTION_RX_SLOTS_AVAILABLE connection_rx_slots_available; + + // Routine to report the RX slot size + VCHI_CONNECTION_RX_SLOT_SIZE connection_rx_slot_size; + + // Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO + VCHI_CONNECTION_RX_BULK_BUFFER_ADDED rx_bulk_buffer_added; + + // Callback to inform a service that a Xon or Xoff message has been received + VCHI_CONNECTION_FLOW_CONTROL flow_control; + + // Callback to inform a service that a server available reply message has been received + VCHI_CONNECTION_SERVER_AVAILABLE_REPLY server_available_reply; + + // Callback to indicate that bulk auxiliary messages have arrived + VCHI_CONNECTION_BULK_AUX_RECEIVED bulk_aux_received; + + // Callback to indicate that a bulk auxiliary message has been transmitted + VCHI_CONNECTION_BULK_AUX_TRANSMITTED bulk_aux_transmitted; + + // Callback to provide information about the connection + VCHI_CONNECTION_INFO connection_info; + + // Callback to notify that peer has requested disconnect + VCHI_CONNECTION_DISCONNECT disconnect; + + // Callback to notify that peer has requested power change + VCHI_CONNECTION_POWER_CONTROL power_control; + + // allocate memory suitably aligned for this connection + VCHI_BUFFER_ALLOCATE buffer_allocate; + + // free memory allocated by buffer_allocate + VCHI_BUFFER_FREE buffer_free; + +}; + +struct vchi_connection_t { + const VCHI_CONNECTION_API_T *api; + VCHI_CONNECTION_STATE_T *state; +#ifdef VCHI_COARSE_LOCKING + struct semaphore sem; +#endif +}; + + +#endif /* CONNECTION_H_ */ + +/****************************** End of file **********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/message_drivers/message.h b/drivers/staging/vc04_services/interface/vchi/message_drivers/message.h new file mode 100644 index 000000000000..8b3f76735bd4 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/message_drivers/message.h @@ -0,0 +1,204 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VCHI_MESSAGE_H_ +#define _VCHI_MESSAGE_H_ + +#include +#include +#include + +#include "interface/vchi/vchi_cfg_internal.h" +#include "interface/vchi/vchi_common.h" + + +typedef enum message_event_type { + MESSAGE_EVENT_NONE, + MESSAGE_EVENT_NOP, + MESSAGE_EVENT_MESSAGE, + MESSAGE_EVENT_SLOT_COMPLETE, + MESSAGE_EVENT_RX_BULK_PAUSED, + MESSAGE_EVENT_RX_BULK_COMPLETE, + MESSAGE_EVENT_TX_COMPLETE, + MESSAGE_EVENT_MSG_DISCARDED +} MESSAGE_EVENT_TYPE_T; + +typedef enum vchi_msg_flags +{ + VCHI_MSG_FLAGS_NONE = 0x0, + VCHI_MSG_FLAGS_TERMINATE_DMA = 0x1 +} VCHI_MSG_FLAGS_T; + +typedef enum message_tx_channel +{ + MESSAGE_TX_CHANNEL_MESSAGE = 0, + MESSAGE_TX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards +} MESSAGE_TX_CHANNEL_T; + +// Macros used for cycling through bulk channels +#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION) +#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION) + +typedef enum message_rx_channel +{ + MESSAGE_RX_CHANNEL_MESSAGE = 0, + MESSAGE_RX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards +} MESSAGE_RX_CHANNEL_T; + +// Message receive slot information +typedef struct rx_msg_slot_info { + + struct rx_msg_slot_info *next; + //struct slot_info *prev; +#if !defined VCHI_COARSE_LOCKING + struct semaphore sem; +#endif + + uint8_t *addr; // base address of slot + uint32_t len; // length of slot in bytes + + uint32_t write_ptr; // hardware causes this to advance + uint32_t read_ptr; // this module does the reading + int active; // is this slot in the hardware dma fifo? + uint32_t msgs_parsed; // count how many messages are in this slot + uint32_t msgs_released; // how many messages have been released + void *state; // connection state information + uint8_t ref_count[VCHI_MAX_SERVICES_PER_CONNECTION]; // reference count for slots held by services +} RX_MSG_SLOTINFO_T; + +// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out. +// In particular, it mustn't use addr and len - they're the client buffer, but the message +// driver will be tasked with sending the aligned core section. +typedef struct rx_bulk_slotinfo_t { + struct rx_bulk_slotinfo_t *next; + + struct semaphore *blocking; + + // needed by DMA + void *addr; + uint32_t len; + + // needed for the callback + void *service; + void *handle; + VCHI_FLAGS_T flags; +} RX_BULK_SLOTINFO_T; + + +/* ---------------------------------------------------------------------- + * each connection driver will have a pool of the following struct. + * + * the pool will be managed by vchi_qman_* + * this means there will be multiple queues (single linked lists) + * a given struct message_info will be on exactly one of these queues + * at any one time + * -------------------------------------------------------------------- */ +typedef struct rx_message_info { + + struct message_info *next; + //struct message_info *prev; + + uint8_t *addr; + uint32_t len; + RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message + uint32_t tx_timestamp; + uint32_t rx_timestamp; + +} RX_MESSAGE_INFO_T; + +typedef struct { + MESSAGE_EVENT_TYPE_T type; + + struct { + // for messages + void *addr; // address of message + uint16_t slot_delta; // whether this message indicated slot delta + uint32_t len; // length of message + RX_MSG_SLOTINFO_T *slot; // slot this message is in + int32_t service; // service id this message is destined for + uint32_t tx_timestamp; // timestamp from the header + uint32_t rx_timestamp; // timestamp when we parsed it + } message; + + // FIXME: cleanup slot reporting... + RX_MSG_SLOTINFO_T *rx_msg; + RX_BULK_SLOTINFO_T *rx_bulk; + void *tx_handle; + MESSAGE_TX_CHANNEL_T tx_channel; + +} MESSAGE_EVENT_T; + + +// callbacks +typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state ); + +typedef struct { + VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback; +} VCHI_MESSAGE_DRIVER_OPEN_T; + + +// handle to this instance of message driver (as returned by ->open) +typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T; + +struct opaque_vchi_message_driver_t { + VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state ); + int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle ); + int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle ); + int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, int32_t enable ); + int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot ); // rx message + int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot ); // rx data (bulk) + int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle ); // tx (message & bulk) + void (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event ); // get the next event from message_driver + int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle ); + int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, int32_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void + *address, uint32_t length_avail, uint32_t max_total_length, int32_t pad_to_fill, int32_t allow_partial ); + + int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count ); + int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length ); + void * (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length ); + void (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address ); + int (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size ); + int (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size ); + + int32_t (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); + uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); + int (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); + int (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel ); + void (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len ); + void (*debug)( VCHI_MDRIVER_HANDLE_T *handle ); +}; + + +#endif // _VCHI_MESSAGE_H_ + +/****************************** End of file ***********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi.h b/drivers/staging/vc04_services/interface/vchi/vchi.h new file mode 100644 index 000000000000..1b17e98f7379 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi.h @@ -0,0 +1,378 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_H_ +#define VCHI_H_ + +#include "interface/vchi/vchi_cfg.h" +#include "interface/vchi/vchi_common.h" +#include "interface/vchi/connections/connection.h" +#include "vchi_mh.h" + + +/****************************************************************************** + Global defs + *****************************************************************************/ + +#define VCHI_BULK_ROUND_UP(x) ((((unsigned long)(x))+VCHI_BULK_ALIGN-1) & ~(VCHI_BULK_ALIGN-1)) +#define VCHI_BULK_ROUND_DOWN(x) (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN-1)) +#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN-1)))) + +#ifdef USE_VCHIQ_ARM +#define VCHI_BULK_ALIGNED(x) 1 +#else +#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN-1)) == 0) +#endif + +struct vchi_version { + uint32_t version; + uint32_t version_min; +}; +#define VCHI_VERSION(v_) { v_, v_ } +#define VCHI_VERSION_EX(v_, m_) { v_, m_ } + +typedef enum +{ + VCHI_VEC_POINTER, + VCHI_VEC_HANDLE, + VCHI_VEC_LIST +} VCHI_MSG_VECTOR_TYPE_T; + +typedef struct vchi_msg_vector_ex { + + VCHI_MSG_VECTOR_TYPE_T type; + union + { + // a memory handle + struct + { + VCHI_MEM_HANDLE_T handle; + uint32_t offset; + int32_t vec_len; + } handle; + + // an ordinary data pointer + struct + { + const void *vec_base; + int32_t vec_len; + } ptr; + + // a nested vector list + struct + { + struct vchi_msg_vector_ex *vec; + uint32_t vec_len; + } list; + } u; +} VCHI_MSG_VECTOR_EX_T; + + +// Construct an entry in a msg vector for a pointer (p) of length (l) +#define VCHI_VEC_POINTER(p,l) VCHI_VEC_POINTER, { { (VCHI_MEM_HANDLE_T)(p), (l) } } + +// Construct an entry in a msg vector for a message handle (h), starting at offset (o) of length (l) +#define VCHI_VEC_HANDLE(h,o,l) VCHI_VEC_HANDLE, { { (h), (o), (l) } } + +// Macros to manipulate 'FOURCC' values +#define MAKE_FOURCC(x) ((int32_t)( (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3] )) +#define FOURCC_TO_CHAR(x) (x >> 24) & 0xFF,(x >> 16) & 0xFF,(x >> 8) & 0xFF, x & 0xFF + + +// Opaque service information +struct opaque_vchi_service_t; + +// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold, +// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only. +typedef struct +{ + struct opaque_vchi_service_t *service; + void *message; +} VCHI_HELD_MSG_T; + + + +// structure used to provide the information needed to open a server or a client +typedef struct { + struct vchi_version version; + int32_t service_id; + VCHI_CONNECTION_T *connection; + uint32_t rx_fifo_size; + uint32_t tx_fifo_size; + VCHI_CALLBACK_T callback; + void *callback_param; + /* client intends to receive bulk transfers of + odd lengths or into unaligned buffers */ + int32_t want_unaligned_bulk_rx; + /* client intends to transmit bulk transfers of + odd lengths or out of unaligned buffers */ + int32_t want_unaligned_bulk_tx; + /* client wants to check CRCs on (bulk) xfers. + Only needs to be set at 1 end - will do both directions. */ + int32_t want_crc; +} SERVICE_CREATION_T; + +// Opaque handle for a VCHI instance +typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T; + +// Opaque handle for a server or client +typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T; + +// Service registration & startup +typedef void (*VCHI_SERVICE_INIT)(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections); + +typedef struct service_info_tag { + const char * const vll_filename; /* VLL to load to start this service. This is an empty string if VLL is "static" */ + VCHI_SERVICE_INIT init; /* Service initialisation function */ + void *vll_handle; /* VLL handle; NULL when unloaded or a "static VLL" in build */ +} SERVICE_INFO_T; + +/****************************************************************************** + Global funcs - implementation is specific to which side you are on (local / remote) + *****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern /*@observer@*/ VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table, + const VCHI_MESSAGE_DRIVER_T * low_level); + + +// Routine used to initialise the vchi on both local + remote connections +extern int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle ); + +extern int32_t vchi_exit( void ); + +extern int32_t vchi_connect( VCHI_CONNECTION_T **connections, + const uint32_t num_connections, + VCHI_INSTANCE_T instance_handle ); + +//When this is called, ensure that all services have no data pending. +//Bulk transfers can remain 'queued' +extern int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle ); + +// Global control over bulk CRC checking +extern int32_t vchi_crc_control( VCHI_CONNECTION_T *connection, + VCHI_CRC_CONTROL_T control ); + +// helper functions +extern void * vchi_allocate_buffer(VCHI_SERVICE_HANDLE_T handle, uint32_t *length); +extern void vchi_free_buffer(VCHI_SERVICE_HANDLE_T handle, void *address); +extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle); + + +/****************************************************************************** + Global service API + *****************************************************************************/ +// Routine to create a named service +extern int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle, + SERVICE_CREATION_T *setup, + VCHI_SERVICE_HANDLE_T *handle ); + +// Routine to destory a service +extern int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle ); + +// Routine to open a named service +extern int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle, + SERVICE_CREATION_T *setup, + VCHI_SERVICE_HANDLE_T *handle); + +extern int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, + short *peer_version ); + +// Routine to close a named service +extern int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle ); + +// Routine to increment ref count on a named service +extern int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle ); + +// Routine to decrement ref count on a named service +extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle ); + +// Routine to set a control option for a named service +extern int32_t vchi_service_set_option( const VCHI_SERVICE_HANDLE_T handle, + VCHI_SERVICE_OPTION_T option, + int value); + +// Routine to send a message across a service +extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle, + const void *data, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// scatter-gather (vector) and send message +int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle, + VCHI_MSG_VECTOR_EX_T *vector, + uint32_t count, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// legacy scatter-gather (vector) and send message, only handles pointers +int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle, + VCHI_MSG_VECTOR_T *vector, + uint32_t count, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// Routine to receive a msg from a service +// Dequeue is equivalent to hold, copy into client buffer, release +extern int32_t vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle, + void *data, + uint32_t max_data_size_to_read, + uint32_t *actual_msg_size, + VCHI_FLAGS_T flags ); + +// Routine to look at a message in place. +// The message is not dequeued, so a subsequent call to peek or dequeue +// will return the same message. +extern int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags ); + +// Routine to remove a message after it has been read in place with peek +// The first message on the queue is dequeued. +extern int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle ); + +// Routine to look at a message in place. +// The message is dequeued, so the caller is left holding it; the descriptor is +// filled in and must be released when the user has finished with the message. +extern int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle, + void **data, // } may be NULL, as info can be + uint32_t *msg_size, // } obtained from HELD_MSG_T + VCHI_FLAGS_T flags, + VCHI_HELD_MSG_T *message_descriptor ); + +// Initialise an iterator to look through messages in place +extern int32_t vchi_msg_look_ahead( VCHI_SERVICE_HANDLE_T handle, + VCHI_MSG_ITER_T *iter, + VCHI_FLAGS_T flags ); + +/****************************************************************************** + Global service support API - operations on held messages and message iterators + *****************************************************************************/ + +// Routine to get the address of a held message +extern void *vchi_held_msg_ptr( const VCHI_HELD_MSG_T *message ); + +// Routine to get the size of a held message +extern int32_t vchi_held_msg_size( const VCHI_HELD_MSG_T *message ); + +// Routine to get the transmit timestamp as written into the header by the peer +extern uint32_t vchi_held_msg_tx_timestamp( const VCHI_HELD_MSG_T *message ); + +// Routine to get the reception timestamp, written as we parsed the header +extern uint32_t vchi_held_msg_rx_timestamp( const VCHI_HELD_MSG_T *message ); + +// Routine to release a held message after it has been processed +extern int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message ); + +// Indicates whether the iterator has a next message. +extern int32_t vchi_msg_iter_has_next( const VCHI_MSG_ITER_T *iter ); + +// Return the pointer and length for the next message and advance the iterator. +extern int32_t vchi_msg_iter_next( VCHI_MSG_ITER_T *iter, + void **data, + uint32_t *msg_size ); + +// Remove the last message returned by vchi_msg_iter_next. +// Can only be called once after each call to vchi_msg_iter_next. +extern int32_t vchi_msg_iter_remove( VCHI_MSG_ITER_T *iter ); + +// Hold the last message returned by vchi_msg_iter_next. +// Can only be called once after each call to vchi_msg_iter_next. +extern int32_t vchi_msg_iter_hold( VCHI_MSG_ITER_T *iter, + VCHI_HELD_MSG_T *message ); + +// Return information for the next message, and hold it, advancing the iterator. +extern int32_t vchi_msg_iter_hold_next( VCHI_MSG_ITER_T *iter, + void **data, // } may be NULL + uint32_t *msg_size, // } + VCHI_HELD_MSG_T *message ); + + +/****************************************************************************** + Global bulk API + *****************************************************************************/ + +// Routine to prepare interface for a transfer from the other side +extern int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle, + void *data_dst, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *transfer_handle ); + + +// Prepare interface for a transfer from the other side into relocatable memory. +int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle, + VCHI_MEM_HANDLE_T h_dst, + uint32_t offset, + uint32_t data_size, + const VCHI_FLAGS_T flags, + void * const bulk_handle ); + +// Routine to queue up data ready for transfer to the other (once they have signalled they are ready) +extern int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle, + const void *data_src, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *transfer_handle ); + + +/****************************************************************************** + Configuration plumbing + *****************************************************************************/ + +// function prototypes for the different mid layers (the state info gives the different physical connections) +extern const VCHI_CONNECTION_API_T *single_get_func_table( void ); +//extern const VCHI_CONNECTION_API_T *local_server_get_func_table( void ); +//extern const VCHI_CONNECTION_API_T *local_client_get_func_table( void ); + +// declare all message drivers here +const VCHI_MESSAGE_DRIVER_T *vchi_mphi_message_driver_func_table( void ); + +#ifdef __cplusplus +} +#endif + +extern int32_t vchi_bulk_queue_transmit_reloc( VCHI_SERVICE_HANDLE_T handle, + VCHI_MEM_HANDLE_T h_src, + uint32_t offset, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *transfer_handle ); +#endif /* VCHI_H_ */ + +/****************************** End of file **********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h b/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h new file mode 100644 index 000000000000..26bc2d38d725 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h @@ -0,0 +1,224 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_CFG_H_ +#define VCHI_CFG_H_ + +/**************************************************************************************** + * Defines in this first section are part of the VCHI API and may be examined by VCHI + * services. + ***************************************************************************************/ + +/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */ +/* Really determined by the message driver, and should be available from a run-time call. */ +#ifndef VCHI_BULK_ALIGN +# if __VCCOREVER__ >= 0x04000000 +# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans +# else +# define VCHI_BULK_ALIGN 16 +# endif +#endif + +/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */ +/* May be less than or greater than VCHI_BULK_ALIGN */ +/* Really determined by the message driver, and should be available from a run-time call. */ +#ifndef VCHI_BULK_GRANULARITY +# if __VCCOREVER__ >= 0x04000000 +# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans +# else +# define VCHI_BULK_GRANULARITY 16 +# endif +#endif + +/* The largest possible message to be queued with vchi_msg_queue. */ +#ifndef VCHI_MAX_MSG_SIZE +# if defined VCHI_LOCAL_HOST_PORT +# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk? +# else +# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!! +# endif +#endif + +/****************************************************************************************** + * Defines below are system configuration options, and should not be used by VCHI services. + *****************************************************************************************/ + +/* How many connections can we support? A localhost implementation uses 2 connections, + * 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW + * driver. */ +#ifndef VCHI_MAX_NUM_CONNECTIONS +# define VCHI_MAX_NUM_CONNECTIONS 3 +#endif + +/* How many services can we open per connection? Extending this doesn't cost processing time, just a small + * amount of static memory. */ +#ifndef VCHI_MAX_SERVICES_PER_CONNECTION +# define VCHI_MAX_SERVICES_PER_CONNECTION 36 +#endif + +/* Adjust if using a message driver that supports more logical TX channels */ +#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION +# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels +#endif + +/* Adjust if using a message driver that supports more logical RX channels */ +#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION +# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI +#endif + +/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective + * receive queue space, less message headers. */ +#ifndef VCHI_NUM_READ_SLOTS +# if defined(VCHI_LOCAL_HOST_PORT) +# define VCHI_NUM_READ_SLOTS 4 +# else +# define VCHI_NUM_READ_SLOTS 48 +# endif +#endif + +/* Do we utilise overrun facility for receive message slots? Can aid peer transmit + * performance. Only define on VideoCore end, talking to host. + */ +//#define VCHI_MSG_RX_OVERRUN + +/* How many transmit slots do we use. Generally don't need many, as the hardware driver + * underneath VCHI will usually have its own buffering. */ +#ifndef VCHI_NUM_WRITE_SLOTS +# define VCHI_NUM_WRITE_SLOTS 4 +#endif + +/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots, + * then it's taking up too much buffer space, and the peer service will be told to stop + * transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS + * needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency + * is too high. */ +#ifndef VCHI_XOFF_THRESHOLD +# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2) +#endif + +/* After we've sent an XOFF, the peer will be told to resume transmission once the local + * service has dequeued/released enough messages that it's now occupying + * VCHI_XON_THRESHOLD slots or fewer. */ +#ifndef VCHI_XON_THRESHOLD +# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4) +#endif + +/* A size below which a bulk transfer omits the handshake completely and always goes + * via the message channel, if bulk auxiliary is being sent on that service. (The user + * can guarantee this by enabling unaligned transmits). + * Not API. */ +#ifndef VCHI_MIN_BULK_SIZE +# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 ) +#endif + +/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between + * speed and latency; the smaller the chunk size the better change of messages and other + * bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not + * break transmissions into chunks. + */ +#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI +# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024) +#endif + +/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode + * with multiple-line frames. Only use if the receiver can cope. */ +#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2 +# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0 +#endif + +/* How many TX messages can we have pending in our transmit slots. Once exhausted, + * vchi_msg_queue will be blocked. */ +#ifndef VCHI_TX_MSG_QUEUE_SIZE +# define VCHI_TX_MSG_QUEUE_SIZE 256 +#endif + +/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing + * will be suspended until older messages are dequeued/released. */ +#ifndef VCHI_RX_MSG_QUEUE_SIZE +# define VCHI_RX_MSG_QUEUE_SIZE 256 +#endif + +/* Really should be able to cope if we run out of received message descriptors, by + * suspending parsing as the comment above says, but we don't. This sweeps the issue + * under the carpet. */ +#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS +# undef VCHI_RX_MSG_QUEUE_SIZE +# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS +#endif + +/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit + * will be blocked. */ +#ifndef VCHI_TX_BULK_QUEUE_SIZE +# define VCHI_TX_BULK_QUEUE_SIZE 64 +#endif + +/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive + * will be blocked. */ +#ifndef VCHI_RX_BULK_QUEUE_SIZE +# define VCHI_RX_BULK_QUEUE_SIZE 64 +#endif + +/* A limit on how many outstanding bulk requests we expect the peer to give us. If + * the peer asks for more than this, VCHI will fail and assert. The number is determined + * by the peer's hardware - it's the number of outstanding requests that can be queued + * on all bulk channels. VC3's MPHI peripheral allows 16. */ +#ifndef VCHI_MAX_PEER_BULK_REQUESTS +# define VCHI_MAX_PEER_BULK_REQUESTS 32 +#endif + +/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2 + * transmitter on and off. + */ +/*#define VCHI_CCP2TX_MANUAL_POWER*/ + +#ifndef VCHI_CCP2TX_MANUAL_POWER + +/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set + * negative for no IDLE. + */ +# ifndef VCHI_CCP2TX_IDLE_TIMEOUT +# define VCHI_CCP2TX_IDLE_TIMEOUT 5 +# endif + +/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set + * negative for no OFF. + */ +# ifndef VCHI_CCP2TX_OFF_TIMEOUT +# define VCHI_CCP2TX_OFF_TIMEOUT 1000 +# endif + +#endif /* VCHI_CCP2TX_MANUAL_POWER */ + +#endif /* VCHI_CFG_H_ */ + +/****************************** End of file **********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_cfg_internal.h b/drivers/staging/vc04_services/interface/vchi/vchi_cfg_internal.h new file mode 100644 index 000000000000..35dcba4837d4 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi_cfg_internal.h @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_CFG_INTERNAL_H_ +#define VCHI_CFG_INTERNAL_H_ + +/**************************************************************************************** + * Control optimisation attempts. + ***************************************************************************************/ + +// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second +#define VCHI_COARSE_LOCKING + +// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx) +// (only relevant if VCHI_COARSE_LOCKING) +#define VCHI_ELIDE_BLOCK_EXIT_LOCK + +// Avoid lock on non-blocking peek +// (only relevant if VCHI_COARSE_LOCKING) +#define VCHI_AVOID_PEEK_LOCK + +// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation. +#define VCHI_MULTIPLE_HANDLER_THREADS + +// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash +// our way through the pool of descriptors. +#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD + +// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING. +#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS + +// Don't use message descriptors for TX messages that don't need them +#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS + +// Nano-locks for multiqueue +//#define VCHI_MQUEUE_NANOLOCKS + +// Lock-free(er) dequeuing +//#define VCHI_RX_NANOLOCKS + +#endif /*VCHI_CFG_INTERNAL_H_*/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_common.h b/drivers/staging/vc04_services/interface/vchi/vchi_common.h new file mode 100644 index 000000000000..d535a72970d3 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi_common.h @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_COMMON_H_ +#define VCHI_COMMON_H_ + + +//flags used when sending messages (must be bitmapped) +typedef enum +{ + VCHI_FLAGS_NONE = 0x0, + VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side) + VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent + VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go + VCHI_FLAGS_ALLOW_PARTIAL = 0x8, + VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10, + VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20, + + VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only + VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only + VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only + VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only + VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only + VCHI_FLAGS_INTERNAL = 0xFF0000 +} VCHI_FLAGS_T; + +// constants for vchi_crc_control() +typedef enum { + VCHI_CRC_NOTHING = -1, + VCHI_CRC_PER_SERVICE = 0, + VCHI_CRC_EVERYTHING = 1, +} VCHI_CRC_CONTROL_T; + +//callback reasons when an event occurs on a service +typedef enum +{ + VCHI_CALLBACK_REASON_MIN, + + //This indicates that there is data available + //handle is the msg id that was transmitted with the data + // When a message is received and there was no FULL message available previously, send callback + // Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails + VCHI_CALLBACK_MSG_AVAILABLE, + VCHI_CALLBACK_MSG_SENT, + VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented + + // This indicates that a transfer from the other side has completed + VCHI_CALLBACK_BULK_RECEIVED, + //This indicates that data queued up to be sent has now gone + //handle is the msg id that was used when sending the data + VCHI_CALLBACK_BULK_SENT, + VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented + VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented + + VCHI_CALLBACK_SERVICE_CLOSED, + + // this side has sent XOFF to peer due to lack of data consumption by service + // (suggests the service may need to take some recovery action if it has + // been deliberately holding off consuming data) + VCHI_CALLBACK_SENT_XOFF, + VCHI_CALLBACK_SENT_XON, + + // indicates that a bulk transfer has finished reading the source buffer + VCHI_CALLBACK_BULK_DATA_READ, + + // power notification events (currently host side only) + VCHI_CALLBACK_PEER_OFF, + VCHI_CALLBACK_PEER_SUSPENDED, + VCHI_CALLBACK_PEER_ON, + VCHI_CALLBACK_PEER_RESUMED, + VCHI_CALLBACK_FORCED_POWER_OFF, + +#ifdef USE_VCHIQ_ARM + // some extra notifications provided by vchiq_arm + VCHI_CALLBACK_SERVICE_OPENED, + VCHI_CALLBACK_BULK_RECEIVE_ABORTED, + VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, +#endif + + VCHI_CALLBACK_REASON_MAX +} VCHI_CALLBACK_REASON_T; + +// service control options +typedef enum +{ + VCHI_SERVICE_OPTION_MIN, + + VCHI_SERVICE_OPTION_TRACE, + VCHI_SERVICE_OPTION_SYNCHRONOUS, + + VCHI_SERVICE_OPTION_MAX +} VCHI_SERVICE_OPTION_T; + + +//Callback used by all services / bulk transfers +typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param + VCHI_CALLBACK_REASON_T reason, + void *handle ); //for transmitting msg's only + + + +/* + * Define vector struct for scatter-gather (vector) operations + * Vectors can be nested - if a vector element has negative length, then + * the data pointer is treated as pointing to another vector array, with + * '-vec_len' elements. Thus to append a header onto an existing vector, + * you can do this: + * + * void foo(const VCHI_MSG_VECTOR_T *v, int n) + * { + * VCHI_MSG_VECTOR_T nv[2]; + * nv[0].vec_base = my_header; + * nv[0].vec_len = sizeof my_header; + * nv[1].vec_base = v; + * nv[1].vec_len = -n; + * ... + * + */ +typedef struct vchi_msg_vector { + const void *vec_base; + int32_t vec_len; +} VCHI_MSG_VECTOR_T; + +// Opaque type for a connection API +typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T; + +// Opaque type for a message driver +typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T; + + +// Iterator structure for reading ahead through received message queue. Allocated by client, +// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only. +// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead - +// will not proceed to messages received since. Behaviour is undefined if an iterator +// is used again after messages for that service are removed/dequeued by any +// means other than vchi_msg_iter_... calls on the iterator itself. +typedef struct { + struct opaque_vchi_service_t *service; + void *last; + void *next; + void *remove; +} VCHI_MSG_ITER_T; + + +#endif // VCHI_COMMON_H_ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_mh.h b/drivers/staging/vc04_services/interface/vchi/vchi_mh.h new file mode 100644 index 000000000000..198bd076b666 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi_mh.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_MH_H_ +#define VCHI_MH_H_ + +#include + +typedef int32_t VCHI_MEM_HANDLE_T; +#define VCHI_MEM_HANDLE_INVALID 0 + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h new file mode 100644 index 000000000000..ad398bae6ee4 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_VCHIQ_H +#define VCHIQ_VCHIQ_H + +#include "vchiq_if.h" +#include "vchiq_util.h" + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835.h new file mode 100644 index 000000000000..7ea5c64d5343 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_2835_H +#define VCHIQ_2835_H + +#include "vchiq_pagelist.h" + +#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0 +#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 + +#endif /* VCHIQ_2835_H */ 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 new file mode 100644 index 000000000000..c29040fdf9a7 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -0,0 +1,586 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define dmac_map_area __glue(_CACHE,_dma_map_area) +#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) + +extern void dmac_map_area(const void *, size_t, int); +extern void dmac_unmap_area(const void *, size_t, int); + +#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) + +#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) + +#include "vchiq_arm.h" +#include "vchiq_2835.h" +#include "vchiq_connected.h" +#include "vchiq_killable.h" + +#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) + +#define BELL0 0x00 +#define BELL2 0x08 + +typedef struct vchiq_2835_state_struct { + int inited; + VCHIQ_ARM_STATE_T arm_state; +} VCHIQ_2835_ARM_STATE_T; + +static void __iomem *g_regs; +static unsigned int g_cache_line_size = sizeof(CACHE_LINE_SIZE); +static unsigned int g_fragments_size; +static char *g_fragments_base; +static char *g_free_fragments; +static struct semaphore g_free_fragments_sema; +static unsigned long g_virt_to_bus_offset; + +extern int vchiq_arm_log_level; + +static DEFINE_SEMAPHORE(g_free_fragments_mutex); + +static irqreturn_t +vchiq_doorbell_irq(int irq, void *dev_id); + +static int +create_pagelist(char __user *buf, size_t count, unsigned short type, + struct task_struct *task, PAGELIST_T ** ppagelist); + +static void +free_pagelist(PAGELIST_T *pagelist, int actual); + +int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) +{ + struct device *dev = &pdev->dev; + struct rpi_firmware *fw = platform_get_drvdata(pdev); + VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; + struct resource *res; + void *slot_mem; + dma_addr_t slot_phys; + u32 channelbase; + int slot_mem_size, frag_mem_size; + int err, irq, i; + + g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); + + (void)of_property_read_u32(dev->of_node, "cache-line-size", + &g_cache_line_size); + g_fragments_size = 2 * g_cache_line_size; + + /* Allocate space for the channels in coherent memory */ + slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); + frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS); + + slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, + &slot_phys, GFP_KERNEL); + if (!slot_mem) { + dev_err(dev, "could not allocate DMA memory\n"); + return -ENOMEM; + } + + WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); + + vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); + if (!vchiq_slot_zero) + return -EINVAL; + + vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = + (int)slot_phys + slot_mem_size; + vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = + MAX_FRAGMENTS; + + g_fragments_base = (char *)slot_mem + slot_mem_size; + slot_mem_size += frag_mem_size; + + g_free_fragments = g_fragments_base; + for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { + *(char **)&g_fragments_base[i*g_fragments_size] = + &g_fragments_base[(i + 1)*g_fragments_size]; + } + *(char **)&g_fragments_base[i * g_fragments_size] = NULL; + sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); + + if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + g_regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(g_regs)) + return PTR_ERR(g_regs); + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(dev, "failed to get IRQ\n"); + return irq; + } + + err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, + "VCHIQ doorbell", state); + if (err) { + dev_err(dev, "failed to register irq=%d\n", irq); + return err; + } + + /* Send the base address of the slots to VideoCore */ + channelbase = slot_phys; + err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT, + &channelbase, sizeof(channelbase)); + if (err || channelbase) { + dev_err(dev, "failed to set channelbase\n"); + return err ? : -ENXIO; + } + + vchiq_log_info(vchiq_arm_log_level, + "vchiq_init - done (slots %x, phys %pad)", + (unsigned int)vchiq_slot_zero, &slot_phys); + + vchiq_call_connected_callbacks(); + + return 0; +} + +VCHIQ_STATUS_T +vchiq_platform_init_state(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + state->platform_state = kzalloc(sizeof(VCHIQ_2835_ARM_STATE_T), GFP_KERNEL); + ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 1; + status = vchiq_arm_init_state(state, &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state); + if(status != VCHIQ_SUCCESS) + { + ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 0; + } + return status; +} + +VCHIQ_ARM_STATE_T* +vchiq_platform_get_arm_state(VCHIQ_STATE_T *state) +{ + if(!((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited) + { + BUG(); + } + return &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state; +} + +void +remote_event_signal(REMOTE_EVENT_T *event) +{ + wmb(); + + event->fired = 1; + + dsb(); /* data barrier operation */ + + if (event->armed) + writel(0, g_regs + BELL2); /* trigger vc interrupt */ +} + +int +vchiq_copy_from_user(void *dst, const void *src, int size) +{ + if ((uint32_t)src < TASK_SIZE) { + return copy_from_user(dst, src, size); + } else { + memcpy(dst, src, size); + return 0; + } +} + +VCHIQ_STATUS_T +vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, + void *offset, int size, int dir) +{ + PAGELIST_T *pagelist; + int ret; + + WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID); + + ret = create_pagelist((char __user *)offset, size, + (dir == VCHIQ_BULK_RECEIVE) + ? PAGELIST_READ + : PAGELIST_WRITE, + current, + &pagelist); + if (ret != 0) + return VCHIQ_ERROR; + + bulk->handle = memhandle; + bulk->data = VCHIQ_ARM_ADDRESS(pagelist); + + /* Store the pagelist address in remote_data, which isn't used by the + slave. */ + bulk->remote_data = pagelist; + + return VCHIQ_SUCCESS; +} + +void +vchiq_complete_bulk(VCHIQ_BULK_T *bulk) +{ + if (bulk && bulk->remote_data && bulk->actual) + free_pagelist((PAGELIST_T *)bulk->remote_data, bulk->actual); +} + +void +vchiq_transfer_bulk(VCHIQ_BULK_T *bulk) +{ + /* + * This should only be called on the master (VideoCore) side, but + * provide an implementation to avoid the need for ifdefery. + */ + BUG(); +} + +void +vchiq_dump_platform_state(void *dump_context) +{ + char buf[80]; + int len; + len = snprintf(buf, sizeof(buf), + " Platform: 2835 (VC master)"); + vchiq_dump(dump_context, buf, len + 1); +} + +VCHIQ_STATUS_T +vchiq_platform_suspend(VCHIQ_STATE_T *state) +{ + return VCHIQ_ERROR; +} + +VCHIQ_STATUS_T +vchiq_platform_resume(VCHIQ_STATE_T *state) +{ + return VCHIQ_SUCCESS; +} + +void +vchiq_platform_paused(VCHIQ_STATE_T *state) +{ +} + +void +vchiq_platform_resumed(VCHIQ_STATE_T *state) +{ +} + +int +vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state) +{ + return 1; // autosuspend not supported - videocore always wanted +} + +int +vchiq_platform_use_suspend_timer(void) +{ + return 0; +} +void +vchiq_dump_platform_use_state(VCHIQ_STATE_T *state) +{ + vchiq_log_info(vchiq_arm_log_level, "Suspend timer not in use"); +} +void +vchiq_platform_handle_timeout(VCHIQ_STATE_T *state) +{ + (void)state; +} +/* + * Local functions + */ + +static irqreturn_t +vchiq_doorbell_irq(int irq, void *dev_id) +{ + VCHIQ_STATE_T *state = dev_id; + irqreturn_t ret = IRQ_NONE; + unsigned int status; + + /* Read (and clear) the doorbell */ + status = readl(g_regs + BELL0); + + if (status & 0x4) { /* Was the doorbell rung? */ + remote_event_pollall(state); + ret = IRQ_HANDLED; + } + + return ret; +} + +/* There is a potential problem with partial cache lines (pages?) +** at the ends of the block when reading. If the CPU accessed anything in +** the same line (page?) then it may have pulled old data into the cache, +** obscuring the new data underneath. We can solve this by transferring the +** partial cache lines separately, and allowing the ARM to copy into the +** cached area. + +** N.B. This implementation plays slightly fast and loose with the Linux +** driver programming rules, e.g. its use of dmac_map_area instead of +** dma_map_single, but it isn't a multi-platform driver and it benefits +** from increased speed as a result. +*/ + +static int +create_pagelist(char __user *buf, size_t count, unsigned short type, + struct task_struct *task, PAGELIST_T ** ppagelist) +{ + PAGELIST_T *pagelist; + struct page **pages; + unsigned long *addrs; + unsigned int num_pages, offset, i; + char *addr, *base_addr, *next_addr; + int run, addridx, actual_pages; + unsigned long *need_release; + + offset = (unsigned int)buf & (PAGE_SIZE - 1); + num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE; + + *ppagelist = NULL; + + /* Allocate enough storage to hold the page pointers and the page + ** list + */ + pagelist = kmalloc(sizeof(PAGELIST_T) + + (num_pages * sizeof(unsigned long)) + + sizeof(unsigned long) + + (num_pages * sizeof(pages[0])), + GFP_KERNEL); + + vchiq_log_trace(vchiq_arm_log_level, + "create_pagelist - %x", (unsigned int)pagelist); + if (!pagelist) + return -ENOMEM; + + addrs = pagelist->addrs; + need_release = (unsigned long *)(addrs + num_pages); + pages = (struct page **)(addrs + num_pages + 1); + + if (is_vmalloc_addr(buf)) { + int dir = (type == PAGELIST_WRITE) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; + unsigned long length = count; + unsigned int off = offset; + + for (actual_pages = 0; actual_pages < num_pages; + actual_pages++) { + struct page *pg = vmalloc_to_page(buf + (actual_pages * + PAGE_SIZE)); + size_t bytes = PAGE_SIZE - off; + + if (bytes > length) + bytes = length; + pages[actual_pages] = pg; + dmac_map_area(page_address(pg) + off, bytes, dir); + length -= bytes; + off = 0; + } + *need_release = 0; /* do not try and release vmalloc pages */ + } else { + down_read(&task->mm->mmap_sem); + actual_pages = get_user_pages(task, task->mm, + (unsigned long)buf & ~(PAGE_SIZE - 1), + num_pages, + (type == PAGELIST_READ) /*Write */ , + 0 /*Force */ , + pages, + NULL /*vmas */); + up_read(&task->mm->mmap_sem); + + if (actual_pages != num_pages) { + vchiq_log_info(vchiq_arm_log_level, + "create_pagelist - only %d/%d pages locked", + actual_pages, + num_pages); + + /* This is probably due to the process being killed */ + while (actual_pages > 0) + { + actual_pages--; + page_cache_release(pages[actual_pages]); + } + kfree(pagelist); + if (actual_pages == 0) + actual_pages = -ENOMEM; + return actual_pages; + } + *need_release = 1; /* release user pages */ + } + + pagelist->length = count; + pagelist->type = type; + pagelist->offset = offset; + + /* Group the pages into runs of contiguous pages */ + + base_addr = VCHIQ_ARM_ADDRESS(page_address(pages[0])); + next_addr = base_addr + PAGE_SIZE; + addridx = 0; + run = 0; + + for (i = 1; i < num_pages; i++) { + addr = VCHIQ_ARM_ADDRESS(page_address(pages[i])); + if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) { + next_addr += PAGE_SIZE; + run++; + } else { + addrs[addridx] = (unsigned long)base_addr + run; + addridx++; + base_addr = addr; + next_addr = addr + PAGE_SIZE; + run = 0; + } + } + + addrs[addridx] = (unsigned long)base_addr + run; + addridx++; + + /* Partial cache lines (fragments) require special measures */ + if ((type == PAGELIST_READ) && + ((pagelist->offset & (g_cache_line_size - 1)) || + ((pagelist->offset + pagelist->length) & + (g_cache_line_size - 1)))) { + char *fragments; + + if (down_interruptible(&g_free_fragments_sema) != 0) { + kfree(pagelist); + return -EINTR; + } + + WARN_ON(g_free_fragments == NULL); + + down(&g_free_fragments_mutex); + fragments = g_free_fragments; + WARN_ON(fragments == NULL); + g_free_fragments = *(char **) g_free_fragments; + up(&g_free_fragments_mutex); + pagelist->type = PAGELIST_READ_WITH_FRAGMENTS + + (fragments - g_fragments_base) / g_fragments_size; + } + + dmac_flush_range(pagelist, addrs + num_pages); + + *ppagelist = pagelist; + + return 0; +} + +static void +free_pagelist(PAGELIST_T *pagelist, int actual) +{ + unsigned long *need_release; + struct page **pages; + unsigned int num_pages, i; + + vchiq_log_trace(vchiq_arm_log_level, + "free_pagelist - %x, %d", (unsigned int)pagelist, actual); + + num_pages = + (pagelist->length + pagelist->offset + PAGE_SIZE - 1) / + PAGE_SIZE; + + need_release = (unsigned long *)(pagelist->addrs + num_pages); + pages = (struct page **)(pagelist->addrs + num_pages + 1); + + /* Deal with any partial cache lines (fragments) */ + if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) { + char *fragments = g_fragments_base + + (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) * + g_fragments_size; + int head_bytes, tail_bytes; + head_bytes = (g_cache_line_size - pagelist->offset) & + (g_cache_line_size - 1); + tail_bytes = (pagelist->offset + actual) & + (g_cache_line_size - 1); + + if ((actual >= 0) && (head_bytes != 0)) { + if (head_bytes > actual) + head_bytes = actual; + + memcpy((char *)page_address(pages[0]) + + pagelist->offset, + fragments, + head_bytes); + } + if ((actual >= 0) && (head_bytes < actual) && + (tail_bytes != 0)) { + memcpy((char *)page_address(pages[num_pages - 1]) + + ((pagelist->offset + actual) & + (PAGE_SIZE - 1) & ~(g_cache_line_size - 1)), + fragments + g_cache_line_size, + tail_bytes); + } + + down(&g_free_fragments_mutex); + *(char **)fragments = g_free_fragments; + g_free_fragments = fragments; + up(&g_free_fragments_mutex); + up(&g_free_fragments_sema); + } + + if (*need_release) { + unsigned int length = pagelist->length; + unsigned int offset = pagelist->offset; + + for (i = 0; i < num_pages; i++) { + struct page *pg = pages[i]; + + if (pagelist->type != PAGELIST_WRITE) { + unsigned int bytes = PAGE_SIZE - offset; + + if (bytes > length) + bytes = length; + dmac_unmap_area(page_address(pg) + offset, + bytes, DMA_FROM_DEVICE); + length -= bytes; + offset = 0; + set_page_dirty(pg); + } + page_cache_release(pg); + } + } + + kfree(pagelist); +} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c new file mode 100644 index 000000000000..e11c0e07471b --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -0,0 +1,2903 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vchiq_core.h" +#include "vchiq_ioctl.h" +#include "vchiq_arm.h" +#include "vchiq_debugfs.h" +#include "vchiq_killable.h" + +#define DEVICE_NAME "vchiq" + +/* Override the default prefix, which would be vchiq_arm (from the filename) */ +#undef MODULE_PARAM_PREFIX +#define MODULE_PARAM_PREFIX DEVICE_NAME "." + +#define VCHIQ_MINOR 0 + +/* Some per-instance constants */ +#define MAX_COMPLETIONS 16 +#define MAX_SERVICES 64 +#define MAX_ELEMENTS 8 +#define MSG_QUEUE_SIZE 64 + +#define KEEPALIVE_VER 1 +#define KEEPALIVE_VER_MIN KEEPALIVE_VER + +/* Run time control of log level, based on KERN_XXX level. */ +int vchiq_arm_log_level = VCHIQ_LOG_DEFAULT; +int vchiq_susp_log_level = VCHIQ_LOG_ERROR; + +#define SUSPEND_TIMER_TIMEOUT_MS 100 +#define SUSPEND_RETRY_TIMER_TIMEOUT_MS 1000 + +#define VC_SUSPEND_NUM_OFFSET 3 /* number of values before idle which are -ve */ +static const char *const suspend_state_names[] = { + "VC_SUSPEND_FORCE_CANCELED", + "VC_SUSPEND_REJECTED", + "VC_SUSPEND_FAILED", + "VC_SUSPEND_IDLE", + "VC_SUSPEND_REQUESTED", + "VC_SUSPEND_IN_PROGRESS", + "VC_SUSPEND_SUSPENDED" +}; +#define VC_RESUME_NUM_OFFSET 1 /* number of values before idle which are -ve */ +static const char *const resume_state_names[] = { + "VC_RESUME_FAILED", + "VC_RESUME_IDLE", + "VC_RESUME_REQUESTED", + "VC_RESUME_IN_PROGRESS", + "VC_RESUME_RESUMED" +}; +/* The number of times we allow force suspend to timeout before actually +** _forcing_ suspend. This is to cater for SW which fails to release vchiq +** correctly - we don't want to prevent ARM suspend indefinitely in this case. +*/ +#define FORCE_SUSPEND_FAIL_MAX 8 + +/* The time in ms allowed for videocore to go idle when force suspend has been + * requested */ +#define FORCE_SUSPEND_TIMEOUT_MS 200 + + +static void suspend_timer_callback(unsigned long context); + + +typedef struct user_service_struct { + VCHIQ_SERVICE_T *service; + void *userdata; + VCHIQ_INSTANCE_T instance; + char is_vchi; + char dequeue_pending; + char close_pending; + int message_available_pos; + int msg_insert; + int msg_remove; + struct semaphore insert_event; + struct semaphore remove_event; + struct semaphore close_event; + VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE]; +} USER_SERVICE_T; + +struct bulk_waiter_node { + struct bulk_waiter bulk_waiter; + int pid; + struct list_head list; +}; + +struct vchiq_instance_struct { + VCHIQ_STATE_T *state; + VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS]; + int completion_insert; + int completion_remove; + struct semaphore insert_event; + struct semaphore remove_event; + struct mutex completion_mutex; + + int connected; + int closing; + int pid; + int mark; + int use_close_delivered; + int trace; + + struct list_head bulk_waiter_list; + struct mutex bulk_waiter_list_mutex; + + VCHIQ_DEBUGFS_NODE_T debugfs_node; +}; + +typedef struct dump_context_struct { + char __user *buf; + size_t actual; + size_t space; + loff_t offset; +} DUMP_CONTEXT_T; + +static struct cdev vchiq_cdev; +static dev_t vchiq_devid; +static VCHIQ_STATE_T g_state; +static struct class *vchiq_class; +static struct device *vchiq_dev; +static DEFINE_SPINLOCK(msg_queue_spinlock); + +static const char *const ioctl_names[] = { + "CONNECT", + "SHUTDOWN", + "CREATE_SERVICE", + "REMOVE_SERVICE", + "QUEUE_MESSAGE", + "QUEUE_BULK_TRANSMIT", + "QUEUE_BULK_RECEIVE", + "AWAIT_COMPLETION", + "DEQUEUE_MESSAGE", + "GET_CLIENT_ID", + "GET_CONFIG", + "CLOSE_SERVICE", + "USE_SERVICE", + "RELEASE_SERVICE", + "SET_SERVICE_OPTION", + "DUMP_PHYS_MEM", + "LIB_VERSION", + "CLOSE_DELIVERED" +}; + +vchiq_static_assert((sizeof(ioctl_names)/sizeof(ioctl_names[0])) == + (VCHIQ_IOC_MAX + 1)); + +static void +dump_phys_mem(void *virt_addr, uint32_t num_bytes); + +/**************************************************************************** +* +* add_completion +* +***************************************************************************/ + +static VCHIQ_STATUS_T +add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + VCHIQ_HEADER_T *header, USER_SERVICE_T *user_service, + void *bulk_userdata) +{ + VCHIQ_COMPLETION_DATA_T *completion; + DEBUG_INITIALISE(g_state.local) + + while (instance->completion_insert == + (instance->completion_remove + MAX_COMPLETIONS)) { + /* Out of space - wait for the client */ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; + } else if (instance->closing) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_ERROR; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + + completion = + &instance->completions[instance->completion_insert & + (MAX_COMPLETIONS - 1)]; + + completion->header = header; + completion->reason = reason; + /* N.B. service_userdata is updated while processing AWAIT_COMPLETION */ + completion->service_userdata = user_service->service; + completion->bulk_userdata = bulk_userdata; + + if (reason == VCHIQ_SERVICE_CLOSED) { + /* Take an extra reference, to be held until + this CLOSED notification is delivered. */ + lock_service(user_service->service); + if (instance->use_close_delivered) + user_service->close_pending = 1; + } + + /* A write barrier is needed here to ensure that the entire completion + record is written out before the insert point. */ + wmb(); + + if (reason == VCHIQ_MESSAGE_AVAILABLE) + user_service->message_available_pos = + instance->completion_insert; + instance->completion_insert++; + + up(&instance->insert_event); + + return VCHIQ_SUCCESS; +} + +/**************************************************************************** +* +* service_callback +* +***************************************************************************/ + +static VCHIQ_STATUS_T +service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, + VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata) +{ + /* How do we ensure the callback goes to the right client? + ** The service_user data points to a USER_SERVICE_T record containing + ** the original callback and the user state structure, which contains a + ** circular buffer for completion records. + */ + USER_SERVICE_T *user_service; + VCHIQ_SERVICE_T *service; + VCHIQ_INSTANCE_T instance; + DEBUG_INITIALISE(g_state.local) + + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + + service = handle_to_service(handle); + BUG_ON(!service); + user_service = (USER_SERVICE_T *)service->base.userdata; + instance = user_service->instance; + + if (!instance || instance->closing) + return VCHIQ_SUCCESS; + + vchiq_log_trace(vchiq_arm_log_level, + "service_callback - service %lx(%d,%p), reason %d, header %lx, " + "instance %lx, bulk_userdata %lx", + (unsigned long)user_service, + service->localport, user_service->userdata, + reason, (unsigned long)header, + (unsigned long)instance, (unsigned long)bulk_userdata); + + if (header && user_service->is_vchi) { + spin_lock(&msg_queue_spinlock); + while (user_service->msg_insert == + (user_service->msg_remove + MSG_QUEUE_SIZE)) { + spin_unlock(&msg_queue_spinlock); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + DEBUG_COUNT(MSG_QUEUE_FULL_COUNT); + vchiq_log_trace(vchiq_arm_log_level, + "service_callback - msg queue full"); + /* If there is no MESSAGE_AVAILABLE in the completion + ** queue, add one + */ + if ((user_service->message_available_pos - + instance->completion_remove) < 0) { + VCHIQ_STATUS_T status; + vchiq_log_info(vchiq_arm_log_level, + "Inserting extra MESSAGE_AVAILABLE"); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + status = add_completion(instance, reason, + NULL, user_service, bulk_userdata); + if (status != VCHIQ_SUCCESS) { + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + return status; + } + } + + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + if (down_interruptible(&user_service->remove_event) + != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + return VCHIQ_RETRY; + } else if (instance->closing) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + return VCHIQ_ERROR; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + spin_lock(&msg_queue_spinlock); + } + + user_service->msg_queue[user_service->msg_insert & + (MSG_QUEUE_SIZE - 1)] = header; + user_service->msg_insert++; + spin_unlock(&msg_queue_spinlock); + + up(&user_service->insert_event); + + /* If there is a thread waiting in DEQUEUE_MESSAGE, or if + ** there is a MESSAGE_AVAILABLE in the completion queue then + ** bypass the completion queue. + */ + if (((user_service->message_available_pos - + instance->completion_remove) >= 0) || + user_service->dequeue_pending) { + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + user_service->dequeue_pending = 0; + return VCHIQ_SUCCESS; + } + + header = NULL; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + + return add_completion(instance, reason, header, user_service, + bulk_userdata); +} + +/**************************************************************************** +* +* user_service_free +* +***************************************************************************/ +static void +user_service_free(void *userdata) +{ + kfree(userdata); +} + +/**************************************************************************** +* +* close_delivered +* +***************************************************************************/ +static void close_delivered(USER_SERVICE_T *user_service) +{ + vchiq_log_info(vchiq_arm_log_level, + "close_delivered(handle=%x)", + user_service->service->handle); + + if (user_service->close_pending) { + /* Allow the underlying service to be culled */ + unlock_service(user_service->service); + + /* Wake the user-thread blocked in close_ or remove_service */ + up(&user_service->close_event); + + user_service->close_pending = 0; + } +} + +/**************************************************************************** +* +* vchiq_ioctl +* +***************************************************************************/ +static long +vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + VCHIQ_INSTANCE_T instance = file->private_data; + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + VCHIQ_SERVICE_T *service = NULL; + long ret = 0; + int i, rc; + DEBUG_INITIALISE(g_state.local) + + vchiq_log_trace(vchiq_arm_log_level, + "vchiq_ioctl - instance %x, cmd %s, arg %lx", + (unsigned int)instance, + ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && + (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ? + ioctl_names[_IOC_NR(cmd)] : "", arg); + + switch (cmd) { + case VCHIQ_IOC_SHUTDOWN: + if (!instance->connected) + break; + + /* Remove all services */ + i = 0; + while ((service = next_service_by_instance(instance->state, + instance, &i)) != NULL) { + status = vchiq_remove_service(service->handle); + unlock_service(service); + if (status != VCHIQ_SUCCESS) + break; + } + service = NULL; + + if (status == VCHIQ_SUCCESS) { + /* Wake the completion thread and ask it to exit */ + instance->closing = 1; + up(&instance->insert_event); + } + + break; + + case VCHIQ_IOC_CONNECT: + if (instance->connected) { + ret = -EINVAL; + break; + } + rc = mutex_lock_interruptible(&instance->state->mutex); + if (rc != 0) { + vchiq_log_error(vchiq_arm_log_level, + "vchiq: connect: could not lock mutex for " + "state %d: %d", + instance->state->id, rc); + ret = -EINTR; + break; + } + status = vchiq_connect_internal(instance->state, instance); + mutex_unlock(&instance->state->mutex); + + if (status == VCHIQ_SUCCESS) + instance->connected = 1; + else + vchiq_log_error(vchiq_arm_log_level, + "vchiq: could not connect: %d", status); + break; + + case VCHIQ_IOC_CREATE_SERVICE: { + VCHIQ_CREATE_SERVICE_T args; + USER_SERVICE_T *user_service = NULL; + void *userdata; + int srvstate; + + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL); + if (!user_service) { + ret = -ENOMEM; + break; + } + + if (args.is_open) { + if (!instance->connected) { + ret = -ENOTCONN; + kfree(user_service); + break; + } + srvstate = VCHIQ_SRVSTATE_OPENING; + } else { + srvstate = + instance->connected ? + VCHIQ_SRVSTATE_LISTENING : + VCHIQ_SRVSTATE_HIDDEN; + } + + userdata = args.params.userdata; + args.params.callback = service_callback; + args.params.userdata = user_service; + service = vchiq_add_service_internal( + instance->state, + &args.params, srvstate, + instance, user_service_free); + + if (service != NULL) { + user_service->service = service; + user_service->userdata = userdata; + user_service->instance = instance; + user_service->is_vchi = (args.is_vchi != 0); + user_service->dequeue_pending = 0; + user_service->close_pending = 0; + user_service->message_available_pos = + instance->completion_remove - 1; + user_service->msg_insert = 0; + user_service->msg_remove = 0; + sema_init(&user_service->insert_event, 0); + sema_init(&user_service->remove_event, 0); + sema_init(&user_service->close_event, 0); + + if (args.is_open) { + status = vchiq_open_service_internal + (service, instance->pid); + if (status != VCHIQ_SUCCESS) { + vchiq_remove_service(service->handle); + service = NULL; + ret = (status == VCHIQ_RETRY) ? + -EINTR : -EIO; + break; + } + } + + if (copy_to_user((void __user *) + &(((VCHIQ_CREATE_SERVICE_T __user *) + arg)->handle), + (const void *)&service->handle, + sizeof(service->handle)) != 0) { + ret = -EFAULT; + vchiq_remove_service(service->handle); + } + + service = NULL; + } else { + ret = -EEXIST; + kfree(user_service); + } + } break; + + case VCHIQ_IOC_CLOSE_SERVICE: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + service = find_service_for_instance(instance, handle); + if (service != NULL) { + USER_SERVICE_T *user_service = + (USER_SERVICE_T *)service->base.userdata; + /* close_pending is false on first entry, and when the + wait in vchiq_close_service has been interrupted. */ + if (!user_service->close_pending) { + status = vchiq_close_service(service->handle); + if (status != VCHIQ_SUCCESS) + break; + } + + /* close_pending is true once the underlying service + has been closed until the client library calls the + CLOSE_DELIVERED ioctl, signalling close_event. */ + if (user_service->close_pending && + down_interruptible(&user_service->close_event)) + status = VCHIQ_RETRY; + } + else + ret = -EINVAL; + } break; + + case VCHIQ_IOC_REMOVE_SERVICE: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + service = find_service_for_instance(instance, handle); + if (service != NULL) { + USER_SERVICE_T *user_service = + (USER_SERVICE_T *)service->base.userdata; + /* close_pending is false on first entry, and when the + wait in vchiq_close_service has been interrupted. */ + if (!user_service->close_pending) { + status = vchiq_remove_service(service->handle); + if (status != VCHIQ_SUCCESS) + break; + } + + /* close_pending is true once the underlying service + has been closed until the client library calls the + CLOSE_DELIVERED ioctl, signalling close_event. */ + if (user_service->close_pending && + down_interruptible(&user_service->close_event)) + status = VCHIQ_RETRY; + } + else + ret = -EINVAL; + } break; + + case VCHIQ_IOC_USE_SERVICE: + case VCHIQ_IOC_RELEASE_SERVICE: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + service = find_service_for_instance(instance, handle); + if (service != NULL) { + status = (cmd == VCHIQ_IOC_USE_SERVICE) ? + vchiq_use_service_internal(service) : + vchiq_release_service_internal(service); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s: cmd %s returned error %d for " + "service %c%c%c%c:%03d", + __func__, + (cmd == VCHIQ_IOC_USE_SERVICE) ? + "VCHIQ_IOC_USE_SERVICE" : + "VCHIQ_IOC_RELEASE_SERVICE", + status, + VCHIQ_FOURCC_AS_4CHARS( + service->base.fourcc), + service->client_id); + ret = -EINVAL; + } + } else + ret = -EINVAL; + } break; + + case VCHIQ_IOC_QUEUE_MESSAGE: { + VCHIQ_QUEUE_MESSAGE_T args; + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + service = find_service_for_instance(instance, args.handle); + + if ((service != NULL) && (args.count <= MAX_ELEMENTS)) { + /* Copy elements into kernel space */ + VCHIQ_ELEMENT_T elements[MAX_ELEMENTS]; + if (copy_from_user(elements, args.elements, + args.count * sizeof(VCHIQ_ELEMENT_T)) == 0) + status = vchiq_queue_message + (args.handle, + elements, args.count); + else + ret = -EFAULT; + } else { + ret = -EINVAL; + } + } break; + + case VCHIQ_IOC_QUEUE_BULK_TRANSMIT: + case VCHIQ_IOC_QUEUE_BULK_RECEIVE: { + VCHIQ_QUEUE_BULK_TRANSFER_T args; + struct bulk_waiter_node *waiter = NULL; + VCHIQ_BULK_DIR_T dir = + (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ? + VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE; + + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + service = find_service_for_instance(instance, args.handle); + if (!service) { + ret = -EINVAL; + break; + } + + if (args.mode == VCHIQ_BULK_MODE_BLOCKING) { + waiter = kzalloc(sizeof(struct bulk_waiter_node), + GFP_KERNEL); + if (!waiter) { + ret = -ENOMEM; + break; + } + args.userdata = &waiter->bulk_waiter; + } else if (args.mode == VCHIQ_BULK_MODE_WAITING) { + struct list_head *pos; + mutex_lock(&instance->bulk_waiter_list_mutex); + list_for_each(pos, &instance->bulk_waiter_list) { + if (list_entry(pos, struct bulk_waiter_node, + list)->pid == current->pid) { + waiter = list_entry(pos, + struct bulk_waiter_node, + list); + list_del(pos); + break; + } + + } + mutex_unlock(&instance->bulk_waiter_list_mutex); + if (!waiter) { + vchiq_log_error(vchiq_arm_log_level, + "no bulk_waiter found for pid %d", + current->pid); + ret = -ESRCH; + break; + } + vchiq_log_info(vchiq_arm_log_level, + "found bulk_waiter %x for pid %d", + (unsigned int)waiter, current->pid); + args.userdata = &waiter->bulk_waiter; + } + status = vchiq_bulk_transfer + (args.handle, + VCHI_MEM_HANDLE_INVALID, + args.data, args.size, + args.userdata, args.mode, + dir); + if (!waiter) + break; + if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || + !waiter->bulk_waiter.bulk) { + if (waiter->bulk_waiter.bulk) { + /* Cancel the signal when the transfer + ** completes. */ + spin_lock(&bulk_waiter_spinlock); + waiter->bulk_waiter.bulk->userdata = NULL; + spin_unlock(&bulk_waiter_spinlock); + } + kfree(waiter); + } else { + const VCHIQ_BULK_MODE_T mode_waiting = + VCHIQ_BULK_MODE_WAITING; + waiter->pid = current->pid; + mutex_lock(&instance->bulk_waiter_list_mutex); + list_add(&waiter->list, &instance->bulk_waiter_list); + mutex_unlock(&instance->bulk_waiter_list_mutex); + vchiq_log_info(vchiq_arm_log_level, + "saved bulk_waiter %x for pid %d", + (unsigned int)waiter, current->pid); + + if (copy_to_user((void __user *) + &(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *) + arg)->mode), + (const void *)&mode_waiting, + sizeof(mode_waiting)) != 0) + ret = -EFAULT; + } + } break; + + case VCHIQ_IOC_AWAIT_COMPLETION: { + VCHIQ_AWAIT_COMPLETION_T args; + + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + if (!instance->connected) { + ret = -ENOTCONN; + break; + } + + if (copy_from_user(&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + mutex_lock(&instance->completion_mutex); + + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + while ((instance->completion_remove == + instance->completion_insert) + && !instance->closing) { + int rc; + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + mutex_unlock(&instance->completion_mutex); + rc = down_interruptible(&instance->insert_event); + mutex_lock(&instance->completion_mutex); + if (rc != 0) { + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + vchiq_log_info(vchiq_arm_log_level, + "AWAIT_COMPLETION interrupted"); + ret = -EINTR; + break; + } + } + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + + /* A read memory barrier is needed to stop prefetch of a stale + ** completion record + */ + rmb(); + + if (ret == 0) { + int msgbufcount = args.msgbufcount; + for (ret = 0; ret < args.count; ret++) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; + if (instance->completion_remove == + instance->completion_insert) + break; + completion = &instance->completions[ + instance->completion_remove & + (MAX_COMPLETIONS - 1)]; + + service = completion->service_userdata; + user_service = service->base.userdata; + completion->service_userdata = + user_service->userdata; + + header = completion->header; + if (header) { + void __user *msgbuf; + int msglen; + + msglen = header->size + + sizeof(VCHIQ_HEADER_T); + /* This must be a VCHIQ-style service */ + if (args.msgbufsize < msglen) { + vchiq_log_error( + vchiq_arm_log_level, + "header %x: msgbufsize" + " %x < msglen %x", + (unsigned int)header, + args.msgbufsize, + msglen); + WARN(1, "invalid message " + "size\n"); + if (ret == 0) + ret = -EMSGSIZE; + break; + } + if (msgbufcount <= 0) + /* Stall here for lack of a + ** buffer for the message. */ + break; + /* Get the pointer from user space */ + msgbufcount--; + if (copy_from_user(&msgbuf, + (const void __user *) + &args.msgbufs[msgbufcount], + sizeof(msgbuf)) != 0) { + if (ret == 0) + ret = -EFAULT; + break; + } + + /* Copy the message to user space */ + if (copy_to_user(msgbuf, header, + msglen) != 0) { + if (ret == 0) + ret = -EFAULT; + break; + } + + /* Now it has been copied, the message + ** can be released. */ + vchiq_release_message(service->handle, + header); + + /* The completion must point to the + ** msgbuf. */ + completion->header = msgbuf; + } + + if ((completion->reason == + VCHIQ_SERVICE_CLOSED) && + !instance->use_close_delivered) + unlock_service(service); + + if (copy_to_user((void __user *)( + (size_t)args.buf + + ret * sizeof(VCHIQ_COMPLETION_DATA_T)), + completion, + sizeof(VCHIQ_COMPLETION_DATA_T)) != 0) { + if (ret == 0) + ret = -EFAULT; + break; + } + + instance->completion_remove++; + } + + if (msgbufcount != args.msgbufcount) { + if (copy_to_user((void __user *) + &((VCHIQ_AWAIT_COMPLETION_T *)arg)-> + msgbufcount, + &msgbufcount, + sizeof(msgbufcount)) != 0) { + ret = -EFAULT; + } + } + } + + if (ret != 0) + up(&instance->remove_event); + mutex_unlock(&instance->completion_mutex); + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + } break; + + case VCHIQ_IOC_DEQUEUE_MESSAGE: { + VCHIQ_DEQUEUE_MESSAGE_T args; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; + + DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + service = find_service_for_instance(instance, args.handle); + if (!service) { + ret = -EINVAL; + break; + } + user_service = (USER_SERVICE_T *)service->base.userdata; + if (user_service->is_vchi == 0) { + ret = -EINVAL; + break; + } + + spin_lock(&msg_queue_spinlock); + if (user_service->msg_remove == user_service->msg_insert) { + if (!args.blocking) { + spin_unlock(&msg_queue_spinlock); + DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); + ret = -EWOULDBLOCK; + break; + } + user_service->dequeue_pending = 1; + do { + spin_unlock(&msg_queue_spinlock); + DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); + if (down_interruptible( + &user_service->insert_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "DEQUEUE_MESSAGE interrupted"); + ret = -EINTR; + break; + } + spin_lock(&msg_queue_spinlock); + } while (user_service->msg_remove == + user_service->msg_insert); + + if (ret) + break; + } + + BUG_ON((int)(user_service->msg_insert - + user_service->msg_remove) < 0); + + header = user_service->msg_queue[user_service->msg_remove & + (MSG_QUEUE_SIZE - 1)]; + user_service->msg_remove++; + spin_unlock(&msg_queue_spinlock); + + up(&user_service->remove_event); + if (header == NULL) + ret = -ENOTCONN; + else if (header->size <= args.bufsize) { + /* Copy to user space if msgbuf is not NULL */ + if ((args.buf == NULL) || + (copy_to_user((void __user *)args.buf, + header->data, + header->size) == 0)) { + ret = header->size; + vchiq_release_message( + service->handle, + header); + } else + ret = -EFAULT; + } else { + vchiq_log_error(vchiq_arm_log_level, + "header %x: bufsize %x < size %x", + (unsigned int)header, args.bufsize, + header->size); + WARN(1, "invalid size\n"); + ret = -EMSGSIZE; + } + DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); + } break; + + case VCHIQ_IOC_GET_CLIENT_ID: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + ret = vchiq_get_client_id(handle); + } break; + + case VCHIQ_IOC_GET_CONFIG: { + VCHIQ_GET_CONFIG_T args; + VCHIQ_CONFIG_T config; + + if (copy_from_user(&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + if (args.config_size > sizeof(config)) { + ret = -EINVAL; + break; + } + status = vchiq_get_config(instance, args.config_size, &config); + if (status == VCHIQ_SUCCESS) { + if (copy_to_user((void __user *)args.pconfig, + &config, args.config_size) != 0) { + ret = -EFAULT; + break; + } + } + } break; + + case VCHIQ_IOC_SET_SERVICE_OPTION: { + VCHIQ_SET_SERVICE_OPTION_T args; + + if (copy_from_user( + &args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + service = find_service_for_instance(instance, args.handle); + if (!service) { + ret = -EINVAL; + break; + } + + status = vchiq_set_service_option( + args.handle, args.option, args.value); + } break; + + case VCHIQ_IOC_DUMP_PHYS_MEM: { + VCHIQ_DUMP_MEM_T args; + + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + dump_phys_mem(args.virt_addr, args.num_bytes); + } break; + + case VCHIQ_IOC_LIB_VERSION: { + unsigned int lib_version = (unsigned int)arg; + + if (lib_version < VCHIQ_VERSION_MIN) + ret = -EINVAL; + else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED) + instance->use_close_delivered = 1; + } break; + + case VCHIQ_IOC_CLOSE_DELIVERED: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + service = find_closed_service_for_instance(instance, handle); + if (service != NULL) { + USER_SERVICE_T *user_service = + (USER_SERVICE_T *)service->base.userdata; + close_delivered(user_service); + } + else + ret = -EINVAL; + } break; + + default: + ret = -ENOTTY; + break; + } + + if (service) + unlock_service(service); + + if (ret == 0) { + if (status == VCHIQ_ERROR) + ret = -EIO; + else if (status == VCHIQ_RETRY) + ret = -EINTR; + } + + if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) && + (ret != -EWOULDBLOCK)) + vchiq_log_info(vchiq_arm_log_level, + " ioctl instance %lx, cmd %s -> status %d, %ld", + (unsigned long)instance, + (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? + ioctl_names[_IOC_NR(cmd)] : + "", + status, ret); + else + vchiq_log_trace(vchiq_arm_log_level, + " ioctl instance %lx, cmd %s -> status %d, %ld", + (unsigned long)instance, + (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? + ioctl_names[_IOC_NR(cmd)] : + "", + status, ret); + + return ret; +} + +/**************************************************************************** +* +* vchiq_open +* +***************************************************************************/ + +static int +vchiq_open(struct inode *inode, struct file *file) +{ + int dev = iminor(inode) & 0x0f; + vchiq_log_info(vchiq_arm_log_level, "vchiq_open"); + switch (dev) { + case VCHIQ_MINOR: { + int ret; + VCHIQ_STATE_T *state = vchiq_get_state(); + VCHIQ_INSTANCE_T instance; + + if (!state) { + vchiq_log_error(vchiq_arm_log_level, + "vchiq has no connection to VideoCore"); + return -ENOTCONN; + } + + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) + return -ENOMEM; + + instance->state = state; + instance->pid = current->tgid; + + ret = vchiq_debugfs_add_instance(instance); + if (ret != 0) { + kfree(instance); + return ret; + } + + sema_init(&instance->insert_event, 0); + sema_init(&instance->remove_event, 0); + mutex_init(&instance->completion_mutex); + mutex_init(&instance->bulk_waiter_list_mutex); + INIT_LIST_HEAD(&instance->bulk_waiter_list); + + file->private_data = instance; + } break; + + default: + vchiq_log_error(vchiq_arm_log_level, + "Unknown minor device: %d", dev); + return -ENXIO; + } + + return 0; +} + +/**************************************************************************** +* +* vchiq_release +* +***************************************************************************/ + +static int +vchiq_release(struct inode *inode, struct file *file) +{ + int dev = iminor(inode) & 0x0f; + int ret = 0; + switch (dev) { + case VCHIQ_MINOR: { + VCHIQ_INSTANCE_T instance = file->private_data; + VCHIQ_STATE_T *state = vchiq_get_state(); + VCHIQ_SERVICE_T *service; + int i; + + vchiq_log_info(vchiq_arm_log_level, + "vchiq_release: instance=%lx", + (unsigned long)instance); + + if (!state) { + ret = -EPERM; + goto out; + } + + /* Ensure videocore is awake to allow termination. */ + vchiq_use_internal(instance->state, NULL, + USE_TYPE_VCHIQ); + + mutex_lock(&instance->completion_mutex); + + /* Wake the completion thread and ask it to exit */ + instance->closing = 1; + up(&instance->insert_event); + + mutex_unlock(&instance->completion_mutex); + + /* Wake the slot handler if the completion queue is full. */ + up(&instance->remove_event); + + /* Mark all services for termination... */ + i = 0; + while ((service = next_service_by_instance(state, instance, + &i)) != NULL) { + USER_SERVICE_T *user_service = service->base.userdata; + + /* Wake the slot handler if the msg queue is full. */ + up(&user_service->remove_event); + + vchiq_terminate_service_internal(service); + unlock_service(service); + } + + /* ...and wait for them to die */ + i = 0; + while ((service = next_service_by_instance(state, instance, &i)) + != NULL) { + USER_SERVICE_T *user_service = service->base.userdata; + + down(&service->remove_event); + + BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); + + spin_lock(&msg_queue_spinlock); + + while (user_service->msg_remove != + user_service->msg_insert) { + VCHIQ_HEADER_T *header = user_service-> + msg_queue[user_service->msg_remove & + (MSG_QUEUE_SIZE - 1)]; + user_service->msg_remove++; + spin_unlock(&msg_queue_spinlock); + + if (header) + vchiq_release_message( + service->handle, + header); + spin_lock(&msg_queue_spinlock); + } + + spin_unlock(&msg_queue_spinlock); + + unlock_service(service); + } + + /* Release any closed services */ + while (instance->completion_remove != + instance->completion_insert) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + completion = &instance->completions[ + instance->completion_remove & + (MAX_COMPLETIONS - 1)]; + service = completion->service_userdata; + if (completion->reason == VCHIQ_SERVICE_CLOSED) + { + USER_SERVICE_T *user_service = + service->base.userdata; + + /* Wake any blocked user-thread */ + if (instance->use_close_delivered) + up(&user_service->close_event); + unlock_service(service); + } + instance->completion_remove++; + } + + /* Release the PEER service count. */ + vchiq_release_internal(instance->state, NULL); + + { + struct list_head *pos, *next; + list_for_each_safe(pos, next, + &instance->bulk_waiter_list) { + struct bulk_waiter_node *waiter; + waiter = list_entry(pos, + struct bulk_waiter_node, + list); + list_del(pos); + vchiq_log_info(vchiq_arm_log_level, + "bulk_waiter - cleaned up %x " + "for pid %d", + (unsigned int)waiter, waiter->pid); + kfree(waiter); + } + } + + vchiq_debugfs_remove_instance(instance); + + kfree(instance); + file->private_data = NULL; + } break; + + default: + vchiq_log_error(vchiq_arm_log_level, + "Unknown minor device: %d", dev); + ret = -ENXIO; + } + +out: + return ret; +} + +/**************************************************************************** +* +* vchiq_dump +* +***************************************************************************/ + +void +vchiq_dump(void *dump_context, const char *str, int len) +{ + DUMP_CONTEXT_T *context = (DUMP_CONTEXT_T *)dump_context; + + if (context->actual < context->space) { + int copy_bytes; + if (context->offset > 0) { + int skip_bytes = min(len, (int)context->offset); + str += skip_bytes; + len -= skip_bytes; + context->offset -= skip_bytes; + if (context->offset > 0) + return; + } + copy_bytes = min(len, (int)(context->space - context->actual)); + if (copy_bytes == 0) + return; + if (copy_to_user(context->buf + context->actual, str, + copy_bytes)) + context->actual = -EFAULT; + context->actual += copy_bytes; + len -= copy_bytes; + + /* If tne terminating NUL is included in the length, then it + ** marks the end of a line and should be replaced with a + ** carriage return. */ + if ((len == 0) && (str[copy_bytes - 1] == '\0')) { + char cr = '\n'; + if (copy_to_user(context->buf + context->actual - 1, + &cr, 1)) + context->actual = -EFAULT; + } + } +} + +/**************************************************************************** +* +* vchiq_dump_platform_instance_state +* +***************************************************************************/ + +void +vchiq_dump_platform_instances(void *dump_context) +{ + VCHIQ_STATE_T *state = vchiq_get_state(); + char buf[80]; + int len; + int i; + + /* There is no list of instances, so instead scan all services, + marking those that have been dumped. */ + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + VCHIQ_INSTANCE_T instance; + + if (service && (service->base.callback == service_callback)) { + instance = service->instance; + if (instance) + instance->mark = 0; + } + } + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + VCHIQ_INSTANCE_T instance; + + if (service && (service->base.callback == service_callback)) { + instance = service->instance; + if (instance && !instance->mark) { + len = snprintf(buf, sizeof(buf), + "Instance %x: pid %d,%s completions " + "%d/%d", + (unsigned int)instance, instance->pid, + instance->connected ? " connected, " : + "", + instance->completion_insert - + instance->completion_remove, + MAX_COMPLETIONS); + + vchiq_dump(dump_context, buf, len + 1); + + instance->mark = 1; + } + } + } +} + +/**************************************************************************** +* +* vchiq_dump_platform_service_state +* +***************************************************************************/ + +void +vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service) +{ + USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata; + char buf[80]; + int len; + + len = snprintf(buf, sizeof(buf), " instance %x", + (unsigned int)service->instance); + + if ((service->base.callback == service_callback) && + user_service->is_vchi) { + len += snprintf(buf + len, sizeof(buf) - len, + ", %d/%d messages", + user_service->msg_insert - user_service->msg_remove, + MSG_QUEUE_SIZE); + + if (user_service->dequeue_pending) + len += snprintf(buf + len, sizeof(buf) - len, + " (dequeue pending)"); + } + + vchiq_dump(dump_context, buf, len + 1); +} + +/**************************************************************************** +* +* dump_user_mem +* +***************************************************************************/ + +static void +dump_phys_mem(void *virt_addr, uint32_t num_bytes) +{ + int rc; + uint8_t *end_virt_addr = virt_addr + num_bytes; + int num_pages; + int offset; + int end_offset; + int page_idx; + int prev_idx; + struct page *page; + struct page **pages; + uint8_t *kmapped_virt_ptr; + + /* Align virtAddr and endVirtAddr to 16 byte boundaries. */ + + virt_addr = (void *)((unsigned long)virt_addr & ~0x0fuL); + end_virt_addr = (void *)(((unsigned long)end_virt_addr + 15uL) & + ~0x0fuL); + + offset = (int)(long)virt_addr & (PAGE_SIZE - 1); + end_offset = (int)(long)end_virt_addr & (PAGE_SIZE - 1); + + num_pages = (offset + num_bytes + PAGE_SIZE - 1) / PAGE_SIZE; + + pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL); + if (pages == NULL) { + vchiq_log_error(vchiq_arm_log_level, + "Unable to allocation memory for %d pages\n", + num_pages); + return; + } + + down_read(¤t->mm->mmap_sem); + rc = get_user_pages(current, /* task */ + current->mm, /* mm */ + (unsigned long)virt_addr, /* start */ + num_pages, /* len */ + 0, /* write */ + 0, /* force */ + pages, /* pages (array of page pointers) */ + NULL); /* vmas */ + up_read(¤t->mm->mmap_sem); + + prev_idx = -1; + page = NULL; + + while (offset < end_offset) { + + int page_offset = offset % PAGE_SIZE; + page_idx = offset / PAGE_SIZE; + + if (page_idx != prev_idx) { + + if (page != NULL) + kunmap(page); + page = pages[page_idx]; + kmapped_virt_ptr = kmap(page); + + prev_idx = page_idx; + } + + if (vchiq_arm_log_level >= VCHIQ_LOG_TRACE) + vchiq_log_dump_mem("ph", + (uint32_t)(unsigned long)&kmapped_virt_ptr[ + page_offset], + &kmapped_virt_ptr[page_offset], 16); + + offset += 16; + } + if (page != NULL) + kunmap(page); + + for (page_idx = 0; page_idx < num_pages; page_idx++) + page_cache_release(pages[page_idx]); + + kfree(pages); +} + +/**************************************************************************** +* +* vchiq_read +* +***************************************************************************/ + +static ssize_t +vchiq_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + DUMP_CONTEXT_T context; + context.buf = buf; + context.actual = 0; + context.space = count; + context.offset = *ppos; + + vchiq_dump_state(&context, &g_state); + + *ppos += context.actual; + + return context.actual; +} + +VCHIQ_STATE_T * +vchiq_get_state(void) +{ + + if (g_state.remote == NULL) + printk(KERN_ERR "%s: g_state.remote == NULL\n", __func__); + else if (g_state.remote->initialised != 1) + printk(KERN_NOTICE "%s: g_state.remote->initialised != 1 (%d)\n", + __func__, g_state.remote->initialised); + + return ((g_state.remote != NULL) && + (g_state.remote->initialised == 1)) ? &g_state : NULL; +} + +static const struct file_operations +vchiq_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = vchiq_ioctl, + .open = vchiq_open, + .release = vchiq_release, + .read = vchiq_read +}; + +/* + * Autosuspend related functionality + */ + +int +vchiq_videocore_wanted(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + if (!arm_state) + /* autosuspend not supported - always return wanted */ + return 1; + else if (arm_state->blocked_count) + return 1; + else if (!arm_state->videocore_use_count) + /* usage count zero - check for override unless we're forcing */ + if (arm_state->resume_blocked) + return 0; + else + return vchiq_platform_videocore_wanted(state); + else + /* non-zero usage count - videocore still required */ + return 1; +} + +static VCHIQ_STATUS_T +vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason, + VCHIQ_HEADER_T *header, + VCHIQ_SERVICE_HANDLE_T service_user, + void *bulk_user) +{ + vchiq_log_error(vchiq_susp_log_level, + "%s callback reason %d", __func__, reason); + return 0; +} + +static int +vchiq_keepalive_thread_func(void *v) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + + VCHIQ_STATUS_T status; + VCHIQ_INSTANCE_T instance; + VCHIQ_SERVICE_HANDLE_T ka_handle; + + VCHIQ_SERVICE_PARAMS_T params = { + .fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'), + .callback = vchiq_keepalive_vchiq_callback, + .version = KEEPALIVE_VER, + .version_min = KEEPALIVE_VER_MIN + }; + + status = vchiq_initialise(&instance); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_initialise failed %d", __func__, status); + goto exit; + } + + status = vchiq_connect(instance); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_connect failed %d", __func__, status); + goto shutdown; + } + + status = vchiq_add_service(instance, ¶ms, &ka_handle); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_open_service failed %d", __func__, status); + goto shutdown; + } + + while (1) { + long rc = 0, uc = 0; + if (wait_for_completion_interruptible(&arm_state->ka_evt) + != 0) { + vchiq_log_error(vchiq_susp_log_level, + "%s interrupted", __func__); + flush_signals(current); + continue; + } + + /* read and clear counters. Do release_count then use_count to + * prevent getting more releases than uses */ + rc = atomic_xchg(&arm_state->ka_release_count, 0); + uc = atomic_xchg(&arm_state->ka_use_count, 0); + + /* Call use/release service the requisite number of times. + * Process use before release so use counts don't go negative */ + while (uc--) { + atomic_inc(&arm_state->ka_use_ack_count); + status = vchiq_use_service(ka_handle); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_use_service error %d", + __func__, status); + } + } + while (rc--) { + status = vchiq_release_service(ka_handle); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_release_service error %d", + __func__, status); + } + } + } + +shutdown: + vchiq_shutdown(instance); +exit: + return 0; +} + + + +VCHIQ_STATUS_T +vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + if (arm_state) { + rwlock_init(&arm_state->susp_res_lock); + + init_completion(&arm_state->ka_evt); + atomic_set(&arm_state->ka_use_count, 0); + atomic_set(&arm_state->ka_use_ack_count, 0); + atomic_set(&arm_state->ka_release_count, 0); + + init_completion(&arm_state->vc_suspend_complete); + + init_completion(&arm_state->vc_resume_complete); + /* Initialise to 'done' state. We only want to block on resume + * completion while videocore is suspended. */ + set_resume_state(arm_state, VC_RESUME_RESUMED); + + init_completion(&arm_state->resume_blocker); + /* Initialise to 'done' state. We only want to block on this + * completion while resume is blocked */ + complete_all(&arm_state->resume_blocker); + + init_completion(&arm_state->blocked_blocker); + /* Initialise to 'done' state. We only want to block on this + * completion while things are waiting on the resume blocker */ + complete_all(&arm_state->blocked_blocker); + + arm_state->suspend_timer_timeout = SUSPEND_TIMER_TIMEOUT_MS; + arm_state->suspend_timer_running = 0; + init_timer(&arm_state->suspend_timer); + arm_state->suspend_timer.data = (unsigned long)(state); + arm_state->suspend_timer.function = suspend_timer_callback; + + arm_state->first_connect = 0; + + } + return status; +} + +/* +** Functions to modify the state variables; +** set_suspend_state +** set_resume_state +** +** There are more state variables than we might like, so ensure they remain in +** step. Suspend and resume state are maintained separately, since most of +** these state machines can operate independently. However, there are a few +** states where state transitions in one state machine cause a reset to the +** other state machine. In addition, there are some completion events which +** need to occur on state machine reset and end-state(s), so these are also +** dealt with in these functions. +** +** In all states we set the state variable according to the input, but in some +** cases we perform additional steps outlined below; +** +** VC_SUSPEND_IDLE - Initialise the suspend completion at the same time. +** The suspend completion is completed after any suspend +** attempt. When we reset the state machine we also reset +** the completion. This reset occurs when videocore is +** resumed, and also if we initiate suspend after a suspend +** failure. +** +** VC_SUSPEND_IN_PROGRESS - This state is considered the point of no return for +** suspend - ie from this point on we must try to suspend +** before resuming can occur. We therefore also reset the +** resume state machine to VC_RESUME_IDLE in this state. +** +** VC_SUSPEND_SUSPENDED - Suspend has completed successfully. Also call +** complete_all on the suspend completion to notify +** anything waiting for suspend to happen. +** +** VC_SUSPEND_REJECTED - Videocore rejected suspend. Videocore will also +** initiate resume, so no need to alter resume state. +** We call complete_all on the suspend completion to notify +** of suspend rejection. +** +** VC_SUSPEND_FAILED - We failed to initiate videocore suspend. We notify the +** suspend completion and reset the resume state machine. +** +** VC_RESUME_IDLE - Initialise the resume completion at the same time. The +** resume completion is in it's 'done' state whenever +** videcore is running. Therfore, the VC_RESUME_IDLE state +** implies that videocore is suspended. +** Hence, any thread which needs to wait until videocore is +** running can wait on this completion - it will only block +** if videocore is suspended. +** +** VC_RESUME_RESUMED - Resume has completed successfully. Videocore is running. +** Call complete_all on the resume completion to unblock +** any threads waiting for resume. Also reset the suspend +** state machine to it's idle state. +** +** VC_RESUME_FAILED - Currently unused - no mechanism to fail resume exists. +*/ + +void +set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, + enum vc_suspend_status new_state) +{ + /* set the state in all cases */ + arm_state->vc_suspend_state = new_state; + + /* state specific additional actions */ + switch (new_state) { + case VC_SUSPEND_FORCE_CANCELED: + complete_all(&arm_state->vc_suspend_complete); + break; + case VC_SUSPEND_REJECTED: + complete_all(&arm_state->vc_suspend_complete); + break; + case VC_SUSPEND_FAILED: + complete_all(&arm_state->vc_suspend_complete); + arm_state->vc_resume_state = VC_RESUME_RESUMED; + complete_all(&arm_state->vc_resume_complete); + break; + case VC_SUSPEND_IDLE: + reinit_completion(&arm_state->vc_suspend_complete); + break; + case VC_SUSPEND_REQUESTED: + break; + case VC_SUSPEND_IN_PROGRESS: + set_resume_state(arm_state, VC_RESUME_IDLE); + break; + case VC_SUSPEND_SUSPENDED: + complete_all(&arm_state->vc_suspend_complete); + break; + default: + BUG(); + break; + } +} + +void +set_resume_state(VCHIQ_ARM_STATE_T *arm_state, + enum vc_resume_status new_state) +{ + /* set the state in all cases */ + arm_state->vc_resume_state = new_state; + + /* state specific additional actions */ + switch (new_state) { + case VC_RESUME_FAILED: + break; + case VC_RESUME_IDLE: + reinit_completion(&arm_state->vc_resume_complete); + break; + case VC_RESUME_REQUESTED: + break; + case VC_RESUME_IN_PROGRESS: + break; + case VC_RESUME_RESUMED: + complete_all(&arm_state->vc_resume_complete); + set_suspend_state(arm_state, VC_SUSPEND_IDLE); + break; + default: + BUG(); + break; + } +} + + +/* should be called with the write lock held */ +inline void +start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) +{ + del_timer(&arm_state->suspend_timer); + arm_state->suspend_timer.expires = jiffies + + msecs_to_jiffies(arm_state-> + suspend_timer_timeout); + add_timer(&arm_state->suspend_timer); + arm_state->suspend_timer_running = 1; +} + +/* should be called with the write lock held */ +static inline void +stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) +{ + if (arm_state->suspend_timer_running) { + del_timer(&arm_state->suspend_timer); + arm_state->suspend_timer_running = 0; + } +} + +static inline int +need_resume(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) && + (arm_state->vc_resume_state < VC_RESUME_REQUESTED) && + vchiq_videocore_wanted(state); +} + +static int +block_resume(VCHIQ_ARM_STATE_T *arm_state) +{ + int status = VCHIQ_SUCCESS; + const unsigned long timeout_val = + msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS); + int resume_count = 0; + + /* Allow any threads which were blocked by the last force suspend to + * complete if they haven't already. Only give this one shot; if + * blocked_count is incremented after blocked_blocker is completed + * (which only happens when blocked_count hits 0) then those threads + * will have to wait until next time around */ + if (arm_state->blocked_count) { + reinit_completion(&arm_state->blocked_blocker); + write_unlock_bh(&arm_state->susp_res_lock); + vchiq_log_info(vchiq_susp_log_level, "%s wait for previously " + "blocked clients", __func__); + if (wait_for_completion_interruptible_timeout( + &arm_state->blocked_blocker, timeout_val) + <= 0) { + vchiq_log_error(vchiq_susp_log_level, "%s wait for " + "previously blocked clients failed" , __func__); + status = VCHIQ_ERROR; + write_lock_bh(&arm_state->susp_res_lock); + goto out; + } + vchiq_log_info(vchiq_susp_log_level, "%s previously blocked " + "clients resumed", __func__); + write_lock_bh(&arm_state->susp_res_lock); + } + + /* We need to wait for resume to complete if it's in process */ + while (arm_state->vc_resume_state != VC_RESUME_RESUMED && + arm_state->vc_resume_state > VC_RESUME_IDLE) { + if (resume_count > 1) { + status = VCHIQ_ERROR; + vchiq_log_error(vchiq_susp_log_level, "%s waited too " + "many times for resume" , __func__); + goto out; + } + write_unlock_bh(&arm_state->susp_res_lock); + vchiq_log_info(vchiq_susp_log_level, "%s wait for resume", + __func__); + if (wait_for_completion_interruptible_timeout( + &arm_state->vc_resume_complete, timeout_val) + <= 0) { + vchiq_log_error(vchiq_susp_log_level, "%s wait for " + "resume failed (%s)", __func__, + resume_state_names[arm_state->vc_resume_state + + VC_RESUME_NUM_OFFSET]); + status = VCHIQ_ERROR; + write_lock_bh(&arm_state->susp_res_lock); + goto out; + } + vchiq_log_info(vchiq_susp_log_level, "%s resumed", __func__); + write_lock_bh(&arm_state->susp_res_lock); + resume_count++; + } + reinit_completion(&arm_state->resume_blocker); + arm_state->resume_blocked = 1; + +out: + return status; +} + +static inline void +unblock_resume(VCHIQ_ARM_STATE_T *arm_state) +{ + complete_all(&arm_state->resume_blocker); + arm_state->resume_blocked = 0; +} + +/* Initiate suspend via slot handler. Should be called with the write lock + * held */ +VCHIQ_STATUS_T +vchiq_arm_vcsuspend(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_ERROR; + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + status = VCHIQ_SUCCESS; + + + switch (arm_state->vc_suspend_state) { + case VC_SUSPEND_REQUESTED: + vchiq_log_info(vchiq_susp_log_level, "%s: suspend already " + "requested", __func__); + break; + case VC_SUSPEND_IN_PROGRESS: + vchiq_log_info(vchiq_susp_log_level, "%s: suspend already in " + "progress", __func__); + break; + + default: + /* We don't expect to be in other states, so log but continue + * anyway */ + vchiq_log_error(vchiq_susp_log_level, + "%s unexpected suspend state %s", __func__, + suspend_state_names[arm_state->vc_suspend_state + + VC_SUSPEND_NUM_OFFSET]); + /* fall through */ + case VC_SUSPEND_REJECTED: + case VC_SUSPEND_FAILED: + /* Ensure any idle state actions have been run */ + set_suspend_state(arm_state, VC_SUSPEND_IDLE); + /* fall through */ + case VC_SUSPEND_IDLE: + vchiq_log_info(vchiq_susp_log_level, + "%s: suspending", __func__); + set_suspend_state(arm_state, VC_SUSPEND_REQUESTED); + /* kick the slot handler thread to initiate suspend */ + request_poll(state, NULL, 0); + break; + } + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); + return status; +} + +void +vchiq_platform_check_suspend(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int susp = 0; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + if (arm_state->vc_suspend_state == VC_SUSPEND_REQUESTED && + arm_state->vc_resume_state == VC_RESUME_RESUMED) { + set_suspend_state(arm_state, VC_SUSPEND_IN_PROGRESS); + susp = 1; + } + write_unlock_bh(&arm_state->susp_res_lock); + + if (susp) + vchiq_platform_suspend(state); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); + return; +} + + +static void +output_timeout_error(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + char service_err[50] = ""; + int vc_use_count = arm_state->videocore_use_count; + int active_services = state->unused_service; + int i; + + if (!arm_state->videocore_use_count) { + snprintf(service_err, 50, " Videocore usecount is 0"); + goto output_msg; + } + for (i = 0; i < active_services; i++) { + VCHIQ_SERVICE_T *service_ptr = state->services[i]; + if (service_ptr && service_ptr->service_use_count && + (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE)) { + snprintf(service_err, 50, " %c%c%c%c(%d) service has " + "use count %d%s", VCHIQ_FOURCC_AS_4CHARS( + service_ptr->base.fourcc), + service_ptr->client_id, + service_ptr->service_use_count, + service_ptr->service_use_count == + vc_use_count ? "" : " (+ more)"); + break; + } + } + +output_msg: + vchiq_log_error(vchiq_susp_log_level, + "timed out waiting for vc suspend (%d).%s", + arm_state->autosuspend_override, service_err); + +} + +/* Try to get videocore into suspended state, regardless of autosuspend state. +** We don't actually force suspend, since videocore may get into a bad state +** if we force suspend at a bad time. Instead, we wait for autosuspend to +** determine a good point to suspend. If this doesn't happen within 100ms we +** report failure. +** +** Returns VCHIQ_SUCCESS if videocore suspended successfully, VCHIQ_RETRY if +** videocore failed to suspend in time or VCHIQ_ERROR if interrupted. +*/ +VCHIQ_STATUS_T +vchiq_arm_force_suspend(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + VCHIQ_STATUS_T status = VCHIQ_ERROR; + long rc = 0; + int repeat = -1; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + + status = block_resume(arm_state); + if (status != VCHIQ_SUCCESS) + goto unlock; + if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { + /* Already suspended - just block resume and exit */ + vchiq_log_info(vchiq_susp_log_level, "%s already suspended", + __func__); + status = VCHIQ_SUCCESS; + goto unlock; + } else if (arm_state->vc_suspend_state <= VC_SUSPEND_IDLE) { + /* initiate suspend immediately in the case that we're waiting + * for the timeout */ + stop_suspend_timer(arm_state); + if (!vchiq_videocore_wanted(state)) { + vchiq_log_info(vchiq_susp_log_level, "%s videocore " + "idle, initiating suspend", __func__); + status = vchiq_arm_vcsuspend(state); + } else if (arm_state->autosuspend_override < + FORCE_SUSPEND_FAIL_MAX) { + vchiq_log_info(vchiq_susp_log_level, "%s letting " + "videocore go idle", __func__); + status = VCHIQ_SUCCESS; + } else { + vchiq_log_warning(vchiq_susp_log_level, "%s failed too " + "many times - attempting suspend", __func__); + status = vchiq_arm_vcsuspend(state); + } + } else { + vchiq_log_info(vchiq_susp_log_level, "%s videocore suspend " + "in progress - wait for completion", __func__); + status = VCHIQ_SUCCESS; + } + + /* Wait for suspend to happen due to system idle (not forced..) */ + if (status != VCHIQ_SUCCESS) + goto unblock_resume; + + do { + write_unlock_bh(&arm_state->susp_res_lock); + + rc = wait_for_completion_interruptible_timeout( + &arm_state->vc_suspend_complete, + msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS)); + + write_lock_bh(&arm_state->susp_res_lock); + if (rc < 0) { + vchiq_log_warning(vchiq_susp_log_level, "%s " + "interrupted waiting for suspend", __func__); + status = VCHIQ_ERROR; + goto unblock_resume; + } else if (rc == 0) { + if (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) { + /* Repeat timeout once if in progress */ + if (repeat < 0) { + repeat = 1; + continue; + } + } + arm_state->autosuspend_override++; + output_timeout_error(state); + + status = VCHIQ_RETRY; + goto unblock_resume; + } + } while (0 < (repeat--)); + + /* Check and report state in case we need to abort ARM suspend */ + if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED) { + status = VCHIQ_RETRY; + vchiq_log_error(vchiq_susp_log_level, + "%s videocore suspend failed (state %s)", __func__, + suspend_state_names[arm_state->vc_suspend_state + + VC_SUSPEND_NUM_OFFSET]); + /* Reset the state only if it's still in an error state. + * Something could have already initiated another suspend. */ + if (arm_state->vc_suspend_state < VC_SUSPEND_IDLE) + set_suspend_state(arm_state, VC_SUSPEND_IDLE); + + goto unblock_resume; + } + + /* successfully suspended - unlock and exit */ + goto unlock; + +unblock_resume: + /* all error states need to unblock resume before exit */ + unblock_resume(arm_state); + +unlock: + write_unlock_bh(&arm_state->susp_res_lock); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); + return status; +} + +void +vchiq_check_suspend(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED && + arm_state->first_connect && + !vchiq_videocore_wanted(state)) { + vchiq_arm_vcsuspend(state); + } + write_unlock_bh(&arm_state->susp_res_lock); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); + return; +} + + +int +vchiq_arm_allow_resume(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int resume = 0; + int ret = -1; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + unblock_resume(arm_state); + resume = vchiq_check_resume(state); + write_unlock_bh(&arm_state->susp_res_lock); + + if (resume) { + if (wait_for_completion_interruptible( + &arm_state->vc_resume_complete) < 0) { + vchiq_log_error(vchiq_susp_log_level, + "%s interrupted", __func__); + /* failed, cannot accurately derive suspend + * state, so exit early. */ + goto out; + } + } + + read_lock_bh(&arm_state->susp_res_lock); + if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { + vchiq_log_info(vchiq_susp_log_level, + "%s: Videocore remains suspended", __func__); + } else { + vchiq_log_info(vchiq_susp_log_level, + "%s: Videocore resumed", __func__); + ret = 0; + } + read_unlock_bh(&arm_state->susp_res_lock); +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); + return ret; +} + +/* This function should be called with the write lock held */ +int +vchiq_check_resume(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int resume = 0; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + if (need_resume(state)) { + set_resume_state(arm_state, VC_RESUME_REQUESTED); + request_poll(state, NULL, 0); + resume = 1; + } + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); + return resume; +} + +void +vchiq_platform_check_resume(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int res = 0; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + if (arm_state->wake_address == 0) { + vchiq_log_info(vchiq_susp_log_level, + "%s: already awake", __func__); + goto unlock; + } + if (arm_state->vc_resume_state == VC_RESUME_IN_PROGRESS) { + vchiq_log_info(vchiq_susp_log_level, + "%s: already resuming", __func__); + goto unlock; + } + + if (arm_state->vc_resume_state == VC_RESUME_REQUESTED) { + set_resume_state(arm_state, VC_RESUME_IN_PROGRESS); + res = 1; + } else + vchiq_log_trace(vchiq_susp_log_level, + "%s: not resuming (resume state %s)", __func__, + resume_state_names[arm_state->vc_resume_state + + VC_RESUME_NUM_OFFSET]); + +unlock: + write_unlock_bh(&arm_state->susp_res_lock); + + if (res) + vchiq_platform_resume(state); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); + return; + +} + + + +VCHIQ_STATUS_T +vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + enum USE_TYPE_E use_type) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; + char entity[16]; + int *entity_uc; + int local_uc, local_entity_uc; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + if (use_type == USE_TYPE_VCHIQ) { + sprintf(entity, "VCHIQ: "); + entity_uc = &arm_state->peer_use_count; + } else if (service) { + sprintf(entity, "%c%c%c%c:%03d", + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->client_id); + entity_uc = &service->service_use_count; + } else { + vchiq_log_error(vchiq_susp_log_level, "%s null service " + "ptr", __func__); + ret = VCHIQ_ERROR; + goto out; + } + + write_lock_bh(&arm_state->susp_res_lock); + while (arm_state->resume_blocked) { + /* If we call 'use' while force suspend is waiting for suspend, + * then we're about to block the thread which the force is + * waiting to complete, so we're bound to just time out. In this + * case, set the suspend state such that the wait will be + * canceled, so we can complete as quickly as possible. */ + if (arm_state->resume_blocked && arm_state->vc_suspend_state == + VC_SUSPEND_IDLE) { + set_suspend_state(arm_state, VC_SUSPEND_FORCE_CANCELED); + break; + } + /* If suspend is already in progress then we need to block */ + if (!try_wait_for_completion(&arm_state->resume_blocker)) { + /* Indicate that there are threads waiting on the resume + * blocker. These need to be allowed to complete before + * a _second_ call to force suspend can complete, + * otherwise low priority threads might never actually + * continue */ + arm_state->blocked_count++; + write_unlock_bh(&arm_state->susp_res_lock); + vchiq_log_info(vchiq_susp_log_level, "%s %s resume " + "blocked - waiting...", __func__, entity); + if (wait_for_completion_killable( + &arm_state->resume_blocker) != 0) { + vchiq_log_error(vchiq_susp_log_level, "%s %s " + "wait for resume blocker interrupted", + __func__, entity); + ret = VCHIQ_ERROR; + write_lock_bh(&arm_state->susp_res_lock); + arm_state->blocked_count--; + write_unlock_bh(&arm_state->susp_res_lock); + goto out; + } + vchiq_log_info(vchiq_susp_log_level, "%s %s resume " + "unblocked", __func__, entity); + write_lock_bh(&arm_state->susp_res_lock); + if (--arm_state->blocked_count == 0) + complete_all(&arm_state->blocked_blocker); + } + } + + stop_suspend_timer(arm_state); + + local_uc = ++arm_state->videocore_use_count; + local_entity_uc = ++(*entity_uc); + + /* If there's a pending request which hasn't yet been serviced then + * just clear it. If we're past VC_SUSPEND_REQUESTED state then + * vc_resume_complete will block until we either resume or fail to + * suspend */ + if (arm_state->vc_suspend_state <= VC_SUSPEND_REQUESTED) + set_suspend_state(arm_state, VC_SUSPEND_IDLE); + + if ((use_type != USE_TYPE_SERVICE_NO_RESUME) && need_resume(state)) { + set_resume_state(arm_state, VC_RESUME_REQUESTED); + vchiq_log_info(vchiq_susp_log_level, + "%s %s count %d, state count %d", + __func__, entity, local_entity_uc, local_uc); + request_poll(state, NULL, 0); + } else + vchiq_log_trace(vchiq_susp_log_level, + "%s %s count %d, state count %d", + __func__, entity, *entity_uc, local_uc); + + + write_unlock_bh(&arm_state->susp_res_lock); + + /* Completion is in a done state when we're not suspended, so this won't + * block for the non-suspended case. */ + if (!try_wait_for_completion(&arm_state->vc_resume_complete)) { + vchiq_log_info(vchiq_susp_log_level, "%s %s wait for resume", + __func__, entity); + if (wait_for_completion_killable( + &arm_state->vc_resume_complete) != 0) { + vchiq_log_error(vchiq_susp_log_level, "%s %s wait for " + "resume interrupted", __func__, entity); + ret = VCHIQ_ERROR; + goto out; + } + vchiq_log_info(vchiq_susp_log_level, "%s %s resumed", __func__, + entity); + } + + if (ret == VCHIQ_SUCCESS) { + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); + while (ack_cnt && (status == VCHIQ_SUCCESS)) { + /* Send the use notify to videocore */ + status = vchiq_send_remote_use_active(state); + if (status == VCHIQ_SUCCESS) + ack_cnt--; + else + atomic_add(ack_cnt, + &arm_state->ka_use_ack_count); + } + } + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); + return ret; +} + +VCHIQ_STATUS_T +vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; + char entity[16]; + int *entity_uc; + int local_uc, local_entity_uc; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + if (service) { + sprintf(entity, "%c%c%c%c:%03d", + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->client_id); + entity_uc = &service->service_use_count; + } else { + sprintf(entity, "PEER: "); + entity_uc = &arm_state->peer_use_count; + } + + write_lock_bh(&arm_state->susp_res_lock); + if (!arm_state->videocore_use_count || !(*entity_uc)) { + /* Don't use BUG_ON - don't allow user thread to crash kernel */ + WARN_ON(!arm_state->videocore_use_count); + WARN_ON(!(*entity_uc)); + ret = VCHIQ_ERROR; + goto unlock; + } + local_uc = --arm_state->videocore_use_count; + local_entity_uc = --(*entity_uc); + + if (!vchiq_videocore_wanted(state)) { + if (vchiq_platform_use_suspend_timer() && + !arm_state->resume_blocked) { + /* Only use the timer if we're not trying to force + * suspend (=> resume_blocked) */ + start_suspend_timer(arm_state); + } else { + vchiq_log_info(vchiq_susp_log_level, + "%s %s count %d, state count %d - suspending", + __func__, entity, *entity_uc, + arm_state->videocore_use_count); + vchiq_arm_vcsuspend(state); + } + } else + vchiq_log_trace(vchiq_susp_log_level, + "%s %s count %d, state count %d", + __func__, entity, *entity_uc, + arm_state->videocore_use_count); + +unlock: + write_unlock_bh(&arm_state->susp_res_lock); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); + return ret; +} + +void +vchiq_on_remote_use(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + atomic_inc(&arm_state->ka_use_count); + complete(&arm_state->ka_evt); +} + +void +vchiq_on_remote_release(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + atomic_inc(&arm_state->ka_release_count); + complete(&arm_state->ka_evt); +} + +VCHIQ_STATUS_T +vchiq_use_service_internal(VCHIQ_SERVICE_T *service) +{ + return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); +} + +VCHIQ_STATUS_T +vchiq_release_service_internal(VCHIQ_SERVICE_T *service) +{ + return vchiq_release_internal(service->state, service); +} + +VCHIQ_DEBUGFS_NODE_T * +vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance) +{ + return &instance->debugfs_node; +} + +int +vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance) +{ + VCHIQ_SERVICE_T *service; + int use_count = 0, i; + i = 0; + while ((service = next_service_by_instance(instance->state, + instance, &i)) != NULL) { + use_count += service->service_use_count; + unlock_service(service); + } + return use_count; +} + +int +vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance) +{ + return instance->pid; +} + +int +vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance) +{ + return instance->trace; +} + +void +vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace) +{ + VCHIQ_SERVICE_T *service; + int i; + i = 0; + while ((service = next_service_by_instance(instance->state, + instance, &i)) != NULL) { + service->trace = trace; + unlock_service(service); + } + instance->trace = (trace != 0); +} + +static void suspend_timer_callback(unsigned long context) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *)context; + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + if (!arm_state) + goto out; + vchiq_log_info(vchiq_susp_log_level, + "%s - suspend timer expired - check suspend", __func__); + vchiq_check_suspend(state); +out: + return; +} + +VCHIQ_STATUS_T +vchiq_use_service_no_resume(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_STATUS_T ret = VCHIQ_ERROR; + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + if (service) { + ret = vchiq_use_internal(service->state, service, + USE_TYPE_SERVICE_NO_RESUME); + unlock_service(service); + } + return ret; +} + +VCHIQ_STATUS_T +vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_STATUS_T ret = VCHIQ_ERROR; + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + if (service) { + ret = vchiq_use_internal(service->state, service, + USE_TYPE_SERVICE); + unlock_service(service); + } + return ret; +} + +VCHIQ_STATUS_T +vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_STATUS_T ret = VCHIQ_ERROR; + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + if (service) { + ret = vchiq_release_internal(service->state, service); + unlock_service(service); + } + return ret; +} + +void +vchiq_dump_service_use_state(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int i, j = 0; + /* Only dump 64 services */ + static const int local_max_services = 64; + /* If there's more than 64 services, only dump ones with + * non-zero counts */ + int only_nonzero = 0; + static const char *nz = "<-- preventing suspend"; + + enum vc_suspend_status vc_suspend_state; + enum vc_resume_status vc_resume_state; + int peer_count; + int vc_use_count; + int active_services; + struct service_data_struct { + int fourcc; + int clientid; + int use_count; + } service_data[local_max_services]; + + if (!arm_state) + return; + + read_lock_bh(&arm_state->susp_res_lock); + vc_suspend_state = arm_state->vc_suspend_state; + vc_resume_state = arm_state->vc_resume_state; + peer_count = arm_state->peer_use_count; + vc_use_count = arm_state->videocore_use_count; + active_services = state->unused_service; + if (active_services > local_max_services) + only_nonzero = 1; + + for (i = 0; (i < active_services) && (j < local_max_services); i++) { + VCHIQ_SERVICE_T *service_ptr = state->services[i]; + if (!service_ptr) + continue; + + if (only_nonzero && !service_ptr->service_use_count) + continue; + + if (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE) { + service_data[j].fourcc = service_ptr->base.fourcc; + service_data[j].clientid = service_ptr->client_id; + service_data[j++].use_count = service_ptr-> + service_use_count; + } + } + + read_unlock_bh(&arm_state->susp_res_lock); + + vchiq_log_warning(vchiq_susp_log_level, + "-- Videcore suspend state: %s --", + suspend_state_names[vc_suspend_state + VC_SUSPEND_NUM_OFFSET]); + vchiq_log_warning(vchiq_susp_log_level, + "-- Videcore resume state: %s --", + resume_state_names[vc_resume_state + VC_RESUME_NUM_OFFSET]); + + if (only_nonzero) + vchiq_log_warning(vchiq_susp_log_level, "Too many active " + "services (%d). Only dumping up to first %d services " + "with non-zero use-count", active_services, + local_max_services); + + for (i = 0; i < j; i++) { + vchiq_log_warning(vchiq_susp_log_level, + "----- %c%c%c%c:%d service count %d %s", + VCHIQ_FOURCC_AS_4CHARS(service_data[i].fourcc), + service_data[i].clientid, + service_data[i].use_count, + service_data[i].use_count ? nz : ""); + } + vchiq_log_warning(vchiq_susp_log_level, + "----- VCHIQ use count count %d", peer_count); + vchiq_log_warning(vchiq_susp_log_level, + "--- Overall vchiq instance use count %d", vc_use_count); + + vchiq_dump_platform_use_state(state); +} + +VCHIQ_STATUS_T +vchiq_check_service(VCHIQ_SERVICE_T *service) +{ + VCHIQ_ARM_STATE_T *arm_state; + VCHIQ_STATUS_T ret = VCHIQ_ERROR; + + if (!service || !service->state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + arm_state = vchiq_platform_get_arm_state(service->state); + + read_lock_bh(&arm_state->susp_res_lock); + if (service->service_use_count) + ret = VCHIQ_SUCCESS; + read_unlock_bh(&arm_state->susp_res_lock); + + if (ret == VCHIQ_ERROR) { + vchiq_log_error(vchiq_susp_log_level, + "%s ERROR - %c%c%c%c:%d service count %d, " + "state count %d, videocore suspend state %s", __func__, + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->client_id, service->service_use_count, + arm_state->videocore_use_count, + suspend_state_names[arm_state->vc_suspend_state + + VC_SUSPEND_NUM_OFFSET]); + vchiq_dump_service_use_state(service->state); + } +out: + return ret; +} + +/* stub functions */ +void vchiq_on_remote_use_active(VCHIQ_STATE_T *state) +{ + (void)state; +} + +void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, + VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + vchiq_log_info(vchiq_susp_log_level, "%d: %s->%s", state->id, + get_conn_state_name(oldstate), get_conn_state_name(newstate)); + if (state->conn_state == VCHIQ_CONNSTATE_CONNECTED) { + write_lock_bh(&arm_state->susp_res_lock); + if (!arm_state->first_connect) { + char threadname[10]; + arm_state->first_connect = 1; + write_unlock_bh(&arm_state->susp_res_lock); + snprintf(threadname, sizeof(threadname), "VCHIQka-%d", + state->id); + arm_state->ka_thread = kthread_create( + &vchiq_keepalive_thread_func, + (void *)state, + threadname); + if (arm_state->ka_thread == NULL) { + vchiq_log_error(vchiq_susp_log_level, + "vchiq: FATAL: couldn't create thread %s", + threadname); + } else { + wake_up_process(arm_state->ka_thread); + } + } else + write_unlock_bh(&arm_state->susp_res_lock); + } +} + +static int vchiq_probe(struct platform_device *pdev) +{ + struct device_node *fw_node; + struct rpi_firmware *fw; + int err; + void *ptr_err; + + fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); +/* Remove comment when booting without Device Tree is no longer supported + if (!fw_node) { + dev_err(&pdev->dev, "Missing firmware node\n"); + return -ENOENT; + } +*/ + fw = rpi_firmware_get(fw_node); + if (!fw) + return -EPROBE_DEFER; + + platform_set_drvdata(pdev, fw); + + /* create debugfs entries */ + err = vchiq_debugfs_init(); + if (err != 0) + goto failed_debugfs_init; + + err = alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1, DEVICE_NAME); + if (err != 0) { + vchiq_log_error(vchiq_arm_log_level, + "Unable to allocate device number"); + goto failed_alloc_chrdev; + } + cdev_init(&vchiq_cdev, &vchiq_fops); + vchiq_cdev.owner = THIS_MODULE; + err = cdev_add(&vchiq_cdev, vchiq_devid, 1); + if (err != 0) { + vchiq_log_error(vchiq_arm_log_level, + "Unable to register device"); + goto failed_cdev_add; + } + + /* create sysfs entries */ + vchiq_class = class_create(THIS_MODULE, DEVICE_NAME); + ptr_err = vchiq_class; + if (IS_ERR(ptr_err)) + goto failed_class_create; + + vchiq_dev = device_create(vchiq_class, NULL, + vchiq_devid, NULL, "vchiq"); + ptr_err = vchiq_dev; + if (IS_ERR(ptr_err)) + goto failed_device_create; + + err = vchiq_platform_init(pdev, &g_state); + if (err != 0) + goto failed_platform_init; + + vchiq_log_info(vchiq_arm_log_level, + "vchiq: initialised - version %d (min %d), device %d.%d", + VCHIQ_VERSION, VCHIQ_VERSION_MIN, + MAJOR(vchiq_devid), MINOR(vchiq_devid)); + + return 0; + +failed_platform_init: + device_destroy(vchiq_class, vchiq_devid); +failed_device_create: + class_destroy(vchiq_class); +failed_class_create: + cdev_del(&vchiq_cdev); + err = PTR_ERR(ptr_err); +failed_cdev_add: + unregister_chrdev_region(vchiq_devid, 1); +failed_alloc_chrdev: + vchiq_debugfs_deinit(); +failed_debugfs_init: + vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq"); + return err; +} + +static int vchiq_remove(struct platform_device *pdev) +{ + device_destroy(vchiq_class, vchiq_devid); + class_destroy(vchiq_class); + cdev_del(&vchiq_cdev); + unregister_chrdev_region(vchiq_devid, 1); + + return 0; +} + +static const struct of_device_id vchiq_of_match[] = { + { .compatible = "brcm,bcm2835-vchiq", }, + {}, +}; +MODULE_DEVICE_TABLE(of, vchiq_of_match); + +static struct platform_driver vchiq_driver = { + .driver = { + .name = "bcm2835_vchiq", + .owner = THIS_MODULE, + .of_match_table = vchiq_of_match, + }, + .probe = vchiq_probe, + .remove = vchiq_remove, +}; +module_platform_driver(vchiq_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h new file mode 100644 index 000000000000..9740e1afbc9d --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_ARM_H +#define VCHIQ_ARM_H + +#include +#include +#include +#include +#include "vchiq_core.h" +#include "vchiq_debugfs.h" + + +enum vc_suspend_status { + VC_SUSPEND_FORCE_CANCELED = -3, /* Force suspend canceled, too busy */ + VC_SUSPEND_REJECTED = -2, /* Videocore rejected suspend request */ + VC_SUSPEND_FAILED = -1, /* Videocore suspend failed */ + VC_SUSPEND_IDLE = 0, /* VC active, no suspend actions */ + VC_SUSPEND_REQUESTED, /* User has requested suspend */ + VC_SUSPEND_IN_PROGRESS, /* Slot handler has recvd suspend request */ + VC_SUSPEND_SUSPENDED /* Videocore suspend succeeded */ +}; + +enum vc_resume_status { + VC_RESUME_FAILED = -1, /* Videocore resume failed */ + VC_RESUME_IDLE = 0, /* VC suspended, no resume actions */ + VC_RESUME_REQUESTED, /* User has requested resume */ + VC_RESUME_IN_PROGRESS, /* Slot handler has received resume request */ + VC_RESUME_RESUMED /* Videocore resumed successfully (active) */ +}; + + +enum USE_TYPE_E { + USE_TYPE_SERVICE, + USE_TYPE_SERVICE_NO_RESUME, + USE_TYPE_VCHIQ +}; + + + +typedef struct vchiq_arm_state_struct { + /* Keepalive-related data */ + struct task_struct *ka_thread; + struct completion ka_evt; + atomic_t ka_use_count; + atomic_t ka_use_ack_count; + atomic_t ka_release_count; + + struct completion vc_suspend_complete; + struct completion vc_resume_complete; + + rwlock_t susp_res_lock; + enum vc_suspend_status vc_suspend_state; + enum vc_resume_status vc_resume_state; + + unsigned int wake_address; + + struct timer_list suspend_timer; + int suspend_timer_timeout; + int suspend_timer_running; + + /* Global use count for videocore. + ** This is equal to the sum of the use counts for all services. When + ** this hits zero the videocore suspend procedure will be initiated. + */ + int videocore_use_count; + + /* Use count to track requests from videocore peer. + ** This use count is not associated with a service, so needs to be + ** tracked separately with the state. + */ + int peer_use_count; + + /* Flag to indicate whether resume is blocked. This happens when the + ** ARM is suspending + */ + struct completion resume_blocker; + int resume_blocked; + struct completion blocked_blocker; + int blocked_count; + + int autosuspend_override; + + /* Flag to indicate that the first vchiq connect has made it through. + ** This means that both sides should be fully ready, and we should + ** be able to suspend after this point. + */ + int first_connect; + + unsigned long long suspend_start_time; + unsigned long long sleep_start_time; + unsigned long long resume_start_time; + unsigned long long last_wake_time; + +} VCHIQ_ARM_STATE_T; + +extern int vchiq_arm_log_level; +extern int vchiq_susp_log_level; + +int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); + +extern VCHIQ_STATE_T * +vchiq_get_state(void); + +extern VCHIQ_STATUS_T +vchiq_arm_vcsuspend(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_arm_force_suspend(VCHIQ_STATE_T *state); + +extern int +vchiq_arm_allow_resume(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_arm_vcresume(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state); + +extern int +vchiq_check_resume(VCHIQ_STATE_T *state); + +extern void +vchiq_check_suspend(VCHIQ_STATE_T *state); + VCHIQ_STATUS_T +vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_STATUS_T +vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_STATUS_T +vchiq_check_service(VCHIQ_SERVICE_T *service); + +extern VCHIQ_STATUS_T +vchiq_platform_suspend(VCHIQ_STATE_T *state); + +extern int +vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state); + +extern int +vchiq_platform_use_suspend_timer(void); + +extern void +vchiq_dump_platform_use_state(VCHIQ_STATE_T *state); + +extern void +vchiq_dump_service_use_state(VCHIQ_STATE_T *state); + +extern VCHIQ_ARM_STATE_T* +vchiq_platform_get_arm_state(VCHIQ_STATE_T *state); + +extern int +vchiq_videocore_wanted(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + enum USE_TYPE_E use_type); +extern VCHIQ_STATUS_T +vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service); + +extern VCHIQ_DEBUGFS_NODE_T * +vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance); + +extern int +vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance); + +extern int +vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance); + +extern int +vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance); + +extern void +vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace); + +extern void +set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, + enum vc_suspend_status new_state); + +extern void +set_resume_state(VCHIQ_ARM_STATE_T *arm_state, + enum vc_resume_status new_state); + +extern void +start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state); + + +#endif /* VCHIQ_ARM_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_build_info.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_build_info.h new file mode 100644 index 000000000000..df645813bdae --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_build_info.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +const char *vchiq_get_build_hostname(void); +const char *vchiq_get_build_version(void); +const char *vchiq_get_build_time(void); +const char *vchiq_get_build_date(void); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h new file mode 100644 index 000000000000..d2797db702f9 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2010-2014 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_CFG_H +#define VCHIQ_CFG_H + +#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I') +/* The version of VCHIQ - change with any non-trivial change */ +#define VCHIQ_VERSION 8 +/* The minimum compatible version - update to match VCHIQ_VERSION with any +** incompatible change */ +#define VCHIQ_VERSION_MIN 3 + +/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */ +#define VCHIQ_VERSION_LIB_VERSION 7 + +/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */ +#define VCHIQ_VERSION_CLOSE_DELIVERED 7 + +/* The version that made it safe to use SYNCHRONOUS mode */ +#define VCHIQ_VERSION_SYNCHRONOUS_MODE 8 + +#define VCHIQ_MAX_STATES 1 +#define VCHIQ_MAX_SERVICES 4096 +#define VCHIQ_MAX_SLOTS 128 +#define VCHIQ_MAX_SLOTS_PER_SIDE 64 + +#define VCHIQ_NUM_CURRENT_BULKS 32 +#define VCHIQ_NUM_SERVICE_BULKS 4 + +#ifndef VCHIQ_ENABLE_DEBUG +#define VCHIQ_ENABLE_DEBUG 1 +#endif + +#ifndef VCHIQ_ENABLE_STATS +#define VCHIQ_ENABLE_STATS 1 +#endif + +#endif /* VCHIQ_CFG_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c new file mode 100644 index 000000000000..5efc62ffb2f5 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vchiq_connected.h" +#include "vchiq_core.h" +#include "vchiq_killable.h" +#include +#include + +#define MAX_CALLBACKS 10 + +static int g_connected; +static int g_num_deferred_callbacks; +static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS]; +static int g_once_init; +static struct mutex g_connected_mutex; + +/**************************************************************************** +* +* Function to initialize our lock. +* +***************************************************************************/ + +static void connected_init(void) +{ + if (!g_once_init) { + mutex_init(&g_connected_mutex); + g_once_init = 1; + } +} + +/**************************************************************************** +* +* This function is used to defer initialization until the vchiq stack is +* initialized. If the stack is already initialized, then the callback will +* be made immediately, otherwise it will be deferred until +* vchiq_call_connected_callbacks is called. +* +***************************************************************************/ + +void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) +{ + connected_init(); + + if (mutex_lock_interruptible(&g_connected_mutex) != 0) + return; + + if (g_connected) + /* We're already connected. Call the callback immediately. */ + + callback(); + else { + if (g_num_deferred_callbacks >= MAX_CALLBACKS) + vchiq_log_error(vchiq_core_log_level, + "There already %d callback registered - " + "please increase MAX_CALLBACKS", + g_num_deferred_callbacks); + else { + g_deferred_callback[g_num_deferred_callbacks] = + callback; + g_num_deferred_callbacks++; + } + } + mutex_unlock(&g_connected_mutex); +} + +/**************************************************************************** +* +* This function is called by the vchiq stack once it has been connected to +* the videocore and clients can start to use the stack. +* +***************************************************************************/ + +void vchiq_call_connected_callbacks(void) +{ + int i; + + connected_init(); + + if (mutex_lock_interruptible(&g_connected_mutex) != 0) + return; + + for (i = 0; i < g_num_deferred_callbacks; i++) + g_deferred_callback[i](); + + g_num_deferred_callbacks = 0; + g_connected = 1; + mutex_unlock(&g_connected_mutex); +} +EXPORT_SYMBOL(vchiq_add_connected_callback); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.h new file mode 100644 index 000000000000..863b3e335c1a --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.h @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_CONNECTED_H +#define VCHIQ_CONNECTED_H + +/* ---- Include Files ----------------------------------------------------- */ + +/* ---- Constants and Types ---------------------------------------------- */ + +typedef void (*VCHIQ_CONNECTED_CALLBACK_T)(void); + +/* ---- Variable Externs ------------------------------------------------- */ + +/* ---- Function Prototypes ---------------------------------------------- */ + +void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback); +void vchiq_call_connected_callbacks(void); + +#endif /* VCHIQ_CONNECTED_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c new file mode 100644 index 000000000000..2c98da4307df --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -0,0 +1,3934 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vchiq_core.h" +#include "vchiq_killable.h" + +#define VCHIQ_SLOT_HANDLER_STACK 8192 + +#define HANDLE_STATE_SHIFT 12 + +#define SLOT_INFO_FROM_INDEX(state, index) (state->slot_info + (index)) +#define SLOT_DATA_FROM_INDEX(state, index) (state->slot_data + (index)) +#define SLOT_INDEX_FROM_DATA(state, data) \ + (((unsigned int)((char *)data - (char *)state->slot_data)) / \ + VCHIQ_SLOT_SIZE) +#define SLOT_INDEX_FROM_INFO(state, info) \ + ((unsigned int)(info - state->slot_info)) +#define SLOT_QUEUE_INDEX_FROM_POS(pos) \ + ((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE)) + +#define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1)) + +#define SRVTRACE_LEVEL(srv) \ + (((srv) && (srv)->trace) ? VCHIQ_LOG_TRACE : vchiq_core_msg_log_level) +#define SRVTRACE_ENABLED(srv, lev) \ + (((srv) && (srv)->trace) || (vchiq_core_msg_log_level >= (lev))) + +struct vchiq_open_payload { + int fourcc; + int client_id; + short version; + short version_min; +}; + +struct vchiq_openack_payload { + short version; +}; + +enum +{ + QMFLAGS_IS_BLOCKING = (1 << 0), + QMFLAGS_NO_MUTEX_LOCK = (1 << 1), + QMFLAGS_NO_MUTEX_UNLOCK = (1 << 2) +}; + +/* we require this for consistency between endpoints */ +vchiq_static_assert(sizeof(VCHIQ_HEADER_T) == 8); +vchiq_static_assert(IS_POW2(sizeof(VCHIQ_HEADER_T))); +vchiq_static_assert(IS_POW2(VCHIQ_NUM_CURRENT_BULKS)); +vchiq_static_assert(IS_POW2(VCHIQ_NUM_SERVICE_BULKS)); +vchiq_static_assert(IS_POW2(VCHIQ_MAX_SERVICES)); +vchiq_static_assert(VCHIQ_VERSION >= VCHIQ_VERSION_MIN); + +/* Run time control of log level, based on KERN_XXX level. */ +int vchiq_core_log_level = VCHIQ_LOG_DEFAULT; +int vchiq_core_msg_log_level = VCHIQ_LOG_DEFAULT; +int vchiq_sync_log_level = VCHIQ_LOG_DEFAULT; + +static atomic_t pause_bulks_count = ATOMIC_INIT(0); + +static DEFINE_SPINLOCK(service_spinlock); +DEFINE_SPINLOCK(bulk_waiter_spinlock); +DEFINE_SPINLOCK(quota_spinlock); + +VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; +static unsigned int handle_seq; + +static const char *const srvstate_names[] = { + "FREE", + "HIDDEN", + "LISTENING", + "OPENING", + "OPEN", + "OPENSYNC", + "CLOSESENT", + "CLOSERECVD", + "CLOSEWAIT", + "CLOSED" +}; + +static const char *const reason_names[] = { + "SERVICE_OPENED", + "SERVICE_CLOSED", + "MESSAGE_AVAILABLE", + "BULK_TRANSMIT_DONE", + "BULK_RECEIVE_DONE", + "BULK_TRANSMIT_ABORTED", + "BULK_RECEIVE_ABORTED" +}; + +static const char *const conn_state_names[] = { + "DISCONNECTED", + "CONNECTING", + "CONNECTED", + "PAUSING", + "PAUSE_SENT", + "PAUSED", + "RESUMING", + "PAUSE_TIMEOUT", + "RESUME_TIMEOUT" +}; + + +static void +release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header); + +static const char *msg_type_str(unsigned int msg_type) +{ + switch (msg_type) { + case VCHIQ_MSG_PADDING: return "PADDING"; + case VCHIQ_MSG_CONNECT: return "CONNECT"; + case VCHIQ_MSG_OPEN: return "OPEN"; + case VCHIQ_MSG_OPENACK: return "OPENACK"; + case VCHIQ_MSG_CLOSE: return "CLOSE"; + case VCHIQ_MSG_DATA: return "DATA"; + case VCHIQ_MSG_BULK_RX: return "BULK_RX"; + case VCHIQ_MSG_BULK_TX: return "BULK_TX"; + case VCHIQ_MSG_BULK_RX_DONE: return "BULK_RX_DONE"; + case VCHIQ_MSG_BULK_TX_DONE: return "BULK_TX_DONE"; + case VCHIQ_MSG_PAUSE: return "PAUSE"; + case VCHIQ_MSG_RESUME: return "RESUME"; + case VCHIQ_MSG_REMOTE_USE: return "REMOTE_USE"; + case VCHIQ_MSG_REMOTE_RELEASE: return "REMOTE_RELEASE"; + case VCHIQ_MSG_REMOTE_USE_ACTIVE: return "REMOTE_USE_ACTIVE"; + } + return "???"; +} + +static inline void +vchiq_set_service_state(VCHIQ_SERVICE_T *service, int newstate) +{ + vchiq_log_info(vchiq_core_log_level, "%d: srv:%d %s->%s", + service->state->id, service->localport, + srvstate_names[service->srvstate], + srvstate_names[newstate]); + service->srvstate = newstate; +} + +VCHIQ_SERVICE_T * +find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_SERVICE_T *service; + + spin_lock(&service_spinlock); + service = handle_to_service(handle); + if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && + (service->handle == handle)) { + BUG_ON(service->ref_count == 0); + service->ref_count++; + } else + service = NULL; + spin_unlock(&service_spinlock); + + if (!service) + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); + + return service; +} + +VCHIQ_SERVICE_T * +find_service_by_port(VCHIQ_STATE_T *state, int localport) +{ + VCHIQ_SERVICE_T *service = NULL; + if ((unsigned int)localport <= VCHIQ_PORT_MAX) { + spin_lock(&service_spinlock); + service = state->services[localport]; + if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE)) { + BUG_ON(service->ref_count == 0); + service->ref_count++; + } else + service = NULL; + spin_unlock(&service_spinlock); + } + + if (!service) + vchiq_log_info(vchiq_core_log_level, + "Invalid port %d", localport); + + return service; +} + +VCHIQ_SERVICE_T * +find_service_for_instance(VCHIQ_INSTANCE_T instance, + VCHIQ_SERVICE_HANDLE_T handle) { + VCHIQ_SERVICE_T *service; + + spin_lock(&service_spinlock); + service = handle_to_service(handle); + if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && + (service->handle == handle) && + (service->instance == instance)) { + BUG_ON(service->ref_count == 0); + service->ref_count++; + } else + service = NULL; + spin_unlock(&service_spinlock); + + if (!service) + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); + + return service; +} + +VCHIQ_SERVICE_T * +find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, + VCHIQ_SERVICE_HANDLE_T handle) { + VCHIQ_SERVICE_T *service; + + spin_lock(&service_spinlock); + service = handle_to_service(handle); + if (service && + ((service->srvstate == VCHIQ_SRVSTATE_FREE) || + (service->srvstate == VCHIQ_SRVSTATE_CLOSED)) && + (service->handle == handle) && + (service->instance == instance)) { + BUG_ON(service->ref_count == 0); + service->ref_count++; + } else + service = NULL; + spin_unlock(&service_spinlock); + + if (!service) + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); + + return service; +} + +VCHIQ_SERVICE_T * +next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, + int *pidx) +{ + VCHIQ_SERVICE_T *service = NULL; + int idx = *pidx; + + spin_lock(&service_spinlock); + while (idx < state->unused_service) { + VCHIQ_SERVICE_T *srv = state->services[idx++]; + if (srv && (srv->srvstate != VCHIQ_SRVSTATE_FREE) && + (srv->instance == instance)) { + service = srv; + BUG_ON(service->ref_count == 0); + service->ref_count++; + break; + } + } + spin_unlock(&service_spinlock); + + *pidx = idx; + + return service; +} + +void +lock_service(VCHIQ_SERVICE_T *service) +{ + spin_lock(&service_spinlock); + BUG_ON(!service || (service->ref_count == 0)); + if (service) + service->ref_count++; + spin_unlock(&service_spinlock); +} + +void +unlock_service(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATE_T *state = service->state; + spin_lock(&service_spinlock); + BUG_ON(!service || (service->ref_count == 0)); + if (service && service->ref_count) { + service->ref_count--; + if (!service->ref_count) { + BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); + state->services[service->localport] = NULL; + } else + service = NULL; + } + spin_unlock(&service_spinlock); + + if (service && service->userdata_term) + service->userdata_term(service->base.userdata); + + kfree(service); +} + +int +vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + int id; + + id = service ? service->client_id : 0; + if (service) + unlock_service(service); + + return id; +} + +void * +vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_SERVICE_T *service = handle_to_service(handle); + + return service ? service->base.userdata : NULL; +} + +int +vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_SERVICE_T *service = handle_to_service(handle); + + return service ? service->base.fourcc : 0; +} + +static void +mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread) +{ + VCHIQ_STATE_T *state = service->state; + VCHIQ_SERVICE_QUOTA_T *service_quota; + + service->closing = 1; + + /* Synchronise with other threads. */ + mutex_lock(&state->recycle_mutex); + mutex_unlock(&state->recycle_mutex); + if (!sh_thread || (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT)) { + /* If we're pausing then the slot_mutex is held until resume + * by the slot handler. Therefore don't try to acquire this + * mutex if we're the slot handler and in the pause sent state. + * We don't need to in this case anyway. */ + mutex_lock(&state->slot_mutex); + mutex_unlock(&state->slot_mutex); + } + + /* Unblock any sending thread. */ + service_quota = &state->service_quotas[service->localport]; + up(&service_quota->quota_event); +} + +static void +mark_service_closing(VCHIQ_SERVICE_T *service) +{ + mark_service_closing_internal(service, 0); +} + +static inline VCHIQ_STATUS_T +make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason, + VCHIQ_HEADER_T *header, void *bulk_userdata) +{ + VCHIQ_STATUS_T status; + vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %x, %x)", + service->state->id, service->localport, reason_names[reason], + (unsigned int)header, (unsigned int)bulk_userdata); + status = service->base.callback(reason, header, service->handle, + bulk_userdata); + if (status == VCHIQ_ERROR) { + vchiq_log_warning(vchiq_core_log_level, + "%d: ignoring ERROR from callback to service %x", + service->state->id, service->handle); + status = VCHIQ_SUCCESS; + } + return status; +} + +inline void +vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate) +{ + VCHIQ_CONNSTATE_T oldstate = state->conn_state; + vchiq_log_info(vchiq_core_log_level, "%d: %s->%s", state->id, + conn_state_names[oldstate], + conn_state_names[newstate]); + state->conn_state = newstate; + vchiq_platform_conn_state_changed(state, oldstate, newstate); +} + +static inline void +remote_event_create(REMOTE_EVENT_T *event) +{ + event->armed = 0; + /* Don't clear the 'fired' flag because it may already have been set + ** by the other side. */ + sema_init(event->event, 0); +} + +static inline void +remote_event_destroy(REMOTE_EVENT_T *event) +{ + (void)event; +} + +static inline int +remote_event_wait(REMOTE_EVENT_T *event) +{ + if (!event->fired) { + event->armed = 1; + dsb(); + if (!event->fired) { + if (down_interruptible(event->event) != 0) { + event->armed = 0; + return 0; + } + } + event->armed = 0; + wmb(); + } + + event->fired = 0; + return 1; +} + +static inline void +remote_event_signal_local(REMOTE_EVENT_T *event) +{ + event->armed = 0; + up(event->event); +} + +static inline void +remote_event_poll(REMOTE_EVENT_T *event) +{ + if (event->fired && event->armed) + remote_event_signal_local(event); +} + +void +remote_event_pollall(VCHIQ_STATE_T *state) +{ + remote_event_poll(&state->local->sync_trigger); + remote_event_poll(&state->local->sync_release); + remote_event_poll(&state->local->trigger); + remote_event_poll(&state->local->recycle); +} + +/* Round up message sizes so that any space at the end of a slot is always big +** enough for a header. This relies on header size being a power of two, which +** has been verified earlier by a static assertion. */ + +static inline unsigned int +calc_stride(unsigned int size) +{ + /* Allow room for the header */ + size += sizeof(VCHIQ_HEADER_T); + + /* Round up */ + return (size + sizeof(VCHIQ_HEADER_T) - 1) & ~(sizeof(VCHIQ_HEADER_T) + - 1); +} + +/* Called by the slot handler thread */ +static VCHIQ_SERVICE_T * +get_listening_service(VCHIQ_STATE_T *state, int fourcc) +{ + int i; + + WARN_ON(fourcc == VCHIQ_FOURCC_INVALID); + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + if (service && + (service->public_fourcc == fourcc) && + ((service->srvstate == VCHIQ_SRVSTATE_LISTENING) || + ((service->srvstate == VCHIQ_SRVSTATE_OPEN) && + (service->remoteport == VCHIQ_PORT_FREE)))) { + lock_service(service); + return service; + } + } + + return NULL; +} + +/* Called by the slot handler thread */ +static VCHIQ_SERVICE_T * +get_connected_service(VCHIQ_STATE_T *state, unsigned int port) +{ + int i; + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + if (service && (service->srvstate == VCHIQ_SRVSTATE_OPEN) + && (service->remoteport == port)) { + lock_service(service); + return service; + } + } + return NULL; +} + +inline void +request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type) +{ + uint32_t value; + + if (service) { + do { + value = atomic_read(&service->poll_flags); + } while (atomic_cmpxchg(&service->poll_flags, value, + value | (1 << poll_type)) != value); + + do { + value = atomic_read(&state->poll_services[ + service->localport>>5]); + } while (atomic_cmpxchg( + &state->poll_services[service->localport>>5], + value, value | (1 << (service->localport & 0x1f))) + != value); + } + + state->poll_needed = 1; + wmb(); + + /* ... and ensure the slot handler runs. */ + remote_event_signal_local(&state->local->trigger); +} + +/* Called from queue_message, by the slot handler and application threads, +** with slot_mutex held */ +static VCHIQ_HEADER_T * +reserve_space(VCHIQ_STATE_T *state, int space, int is_blocking) +{ + VCHIQ_SHARED_STATE_T *local = state->local; + int tx_pos = state->local_tx_pos; + int slot_space = VCHIQ_SLOT_SIZE - (tx_pos & VCHIQ_SLOT_MASK); + + if (space > slot_space) { + VCHIQ_HEADER_T *header; + /* Fill the remaining space with padding */ + WARN_ON(state->tx_data == NULL); + header = (VCHIQ_HEADER_T *) + (state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); + header->msgid = VCHIQ_MSGID_PADDING; + header->size = slot_space - sizeof(VCHIQ_HEADER_T); + + tx_pos += slot_space; + } + + /* If necessary, get the next slot. */ + if ((tx_pos & VCHIQ_SLOT_MASK) == 0) { + int slot_index; + + /* If there is no free slot... */ + + if (down_trylock(&state->slot_available_event) != 0) { + /* ...wait for one. */ + + VCHIQ_STATS_INC(state, slot_stalls); + + /* But first, flush through the last slot. */ + state->local_tx_pos = tx_pos; + local->tx_pos = tx_pos; + remote_event_signal(&state->remote->trigger); + + if (!is_blocking || + (down_interruptible( + &state->slot_available_event) != 0)) + return NULL; /* No space available */ + } + + BUG_ON(tx_pos == + (state->slot_queue_available * VCHIQ_SLOT_SIZE)); + + slot_index = local->slot_queue[ + SLOT_QUEUE_INDEX_FROM_POS(tx_pos) & + VCHIQ_SLOT_QUEUE_MASK]; + state->tx_data = + (char *)SLOT_DATA_FROM_INDEX(state, slot_index); + } + + state->local_tx_pos = tx_pos + space; + + return (VCHIQ_HEADER_T *)(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); +} + +/* Called by the recycle thread. */ +static void +process_free_queue(VCHIQ_STATE_T *state) +{ + VCHIQ_SHARED_STATE_T *local = state->local; + BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + int slot_queue_available; + + /* Use a read memory barrier to ensure that any state that may have + ** been modified by another thread is not masked by stale prefetched + ** values. */ + rmb(); + + /* Find slots which have been freed by the other side, and return them + ** to the available queue. */ + slot_queue_available = state->slot_queue_available; + + while (slot_queue_available != local->slot_queue_recycle) { + unsigned int pos; + int slot_index = local->slot_queue[slot_queue_available++ & + VCHIQ_SLOT_QUEUE_MASK]; + char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); + int data_found = 0; + + vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", + state->id, slot_index, (unsigned int)data, + local->slot_queue_recycle, slot_queue_available); + + /* Initialise the bitmask for services which have used this + ** slot */ + BITSET_ZERO(service_found); + + pos = 0; + + while (pos < VCHIQ_SLOT_SIZE) { + VCHIQ_HEADER_T *header = + (VCHIQ_HEADER_T *)(data + pos); + int msgid = header->msgid; + if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA) { + int port = VCHIQ_MSG_SRCPORT(msgid); + VCHIQ_SERVICE_QUOTA_T *service_quota = + &state->service_quotas[port]; + int count; + spin_lock("a_spinlock); + count = service_quota->message_use_count; + if (count > 0) + service_quota->message_use_count = + count - 1; + spin_unlock("a_spinlock); + + if (count == service_quota->message_quota) + /* Signal the service that it + ** has dropped below its quota + */ + up(&service_quota->quota_event); + else if (count == 0) { + vchiq_log_error(vchiq_core_log_level, + "service %d " + "message_use_count=%d " + "(header %x, msgid %x, " + "header->msgid %x, " + "header->size %x)", + port, + service_quota-> + message_use_count, + (unsigned int)header, msgid, + header->msgid, + header->size); + WARN(1, "invalid message use count\n"); + } + if (!BITSET_IS_SET(service_found, port)) { + /* Set the found bit for this service */ + BITSET_SET(service_found, port); + + spin_lock("a_spinlock); + count = service_quota->slot_use_count; + if (count > 0) + service_quota->slot_use_count = + count - 1; + spin_unlock("a_spinlock); + + if (count > 0) { + /* Signal the service in case + ** it has dropped below its + ** quota */ + up(&service_quota->quota_event); + vchiq_log_trace( + vchiq_core_log_level, + "%d: pfq:%d %x@%x - " + "slot_use->%d", + state->id, port, + header->size, + (unsigned int)header, + count - 1); + } else { + vchiq_log_error( + vchiq_core_log_level, + "service %d " + "slot_use_count" + "=%d (header %x" + ", msgid %x, " + "header->msgid" + " %x, header->" + "size %x)", + port, count, + (unsigned int)header, + msgid, + header->msgid, + header->size); + WARN(1, "bad slot use count\n"); + } + } + + data_found = 1; + } + + pos += calc_stride(header->size); + if (pos > VCHIQ_SLOT_SIZE) { + vchiq_log_error(vchiq_core_log_level, + "pfq - pos %x: header %x, msgid %x, " + "header->msgid %x, header->size %x", + pos, (unsigned int)header, msgid, + header->msgid, header->size); + WARN(1, "invalid slot position\n"); + } + } + + if (data_found) { + int count; + spin_lock("a_spinlock); + count = state->data_use_count; + if (count > 0) + state->data_use_count = + count - 1; + spin_unlock("a_spinlock); + if (count == state->data_quota) + up(&state->data_quota_event); + } + + state->slot_queue_available = slot_queue_available; + up(&state->slot_available_event); + } +} + +/* Called by the slot handler and application threads */ +static VCHIQ_STATUS_T +queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + int msgid, const VCHIQ_ELEMENT_T *elements, + int count, int size, int flags) +{ + VCHIQ_SHARED_STATE_T *local; + VCHIQ_SERVICE_QUOTA_T *service_quota = NULL; + VCHIQ_HEADER_T *header; + int type = VCHIQ_MSG_TYPE(msgid); + + unsigned int stride; + + local = state->local; + + stride = calc_stride(size); + + WARN_ON(!(stride <= VCHIQ_SLOT_SIZE)); + + if (!(flags & QMFLAGS_NO_MUTEX_LOCK) && + (mutex_lock_interruptible(&state->slot_mutex) != 0)) + return VCHIQ_RETRY; + + if (type == VCHIQ_MSG_DATA) { + int tx_end_index; + + BUG_ON(!service); + BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | + QMFLAGS_NO_MUTEX_UNLOCK)) != 0); + + if (service->closing) { + /* The service has been closed */ + mutex_unlock(&state->slot_mutex); + return VCHIQ_ERROR; + } + + service_quota = &state->service_quotas[service->localport]; + + spin_lock("a_spinlock); + + /* Ensure this service doesn't use more than its quota of + ** messages or slots */ + tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( + state->local_tx_pos + stride - 1); + + /* Ensure data messages don't use more than their quota of + ** slots */ + while ((tx_end_index != state->previous_data_index) && + (state->data_use_count == state->data_quota)) { + VCHIQ_STATS_INC(state, data_stalls); + spin_unlock("a_spinlock); + mutex_unlock(&state->slot_mutex); + + if (down_interruptible(&state->data_quota_event) + != 0) + return VCHIQ_RETRY; + + mutex_lock(&state->slot_mutex); + spin_lock("a_spinlock); + tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( + state->local_tx_pos + stride - 1); + if ((tx_end_index == state->previous_data_index) || + (state->data_use_count < state->data_quota)) { + /* Pass the signal on to other waiters */ + up(&state->data_quota_event); + break; + } + } + + while ((service_quota->message_use_count == + service_quota->message_quota) || + ((tx_end_index != service_quota->previous_tx_index) && + (service_quota->slot_use_count == + service_quota->slot_quota))) { + spin_unlock("a_spinlock); + vchiq_log_trace(vchiq_core_log_level, + "%d: qm:%d %s,%x - quota stall " + "(msg %d, slot %d)", + state->id, service->localport, + msg_type_str(type), size, + service_quota->message_use_count, + service_quota->slot_use_count); + VCHIQ_SERVICE_STATS_INC(service, quota_stalls); + mutex_unlock(&state->slot_mutex); + if (down_interruptible(&service_quota->quota_event) + != 0) + return VCHIQ_RETRY; + if (service->closing) + return VCHIQ_ERROR; + if (mutex_lock_interruptible(&state->slot_mutex) != 0) + return VCHIQ_RETRY; + if (service->srvstate != VCHIQ_SRVSTATE_OPEN) { + /* The service has been closed */ + mutex_unlock(&state->slot_mutex); + return VCHIQ_ERROR; + } + spin_lock("a_spinlock); + tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( + state->local_tx_pos + stride - 1); + } + + spin_unlock("a_spinlock); + } + + header = reserve_space(state, stride, flags & QMFLAGS_IS_BLOCKING); + + if (!header) { + if (service) + VCHIQ_SERVICE_STATS_INC(service, slot_stalls); + /* In the event of a failure, return the mutex to the + state it was in */ + if (!(flags & QMFLAGS_NO_MUTEX_LOCK)) + mutex_unlock(&state->slot_mutex); + return VCHIQ_RETRY; + } + + if (type == VCHIQ_MSG_DATA) { + int i, pos; + int tx_end_index; + int slot_use_count; + + vchiq_log_info(vchiq_core_log_level, + "%d: qm %s@%x,%x (%d->%d)", + state->id, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + (unsigned int)header, size, + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid)); + + BUG_ON(!service); + BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | + QMFLAGS_NO_MUTEX_UNLOCK)) != 0); + + for (i = 0, pos = 0; i < (unsigned int)count; + pos += elements[i++].size) + if (elements[i].size) { + if (vchiq_copy_from_user + (header->data + pos, elements[i].data, + (size_t) elements[i].size) != + VCHIQ_SUCCESS) { + mutex_unlock(&state->slot_mutex); + VCHIQ_SERVICE_STATS_INC(service, + error_count); + return VCHIQ_ERROR; + } + if (i == 0) { + if (SRVTRACE_ENABLED(service, + VCHIQ_LOG_INFO)) + vchiq_log_dump_mem("Sent", 0, + header->data + pos, + min(64u, + elements[0].size)); + } + } + + spin_lock("a_spinlock); + service_quota->message_use_count++; + + tx_end_index = + SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos - 1); + + /* If this transmission can't fit in the last slot used by any + ** service, the data_use_count must be increased. */ + if (tx_end_index != state->previous_data_index) { + state->previous_data_index = tx_end_index; + state->data_use_count++; + } + + /* If this isn't the same slot last used by this service, + ** the service's slot_use_count must be increased. */ + if (tx_end_index != service_quota->previous_tx_index) { + service_quota->previous_tx_index = tx_end_index; + slot_use_count = ++service_quota->slot_use_count; + } else { + slot_use_count = 0; + } + + spin_unlock("a_spinlock); + + if (slot_use_count) + vchiq_log_trace(vchiq_core_log_level, + "%d: qm:%d %s,%x - slot_use->%d (hdr %p)", + state->id, service->localport, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), size, + slot_use_count, header); + + VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); + } else { + vchiq_log_info(vchiq_core_log_level, + "%d: qm %s@%x,%x (%d->%d)", state->id, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + (unsigned int)header, size, + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid)); + if (size != 0) { + WARN_ON(!((count == 1) && (size == elements[0].size))); + memcpy(header->data, elements[0].data, + elements[0].size); + } + VCHIQ_STATS_INC(state, ctrl_tx_count); + } + + header->msgid = msgid; + header->size = size; + + { + int svc_fourcc; + + svc_fourcc = service + ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + + vchiq_log_info(SRVTRACE_LEVEL(service), + "Sent Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d", + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + VCHIQ_MSG_TYPE(msgid), + VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid), + size); + } + + /* Make sure the new header is visible to the peer. */ + wmb(); + + /* Make the new tx_pos visible to the peer. */ + local->tx_pos = state->local_tx_pos; + wmb(); + + if (service && (type == VCHIQ_MSG_CLOSE)) + vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT); + + if (!(flags & QMFLAGS_NO_MUTEX_UNLOCK)) + mutex_unlock(&state->slot_mutex); + + remote_event_signal(&state->remote->trigger); + + return VCHIQ_SUCCESS; +} + +/* Called by the slot handler and application threads */ +static VCHIQ_STATUS_T +queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + int msgid, const VCHIQ_ELEMENT_T *elements, + int count, int size, int is_blocking) +{ + VCHIQ_SHARED_STATE_T *local; + VCHIQ_HEADER_T *header; + + local = state->local; + + if ((VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME) && + (mutex_lock_interruptible(&state->sync_mutex) != 0)) + return VCHIQ_RETRY; + + remote_event_wait(&local->sync_release); + + rmb(); + + header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, + local->slot_sync); + + { + int oldmsgid = header->msgid; + if (oldmsgid != VCHIQ_MSGID_PADDING) + vchiq_log_error(vchiq_core_log_level, + "%d: qms - msgid %x, not PADDING", + state->id, oldmsgid); + } + + if (service) { + int i, pos; + + vchiq_log_info(vchiq_sync_log_level, + "%d: qms %s@%x,%x (%d->%d)", state->id, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + (unsigned int)header, size, + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid)); + + for (i = 0, pos = 0; i < (unsigned int)count; + pos += elements[i++].size) + if (elements[i].size) { + if (vchiq_copy_from_user + (header->data + pos, elements[i].data, + (size_t) elements[i].size) != + VCHIQ_SUCCESS) { + mutex_unlock(&state->sync_mutex); + VCHIQ_SERVICE_STATS_INC(service, + error_count); + return VCHIQ_ERROR; + } + if (i == 0) { + if (vchiq_sync_log_level >= + VCHIQ_LOG_TRACE) + vchiq_log_dump_mem("Sent Sync", + 0, header->data + pos, + min(64u, + elements[0].size)); + } + } + + VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); + } else { + vchiq_log_info(vchiq_sync_log_level, + "%d: qms %s@%x,%x (%d->%d)", state->id, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + (unsigned int)header, size, + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid)); + if (size != 0) { + WARN_ON(!((count == 1) && (size == elements[0].size))); + memcpy(header->data, elements[0].data, + elements[0].size); + } + VCHIQ_STATS_INC(state, ctrl_tx_count); + } + + header->size = size; + header->msgid = msgid; + + if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) { + int svc_fourcc; + + svc_fourcc = service + ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + + vchiq_log_trace(vchiq_sync_log_level, + "Sent Sync Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d", + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + VCHIQ_MSG_TYPE(msgid), + VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid), + size); + } + + /* Make sure the new header is visible to the peer. */ + wmb(); + + remote_event_signal(&state->remote->sync_trigger); + + if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE) + mutex_unlock(&state->sync_mutex); + + return VCHIQ_SUCCESS; +} + +static inline void +claim_slot(VCHIQ_SLOT_INFO_T *slot) +{ + slot->use_count++; +} + +static void +release_slot(VCHIQ_STATE_T *state, VCHIQ_SLOT_INFO_T *slot_info, + VCHIQ_HEADER_T *header, VCHIQ_SERVICE_T *service) +{ + int release_count; + + mutex_lock(&state->recycle_mutex); + + if (header) { + int msgid = header->msgid; + if (((msgid & VCHIQ_MSGID_CLAIMED) == 0) || + (service && service->closing)) { + mutex_unlock(&state->recycle_mutex); + return; + } + + /* Rewrite the message header to prevent a double + ** release */ + header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED; + } + + release_count = slot_info->release_count; + slot_info->release_count = ++release_count; + + if (release_count == slot_info->use_count) { + int slot_queue_recycle; + /* Add to the freed queue */ + + /* A read barrier is necessary here to prevent speculative + ** fetches of remote->slot_queue_recycle from overtaking the + ** mutex. */ + rmb(); + + slot_queue_recycle = state->remote->slot_queue_recycle; + state->remote->slot_queue[slot_queue_recycle & + VCHIQ_SLOT_QUEUE_MASK] = + SLOT_INDEX_FROM_INFO(state, slot_info); + state->remote->slot_queue_recycle = slot_queue_recycle + 1; + vchiq_log_info(vchiq_core_log_level, + "%d: release_slot %d - recycle->%x", + state->id, SLOT_INDEX_FROM_INFO(state, slot_info), + state->remote->slot_queue_recycle); + + /* A write barrier is necessary, but remote_event_signal + ** contains one. */ + remote_event_signal(&state->remote->recycle); + } + + mutex_unlock(&state->recycle_mutex); +} + +/* Called by the slot handler - don't hold the bulk mutex */ +static VCHIQ_STATUS_T +notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, + int retry_poll) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + vchiq_log_trace(vchiq_core_log_level, + "%d: nb:%d %cx - p=%x rn=%x r=%x", + service->state->id, service->localport, + (queue == &service->bulk_tx) ? 't' : 'r', + queue->process, queue->remote_notify, queue->remove); + + if (service->state->is_master) { + while (queue->remote_notify != queue->process) { + VCHIQ_BULK_T *bulk = + &queue->bulks[BULK_INDEX(queue->remote_notify)]; + int msgtype = (bulk->dir == VCHIQ_BULK_TRANSMIT) ? + VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE; + int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport, + service->remoteport); + VCHIQ_ELEMENT_T element = { &bulk->actual, 4 }; + /* Only reply to non-dummy bulk requests */ + if (bulk->remote_data) { + status = queue_message(service->state, NULL, + msgid, &element, 1, 4, 0); + if (status != VCHIQ_SUCCESS) + break; + } + queue->remote_notify++; + } + } else { + queue->remote_notify = queue->process; + } + + if (status == VCHIQ_SUCCESS) { + while (queue->remove != queue->remote_notify) { + VCHIQ_BULK_T *bulk = + &queue->bulks[BULK_INDEX(queue->remove)]; + + /* Only generate callbacks for non-dummy bulk + ** requests, and non-terminated services */ + if (bulk->data && service->instance) { + if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) { + if (bulk->dir == VCHIQ_BULK_TRANSMIT) { + VCHIQ_SERVICE_STATS_INC(service, + bulk_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, + bulk_tx_bytes, + bulk->actual); + } else { + VCHIQ_SERVICE_STATS_INC(service, + bulk_rx_count); + VCHIQ_SERVICE_STATS_ADD(service, + bulk_rx_bytes, + bulk->actual); + } + } else { + VCHIQ_SERVICE_STATS_INC(service, + bulk_aborted_count); + } + if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) { + struct bulk_waiter *waiter; + spin_lock(&bulk_waiter_spinlock); + waiter = bulk->userdata; + if (waiter) { + waiter->actual = bulk->actual; + up(&waiter->event); + } + spin_unlock(&bulk_waiter_spinlock); + } else if (bulk->mode == + VCHIQ_BULK_MODE_CALLBACK) { + VCHIQ_REASON_T reason = (bulk->dir == + VCHIQ_BULK_TRANSMIT) ? + ((bulk->actual == + VCHIQ_BULK_ACTUAL_ABORTED) ? + VCHIQ_BULK_TRANSMIT_ABORTED : + VCHIQ_BULK_TRANSMIT_DONE) : + ((bulk->actual == + VCHIQ_BULK_ACTUAL_ABORTED) ? + VCHIQ_BULK_RECEIVE_ABORTED : + VCHIQ_BULK_RECEIVE_DONE); + status = make_service_callback(service, + reason, NULL, bulk->userdata); + if (status == VCHIQ_RETRY) + break; + } + } + + queue->remove++; + up(&service->bulk_remove_event); + } + if (!retry_poll) + status = VCHIQ_SUCCESS; + } + + if (status == VCHIQ_RETRY) + request_poll(service->state, service, + (queue == &service->bulk_tx) ? + VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); + + return status; +} + +/* Called by the slot handler thread */ +static void +poll_services(VCHIQ_STATE_T *state) +{ + int group, i; + + for (group = 0; group < BITSET_SIZE(state->unused_service); group++) { + uint32_t flags; + flags = atomic_xchg(&state->poll_services[group], 0); + for (i = 0; flags; i++) { + if (flags & (1 << i)) { + VCHIQ_SERVICE_T *service = + find_service_by_port(state, + (group<<5) + i); + uint32_t service_flags; + flags &= ~(1 << i); + if (!service) + continue; + service_flags = + atomic_xchg(&service->poll_flags, 0); + if (service_flags & + (1 << VCHIQ_POLL_REMOVE)) { + vchiq_log_info(vchiq_core_log_level, + "%d: ps - remove %d<->%d", + state->id, service->localport, + service->remoteport); + + /* Make it look like a client, because + it must be removed and not left in + the LISTENING state. */ + service->public_fourcc = + VCHIQ_FOURCC_INVALID; + + if (vchiq_close_service_internal( + service, 0/*!close_recvd*/) != + VCHIQ_SUCCESS) + request_poll(state, service, + VCHIQ_POLL_REMOVE); + } else if (service_flags & + (1 << VCHIQ_POLL_TERMINATE)) { + vchiq_log_info(vchiq_core_log_level, + "%d: ps - terminate %d<->%d", + state->id, service->localport, + service->remoteport); + if (vchiq_close_service_internal( + service, 0/*!close_recvd*/) != + VCHIQ_SUCCESS) + request_poll(state, service, + VCHIQ_POLL_TERMINATE); + } + if (service_flags & (1 << VCHIQ_POLL_TXNOTIFY)) + notify_bulks(service, + &service->bulk_tx, + 1/*retry_poll*/); + if (service_flags & (1 << VCHIQ_POLL_RXNOTIFY)) + notify_bulks(service, + &service->bulk_rx, + 1/*retry_poll*/); + unlock_service(service); + } + } + } +} + +/* Called by the slot handler or application threads, holding the bulk mutex. */ +static int +resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) +{ + VCHIQ_STATE_T *state = service->state; + int resolved = 0; + int rc; + + while ((queue->process != queue->local_insert) && + (queue->process != queue->remote_insert)) { + VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; + + vchiq_log_trace(vchiq_core_log_level, + "%d: rb:%d %cx - li=%x ri=%x p=%x", + state->id, service->localport, + (queue == &service->bulk_tx) ? 't' : 'r', + queue->local_insert, queue->remote_insert, + queue->process); + + WARN_ON(!((int)(queue->local_insert - queue->process) > 0)); + WARN_ON(!((int)(queue->remote_insert - queue->process) > 0)); + + rc = mutex_lock_interruptible(&state->bulk_transfer_mutex); + if (rc != 0) + break; + + vchiq_transfer_bulk(bulk); + mutex_unlock(&state->bulk_transfer_mutex); + + if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { + const char *header = (queue == &service->bulk_tx) ? + "Send Bulk to" : "Recv Bulk from"; + if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) + vchiq_log_info(SRVTRACE_LEVEL(service), + "%s %c%c%c%c d:%d len:%d %x<->%x", + header, + VCHIQ_FOURCC_AS_4CHARS( + service->base.fourcc), + service->remoteport, + bulk->size, + (unsigned int)bulk->data, + (unsigned int)bulk->remote_data); + else + vchiq_log_info(SRVTRACE_LEVEL(service), + "%s %c%c%c%c d:%d ABORTED - tx len:%d," + " rx len:%d %x<->%x", + header, + VCHIQ_FOURCC_AS_4CHARS( + service->base.fourcc), + service->remoteport, + bulk->size, + bulk->remote_size, + (unsigned int)bulk->data, + (unsigned int)bulk->remote_data); + } + + vchiq_complete_bulk(bulk); + queue->process++; + resolved++; + } + return resolved; +} + +/* Called with the bulk_mutex held */ +static void +abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) +{ + int is_tx = (queue == &service->bulk_tx); + vchiq_log_trace(vchiq_core_log_level, + "%d: aob:%d %cx - li=%x ri=%x p=%x", + service->state->id, service->localport, is_tx ? 't' : 'r', + queue->local_insert, queue->remote_insert, queue->process); + + WARN_ON(!((int)(queue->local_insert - queue->process) >= 0)); + WARN_ON(!((int)(queue->remote_insert - queue->process) >= 0)); + + while ((queue->process != queue->local_insert) || + (queue->process != queue->remote_insert)) { + VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; + + if (queue->process == queue->remote_insert) { + /* fabricate a matching dummy bulk */ + bulk->remote_data = NULL; + bulk->remote_size = 0; + queue->remote_insert++; + } + + if (queue->process != queue->local_insert) { + vchiq_complete_bulk(bulk); + + vchiq_log_info(SRVTRACE_LEVEL(service), + "%s %c%c%c%c d:%d ABORTED - tx len:%d, " + "rx len:%d", + is_tx ? "Send Bulk to" : "Recv Bulk from", + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->remoteport, + bulk->size, + bulk->remote_size); + } else { + /* fabricate a matching dummy bulk */ + bulk->data = NULL; + bulk->size = 0; + bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; + bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT : + VCHIQ_BULK_RECEIVE; + queue->local_insert++; + } + + queue->process++; + } +} + +/* Called from the slot handler thread */ +static void +pause_bulks(VCHIQ_STATE_T *state) +{ + if (unlikely(atomic_inc_return(&pause_bulks_count) != 1)) { + WARN_ON_ONCE(1); + atomic_set(&pause_bulks_count, 1); + return; + } + + /* Block bulk transfers from all services */ + mutex_lock(&state->bulk_transfer_mutex); +} + +/* Called from the slot handler thread */ +static void +resume_bulks(VCHIQ_STATE_T *state) +{ + int i; + if (unlikely(atomic_dec_return(&pause_bulks_count) != 0)) { + WARN_ON_ONCE(1); + atomic_set(&pause_bulks_count, 0); + return; + } + + /* Allow bulk transfers from all services */ + mutex_unlock(&state->bulk_transfer_mutex); + + if (state->deferred_bulks == 0) + return; + + /* Deal with any bulks which had to be deferred due to being in + * paused state. Don't try to match up to number of deferred bulks + * in case we've had something come and close the service in the + * interim - just process all bulk queues for all services */ + vchiq_log_info(vchiq_core_log_level, "%s: processing %d deferred bulks", + __func__, state->deferred_bulks); + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + int resolved_rx = 0; + int resolved_tx = 0; + if (!service || (service->srvstate != VCHIQ_SRVSTATE_OPEN)) + continue; + + mutex_lock(&service->bulk_mutex); + resolved_rx = resolve_bulks(service, &service->bulk_rx); + resolved_tx = resolve_bulks(service, &service->bulk_tx); + mutex_unlock(&service->bulk_mutex); + if (resolved_rx) + notify_bulks(service, &service->bulk_rx, 1); + if (resolved_tx) + notify_bulks(service, &service->bulk_tx, 1); + } + state->deferred_bulks = 0; +} + +static int +parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) +{ + VCHIQ_SERVICE_T *service = NULL; + int msgid, size; + int type; + unsigned int localport, remoteport; + + msgid = header->msgid; + size = header->size; + type = VCHIQ_MSG_TYPE(msgid); + localport = VCHIQ_MSG_DSTPORT(msgid); + remoteport = VCHIQ_MSG_SRCPORT(msgid); + if (size >= sizeof(struct vchiq_open_payload)) { + const struct vchiq_open_payload *payload = + (struct vchiq_open_payload *)header->data; + unsigned int fourcc; + + fourcc = payload->fourcc; + vchiq_log_info(vchiq_core_log_level, + "%d: prs OPEN@%x (%d->'%c%c%c%c')", + state->id, (unsigned int)header, + localport, + VCHIQ_FOURCC_AS_4CHARS(fourcc)); + + service = get_listening_service(state, fourcc); + + if (service) { + /* A matching service exists */ + short version = payload->version; + short version_min = payload->version_min; + if ((service->version < version_min) || + (version < service->version_min)) { + /* Version mismatch */ + vchiq_loud_error_header(); + vchiq_loud_error("%d: service %d (%c%c%c%c) " + "version mismatch - local (%d, min %d)" + " vs. remote (%d, min %d)", + state->id, service->localport, + VCHIQ_FOURCC_AS_4CHARS(fourcc), + service->version, service->version_min, + version, version_min); + vchiq_loud_error_footer(); + unlock_service(service); + service = NULL; + goto fail_open; + } + service->peer_version = version; + + if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { + struct vchiq_openack_payload ack_payload = { + service->version + }; + VCHIQ_ELEMENT_T body = { + &ack_payload, + sizeof(ack_payload) + }; + + if (state->version_common < + VCHIQ_VERSION_SYNCHRONOUS_MODE) + service->sync = 0; + + /* Acknowledge the OPEN */ + if (service->sync && + (state->version_common >= + VCHIQ_VERSION_SYNCHRONOUS_MODE)) { + if (queue_message_sync(state, NULL, + VCHIQ_MAKE_MSG( + VCHIQ_MSG_OPENACK, + service->localport, + remoteport), + &body, 1, sizeof(ack_payload), + 0) == VCHIQ_RETRY) + goto bail_not_ready; + } else { + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG( + VCHIQ_MSG_OPENACK, + service->localport, + remoteport), + &body, 1, sizeof(ack_payload), + 0) == VCHIQ_RETRY) + goto bail_not_ready; + } + + /* The service is now open */ + vchiq_set_service_state(service, + service->sync ? VCHIQ_SRVSTATE_OPENSYNC + : VCHIQ_SRVSTATE_OPEN); + } + + service->remoteport = remoteport; + service->client_id = ((int *)header->data)[1]; + if (make_service_callback(service, VCHIQ_SERVICE_OPENED, + NULL, NULL) == VCHIQ_RETRY) { + /* Bail out if not ready */ + service->remoteport = VCHIQ_PORT_FREE; + goto bail_not_ready; + } + + /* Success - the message has been dealt with */ + unlock_service(service); + return 1; + } + } + +fail_open: + /* No available service, or an invalid request - send a CLOSE */ + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, 0, VCHIQ_MSG_SRCPORT(msgid)), + NULL, 0, 0, 0) == VCHIQ_RETRY) + goto bail_not_ready; + + return 1; + +bail_not_ready: + if (service) + unlock_service(service); + + return 0; +} + +/* Called by the slot handler thread */ +static void +parse_rx_slots(VCHIQ_STATE_T *state) +{ + VCHIQ_SHARED_STATE_T *remote = state->remote; + VCHIQ_SERVICE_T *service = NULL; + int tx_pos; + DEBUG_INITIALISE(state->local) + + tx_pos = remote->tx_pos; + + while (state->rx_pos != tx_pos) { + VCHIQ_HEADER_T *header; + int msgid, size; + int type; + unsigned int localport, remoteport; + + DEBUG_TRACE(PARSE_LINE); + if (!state->rx_data) { + int rx_index; + WARN_ON(!((state->rx_pos & VCHIQ_SLOT_MASK) == 0)); + rx_index = remote->slot_queue[ + SLOT_QUEUE_INDEX_FROM_POS(state->rx_pos) & + VCHIQ_SLOT_QUEUE_MASK]; + state->rx_data = (char *)SLOT_DATA_FROM_INDEX(state, + rx_index); + state->rx_info = SLOT_INFO_FROM_INDEX(state, rx_index); + + /* Initialise use_count to one, and increment + ** release_count at the end of the slot to avoid + ** releasing the slot prematurely. */ + state->rx_info->use_count = 1; + state->rx_info->release_count = 0; + } + + header = (VCHIQ_HEADER_T *)(state->rx_data + + (state->rx_pos & VCHIQ_SLOT_MASK)); + DEBUG_VALUE(PARSE_HEADER, (int)header); + msgid = header->msgid; + DEBUG_VALUE(PARSE_MSGID, msgid); + size = header->size; + type = VCHIQ_MSG_TYPE(msgid); + localport = VCHIQ_MSG_DSTPORT(msgid); + remoteport = VCHIQ_MSG_SRCPORT(msgid); + + if (type != VCHIQ_MSG_DATA) + VCHIQ_STATS_INC(state, ctrl_rx_count); + + switch (type) { + case VCHIQ_MSG_OPENACK: + case VCHIQ_MSG_CLOSE: + case VCHIQ_MSG_DATA: + case VCHIQ_MSG_BULK_RX: + case VCHIQ_MSG_BULK_TX: + case VCHIQ_MSG_BULK_RX_DONE: + case VCHIQ_MSG_BULK_TX_DONE: + service = find_service_by_port(state, localport); + if ((!service || + ((service->remoteport != remoteport) && + (service->remoteport != VCHIQ_PORT_FREE))) && + (localport == 0) && + (type == VCHIQ_MSG_CLOSE)) { + /* This could be a CLOSE from a client which + hadn't yet received the OPENACK - look for + the connected service */ + if (service) + unlock_service(service); + service = get_connected_service(state, + remoteport); + if (service) + vchiq_log_warning(vchiq_core_log_level, + "%d: prs %s@%x (%d->%d) - " + "found connected service %d", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, + service->localport); + } + + if (!service) { + vchiq_log_error(vchiq_core_log_level, + "%d: prs %s@%x (%d->%d) - " + "invalid/closed service %d", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, localport); + goto skip_message; + } + break; + default: + break; + } + + if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { + int svc_fourcc; + + svc_fourcc = service + ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + vchiq_log_info(SRVTRACE_LEVEL(service), + "Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d " + "len:%d", + msg_type_str(type), type, + VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, + min(64, size)); + } + + if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) + > VCHIQ_SLOT_SIZE) { + vchiq_log_error(vchiq_core_log_level, + "header %x (msgid %x) - size %x too big for " + "slot", + (unsigned int)header, (unsigned int)msgid, + (unsigned int)size); + WARN(1, "oversized for slot\n"); + } + + switch (type) { + case VCHIQ_MSG_OPEN: + WARN_ON(!(VCHIQ_MSG_DSTPORT(msgid) == 0)); + if (!parse_open(state, header)) + goto bail_not_ready; + break; + case VCHIQ_MSG_OPENACK: + if (size >= sizeof(struct vchiq_openack_payload)) { + const struct vchiq_openack_payload *payload = + (struct vchiq_openack_payload *) + header->data; + service->peer_version = payload->version; + } + vchiq_log_info(vchiq_core_log_level, + "%d: prs OPENACK@%x,%x (%d->%d) v:%d", + state->id, (unsigned int)header, size, + remoteport, localport, service->peer_version); + if (service->srvstate == + VCHIQ_SRVSTATE_OPENING) { + service->remoteport = remoteport; + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_OPEN); + up(&service->remove_event); + } else + vchiq_log_error(vchiq_core_log_level, + "OPENACK received in state %s", + srvstate_names[service->srvstate]); + break; + case VCHIQ_MSG_CLOSE: + WARN_ON(size != 0); /* There should be no data */ + + vchiq_log_info(vchiq_core_log_level, + "%d: prs CLOSE@%x (%d->%d)", + state->id, (unsigned int)header, + remoteport, localport); + + mark_service_closing_internal(service, 1); + + if (vchiq_close_service_internal(service, + 1/*close_recvd*/) == VCHIQ_RETRY) + goto bail_not_ready; + + vchiq_log_info(vchiq_core_log_level, + "Close Service %c%c%c%c s:%u d:%d", + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->localport, + service->remoteport); + break; + case VCHIQ_MSG_DATA: + vchiq_log_info(vchiq_core_log_level, + "%d: prs DATA@%x,%x (%d->%d)", + state->id, (unsigned int)header, size, + remoteport, localport); + + if ((service->remoteport == remoteport) + && (service->srvstate == + VCHIQ_SRVSTATE_OPEN)) { + header->msgid = msgid | VCHIQ_MSGID_CLAIMED; + claim_slot(state->rx_info); + DEBUG_TRACE(PARSE_LINE); + if (make_service_callback(service, + VCHIQ_MESSAGE_AVAILABLE, header, + NULL) == VCHIQ_RETRY) { + DEBUG_TRACE(PARSE_LINE); + goto bail_not_ready; + } + VCHIQ_SERVICE_STATS_INC(service, ctrl_rx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_rx_bytes, + size); + } else { + VCHIQ_STATS_INC(state, error_count); + } + break; + case VCHIQ_MSG_CONNECT: + vchiq_log_info(vchiq_core_log_level, + "%d: prs CONNECT@%x", + state->id, (unsigned int)header); + state->version_common = ((VCHIQ_SLOT_ZERO_T *) + state->slot_data)->version; + up(&state->connect); + break; + case VCHIQ_MSG_BULK_RX: + case VCHIQ_MSG_BULK_TX: { + VCHIQ_BULK_QUEUE_T *queue; + WARN_ON(!state->is_master); + queue = (type == VCHIQ_MSG_BULK_RX) ? + &service->bulk_tx : &service->bulk_rx; + if ((service->remoteport == remoteport) + && (service->srvstate == + VCHIQ_SRVSTATE_OPEN)) { + VCHIQ_BULK_T *bulk; + int resolved = 0; + + DEBUG_TRACE(PARSE_LINE); + if (mutex_lock_interruptible( + &service->bulk_mutex) != 0) { + DEBUG_TRACE(PARSE_LINE); + goto bail_not_ready; + } + + WARN_ON(!(queue->remote_insert < queue->remove + + VCHIQ_NUM_SERVICE_BULKS)); + bulk = &queue->bulks[ + BULK_INDEX(queue->remote_insert)]; + bulk->remote_data = + (void *)((int *)header->data)[0]; + bulk->remote_size = ((int *)header->data)[1]; + wmb(); + + vchiq_log_info(vchiq_core_log_level, + "%d: prs %s@%x (%d->%d) %x@%x", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, + bulk->remote_size, + (unsigned int)bulk->remote_data); + + queue->remote_insert++; + + if (atomic_read(&pause_bulks_count)) { + state->deferred_bulks++; + vchiq_log_info(vchiq_core_log_level, + "%s: deferring bulk (%d)", + __func__, + state->deferred_bulks); + if (state->conn_state != + VCHIQ_CONNSTATE_PAUSE_SENT) + vchiq_log_error( + vchiq_core_log_level, + "%s: bulks paused in " + "unexpected state %s", + __func__, + conn_state_names[ + state->conn_state]); + } else if (state->conn_state == + VCHIQ_CONNSTATE_CONNECTED) { + DEBUG_TRACE(PARSE_LINE); + resolved = resolve_bulks(service, + queue); + } + + mutex_unlock(&service->bulk_mutex); + if (resolved) + notify_bulks(service, queue, + 1/*retry_poll*/); + } + } break; + case VCHIQ_MSG_BULK_RX_DONE: + case VCHIQ_MSG_BULK_TX_DONE: + WARN_ON(state->is_master); + if ((service->remoteport == remoteport) + && (service->srvstate != + VCHIQ_SRVSTATE_FREE)) { + VCHIQ_BULK_QUEUE_T *queue; + VCHIQ_BULK_T *bulk; + + queue = (type == VCHIQ_MSG_BULK_RX_DONE) ? + &service->bulk_rx : &service->bulk_tx; + + DEBUG_TRACE(PARSE_LINE); + if (mutex_lock_interruptible( + &service->bulk_mutex) != 0) { + DEBUG_TRACE(PARSE_LINE); + goto bail_not_ready; + } + if ((int)(queue->remote_insert - + queue->local_insert) >= 0) { + vchiq_log_error(vchiq_core_log_level, + "%d: prs %s@%x (%d->%d) " + "unexpected (ri=%d,li=%d)", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, + queue->remote_insert, + queue->local_insert); + mutex_unlock(&service->bulk_mutex); + break; + } + + BUG_ON(queue->process == queue->local_insert); + BUG_ON(queue->process != queue->remote_insert); + + bulk = &queue->bulks[ + BULK_INDEX(queue->remote_insert)]; + bulk->actual = *(int *)header->data; + queue->remote_insert++; + + vchiq_log_info(vchiq_core_log_level, + "%d: prs %s@%x (%d->%d) %x@%x", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, + bulk->actual, (unsigned int)bulk->data); + + vchiq_log_trace(vchiq_core_log_level, + "%d: prs:%d %cx li=%x ri=%x p=%x", + state->id, localport, + (type == VCHIQ_MSG_BULK_RX_DONE) ? + 'r' : 't', + queue->local_insert, + queue->remote_insert, queue->process); + + DEBUG_TRACE(PARSE_LINE); + WARN_ON(queue->process == queue->local_insert); + vchiq_complete_bulk(bulk); + queue->process++; + mutex_unlock(&service->bulk_mutex); + DEBUG_TRACE(PARSE_LINE); + notify_bulks(service, queue, 1/*retry_poll*/); + DEBUG_TRACE(PARSE_LINE); + } + break; + case VCHIQ_MSG_PADDING: + vchiq_log_trace(vchiq_core_log_level, + "%d: prs PADDING@%x,%x", + state->id, (unsigned int)header, size); + break; + case VCHIQ_MSG_PAUSE: + /* If initiated, signal the application thread */ + vchiq_log_trace(vchiq_core_log_level, + "%d: prs PAUSE@%x,%x", + state->id, (unsigned int)header, size); + if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { + vchiq_log_error(vchiq_core_log_level, + "%d: PAUSE received in state PAUSED", + state->id); + break; + } + if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) { + /* Send a PAUSE in response */ + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), + NULL, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK) + == VCHIQ_RETRY) + goto bail_not_ready; + if (state->is_master) + pause_bulks(state); + } + /* At this point slot_mutex is held */ + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); + vchiq_platform_paused(state); + break; + case VCHIQ_MSG_RESUME: + vchiq_log_trace(vchiq_core_log_level, + "%d: prs RESUME@%x,%x", + state->id, (unsigned int)header, size); + /* Release the slot mutex */ + mutex_unlock(&state->slot_mutex); + if (state->is_master) + resume_bulks(state); + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); + vchiq_platform_resumed(state); + break; + + case VCHIQ_MSG_REMOTE_USE: + vchiq_on_remote_use(state); + break; + case VCHIQ_MSG_REMOTE_RELEASE: + vchiq_on_remote_release(state); + break; + case VCHIQ_MSG_REMOTE_USE_ACTIVE: + vchiq_on_remote_use_active(state); + break; + + default: + vchiq_log_error(vchiq_core_log_level, + "%d: prs invalid msgid %x@%x,%x", + state->id, msgid, (unsigned int)header, size); + WARN(1, "invalid message\n"); + break; + } + +skip_message: + if (service) { + unlock_service(service); + service = NULL; + } + + state->rx_pos += calc_stride(size); + + DEBUG_TRACE(PARSE_LINE); + /* Perform some housekeeping when the end of the slot is + ** reached. */ + if ((state->rx_pos & VCHIQ_SLOT_MASK) == 0) { + /* Remove the extra reference count. */ + release_slot(state, state->rx_info, NULL, NULL); + state->rx_data = NULL; + } + } + +bail_not_ready: + if (service) + unlock_service(service); +} + +/* Called by the slot handler thread */ +static int +slot_handler_func(void *v) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; + VCHIQ_SHARED_STATE_T *local = state->local; + DEBUG_INITIALISE(local) + + while (1) { + DEBUG_COUNT(SLOT_HANDLER_COUNT); + DEBUG_TRACE(SLOT_HANDLER_LINE); + remote_event_wait(&local->trigger); + + rmb(); + + DEBUG_TRACE(SLOT_HANDLER_LINE); + if (state->poll_needed) { + /* Check if we need to suspend - may change our + * conn_state */ + vchiq_platform_check_suspend(state); + + state->poll_needed = 0; + + /* Handle service polling and other rare conditions here + ** out of the mainline code */ + switch (state->conn_state) { + case VCHIQ_CONNSTATE_CONNECTED: + /* Poll the services as requested */ + poll_services(state); + break; + + case VCHIQ_CONNSTATE_PAUSING: + if (state->is_master) + pause_bulks(state); + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), + NULL, 0, 0, + QMFLAGS_NO_MUTEX_UNLOCK) + != VCHIQ_RETRY) { + vchiq_set_conn_state(state, + VCHIQ_CONNSTATE_PAUSE_SENT); + } else { + if (state->is_master) + resume_bulks(state); + /* Retry later */ + state->poll_needed = 1; + } + break; + + case VCHIQ_CONNSTATE_PAUSED: + vchiq_platform_resume(state); + break; + + case VCHIQ_CONNSTATE_RESUMING: + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0), + NULL, 0, 0, QMFLAGS_NO_MUTEX_LOCK) + != VCHIQ_RETRY) { + if (state->is_master) + resume_bulks(state); + vchiq_set_conn_state(state, + VCHIQ_CONNSTATE_CONNECTED); + vchiq_platform_resumed(state); + } else { + /* This should really be impossible, + ** since the PAUSE should have flushed + ** through outstanding messages. */ + vchiq_log_error(vchiq_core_log_level, + "Failed to send RESUME " + "message"); + BUG(); + } + break; + + case VCHIQ_CONNSTATE_PAUSE_TIMEOUT: + case VCHIQ_CONNSTATE_RESUME_TIMEOUT: + vchiq_platform_handle_timeout(state); + break; + default: + break; + } + + + } + + DEBUG_TRACE(SLOT_HANDLER_LINE); + parse_rx_slots(state); + } + return 0; +} + + +/* Called by the recycle thread */ +static int +recycle_func(void *v) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; + VCHIQ_SHARED_STATE_T *local = state->local; + + while (1) { + remote_event_wait(&local->recycle); + + process_free_queue(state); + } + return 0; +} + + +/* Called by the sync thread */ +static int +sync_func(void *v) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; + VCHIQ_SHARED_STATE_T *local = state->local; + VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, + state->remote->slot_sync); + + while (1) { + VCHIQ_SERVICE_T *service; + int msgid, size; + int type; + unsigned int localport, remoteport; + + remote_event_wait(&local->sync_trigger); + + rmb(); + + msgid = header->msgid; + size = header->size; + type = VCHIQ_MSG_TYPE(msgid); + localport = VCHIQ_MSG_DSTPORT(msgid); + remoteport = VCHIQ_MSG_SRCPORT(msgid); + + service = find_service_by_port(state, localport); + + if (!service) { + vchiq_log_error(vchiq_sync_log_level, + "%d: sf %s@%x (%d->%d) - " + "invalid/closed service %d", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, localport); + release_message_sync(state, header); + continue; + } + + if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) { + int svc_fourcc; + + svc_fourcc = service + ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + vchiq_log_trace(vchiq_sync_log_level, + "Rcvd Msg %s from %c%c%c%c s:%d d:%d len:%d", + msg_type_str(type), + VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, + min(64, size)); + } + + switch (type) { + case VCHIQ_MSG_OPENACK: + if (size >= sizeof(struct vchiq_openack_payload)) { + const struct vchiq_openack_payload *payload = + (struct vchiq_openack_payload *) + header->data; + service->peer_version = payload->version; + } + vchiq_log_info(vchiq_sync_log_level, + "%d: sf OPENACK@%x,%x (%d->%d) v:%d", + state->id, (unsigned int)header, size, + remoteport, localport, service->peer_version); + if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { + service->remoteport = remoteport; + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_OPENSYNC); + service->sync = 1; + up(&service->remove_event); + } + release_message_sync(state, header); + break; + + case VCHIQ_MSG_DATA: + vchiq_log_trace(vchiq_sync_log_level, + "%d: sf DATA@%x,%x (%d->%d)", + state->id, (unsigned int)header, size, + remoteport, localport); + + if ((service->remoteport == remoteport) && + (service->srvstate == + VCHIQ_SRVSTATE_OPENSYNC)) { + if (make_service_callback(service, + VCHIQ_MESSAGE_AVAILABLE, header, + NULL) == VCHIQ_RETRY) + vchiq_log_error(vchiq_sync_log_level, + "synchronous callback to " + "service %d returns " + "VCHIQ_RETRY", + localport); + } + break; + + default: + vchiq_log_error(vchiq_sync_log_level, + "%d: sf unexpected msgid %x@%x,%x", + state->id, msgid, (unsigned int)header, size); + release_message_sync(state, header); + break; + } + + unlock_service(service); + } + + return 0; +} + + +static void +init_bulk_queue(VCHIQ_BULK_QUEUE_T *queue) +{ + queue->local_insert = 0; + queue->remote_insert = 0; + queue->process = 0; + queue->remote_notify = 0; + queue->remove = 0; +} + + +inline const char * +get_conn_state_name(VCHIQ_CONNSTATE_T conn_state) +{ + return conn_state_names[conn_state]; +} + + +VCHIQ_SLOT_ZERO_T * +vchiq_init_slots(void *mem_base, int mem_size) +{ + int mem_align = (VCHIQ_SLOT_SIZE - (int)mem_base) & VCHIQ_SLOT_MASK; + VCHIQ_SLOT_ZERO_T *slot_zero = + (VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align); + int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE; + int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS; + + /* Ensure there is enough memory to run an absolutely minimum system */ + num_slots -= first_data_slot; + + if (num_slots < 4) { + vchiq_log_error(vchiq_core_log_level, + "vchiq_init_slots - insufficient memory %x bytes", + mem_size); + return NULL; + } + + memset(slot_zero, 0, sizeof(VCHIQ_SLOT_ZERO_T)); + + slot_zero->magic = VCHIQ_MAGIC; + slot_zero->version = VCHIQ_VERSION; + slot_zero->version_min = VCHIQ_VERSION_MIN; + slot_zero->slot_zero_size = sizeof(VCHIQ_SLOT_ZERO_T); + slot_zero->slot_size = VCHIQ_SLOT_SIZE; + slot_zero->max_slots = VCHIQ_MAX_SLOTS; + slot_zero->max_slots_per_side = VCHIQ_MAX_SLOTS_PER_SIDE; + + slot_zero->master.slot_sync = first_data_slot; + slot_zero->master.slot_first = first_data_slot + 1; + slot_zero->master.slot_last = first_data_slot + (num_slots/2) - 1; + slot_zero->slave.slot_sync = first_data_slot + (num_slots/2); + slot_zero->slave.slot_first = first_data_slot + (num_slots/2) + 1; + slot_zero->slave.slot_last = first_data_slot + num_slots - 1; + + return slot_zero; +} + +VCHIQ_STATUS_T +vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, + int is_master) +{ + VCHIQ_SHARED_STATE_T *local; + VCHIQ_SHARED_STATE_T *remote; + VCHIQ_STATUS_T status; + char threadname[10]; + static int id; + int i; + + vchiq_log_warning(vchiq_core_log_level, + "%s: slot_zero = 0x%08lx, is_master = %d", + __func__, (unsigned long)slot_zero, is_master); + + /* Check the input configuration */ + + if (slot_zero->magic != VCHIQ_MAGIC) { + vchiq_loud_error_header(); + vchiq_loud_error("Invalid VCHIQ magic value found."); + vchiq_loud_error("slot_zero=%x: magic=%x (expected %x)", + (unsigned int)slot_zero, slot_zero->magic, VCHIQ_MAGIC); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + if (slot_zero->version < VCHIQ_VERSION_MIN) { + vchiq_loud_error_header(); + vchiq_loud_error("Incompatible VCHIQ versions found."); + vchiq_loud_error("slot_zero=%x: VideoCore version=%d " + "(minimum %d)", + (unsigned int)slot_zero, slot_zero->version, + VCHIQ_VERSION_MIN); + vchiq_loud_error("Restart with a newer VideoCore image."); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + if (VCHIQ_VERSION < slot_zero->version_min) { + vchiq_loud_error_header(); + vchiq_loud_error("Incompatible VCHIQ versions found."); + vchiq_loud_error("slot_zero=%x: version=%d (VideoCore " + "minimum %d)", + (unsigned int)slot_zero, VCHIQ_VERSION, + slot_zero->version_min); + vchiq_loud_error("Restart with a newer kernel."); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + if ((slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) || + (slot_zero->slot_size != VCHIQ_SLOT_SIZE) || + (slot_zero->max_slots != VCHIQ_MAX_SLOTS) || + (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)) { + vchiq_loud_error_header(); + if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) + vchiq_loud_error("slot_zero=%x: slot_zero_size=%x " + "(expected %x)", + (unsigned int)slot_zero, + slot_zero->slot_zero_size, + sizeof(VCHIQ_SLOT_ZERO_T)); + if (slot_zero->slot_size != VCHIQ_SLOT_SIZE) + vchiq_loud_error("slot_zero=%x: slot_size=%d " + "(expected %d", + (unsigned int)slot_zero, slot_zero->slot_size, + VCHIQ_SLOT_SIZE); + if (slot_zero->max_slots != VCHIQ_MAX_SLOTS) + vchiq_loud_error("slot_zero=%x: max_slots=%d " + "(expected %d)", + (unsigned int)slot_zero, slot_zero->max_slots, + VCHIQ_MAX_SLOTS); + if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE) + vchiq_loud_error("slot_zero=%x: max_slots_per_side=%d " + "(expected %d)", + (unsigned int)slot_zero, + slot_zero->max_slots_per_side, + VCHIQ_MAX_SLOTS_PER_SIDE); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + if (VCHIQ_VERSION < slot_zero->version) + slot_zero->version = VCHIQ_VERSION; + + if (is_master) { + local = &slot_zero->master; + remote = &slot_zero->slave; + } else { + local = &slot_zero->slave; + remote = &slot_zero->master; + } + + if (local->initialised) { + vchiq_loud_error_header(); + if (remote->initialised) + vchiq_loud_error("local state has already been " + "initialised"); + else + vchiq_loud_error("master/slave mismatch - two %ss", + is_master ? "master" : "slave"); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + memset(state, 0, sizeof(VCHIQ_STATE_T)); + + state->id = id++; + state->is_master = is_master; + + /* + initialize shared state pointers + */ + + state->local = local; + state->remote = remote; + state->slot_data = (VCHIQ_SLOT_T *)slot_zero; + + /* + initialize events and mutexes + */ + + sema_init(&state->connect, 0); + mutex_init(&state->mutex); + sema_init(&state->trigger_event, 0); + sema_init(&state->recycle_event, 0); + sema_init(&state->sync_trigger_event, 0); + sema_init(&state->sync_release_event, 0); + + mutex_init(&state->slot_mutex); + mutex_init(&state->recycle_mutex); + mutex_init(&state->sync_mutex); + mutex_init(&state->bulk_transfer_mutex); + + sema_init(&state->slot_available_event, 0); + sema_init(&state->slot_remove_event, 0); + sema_init(&state->data_quota_event, 0); + + state->slot_queue_available = 0; + + for (i = 0; i < VCHIQ_MAX_SERVICES; i++) { + VCHIQ_SERVICE_QUOTA_T *service_quota = + &state->service_quotas[i]; + sema_init(&service_quota->quota_event, 0); + } + + for (i = local->slot_first; i <= local->slot_last; i++) { + local->slot_queue[state->slot_queue_available++] = i; + up(&state->slot_available_event); + } + + state->default_slot_quota = state->slot_queue_available/2; + state->default_message_quota = + min((unsigned short)(state->default_slot_quota * 256), + (unsigned short)~0); + + state->previous_data_index = -1; + state->data_use_count = 0; + state->data_quota = state->slot_queue_available - 1; + + local->trigger.event = &state->trigger_event; + remote_event_create(&local->trigger); + local->tx_pos = 0; + + local->recycle.event = &state->recycle_event; + remote_event_create(&local->recycle); + local->slot_queue_recycle = state->slot_queue_available; + + local->sync_trigger.event = &state->sync_trigger_event; + remote_event_create(&local->sync_trigger); + + local->sync_release.event = &state->sync_release_event; + remote_event_create(&local->sync_release); + + /* At start-of-day, the slot is empty and available */ + ((VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid + = VCHIQ_MSGID_PADDING; + remote_event_signal_local(&local->sync_release); + + local->debug[DEBUG_ENTRIES] = DEBUG_MAX; + + status = vchiq_platform_init_state(state); + + /* + bring up slot handler thread + */ + snprintf(threadname, sizeof(threadname), "VCHIQ-%d", state->id); + state->slot_handler_thread = kthread_create(&slot_handler_func, + (void *)state, + threadname); + + if (state->slot_handler_thread == NULL) { + vchiq_loud_error_header(); + vchiq_loud_error("couldn't create thread %s", threadname); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + set_user_nice(state->slot_handler_thread, -19); + wake_up_process(state->slot_handler_thread); + + snprintf(threadname, sizeof(threadname), "VCHIQr-%d", state->id); + state->recycle_thread = kthread_create(&recycle_func, + (void *)state, + threadname); + if (state->recycle_thread == NULL) { + vchiq_loud_error_header(); + vchiq_loud_error("couldn't create thread %s", threadname); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + set_user_nice(state->recycle_thread, -19); + wake_up_process(state->recycle_thread); + + snprintf(threadname, sizeof(threadname), "VCHIQs-%d", state->id); + state->sync_thread = kthread_create(&sync_func, + (void *)state, + threadname); + if (state->sync_thread == NULL) { + vchiq_loud_error_header(); + vchiq_loud_error("couldn't create thread %s", threadname); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + set_user_nice(state->sync_thread, -20); + wake_up_process(state->sync_thread); + + BUG_ON(state->id >= VCHIQ_MAX_STATES); + vchiq_states[state->id] = state; + + /* Indicate readiness to the other side */ + local->initialised = 1; + + return status; +} + +/* Called from application thread when a client or server service is created. */ +VCHIQ_SERVICE_T * +vchiq_add_service_internal(VCHIQ_STATE_T *state, + const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, + VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term) +{ + VCHIQ_SERVICE_T *service; + + service = kmalloc(sizeof(VCHIQ_SERVICE_T), GFP_KERNEL); + if (service) { + service->base.fourcc = params->fourcc; + service->base.callback = params->callback; + service->base.userdata = params->userdata; + service->handle = VCHIQ_SERVICE_HANDLE_INVALID; + service->ref_count = 1; + service->srvstate = VCHIQ_SRVSTATE_FREE; + service->userdata_term = userdata_term; + service->localport = VCHIQ_PORT_FREE; + service->remoteport = VCHIQ_PORT_FREE; + + service->public_fourcc = (srvstate == VCHIQ_SRVSTATE_OPENING) ? + VCHIQ_FOURCC_INVALID : params->fourcc; + service->client_id = 0; + service->auto_close = 1; + service->sync = 0; + service->closing = 0; + service->trace = 0; + atomic_set(&service->poll_flags, 0); + service->version = params->version; + service->version_min = params->version_min; + service->state = state; + service->instance = instance; + service->service_use_count = 0; + init_bulk_queue(&service->bulk_tx); + init_bulk_queue(&service->bulk_rx); + sema_init(&service->remove_event, 0); + sema_init(&service->bulk_remove_event, 0); + mutex_init(&service->bulk_mutex); + memset(&service->stats, 0, sizeof(service->stats)); + } else { + vchiq_log_error(vchiq_core_log_level, + "Out of memory"); + } + + if (service) { + VCHIQ_SERVICE_T **pservice = NULL; + int i; + + /* Although it is perfectly possible to use service_spinlock + ** to protect the creation of services, it is overkill as it + ** disables interrupts while the array is searched. + ** The only danger is of another thread trying to create a + ** service - service deletion is safe. + ** Therefore it is preferable to use state->mutex which, + ** although slower to claim, doesn't block interrupts while + ** it is held. + */ + + mutex_lock(&state->mutex); + + /* Prepare to use a previously unused service */ + if (state->unused_service < VCHIQ_MAX_SERVICES) + pservice = &state->services[state->unused_service]; + + if (srvstate == VCHIQ_SRVSTATE_OPENING) { + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *srv = state->services[i]; + if (!srv) { + pservice = &state->services[i]; + break; + } + } + } else { + for (i = (state->unused_service - 1); i >= 0; i--) { + VCHIQ_SERVICE_T *srv = state->services[i]; + if (!srv) + pservice = &state->services[i]; + else if ((srv->public_fourcc == params->fourcc) + && ((srv->instance != instance) || + (srv->base.callback != + params->callback))) { + /* There is another server using this + ** fourcc which doesn't match. */ + pservice = NULL; + break; + } + } + } + + if (pservice) { + service->localport = (pservice - state->services); + if (!handle_seq) + handle_seq = VCHIQ_MAX_STATES * + VCHIQ_MAX_SERVICES; + service->handle = handle_seq | + (state->id * VCHIQ_MAX_SERVICES) | + service->localport; + handle_seq += VCHIQ_MAX_STATES * VCHIQ_MAX_SERVICES; + *pservice = service; + if (pservice == &state->services[state->unused_service]) + state->unused_service++; + } + + mutex_unlock(&state->mutex); + + if (!pservice) { + kfree(service); + service = NULL; + } + } + + if (service) { + VCHIQ_SERVICE_QUOTA_T *service_quota = + &state->service_quotas[service->localport]; + service_quota->slot_quota = state->default_slot_quota; + service_quota->message_quota = state->default_message_quota; + if (service_quota->slot_use_count == 0) + service_quota->previous_tx_index = + SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos) + - 1; + + /* Bring this service online */ + vchiq_set_service_state(service, srvstate); + + vchiq_log_info(vchiq_core_msg_log_level, + "%s Service %c%c%c%c SrcPort:%d", + (srvstate == VCHIQ_SRVSTATE_OPENING) + ? "Open" : "Add", + VCHIQ_FOURCC_AS_4CHARS(params->fourcc), + service->localport); + } + + /* Don't unlock the service - leave it with a ref_count of 1. */ + + return service; +} + +VCHIQ_STATUS_T +vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) +{ + struct vchiq_open_payload payload = { + service->base.fourcc, + client_id, + service->version, + service->version_min + }; + VCHIQ_ELEMENT_T body = { &payload, sizeof(payload) }; + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + service->client_id = client_id; + vchiq_use_service_internal(service); + status = queue_message(service->state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0), + &body, 1, sizeof(payload), QMFLAGS_IS_BLOCKING); + if (status == VCHIQ_SUCCESS) { + /* Wait for the ACK/NAK */ + if (down_interruptible(&service->remove_event) != 0) { + status = VCHIQ_RETRY; + vchiq_release_service_internal(service); + } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) && + (service->srvstate != VCHIQ_SRVSTATE_OPENSYNC)) { + if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) + vchiq_log_error(vchiq_core_log_level, + "%d: osi - srvstate = %s (ref %d)", + service->state->id, + srvstate_names[service->srvstate], + service->ref_count); + status = VCHIQ_ERROR; + VCHIQ_SERVICE_STATS_INC(service, error_count); + vchiq_release_service_internal(service); + } + } + return status; +} + +static void +release_service_messages(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATE_T *state = service->state; + int slot_last = state->remote->slot_last; + int i; + + /* Release any claimed messages aimed at this service */ + + if (service->sync) { + VCHIQ_HEADER_T *header = + (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, + state->remote->slot_sync); + if (VCHIQ_MSG_DSTPORT(header->msgid) == service->localport) + release_message_sync(state, header); + + return; + } + + for (i = state->remote->slot_first; i <= slot_last; i++) { + VCHIQ_SLOT_INFO_T *slot_info = + SLOT_INFO_FROM_INDEX(state, i); + if (slot_info->release_count != slot_info->use_count) { + char *data = + (char *)SLOT_DATA_FROM_INDEX(state, i); + unsigned int pos, end; + + end = VCHIQ_SLOT_SIZE; + if (data == state->rx_data) + /* This buffer is still being read from - stop + ** at the current read position */ + end = state->rx_pos & VCHIQ_SLOT_MASK; + + pos = 0; + + while (pos < end) { + VCHIQ_HEADER_T *header = + (VCHIQ_HEADER_T *)(data + pos); + int msgid = header->msgid; + int port = VCHIQ_MSG_DSTPORT(msgid); + if ((port == service->localport) && + (msgid & VCHIQ_MSGID_CLAIMED)) { + vchiq_log_info(vchiq_core_log_level, + " fsi - hdr %x", + (unsigned int)header); + release_slot(state, slot_info, header, + NULL); + } + pos += calc_stride(header->size); + if (pos > VCHIQ_SLOT_SIZE) { + vchiq_log_error(vchiq_core_log_level, + "fsi - pos %x: header %x, " + "msgid %x, header->msgid %x, " + "header->size %x", + pos, (unsigned int)header, + msgid, header->msgid, + header->size); + WARN(1, "invalid slot position\n"); + } + } + } + } +} + +static int +do_abort_bulks(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATUS_T status; + + /* Abort any outstanding bulk transfers */ + if (mutex_lock_interruptible(&service->bulk_mutex) != 0) + return 0; + abort_outstanding_bulks(service, &service->bulk_tx); + abort_outstanding_bulks(service, &service->bulk_rx); + mutex_unlock(&service->bulk_mutex); + + status = notify_bulks(service, &service->bulk_tx, 0/*!retry_poll*/); + if (status == VCHIQ_SUCCESS) + status = notify_bulks(service, &service->bulk_rx, + 0/*!retry_poll*/); + return (status == VCHIQ_SUCCESS); +} + +static VCHIQ_STATUS_T +close_service_complete(VCHIQ_SERVICE_T *service, int failstate) +{ + VCHIQ_STATUS_T status; + int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); + int newstate; + + switch (service->srvstate) { + case VCHIQ_SRVSTATE_OPEN: + case VCHIQ_SRVSTATE_CLOSESENT: + case VCHIQ_SRVSTATE_CLOSERECVD: + if (is_server) { + if (service->auto_close) { + service->client_id = 0; + service->remoteport = VCHIQ_PORT_FREE; + newstate = VCHIQ_SRVSTATE_LISTENING; + } else + newstate = VCHIQ_SRVSTATE_CLOSEWAIT; + } else + newstate = VCHIQ_SRVSTATE_CLOSED; + vchiq_set_service_state(service, newstate); + break; + case VCHIQ_SRVSTATE_LISTENING: + break; + default: + vchiq_log_error(vchiq_core_log_level, + "close_service_complete(%x) called in state %s", + service->handle, srvstate_names[service->srvstate]); + WARN(1, "close_service_complete in unexpected state\n"); + return VCHIQ_ERROR; + } + + status = make_service_callback(service, + VCHIQ_SERVICE_CLOSED, NULL, NULL); + + if (status != VCHIQ_RETRY) { + int uc = service->service_use_count; + int i; + /* Complete the close process */ + for (i = 0; i < uc; i++) + /* cater for cases where close is forced and the + ** client may not close all it's handles */ + vchiq_release_service_internal(service); + + service->client_id = 0; + service->remoteport = VCHIQ_PORT_FREE; + + if (service->srvstate == VCHIQ_SRVSTATE_CLOSED) + vchiq_free_service_internal(service); + else if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) { + if (is_server) + service->closing = 0; + + up(&service->remove_event); + } + } else + vchiq_set_service_state(service, failstate); + + return status; +} + +/* Called by the slot handler */ +VCHIQ_STATUS_T +vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) +{ + VCHIQ_STATE_T *state = service->state; + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); + + vchiq_log_info(vchiq_core_log_level, "%d: csi:%d,%d (%s)", + service->state->id, service->localport, close_recvd, + srvstate_names[service->srvstate]); + + switch (service->srvstate) { + case VCHIQ_SRVSTATE_CLOSED: + case VCHIQ_SRVSTATE_HIDDEN: + case VCHIQ_SRVSTATE_LISTENING: + case VCHIQ_SRVSTATE_CLOSEWAIT: + if (close_recvd) + vchiq_log_error(vchiq_core_log_level, + "vchiq_close_service_internal(1) called " + "in state %s", + srvstate_names[service->srvstate]); + else if (is_server) { + if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { + status = VCHIQ_ERROR; + } else { + service->client_id = 0; + service->remoteport = VCHIQ_PORT_FREE; + if (service->srvstate == + VCHIQ_SRVSTATE_CLOSEWAIT) + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_LISTENING); + } + up(&service->remove_event); + } else + vchiq_free_service_internal(service); + break; + case VCHIQ_SRVSTATE_OPENING: + if (close_recvd) { + /* The open was rejected - tell the user */ + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_CLOSEWAIT); + up(&service->remove_event); + } else { + /* Shutdown mid-open - let the other side know */ + status = queue_message(state, service, + VCHIQ_MAKE_MSG + (VCHIQ_MSG_CLOSE, + service->localport, + VCHIQ_MSG_DSTPORT(service->remoteport)), + NULL, 0, 0, 0); + } + break; + + case VCHIQ_SRVSTATE_OPENSYNC: + mutex_lock(&state->sync_mutex); + /* Drop through */ + + case VCHIQ_SRVSTATE_OPEN: + if (state->is_master || close_recvd) { + if (!do_abort_bulks(service)) + status = VCHIQ_RETRY; + } + + release_service_messages(service); + + if (status == VCHIQ_SUCCESS) + status = queue_message(state, service, + VCHIQ_MAKE_MSG + (VCHIQ_MSG_CLOSE, + service->localport, + VCHIQ_MSG_DSTPORT(service->remoteport)), + NULL, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK); + + if (status == VCHIQ_SUCCESS) { + if (!close_recvd) { + /* Change the state while the mutex is + still held */ + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_CLOSESENT); + mutex_unlock(&state->slot_mutex); + if (service->sync) + mutex_unlock(&state->sync_mutex); + break; + } + } else if (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC) { + mutex_unlock(&state->sync_mutex); + break; + } else + break; + + /* Change the state while the mutex is still held */ + vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD); + mutex_unlock(&state->slot_mutex); + if (service->sync) + mutex_unlock(&state->sync_mutex); + + status = close_service_complete(service, + VCHIQ_SRVSTATE_CLOSERECVD); + break; + + case VCHIQ_SRVSTATE_CLOSESENT: + if (!close_recvd) + /* This happens when a process is killed mid-close */ + break; + + if (!state->is_master) { + if (!do_abort_bulks(service)) { + status = VCHIQ_RETRY; + break; + } + } + + if (status == VCHIQ_SUCCESS) + status = close_service_complete(service, + VCHIQ_SRVSTATE_CLOSERECVD); + break; + + case VCHIQ_SRVSTATE_CLOSERECVD: + if (!close_recvd && is_server) + /* Force into LISTENING mode */ + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_LISTENING); + status = close_service_complete(service, + VCHIQ_SRVSTATE_CLOSERECVD); + break; + + default: + vchiq_log_error(vchiq_core_log_level, + "vchiq_close_service_internal(%d) called in state %s", + close_recvd, srvstate_names[service->srvstate]); + break; + } + + return status; +} + +/* Called from the application process upon process death */ +void +vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATE_T *state = service->state; + + vchiq_log_info(vchiq_core_log_level, "%d: tsi - (%d<->%d)", + state->id, service->localport, service->remoteport); + + mark_service_closing(service); + + /* Mark the service for removal by the slot handler */ + request_poll(state, service, VCHIQ_POLL_REMOVE); +} + +/* Called from the slot handler */ +void +vchiq_free_service_internal(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATE_T *state = service->state; + + vchiq_log_info(vchiq_core_log_level, "%d: fsi - (%d)", + state->id, service->localport); + + switch (service->srvstate) { + case VCHIQ_SRVSTATE_OPENING: + case VCHIQ_SRVSTATE_CLOSED: + case VCHIQ_SRVSTATE_HIDDEN: + case VCHIQ_SRVSTATE_LISTENING: + case VCHIQ_SRVSTATE_CLOSEWAIT: + break; + default: + vchiq_log_error(vchiq_core_log_level, + "%d: fsi - (%d) in state %s", + state->id, service->localport, + srvstate_names[service->srvstate]); + return; + } + + vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE); + + up(&service->remove_event); + + /* Release the initial lock */ + unlock_service(service); +} + +VCHIQ_STATUS_T +vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) +{ + VCHIQ_SERVICE_T *service; + int i; + + /* Find all services registered to this client and enable them. */ + i = 0; + while ((service = next_service_by_instance(state, instance, + &i)) != NULL) { + if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN) + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_LISTENING); + unlock_service(service); + } + + if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) { + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0, + 0, QMFLAGS_IS_BLOCKING) == VCHIQ_RETRY) + return VCHIQ_RETRY; + + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING); + } + + if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) { + if (down_interruptible(&state->connect) != 0) + return VCHIQ_RETRY; + + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); + up(&state->connect); + } + + return VCHIQ_SUCCESS; +} + +VCHIQ_STATUS_T +vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) +{ + VCHIQ_SERVICE_T *service; + int i; + + /* Find all services registered to this client and enable them. */ + i = 0; + while ((service = next_service_by_instance(state, instance, + &i)) != NULL) { + (void)vchiq_remove_service(service->handle); + unlock_service(service); + } + + return VCHIQ_SUCCESS; +} + +VCHIQ_STATUS_T +vchiq_pause_internal(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + switch (state->conn_state) { + case VCHIQ_CONNSTATE_CONNECTED: + /* Request a pause */ + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSING); + request_poll(state, NULL, 0); + break; + default: + vchiq_log_error(vchiq_core_log_level, + "vchiq_pause_internal in state %s\n", + conn_state_names[state->conn_state]); + status = VCHIQ_ERROR; + VCHIQ_STATS_INC(state, error_count); + break; + } + + return status; +} + +VCHIQ_STATUS_T +vchiq_resume_internal(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_RESUMING); + request_poll(state, NULL, 0); + } else { + status = VCHIQ_ERROR; + VCHIQ_STATS_INC(state, error_count); + } + + return status; +} + +VCHIQ_STATUS_T +vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + /* Unregister the service */ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + if (!service) + return VCHIQ_ERROR; + + vchiq_log_info(vchiq_core_log_level, + "%d: close_service:%d", + service->state->id, service->localport); + + if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || + (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || + (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)) { + unlock_service(service); + return VCHIQ_ERROR; + } + + mark_service_closing(service); + + if (current == service->state->slot_handler_thread) { + status = vchiq_close_service_internal(service, + 0/*!close_recvd*/); + BUG_ON(status == VCHIQ_RETRY); + } else { + /* Mark the service for termination by the slot handler */ + request_poll(service->state, service, VCHIQ_POLL_TERMINATE); + } + + while (1) { + if (down_interruptible(&service->remove_event) != 0) { + status = VCHIQ_RETRY; + break; + } + + if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || + (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || + (service->srvstate == VCHIQ_SRVSTATE_OPEN)) + break; + + vchiq_log_warning(vchiq_core_log_level, + "%d: close_service:%d - waiting in state %s", + service->state->id, service->localport, + srvstate_names[service->srvstate]); + } + + if ((status == VCHIQ_SUCCESS) && + (service->srvstate != VCHIQ_SRVSTATE_FREE) && + (service->srvstate != VCHIQ_SRVSTATE_LISTENING)) + status = VCHIQ_ERROR; + + unlock_service(service); + + return status; +} + +VCHIQ_STATUS_T +vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + /* Unregister the service */ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + if (!service) + return VCHIQ_ERROR; + + vchiq_log_info(vchiq_core_log_level, + "%d: remove_service:%d", + service->state->id, service->localport); + + if (service->srvstate == VCHIQ_SRVSTATE_FREE) { + unlock_service(service); + return VCHIQ_ERROR; + } + + mark_service_closing(service); + + if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || + (current == service->state->slot_handler_thread)) { + /* Make it look like a client, because it must be removed and + not left in the LISTENING state. */ + service->public_fourcc = VCHIQ_FOURCC_INVALID; + + status = vchiq_close_service_internal(service, + 0/*!close_recvd*/); + BUG_ON(status == VCHIQ_RETRY); + } else { + /* Mark the service for removal by the slot handler */ + request_poll(service->state, service, VCHIQ_POLL_REMOVE); + } + while (1) { + if (down_interruptible(&service->remove_event) != 0) { + status = VCHIQ_RETRY; + break; + } + + if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || + (service->srvstate == VCHIQ_SRVSTATE_OPEN)) + break; + + vchiq_log_warning(vchiq_core_log_level, + "%d: remove_service:%d - waiting in state %s", + service->state->id, service->localport, + srvstate_names[service->srvstate]); + } + + if ((status == VCHIQ_SUCCESS) && + (service->srvstate != VCHIQ_SRVSTATE_FREE)) + status = VCHIQ_ERROR; + + unlock_service(service); + + return status; +} + + +/* This function may be called by kernel threads or user threads. + * User threads may receive VCHIQ_RETRY to indicate that a signal has been + * received and the call should be retried after being returned to user + * context. + * When called in blocking mode, the userdata field points to a bulk_waiter + * structure. + */ +VCHIQ_STATUS_T +vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, + VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, + VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_BULK_QUEUE_T *queue; + VCHIQ_BULK_T *bulk; + VCHIQ_STATE_T *state; + struct bulk_waiter *bulk_waiter = NULL; + const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r'; + const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ? + VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX; + VCHIQ_STATUS_T status = VCHIQ_ERROR; + + if (!service || + (service->srvstate != VCHIQ_SRVSTATE_OPEN) || + ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)) || + (vchiq_check_service(service) != VCHIQ_SUCCESS)) + goto error_exit; + + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + break; + case VCHIQ_BULK_MODE_BLOCKING: + bulk_waiter = (struct bulk_waiter *)userdata; + sema_init(&bulk_waiter->event, 0); + bulk_waiter->actual = 0; + bulk_waiter->bulk = NULL; + break; + case VCHIQ_BULK_MODE_WAITING: + bulk_waiter = (struct bulk_waiter *)userdata; + bulk = bulk_waiter->bulk; + goto waiting; + default: + goto error_exit; + } + + state = service->state; + + queue = (dir == VCHIQ_BULK_TRANSMIT) ? + &service->bulk_tx : &service->bulk_rx; + + if (mutex_lock_interruptible(&service->bulk_mutex) != 0) { + status = VCHIQ_RETRY; + goto error_exit; + } + + if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) { + VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); + do { + mutex_unlock(&service->bulk_mutex); + if (down_interruptible(&service->bulk_remove_event) + != 0) { + status = VCHIQ_RETRY; + goto error_exit; + } + if (mutex_lock_interruptible(&service->bulk_mutex) + != 0) { + status = VCHIQ_RETRY; + goto error_exit; + } + } while (queue->local_insert == queue->remove + + VCHIQ_NUM_SERVICE_BULKS); + } + + bulk = &queue->bulks[BULK_INDEX(queue->local_insert)]; + + bulk->mode = mode; + bulk->dir = dir; + bulk->userdata = userdata; + bulk->size = size; + bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; + + if (vchiq_prepare_bulk_data(bulk, memhandle, offset, size, dir) != + VCHIQ_SUCCESS) + goto unlock_error_exit; + + wmb(); + + vchiq_log_info(vchiq_core_log_level, + "%d: bt (%d->%d) %cx %x@%x %x", + state->id, + service->localport, service->remoteport, dir_char, + size, (unsigned int)bulk->data, (unsigned int)userdata); + + /* The slot mutex must be held when the service is being closed, so + claim it here to ensure that isn't happening */ + if (mutex_lock_interruptible(&state->slot_mutex) != 0) { + status = VCHIQ_RETRY; + goto cancel_bulk_error_exit; + } + + if (service->srvstate != VCHIQ_SRVSTATE_OPEN) + goto unlock_both_error_exit; + + if (state->is_master) { + queue->local_insert++; + if (resolve_bulks(service, queue)) + request_poll(state, service, + (dir == VCHIQ_BULK_TRANSMIT) ? + VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); + } else { + int payload[2] = { (int)bulk->data, bulk->size }; + VCHIQ_ELEMENT_T element = { payload, sizeof(payload) }; + + status = queue_message(state, NULL, + VCHIQ_MAKE_MSG(dir_msgtype, + service->localport, service->remoteport), + &element, 1, sizeof(payload), + QMFLAGS_IS_BLOCKING | + QMFLAGS_NO_MUTEX_LOCK | + QMFLAGS_NO_MUTEX_UNLOCK); + if (status != VCHIQ_SUCCESS) { + goto unlock_both_error_exit; + } + queue->local_insert++; + } + + mutex_unlock(&state->slot_mutex); + mutex_unlock(&service->bulk_mutex); + + vchiq_log_trace(vchiq_core_log_level, + "%d: bt:%d %cx li=%x ri=%x p=%x", + state->id, + service->localport, dir_char, + queue->local_insert, queue->remote_insert, queue->process); + +waiting: + unlock_service(service); + + status = VCHIQ_SUCCESS; + + if (bulk_waiter) { + bulk_waiter->bulk = bulk; + if (down_interruptible(&bulk_waiter->event) != 0) + status = VCHIQ_RETRY; + else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) + status = VCHIQ_ERROR; + } + + return status; + +unlock_both_error_exit: + mutex_unlock(&state->slot_mutex); +cancel_bulk_error_exit: + vchiq_complete_bulk(bulk); +unlock_error_exit: + mutex_unlock(&service->bulk_mutex); + +error_exit: + if (service) + unlock_service(service); + return status; +} + +VCHIQ_STATUS_T +vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, + const VCHIQ_ELEMENT_T *elements, unsigned int count) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_STATUS_T status = VCHIQ_ERROR; + + unsigned int size = 0; + unsigned int i; + + if (!service || + (vchiq_check_service(service) != VCHIQ_SUCCESS)) + goto error_exit; + + for (i = 0; i < (unsigned int)count; i++) { + if (elements[i].size) { + if (elements[i].data == NULL) { + VCHIQ_SERVICE_STATS_INC(service, error_count); + goto error_exit; + } + size += elements[i].size; + } + } + + if (size > VCHIQ_MAX_MSG_SIZE) { + VCHIQ_SERVICE_STATS_INC(service, error_count); + goto error_exit; + } + + switch (service->srvstate) { + case VCHIQ_SRVSTATE_OPEN: + status = queue_message(service->state, service, + VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, + service->localport, + service->remoteport), + elements, count, size, 1); + break; + case VCHIQ_SRVSTATE_OPENSYNC: + status = queue_message_sync(service->state, service, + VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, + service->localport, + service->remoteport), + elements, count, size, 1); + break; + default: + status = VCHIQ_ERROR; + break; + } + +error_exit: + if (service) + unlock_service(service); + + return status; +} + +void +vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_SHARED_STATE_T *remote; + VCHIQ_STATE_T *state; + int slot_index; + + if (!service) + return; + + state = service->state; + remote = state->remote; + + slot_index = SLOT_INDEX_FROM_DATA(state, (void *)header); + + if ((slot_index >= remote->slot_first) && + (slot_index <= remote->slot_last)) { + int msgid = header->msgid; + if (msgid & VCHIQ_MSGID_CLAIMED) { + VCHIQ_SLOT_INFO_T *slot_info = + SLOT_INFO_FROM_INDEX(state, slot_index); + + release_slot(state, slot_info, header, service); + } + } else if (slot_index == remote->slot_sync) + release_message_sync(state, header); + + unlock_service(service); +} + +static void +release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) +{ + header->msgid = VCHIQ_MSGID_PADDING; + wmb(); + remote_event_signal(&state->remote->sync_release); +} + +VCHIQ_STATUS_T +vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, short *peer_version) +{ + VCHIQ_STATUS_T status = VCHIQ_ERROR; + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + + if (!service || + (vchiq_check_service(service) != VCHIQ_SUCCESS) || + !peer_version) + goto exit; + *peer_version = service->peer_version; + status = VCHIQ_SUCCESS; + +exit: + if (service) + unlock_service(service); + return status; +} + +VCHIQ_STATUS_T +vchiq_get_config(VCHIQ_INSTANCE_T instance, + int config_size, VCHIQ_CONFIG_T *pconfig) +{ + VCHIQ_CONFIG_T config; + + (void)instance; + + config.max_msg_size = VCHIQ_MAX_MSG_SIZE; + config.bulk_threshold = VCHIQ_MAX_MSG_SIZE; + config.max_outstanding_bulks = VCHIQ_NUM_SERVICE_BULKS; + config.max_services = VCHIQ_MAX_SERVICES; + config.version = VCHIQ_VERSION; + config.version_min = VCHIQ_VERSION_MIN; + + if (config_size > sizeof(VCHIQ_CONFIG_T)) + return VCHIQ_ERROR; + + memcpy(pconfig, &config, + min(config_size, (int)(sizeof(VCHIQ_CONFIG_T)))); + + return VCHIQ_SUCCESS; +} + +VCHIQ_STATUS_T +vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, + VCHIQ_SERVICE_OPTION_T option, int value) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_STATUS_T status = VCHIQ_ERROR; + + if (service) { + switch (option) { + case VCHIQ_SERVICE_OPTION_AUTOCLOSE: + service->auto_close = value; + status = VCHIQ_SUCCESS; + break; + + case VCHIQ_SERVICE_OPTION_SLOT_QUOTA: { + VCHIQ_SERVICE_QUOTA_T *service_quota = + &service->state->service_quotas[ + service->localport]; + if (value == 0) + value = service->state->default_slot_quota; + if ((value >= service_quota->slot_use_count) && + (value < (unsigned short)~0)) { + service_quota->slot_quota = value; + if ((value >= service_quota->slot_use_count) && + (service_quota->message_quota >= + service_quota->message_use_count)) { + /* Signal the service that it may have + ** dropped below its quota */ + up(&service_quota->quota_event); + } + status = VCHIQ_SUCCESS; + } + } break; + + case VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA: { + VCHIQ_SERVICE_QUOTA_T *service_quota = + &service->state->service_quotas[ + service->localport]; + if (value == 0) + value = service->state->default_message_quota; + if ((value >= service_quota->message_use_count) && + (value < (unsigned short)~0)) { + service_quota->message_quota = value; + if ((value >= + service_quota->message_use_count) && + (service_quota->slot_quota >= + service_quota->slot_use_count)) + /* Signal the service that it may have + ** dropped below its quota */ + up(&service_quota->quota_event); + status = VCHIQ_SUCCESS; + } + } break; + + case VCHIQ_SERVICE_OPTION_SYNCHRONOUS: + if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || + (service->srvstate == + VCHIQ_SRVSTATE_LISTENING)) { + service->sync = value; + status = VCHIQ_SUCCESS; + } + break; + + case VCHIQ_SERVICE_OPTION_TRACE: + service->trace = value; + status = VCHIQ_SUCCESS; + break; + + default: + break; + } + unlock_service(service); + } + + return status; +} + +void +vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state, + VCHIQ_SHARED_STATE_T *shared, const char *label) +{ + static const char *const debug_names[] = { + "", + "SLOT_HANDLER_COUNT", + "SLOT_HANDLER_LINE", + "PARSE_LINE", + "PARSE_HEADER", + "PARSE_MSGID", + "AWAIT_COMPLETION_LINE", + "DEQUEUE_MESSAGE_LINE", + "SERVICE_CALLBACK_LINE", + "MSG_QUEUE_FULL_COUNT", + "COMPLETION_QUEUE_FULL_COUNT" + }; + int i; + + char buf[80]; + int len; + len = snprintf(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), + " Slots claimed:"); + vchiq_dump(dump_context, buf, len + 1); + + for (i = shared->slot_first; i <= shared->slot_last; i++) { + VCHIQ_SLOT_INFO_T slot_info = *SLOT_INFO_FROM_INDEX(state, i); + if (slot_info.use_count != slot_info.release_count) { + len = snprintf(buf, sizeof(buf), + " %d: %d/%d", i, slot_info.use_count, + slot_info.release_count); + vchiq_dump(dump_context, buf, len + 1); + } + } + + for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) { + len = snprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", + debug_names[i], shared->debug[i], shared->debug[i]); + vchiq_dump(dump_context, buf, len + 1); + } +} + +void +vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state) +{ + char buf[80]; + int len; + int i; + + len = snprintf(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), + " tx_pos=%x(@%x), rx_pos=%x(@%x)", + state->local->tx_pos, + (uint32_t)state->tx_data + + (state->local_tx_pos & VCHIQ_SLOT_MASK), + state->rx_pos, + (uint32_t)state->rx_data + + (state->rx_pos & VCHIQ_SLOT_MASK)); + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(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), + " Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, " + "error_count=%d", + state->stats.ctrl_tx_count, state->stats.ctrl_rx_count, + state->stats.error_count); + vchiq_dump(dump_context, buf, len + 1); + } + + len = snprintf(buf, sizeof(buf), + " Slots: %d available (%d data), %d recyclable, %d stalls " + "(%d data)", + ((state->slot_queue_available * VCHIQ_SLOT_SIZE) - + state->local_tx_pos) / VCHIQ_SLOT_SIZE, + state->data_quota - state->data_use_count, + state->local->slot_queue_recycle - state->slot_queue_available, + state->stats.slot_stalls, state->stats.data_stalls); + vchiq_dump(dump_context, buf, len + 1); + + vchiq_dump_platform_state(dump_context); + + vchiq_dump_shared_state(dump_context, state, state->local, "Local"); + vchiq_dump_shared_state(dump_context, state, state->remote, "Remote"); + + vchiq_dump_platform_instances(dump_context); + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = find_service_by_port(state, i); + + if (service) { + vchiq_dump_service_state(dump_context, service); + unlock_service(service); + } + } +} + +void +vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service) +{ + char buf[80]; + int len; + + len = snprintf(buf, sizeof(buf), "Service %d: %s (ref %u)", + service->localport, srvstate_names[service->srvstate], + service->ref_count - 1); /*Don't include the lock just taken*/ + + if (service->srvstate != VCHIQ_SRVSTATE_FREE) { + char remoteport[30]; + VCHIQ_SERVICE_QUOTA_T *service_quota = + &service->state->service_quotas[service->localport]; + int fourcc = service->base.fourcc; + int tx_pending, rx_pending; + if (service->remoteport != VCHIQ_PORT_FREE) { + int len2 = snprintf(remoteport, sizeof(remoteport), + "%d", service->remoteport); + if (service->public_fourcc != VCHIQ_FOURCC_INVALID) + snprintf(remoteport + len2, + sizeof(remoteport) - len2, + " (client %x)", service->client_id); + } else + strcpy(remoteport, "n/a"); + + len += snprintf(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, + service_quota->message_use_count, + service_quota->message_quota, + service_quota->slot_use_count, + service_quota->slot_quota); + + vchiq_dump(dump_context, buf, len + 1); + + tx_pending = service->bulk_tx.local_insert - + service->bulk_tx.remote_insert; + + rx_pending = service->bulk_rx.local_insert - + service->bulk_rx.remote_insert; + + len = snprintf(buf, sizeof(buf), + " Bulk: tx_pending=%d (size %d)," + " rx_pending=%d (size %d)", + tx_pending, + tx_pending ? service->bulk_tx.bulks[ + BULK_INDEX(service->bulk_tx.remove)].size : 0, + rx_pending, + rx_pending ? service->bulk_rx.bulks[ + BULK_INDEX(service->bulk_rx.remove)].size : 0); + + if (VCHIQ_ENABLE_STATS) { + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " Ctrl: tx_count=%d, tx_bytes=%llu, " + "rx_count=%d, rx_bytes=%llu", + service->stats.ctrl_tx_count, + service->stats.ctrl_tx_bytes, + service->stats.ctrl_rx_count, + service->stats.ctrl_rx_bytes); + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " Bulk: tx_count=%d, tx_bytes=%llu, " + "rx_count=%d, rx_bytes=%llu", + service->stats.bulk_tx_count, + service->stats.bulk_tx_bytes, + service->stats.bulk_rx_count, + service->stats.bulk_rx_bytes); + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " %d quota stalls, %d slot stalls, " + "%d bulk stalls, %d aborted, %d errors", + service->stats.quota_stalls, + service->stats.slot_stalls, + service->stats.bulk_stalls, + service->stats.bulk_aborted_count, + service->stats.error_count); + } + } + + vchiq_dump(dump_context, buf, len + 1); + + if (service->srvstate != VCHIQ_SRVSTATE_FREE) + vchiq_dump_platform_service_state(dump_context, service); +} + + +void +vchiq_loud_error_header(void) +{ + vchiq_log_error(vchiq_core_log_level, + "============================================================" + "================"); + vchiq_log_error(vchiq_core_log_level, + "============================================================" + "================"); + vchiq_log_error(vchiq_core_log_level, "====="); +} + +void +vchiq_loud_error_footer(void) +{ + vchiq_log_error(vchiq_core_log_level, "====="); + vchiq_log_error(vchiq_core_log_level, + "============================================================" + "================"); + vchiq_log_error(vchiq_core_log_level, + "============================================================" + "================"); +} + + +VCHIQ_STATUS_T vchiq_send_remote_use(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_RETRY; + if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) + status = queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE, 0, 0), + NULL, 0, 0, 0); + return status; +} + +VCHIQ_STATUS_T vchiq_send_remote_release(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_RETRY; + if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) + status = queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_RELEASE, 0, 0), + NULL, 0, 0, 0); + return status; +} + +VCHIQ_STATUS_T vchiq_send_remote_use_active(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_RETRY; + if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) + status = queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE_ACTIVE, 0, 0), + NULL, 0, 0, 0); + return status; +} + +void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, + size_t numBytes) +{ + const uint8_t *mem = (const uint8_t *)voidMem; + size_t offset; + char lineBuf[100]; + char *s; + + while (numBytes > 0) { + s = lineBuf; + + for (offset = 0; offset < 16; offset++) { + if (offset < numBytes) + s += snprintf(s, 4, "%02x ", mem[offset]); + else + s += snprintf(s, 4, " "); + } + + for (offset = 0; offset < 16; offset++) { + if (offset < numBytes) { + uint8_t ch = mem[offset]; + + if ((ch < ' ') || (ch > '~')) + ch = '.'; + *s++ = (char)ch; + } + } + *s++ = '\0'; + + if ((label != NULL) && (*label != '\0')) + vchiq_log_trace(VCHIQ_LOG_TRACE, + "%s: %08x: %s", label, addr, lineBuf); + else + vchiq_log_trace(VCHIQ_LOG_TRACE, + "%08x: %s", addr, lineBuf); + + addr += 16; + mem += 16; + if (numBytes > 16) + numBytes -= 16; + else + numBytes = 0; + } +} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h new file mode 100644 index 000000000000..9be484c776d0 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -0,0 +1,712 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_CORE_H +#define VCHIQ_CORE_H + +#include +#include +#include + +#include "vchiq_cfg.h" + +#include "vchiq.h" + +/* Run time control of log level, based on KERN_XXX level. */ +#define VCHIQ_LOG_DEFAULT 4 +#define VCHIQ_LOG_ERROR 3 +#define VCHIQ_LOG_WARNING 4 +#define VCHIQ_LOG_INFO 6 +#define VCHIQ_LOG_TRACE 7 + +#define VCHIQ_LOG_PREFIX KERN_INFO "vchiq: " + +#ifndef vchiq_log_error +#define vchiq_log_error(cat, fmt, ...) \ + do { if (cat >= VCHIQ_LOG_ERROR) \ + printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) +#endif +#ifndef vchiq_log_warning +#define vchiq_log_warning(cat, fmt, ...) \ + do { if (cat >= VCHIQ_LOG_WARNING) \ + printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) +#endif +#ifndef vchiq_log_info +#define vchiq_log_info(cat, fmt, ...) \ + do { if (cat >= VCHIQ_LOG_INFO) \ + printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) +#endif +#ifndef vchiq_log_trace +#define vchiq_log_trace(cat, fmt, ...) \ + do { if (cat >= VCHIQ_LOG_TRACE) \ + printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) +#endif + +#define vchiq_loud_error(...) \ + vchiq_log_error(vchiq_core_log_level, "===== " __VA_ARGS__) + +#ifndef vchiq_static_assert +#define vchiq_static_assert(cond) __attribute__((unused)) \ + extern int vchiq_static_assert[(cond) ? 1 : -1] +#endif + +#define IS_POW2(x) (x && ((x & (x - 1)) == 0)) + +/* Ensure that the slot size and maximum number of slots are powers of 2 */ +vchiq_static_assert(IS_POW2(VCHIQ_SLOT_SIZE)); +vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS)); +vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE)); + +#define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) +#define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) +#define VCHIQ_SLOT_ZERO_SLOTS ((sizeof(VCHIQ_SLOT_ZERO_T) + \ + VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE) + +#define VCHIQ_MSG_PADDING 0 /* - */ +#define VCHIQ_MSG_CONNECT 1 /* - */ +#define VCHIQ_MSG_OPEN 2 /* + (srcport, -), fourcc, client_id */ +#define VCHIQ_MSG_OPENACK 3 /* + (srcport, dstport) */ +#define VCHIQ_MSG_CLOSE 4 /* + (srcport, dstport) */ +#define VCHIQ_MSG_DATA 5 /* + (srcport, dstport) */ +#define VCHIQ_MSG_BULK_RX 6 /* + (srcport, dstport), data, size */ +#define VCHIQ_MSG_BULK_TX 7 /* + (srcport, dstport), data, size */ +#define VCHIQ_MSG_BULK_RX_DONE 8 /* + (srcport, dstport), actual */ +#define VCHIQ_MSG_BULK_TX_DONE 9 /* + (srcport, dstport), actual */ +#define VCHIQ_MSG_PAUSE 10 /* - */ +#define VCHIQ_MSG_RESUME 11 /* - */ +#define VCHIQ_MSG_REMOTE_USE 12 /* - */ +#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */ +#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */ + +#define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1) +#define VCHIQ_PORT_FREE 0x1000 +#define VCHIQ_PORT_IS_VALID(port) (port < VCHIQ_PORT_FREE) +#define VCHIQ_MAKE_MSG(type, srcport, dstport) \ + ((type<<24) | (srcport<<12) | (dstport<<0)) +#define VCHIQ_MSG_TYPE(msgid) ((unsigned int)msgid >> 24) +#define VCHIQ_MSG_SRCPORT(msgid) \ + (unsigned short)(((unsigned int)msgid >> 12) & 0xfff) +#define VCHIQ_MSG_DSTPORT(msgid) \ + ((unsigned short)msgid & 0xfff) + +#define VCHIQ_FOURCC_AS_4CHARS(fourcc) \ + ((fourcc) >> 24) & 0xff, \ + ((fourcc) >> 16) & 0xff, \ + ((fourcc) >> 8) & 0xff, \ + (fourcc) & 0xff + +/* Ensure the fields are wide enough */ +vchiq_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) + == 0); +vchiq_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0); +vchiq_static_assert((unsigned int)VCHIQ_PORT_MAX < + (unsigned int)VCHIQ_PORT_FREE); + +#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0) +#define VCHIQ_MSGID_CLAIMED 0x40000000 + +#define VCHIQ_FOURCC_INVALID 0x00000000 +#define VCHIQ_FOURCC_IS_LEGAL(fourcc) (fourcc != VCHIQ_FOURCC_INVALID) + +#define VCHIQ_BULK_ACTUAL_ABORTED -1 + +typedef uint32_t BITSET_T; + +vchiq_static_assert((sizeof(BITSET_T) * 8) == 32); + +#define BITSET_SIZE(b) ((b + 31) >> 5) +#define BITSET_WORD(b) (b >> 5) +#define BITSET_BIT(b) (1 << (b & 31)) +#define BITSET_ZERO(bs) memset(bs, 0, sizeof(bs)) +#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b)) +#define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b)) +#define BITSET_CLR(bs, b) (bs[BITSET_WORD(b)] &= ~BITSET_BIT(b)) + +#if VCHIQ_ENABLE_STATS +#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++) +#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++) +#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \ + (service->stats. stat += addend) +#else +#define VCHIQ_STATS_INC(state, stat) ((void)0) +#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0) +#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0) +#endif + +enum { + DEBUG_ENTRIES, +#if VCHIQ_ENABLE_DEBUG + DEBUG_SLOT_HANDLER_COUNT, + DEBUG_SLOT_HANDLER_LINE, + DEBUG_PARSE_LINE, + DEBUG_PARSE_HEADER, + DEBUG_PARSE_MSGID, + DEBUG_AWAIT_COMPLETION_LINE, + DEBUG_DEQUEUE_MESSAGE_LINE, + DEBUG_SERVICE_CALLBACK_LINE, + DEBUG_MSG_QUEUE_FULL_COUNT, + DEBUG_COMPLETION_QUEUE_FULL_COUNT, +#endif + DEBUG_MAX +}; + +#if VCHIQ_ENABLE_DEBUG + +#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug; +#define DEBUG_TRACE(d) \ + do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0) +#define DEBUG_VALUE(d, v) \ + do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0) +#define DEBUG_COUNT(d) \ + do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0) + +#else /* VCHIQ_ENABLE_DEBUG */ + +#define DEBUG_INITIALISE(local) +#define DEBUG_TRACE(d) +#define DEBUG_VALUE(d, v) +#define DEBUG_COUNT(d) + +#endif /* VCHIQ_ENABLE_DEBUG */ + +typedef enum { + VCHIQ_CONNSTATE_DISCONNECTED, + VCHIQ_CONNSTATE_CONNECTING, + VCHIQ_CONNSTATE_CONNECTED, + VCHIQ_CONNSTATE_PAUSING, + VCHIQ_CONNSTATE_PAUSE_SENT, + VCHIQ_CONNSTATE_PAUSED, + VCHIQ_CONNSTATE_RESUMING, + VCHIQ_CONNSTATE_PAUSE_TIMEOUT, + VCHIQ_CONNSTATE_RESUME_TIMEOUT +} VCHIQ_CONNSTATE_T; + +enum { + VCHIQ_SRVSTATE_FREE, + VCHIQ_SRVSTATE_HIDDEN, + VCHIQ_SRVSTATE_LISTENING, + VCHIQ_SRVSTATE_OPENING, + VCHIQ_SRVSTATE_OPEN, + VCHIQ_SRVSTATE_OPENSYNC, + VCHIQ_SRVSTATE_CLOSESENT, + VCHIQ_SRVSTATE_CLOSERECVD, + VCHIQ_SRVSTATE_CLOSEWAIT, + VCHIQ_SRVSTATE_CLOSED +}; + +enum { + VCHIQ_POLL_TERMINATE, + VCHIQ_POLL_REMOVE, + VCHIQ_POLL_TXNOTIFY, + VCHIQ_POLL_RXNOTIFY, + VCHIQ_POLL_COUNT +}; + +typedef enum { + VCHIQ_BULK_TRANSMIT, + VCHIQ_BULK_RECEIVE +} VCHIQ_BULK_DIR_T; + +typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata); + +typedef struct vchiq_bulk_struct { + short mode; + short dir; + void *userdata; + VCHI_MEM_HANDLE_T handle; + void *data; + int size; + void *remote_data; + int remote_size; + int actual; +} VCHIQ_BULK_T; + +typedef struct vchiq_bulk_queue_struct { + int local_insert; /* Where to insert the next local bulk */ + int remote_insert; /* Where to insert the next remote bulk (master) */ + int process; /* Bulk to transfer next */ + int remote_notify; /* Bulk to notify the remote client of next (mstr) */ + int remove; /* Bulk to notify the local client of, and remove, + ** next */ + VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS]; +} VCHIQ_BULK_QUEUE_T; + +typedef struct remote_event_struct { + int armed; + int fired; + struct semaphore *event; +} REMOTE_EVENT_T; + +typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T; + +typedef struct vchiq_state_struct VCHIQ_STATE_T; + +typedef struct vchiq_slot_struct { + char data[VCHIQ_SLOT_SIZE]; +} VCHIQ_SLOT_T; + +typedef struct vchiq_slot_info_struct { + /* Use two counters rather than one to avoid the need for a mutex. */ + short use_count; + short release_count; +} VCHIQ_SLOT_INFO_T; + +typedef struct vchiq_service_struct { + VCHIQ_SERVICE_BASE_T base; + VCHIQ_SERVICE_HANDLE_T handle; + unsigned int ref_count; + int srvstate; + VCHIQ_USERDATA_TERM_T userdata_term; + unsigned int localport; + unsigned int remoteport; + int public_fourcc; + int client_id; + char auto_close; + char sync; + char closing; + char trace; + atomic_t poll_flags; + short version; + short version_min; + short peer_version; + + VCHIQ_STATE_T *state; + VCHIQ_INSTANCE_T instance; + + int service_use_count; + + VCHIQ_BULK_QUEUE_T bulk_tx; + VCHIQ_BULK_QUEUE_T bulk_rx; + + struct semaphore remove_event; + struct semaphore bulk_remove_event; + struct mutex bulk_mutex; + + struct service_stats_struct { + int quota_stalls; + int slot_stalls; + int bulk_stalls; + int error_count; + int ctrl_tx_count; + int ctrl_rx_count; + int bulk_tx_count; + int bulk_rx_count; + int bulk_aborted_count; + uint64_t ctrl_tx_bytes; + uint64_t ctrl_rx_bytes; + uint64_t bulk_tx_bytes; + uint64_t bulk_rx_bytes; + } stats; +} VCHIQ_SERVICE_T; + +/* The quota information is outside VCHIQ_SERVICE_T so that it can be + statically allocated, since for accounting reasons a service's slot + usage is carried over between users of the same port number. + */ +typedef struct vchiq_service_quota_struct { + unsigned short slot_quota; + unsigned short slot_use_count; + unsigned short message_quota; + unsigned short message_use_count; + struct semaphore quota_event; + int previous_tx_index; +} VCHIQ_SERVICE_QUOTA_T; + +typedef struct vchiq_shared_state_struct { + + /* A non-zero value here indicates that the content is valid. */ + int initialised; + + /* The first and last (inclusive) slots allocated to the owner. */ + int slot_first; + int slot_last; + + /* The slot allocated to synchronous messages from the owner. */ + int slot_sync; + + /* Signalling this event indicates that owner's slot handler thread + ** should run. */ + REMOTE_EVENT_T trigger; + + /* Indicates the byte position within the stream where the next message + ** will be written. The least significant bits are an index into the + ** slot. The next bits are the index of the slot in slot_queue. */ + int tx_pos; + + /* This event should be signalled when a slot is recycled. */ + REMOTE_EVENT_T recycle; + + /* The slot_queue index where the next recycled slot will be written. */ + int slot_queue_recycle; + + /* This event should be signalled when a synchronous message is sent. */ + REMOTE_EVENT_T sync_trigger; + + /* This event should be signalled when a synchronous message has been + ** released. */ + REMOTE_EVENT_T sync_release; + + /* A circular buffer of slot indexes. */ + int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; + + /* Debugging state */ + int debug[DEBUG_MAX]; +} VCHIQ_SHARED_STATE_T; + +typedef struct vchiq_slot_zero_struct { + int magic; + short version; + short version_min; + int slot_zero_size; + int slot_size; + int max_slots; + int max_slots_per_side; + int platform_data[2]; + VCHIQ_SHARED_STATE_T master; + VCHIQ_SHARED_STATE_T slave; + VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS]; +} VCHIQ_SLOT_ZERO_T; + +struct vchiq_state_struct { + int id; + int initialised; + VCHIQ_CONNSTATE_T conn_state; + int is_master; + short version_common; + + VCHIQ_SHARED_STATE_T *local; + VCHIQ_SHARED_STATE_T *remote; + VCHIQ_SLOT_T *slot_data; + + unsigned short default_slot_quota; + unsigned short default_message_quota; + + /* Event indicating connect message received */ + struct semaphore connect; + + /* Mutex protecting services */ + struct mutex mutex; + VCHIQ_INSTANCE_T *instance; + + /* Processes incoming messages */ + struct task_struct *slot_handler_thread; + + /* Processes recycled slots */ + struct task_struct *recycle_thread; + + /* Processes synchronous messages */ + struct task_struct *sync_thread; + + /* Local implementation of the trigger remote event */ + struct semaphore trigger_event; + + /* Local implementation of the recycle remote event */ + struct semaphore recycle_event; + + /* Local implementation of the sync trigger remote event */ + struct semaphore sync_trigger_event; + + /* Local implementation of the sync release remote event */ + struct semaphore sync_release_event; + + char *tx_data; + char *rx_data; + VCHIQ_SLOT_INFO_T *rx_info; + + struct mutex slot_mutex; + + struct mutex recycle_mutex; + + struct mutex sync_mutex; + + struct mutex bulk_transfer_mutex; + + /* Indicates the byte position within the stream from where the next + ** message will be read. The least significant bits are an index into + ** the slot.The next bits are the index of the slot in + ** remote->slot_queue. */ + int rx_pos; + + /* A cached copy of local->tx_pos. Only write to local->tx_pos, and read + from remote->tx_pos. */ + int local_tx_pos; + + /* The slot_queue index of the slot to become available next. */ + int slot_queue_available; + + /* A flag to indicate if any poll has been requested */ + int poll_needed; + + /* Ths index of the previous slot used for data messages. */ + int previous_data_index; + + /* The number of slots occupied by data messages. */ + unsigned short data_use_count; + + /* The maximum number of slots to be occupied by data messages. */ + unsigned short data_quota; + + /* An array of bit sets indicating which services must be polled. */ + atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + + /* The number of the first unused service */ + int unused_service; + + /* Signalled when a free slot becomes available. */ + struct semaphore slot_available_event; + + struct semaphore slot_remove_event; + + /* Signalled when a free data slot becomes available. */ + struct semaphore data_quota_event; + + /* Incremented when there are bulk transfers which cannot be processed + * whilst paused and must be processed on resume */ + int deferred_bulks; + + struct state_stats_struct { + int slot_stalls; + int data_stalls; + int ctrl_tx_count; + int ctrl_rx_count; + int error_count; + } stats; + + VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES]; + VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES]; + VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS]; + + VCHIQ_PLATFORM_STATE_T platform_state; +}; + +struct bulk_waiter { + VCHIQ_BULK_T *bulk; + struct semaphore event; + int actual; +}; + +extern spinlock_t bulk_waiter_spinlock; + +extern int vchiq_core_log_level; +extern int vchiq_core_msg_log_level; +extern int vchiq_sync_log_level; + +extern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; + +extern const char * +get_conn_state_name(VCHIQ_CONNSTATE_T conn_state); + +extern VCHIQ_SLOT_ZERO_T * +vchiq_init_slots(void *mem_base, int mem_size); + +extern VCHIQ_STATUS_T +vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, + int is_master); + +extern VCHIQ_STATUS_T +vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); + +extern VCHIQ_SERVICE_T * +vchiq_add_service_internal(VCHIQ_STATE_T *state, + const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, + VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term); + +extern VCHIQ_STATUS_T +vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id); + +extern VCHIQ_STATUS_T +vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd); + +extern void +vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service); + +extern void +vchiq_free_service_internal(VCHIQ_SERVICE_T *service); + +extern VCHIQ_STATUS_T +vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); + +extern VCHIQ_STATUS_T +vchiq_pause_internal(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_resume_internal(VCHIQ_STATE_T *state); + +extern void +remote_event_pollall(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, + VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, + VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir); + +extern void +vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state); + +extern void +vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service); + +extern void +vchiq_loud_error_header(void); + +extern void +vchiq_loud_error_footer(void); + +extern void +request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type); + +static inline VCHIQ_SERVICE_T * +handle_to_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & + (VCHIQ_MAX_STATES - 1)]; + if (!state) + return NULL; + + return state->services[handle & (VCHIQ_MAX_SERVICES - 1)]; +} + +extern VCHIQ_SERVICE_T * +find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_SERVICE_T * +find_service_by_port(VCHIQ_STATE_T *state, int localport); + +extern VCHIQ_SERVICE_T * +find_service_for_instance(VCHIQ_INSTANCE_T instance, + VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_SERVICE_T * +find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, + VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_SERVICE_T * +next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, + int *pidx); + +extern void +lock_service(VCHIQ_SERVICE_T *service); + +extern void +unlock_service(VCHIQ_SERVICE_T *service); + +/* The following functions are called from vchiq_core, and external +** implementations must be provided. */ + +extern VCHIQ_STATUS_T +vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, + VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir); + +extern void +vchiq_transfer_bulk(VCHIQ_BULK_T *bulk); + +extern void +vchiq_complete_bulk(VCHIQ_BULK_T *bulk); + +extern VCHIQ_STATUS_T +vchiq_copy_from_user(void *dst, const void *src, int size); + +extern void +remote_event_signal(REMOTE_EVENT_T *event); + +void +vchiq_platform_check_suspend(VCHIQ_STATE_T *state); + +extern void +vchiq_platform_paused(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_platform_resume(VCHIQ_STATE_T *state); + +extern void +vchiq_platform_resumed(VCHIQ_STATE_T *state); + +extern void +vchiq_dump(void *dump_context, const char *str, int len); + +extern void +vchiq_dump_platform_state(void *dump_context); + +extern void +vchiq_dump_platform_instances(void *dump_context); + +extern void +vchiq_dump_platform_service_state(void *dump_context, + VCHIQ_SERVICE_T *service); + +extern VCHIQ_STATUS_T +vchiq_use_service_internal(VCHIQ_SERVICE_T *service); + +extern VCHIQ_STATUS_T +vchiq_release_service_internal(VCHIQ_SERVICE_T *service); + +extern void +vchiq_on_remote_use(VCHIQ_STATE_T *state); + +extern void +vchiq_on_remote_release(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_platform_init_state(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_check_service(VCHIQ_SERVICE_T *service); + +extern void +vchiq_on_remote_use_active(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_send_remote_use(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_send_remote_release(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_send_remote_use_active(VCHIQ_STATE_T *state); + +extern void +vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, + VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate); + +extern void +vchiq_platform_handle_timeout(VCHIQ_STATE_T *state); + +extern void +vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate); + + +extern void +vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, + size_t numBytes); + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c new file mode 100644 index 000000000000..7e032130d967 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c @@ -0,0 +1,383 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include "vchiq_core.h" +#include "vchiq_arm.h" +#include "vchiq_debugfs.h" + +#ifdef CONFIG_DEBUG_FS + +/**************************************************************************** +* +* log category entries +* +***************************************************************************/ +#define DEBUGFS_WRITE_BUF_SIZE 256 + +#define VCHIQ_LOG_ERROR_STR "error" +#define VCHIQ_LOG_WARNING_STR "warning" +#define VCHIQ_LOG_INFO_STR "info" +#define VCHIQ_LOG_TRACE_STR "trace" + + +/* Top-level debug info */ +struct vchiq_debugfs_info { + /* Global 'vchiq' debugfs entry used by all instances */ + struct dentry *vchiq_cfg_dir; + + /* one entry per client process */ + struct dentry *clients; + + /* log categories */ + struct dentry *log_categories; +}; + +static struct vchiq_debugfs_info debugfs_info; + +/* Log category debugfs entries */ +struct vchiq_debugfs_log_entry { + const char *name; + int *plevel; + struct dentry *dir; +}; + +static struct vchiq_debugfs_log_entry vchiq_debugfs_log_entries[] = { + { "core", &vchiq_core_log_level }, + { "msg", &vchiq_core_msg_log_level }, + { "sync", &vchiq_sync_log_level }, + { "susp", &vchiq_susp_log_level }, + { "arm", &vchiq_arm_log_level }, +}; +static int n_log_entries = + sizeof(vchiq_debugfs_log_entries)/sizeof(vchiq_debugfs_log_entries[0]); + + +static struct dentry *vchiq_clients_top(void); +static struct dentry *vchiq_debugfs_top(void); + +static int debugfs_log_show(struct seq_file *f, void *offset) +{ + int *levp = f->private; + char *log_value = NULL; + + switch (*levp) { + case VCHIQ_LOG_ERROR: + log_value = VCHIQ_LOG_ERROR_STR; + break; + case VCHIQ_LOG_WARNING: + log_value = VCHIQ_LOG_WARNING_STR; + break; + case VCHIQ_LOG_INFO: + log_value = VCHIQ_LOG_INFO_STR; + break; + case VCHIQ_LOG_TRACE: + log_value = VCHIQ_LOG_TRACE_STR; + break; + default: + break; + } + + seq_printf(f, "%s\n", log_value ? log_value : "(null)"); + + return 0; +} + +static int debugfs_log_open(struct inode *inode, struct file *file) +{ + return single_open(file, debugfs_log_show, inode->i_private); +} + +static int debugfs_log_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct seq_file *f = (struct seq_file *)file->private_data; + int *levp = f->private; + char kbuf[DEBUGFS_WRITE_BUF_SIZE + 1]; + + memset(kbuf, 0, DEBUGFS_WRITE_BUF_SIZE + 1); + if (count >= DEBUGFS_WRITE_BUF_SIZE) + count = DEBUGFS_WRITE_BUF_SIZE; + + if (copy_from_user(kbuf, buffer, count) != 0) + return -EFAULT; + kbuf[count - 1] = 0; + + if (strncmp("error", kbuf, strlen("error")) == 0) + *levp = VCHIQ_LOG_ERROR; + else if (strncmp("warning", kbuf, strlen("warning")) == 0) + *levp = VCHIQ_LOG_WARNING; + else if (strncmp("info", kbuf, strlen("info")) == 0) + *levp = VCHIQ_LOG_INFO; + else if (strncmp("trace", kbuf, strlen("trace")) == 0) + *levp = VCHIQ_LOG_TRACE; + else + *levp = VCHIQ_LOG_DEFAULT; + + *ppos += count; + + return count; +} + +static const struct file_operations debugfs_log_fops = { + .owner = THIS_MODULE, + .open = debugfs_log_open, + .write = debugfs_log_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* create an entry under /vchiq/log for each log category */ +static int vchiq_debugfs_create_log_entries(struct dentry *top) +{ + struct dentry *dir; + size_t i; + int ret = 0; + dir = debugfs_create_dir("log", vchiq_debugfs_top()); + if (!dir) + return -ENOMEM; + debugfs_info.log_categories = dir; + + for (i = 0; i < n_log_entries; i++) { + void *levp = (void *)vchiq_debugfs_log_entries[i].plevel; + dir = debugfs_create_file(vchiq_debugfs_log_entries[i].name, + 0644, + debugfs_info.log_categories, + levp, + &debugfs_log_fops); + if (!dir) { + ret = -ENOMEM; + break; + } + + vchiq_debugfs_log_entries[i].dir = dir; + } + return ret; +} + +static int debugfs_usecount_show(struct seq_file *f, void *offset) +{ + VCHIQ_INSTANCE_T instance = f->private; + int use_count; + + use_count = vchiq_instance_get_use_count(instance); + seq_printf(f, "%d\n", use_count); + + return 0; +} + +static int debugfs_usecount_open(struct inode *inode, struct file *file) +{ + return single_open(file, debugfs_usecount_show, inode->i_private); +} + +static const struct file_operations debugfs_usecount_fops = { + .owner = THIS_MODULE, + .open = debugfs_usecount_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int debugfs_trace_show(struct seq_file *f, void *offset) +{ + VCHIQ_INSTANCE_T instance = f->private; + int trace; + + trace = vchiq_instance_get_trace(instance); + seq_printf(f, "%s\n", trace ? "Y" : "N"); + + return 0; +} + +static int debugfs_trace_open(struct inode *inode, struct file *file) +{ + return single_open(file, debugfs_trace_show, inode->i_private); +} + +static int debugfs_trace_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct seq_file *f = (struct seq_file *)file->private_data; + VCHIQ_INSTANCE_T instance = f->private; + char firstchar; + + if (copy_from_user(&firstchar, buffer, 1) != 0) + return -EFAULT; + + switch (firstchar) { + case 'Y': + case 'y': + case '1': + vchiq_instance_set_trace(instance, 1); + break; + case 'N': + case 'n': + case '0': + vchiq_instance_set_trace(instance, 0); + break; + default: + break; + } + + *ppos += count; + + return count; +} + +static const struct file_operations debugfs_trace_fops = { + .owner = THIS_MODULE, + .open = debugfs_trace_open, + .write = debugfs_trace_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* add an instance (process) to the debugfs entries */ +int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) +{ + char pidstr[16]; + struct dentry *top, *use_count, *trace; + struct dentry *clients = vchiq_clients_top(); + + snprintf(pidstr, sizeof(pidstr), "%d", + vchiq_instance_get_pid(instance)); + + top = debugfs_create_dir(pidstr, clients); + if (!top) + goto fail_top; + + use_count = debugfs_create_file("use_count", + 0444, top, + instance, + &debugfs_usecount_fops); + if (!use_count) + goto fail_use_count; + + trace = debugfs_create_file("trace", + 0644, top, + instance, + &debugfs_trace_fops); + if (!trace) + goto fail_trace; + + vchiq_instance_get_debugfs_node(instance)->dentry = top; + + return 0; + +fail_trace: + debugfs_remove(use_count); +fail_use_count: + debugfs_remove(top); +fail_top: + return -ENOMEM; +} + +void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) +{ + VCHIQ_DEBUGFS_NODE_T *node = vchiq_instance_get_debugfs_node(instance); + debugfs_remove_recursive(node->dentry); +} + + +int vchiq_debugfs_init(void) +{ + BUG_ON(debugfs_info.vchiq_cfg_dir != NULL); + + debugfs_info.vchiq_cfg_dir = debugfs_create_dir("vchiq", NULL); + if (debugfs_info.vchiq_cfg_dir == NULL) + goto fail; + + debugfs_info.clients = debugfs_create_dir("clients", + vchiq_debugfs_top()); + if (!debugfs_info.clients) + goto fail; + + if (vchiq_debugfs_create_log_entries(vchiq_debugfs_top()) != 0) + goto fail; + + return 0; + +fail: + vchiq_debugfs_deinit(); + vchiq_log_error(vchiq_arm_log_level, + "%s: failed to create debugfs directory", + __func__); + + return -ENOMEM; +} + +/* remove all the debugfs entries */ +void vchiq_debugfs_deinit(void) +{ + debugfs_remove_recursive(vchiq_debugfs_top()); +} + +static struct dentry *vchiq_clients_top(void) +{ + return debugfs_info.clients; +} + +static struct dentry *vchiq_debugfs_top(void) +{ + BUG_ON(debugfs_info.vchiq_cfg_dir == NULL); + return debugfs_info.vchiq_cfg_dir; +} + +#else /* CONFIG_DEBUG_FS */ + +int vchiq_debugfs_init(void) +{ + return 0; +} + +void vchiq_debugfs_deinit(void) +{ +} + +int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) +{ + return 0; +} + +void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) +{ +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h new file mode 100644 index 000000000000..4d6a3788e9c5 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_DEBUGFS_H +#define VCHIQ_DEBUGFS_H + +#include "vchiq_core.h" + +typedef struct vchiq_debugfs_node_struct +{ + struct dentry *dentry; +} VCHIQ_DEBUGFS_NODE_T; + +int vchiq_debugfs_init(void); + +void vchiq_debugfs_deinit(void); + +int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance); + +void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance); + +#endif /* VCHIQ_DEBUGFS_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_genversion b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_genversion new file mode 100644 index 000000000000..9f5b6344b9b7 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_genversion @@ -0,0 +1,87 @@ +#!/usr/bin/perl -w + +use strict; + +# +# Generate a version from available information +# + +my $prefix = shift @ARGV; +my $root = shift @ARGV; + + +if ( not defined $root ) { + die "usage: $0 prefix root-dir\n"; +} + +if ( ! -d $root ) { + die "root directory $root not found\n"; +} + +my $version = "unknown"; +my $tainted = ""; + +if ( -d "$root/.git" ) { + # attempt to work out git version. only do so + # on a linux build host, as cygwin builds are + # already slow enough + + if ( -f "/usr/bin/git" || -f "/usr/local/bin/git" ) { + if (not open(F, "git --git-dir $root/.git rev-parse --verify HEAD|")) { + $version = "no git version"; + } + else { + $version = ; + $version =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). + $version =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). + } + + if (open(G, "git --git-dir $root/.git status --porcelain|")) { + $tainted = ; + $tainted =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). + $tainted =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). + if (length $tainted) { + $version = join ' ', $version, "(tainted)"; + } + else { + $version = join ' ', $version, "(clean)"; + } + } + } +} + +my $hostname = `hostname`; +$hostname =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). +$hostname =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). + + +print STDERR "Version $version\n"; +print < + +VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_hostname, "$hostname" ); +VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_version, "$version" ); +VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_time, __TIME__ ); +VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_date, __DATE__ ); + +const char *vchiq_get_build_hostname( void ) +{ + return vchiq_build_hostname; +} + +const char *vchiq_get_build_version( void ) +{ + return vchiq_build_version; +} + +const char *vchiq_get_build_date( void ) +{ + return vchiq_build_date; +} + +const char *vchiq_get_build_time( void ) +{ + return vchiq_build_time; +} +EOF diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h new file mode 100644 index 000000000000..8067bbe7ce8d --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_IF_H +#define VCHIQ_IF_H + +#include "interface/vchi/vchi_mh.h" + +#define VCHIQ_SERVICE_HANDLE_INVALID 0 + +#define VCHIQ_SLOT_SIZE 4096 +#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(VCHIQ_HEADER_T)) +#define VCHIQ_CHANNEL_SIZE VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */ + +#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ + (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) +#define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service) +#define VCHIQ_GET_SERVICE_FOURCC(service) vchiq_get_service_fourcc(service) + +typedef enum { + VCHIQ_SERVICE_OPENED, /* service, -, - */ + VCHIQ_SERVICE_CLOSED, /* service, -, - */ + VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */ + VCHIQ_BULK_TRANSMIT_DONE, /* service, -, bulk_userdata */ + VCHIQ_BULK_RECEIVE_DONE, /* service, -, bulk_userdata */ + VCHIQ_BULK_TRANSMIT_ABORTED, /* service, -, bulk_userdata */ + VCHIQ_BULK_RECEIVE_ABORTED /* service, -, bulk_userdata */ +} VCHIQ_REASON_T; + +typedef enum { + VCHIQ_ERROR = -1, + VCHIQ_SUCCESS = 0, + VCHIQ_RETRY = 1 +} VCHIQ_STATUS_T; + +typedef enum { + VCHIQ_BULK_MODE_CALLBACK, + VCHIQ_BULK_MODE_BLOCKING, + VCHIQ_BULK_MODE_NOCALLBACK, + VCHIQ_BULK_MODE_WAITING /* Reserved for internal use */ +} VCHIQ_BULK_MODE_T; + +typedef enum { + VCHIQ_SERVICE_OPTION_AUTOCLOSE, + VCHIQ_SERVICE_OPTION_SLOT_QUOTA, + VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, + VCHIQ_SERVICE_OPTION_SYNCHRONOUS, + VCHIQ_SERVICE_OPTION_TRACE +} VCHIQ_SERVICE_OPTION_T; + +typedef struct vchiq_header_struct { + /* The message identifier - opaque to applications. */ + int msgid; + + /* Size of message data. */ + unsigned int size; + + char data[0]; /* message */ +} VCHIQ_HEADER_T; + +typedef struct { + const void *data; + unsigned int size; +} VCHIQ_ELEMENT_T; + +typedef unsigned int VCHIQ_SERVICE_HANDLE_T; + +typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *, + VCHIQ_SERVICE_HANDLE_T, void *); + +typedef struct vchiq_service_base_struct { + int fourcc; + VCHIQ_CALLBACK_T callback; + void *userdata; +} VCHIQ_SERVICE_BASE_T; + +typedef struct vchiq_service_params_struct { + int fourcc; + VCHIQ_CALLBACK_T callback; + void *userdata; + short version; /* Increment for non-trivial changes */ + short version_min; /* Update for incompatible changes */ +} VCHIQ_SERVICE_PARAMS_T; + +typedef struct vchiq_config_struct { + unsigned int max_msg_size; + unsigned int bulk_threshold; /* The message size above which it + is better to use a bulk transfer + (<= max_msg_size) */ + unsigned int max_outstanding_bulks; + unsigned int max_services; + short version; /* The version of VCHIQ */ + short version_min; /* The minimum compatible version of VCHIQ */ +} VCHIQ_CONFIG_T; + +typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T; +typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg); + +extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance); +extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance); +extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance); +extern VCHIQ_STATUS_T vchiq_add_service(VCHIQ_INSTANCE_T instance, + const VCHIQ_SERVICE_PARAMS_T *params, + VCHIQ_SERVICE_HANDLE_T *pservice); +extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance, + const VCHIQ_SERVICE_PARAMS_T *params, + VCHIQ_SERVICE_HANDLE_T *pservice); +extern VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_use_service_no_resume( + VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service); + +extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service, + const VCHIQ_ELEMENT_T *elements, unsigned int count); +extern void vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service, + VCHIQ_HEADER_T *header); +extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, + const void *data, unsigned int size, void *userdata); +extern VCHIQ_STATUS_T vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, + void *data, unsigned int size, void *userdata); +extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit_handle( + VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, + const void *offset, unsigned int size, void *userdata); +extern VCHIQ_STATUS_T vchiq_queue_bulk_receive_handle( + VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, + void *offset, unsigned int size, void *userdata); +extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, + const void *data, unsigned int size, void *userdata, + VCHIQ_BULK_MODE_T mode); +extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, + void *data, unsigned int size, void *userdata, + VCHIQ_BULK_MODE_T mode); +extern VCHIQ_STATUS_T vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service, + VCHI_MEM_HANDLE_T handle, const void *offset, unsigned int size, + void *userdata, VCHIQ_BULK_MODE_T mode); +extern VCHIQ_STATUS_T vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service, + VCHI_MEM_HANDLE_T handle, void *offset, unsigned int size, + void *userdata, VCHIQ_BULK_MODE_T mode); +extern int vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service); +extern void *vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T service); +extern int vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance, + int config_size, VCHIQ_CONFIG_T *pconfig); +extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service, + VCHIQ_SERVICE_OPTION_T option, int value); + +extern VCHIQ_STATUS_T vchiq_remote_use(VCHIQ_INSTANCE_T instance, + VCHIQ_REMOTE_USE_CALLBACK_T callback, void *cb_arg); +extern VCHIQ_STATUS_T vchiq_remote_release(VCHIQ_INSTANCE_T instance); + +extern VCHIQ_STATUS_T vchiq_dump_phys_mem(VCHIQ_SERVICE_HANDLE_T service, + void *ptr, size_t num_bytes); + +extern VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, + short *peer_version); + +#endif /* VCHIQ_IF_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h new file mode 100644 index 000000000000..6137ae9de1c1 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_IOCTLS_H +#define VCHIQ_IOCTLS_H + +#include +#include "vchiq_if.h" + +#define VCHIQ_IOC_MAGIC 0xc4 +#define VCHIQ_INVALID_HANDLE (~0) + +typedef struct { + VCHIQ_SERVICE_PARAMS_T params; + int is_open; + int is_vchi; + unsigned int handle; /* OUT */ +} VCHIQ_CREATE_SERVICE_T; + +typedef struct { + unsigned int handle; + unsigned int count; + const VCHIQ_ELEMENT_T *elements; +} VCHIQ_QUEUE_MESSAGE_T; + +typedef struct { + unsigned int handle; + void *data; + unsigned int size; + void *userdata; + VCHIQ_BULK_MODE_T mode; +} VCHIQ_QUEUE_BULK_TRANSFER_T; + +typedef struct { + VCHIQ_REASON_T reason; + VCHIQ_HEADER_T *header; + void *service_userdata; + void *bulk_userdata; +} VCHIQ_COMPLETION_DATA_T; + +typedef struct { + unsigned int count; + VCHIQ_COMPLETION_DATA_T *buf; + unsigned int msgbufsize; + unsigned int msgbufcount; /* IN/OUT */ + void **msgbufs; +} VCHIQ_AWAIT_COMPLETION_T; + +typedef struct { + unsigned int handle; + int blocking; + unsigned int bufsize; + void *buf; +} VCHIQ_DEQUEUE_MESSAGE_T; + +typedef struct { + unsigned int config_size; + VCHIQ_CONFIG_T *pconfig; +} VCHIQ_GET_CONFIG_T; + +typedef struct { + unsigned int handle; + VCHIQ_SERVICE_OPTION_T option; + int value; +} VCHIQ_SET_SERVICE_OPTION_T; + +typedef struct { + void *virt_addr; + size_t num_bytes; +} VCHIQ_DUMP_MEM_T; + +#define VCHIQ_IOC_CONNECT _IO(VCHIQ_IOC_MAGIC, 0) +#define VCHIQ_IOC_SHUTDOWN _IO(VCHIQ_IOC_MAGIC, 1) +#define VCHIQ_IOC_CREATE_SERVICE \ + _IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T) +#define VCHIQ_IOC_REMOVE_SERVICE _IO(VCHIQ_IOC_MAGIC, 3) +#define VCHIQ_IOC_QUEUE_MESSAGE \ + _IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T) +#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \ + _IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T) +#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \ + _IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T) +#define VCHIQ_IOC_AWAIT_COMPLETION \ + _IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T) +#define VCHIQ_IOC_DEQUEUE_MESSAGE \ + _IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T) +#define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9) +#define VCHIQ_IOC_GET_CONFIG \ + _IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T) +#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11) +#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12) +#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13) +#define VCHIQ_IOC_SET_SERVICE_OPTION \ + _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T) +#define VCHIQ_IOC_DUMP_PHYS_MEM \ + _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T) +#define VCHIQ_IOC_LIB_VERSION _IO(VCHIQ_IOC_MAGIC, 16) +#define VCHIQ_IOC_CLOSE_DELIVERED _IO(VCHIQ_IOC_MAGIC, 17) +#define VCHIQ_IOC_MAX 17 + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c new file mode 100644 index 000000000000..25e7011edc50 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c @@ -0,0 +1,458 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---- Include Files ---------------------------------------------------- */ + +#include +#include +#include + +#include "vchiq_core.h" +#include "vchiq_arm.h" +#include "vchiq_killable.h" + +/* ---- Public Variables ------------------------------------------------- */ + +/* ---- Private Constants and Types -------------------------------------- */ + +struct bulk_waiter_node { + struct bulk_waiter bulk_waiter; + int pid; + struct list_head list; +}; + +struct vchiq_instance_struct { + VCHIQ_STATE_T *state; + + int connected; + + struct list_head bulk_waiter_list; + struct mutex bulk_waiter_list_mutex; +}; + +static VCHIQ_STATUS_T +vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, + unsigned int size, VCHIQ_BULK_DIR_T dir); + +/**************************************************************************** +* +* vchiq_initialise +* +***************************************************************************/ +#define VCHIQ_INIT_RETRIES 10 +VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut) +{ + VCHIQ_STATUS_T status = VCHIQ_ERROR; + VCHIQ_STATE_T *state; + VCHIQ_INSTANCE_T instance = NULL; + int i; + + vchiq_log_trace(vchiq_core_log_level, "%s called", __func__); + + /* VideoCore may not be ready due to boot up timing. + It may never be ready if kernel and firmware are mismatched, so don't block forever. */ + for (i=0; i0) { + vchiq_log_warning(vchiq_core_log_level, + "%s: videocore initialized after %d retries\n", __func__, i); + } + + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) { + vchiq_log_error(vchiq_core_log_level, + "%s: error allocating vchiq instance\n", __func__); + goto failed; + } + + instance->connected = 0; + instance->state = state; + mutex_init(&instance->bulk_waiter_list_mutex); + INIT_LIST_HEAD(&instance->bulk_waiter_list); + + *instanceOut = instance; + + status = VCHIQ_SUCCESS; + +failed: + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + return status; +} +EXPORT_SYMBOL(vchiq_initialise); + +/**************************************************************************** +* +* vchiq_shutdown +* +***************************************************************************/ + +VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) +{ + VCHIQ_STATUS_T status; + VCHIQ_STATE_T *state = instance->state; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p) called", __func__, instance); + + if (mutex_lock_interruptible(&state->mutex) != 0) + return VCHIQ_RETRY; + + /* Remove all services */ + status = vchiq_shutdown_internal(state, instance); + + mutex_unlock(&state->mutex); + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + if (status == VCHIQ_SUCCESS) { + struct list_head *pos, *next; + list_for_each_safe(pos, next, + &instance->bulk_waiter_list) { + struct bulk_waiter_node *waiter; + waiter = list_entry(pos, + struct bulk_waiter_node, + list); + list_del(pos); + vchiq_log_info(vchiq_arm_log_level, + "bulk_waiter - cleaned up %x " + "for pid %d", + (unsigned int)waiter, waiter->pid); + kfree(waiter); + } + kfree(instance); + } + + return status; +} +EXPORT_SYMBOL(vchiq_shutdown); + +/**************************************************************************** +* +* vchiq_is_connected +* +***************************************************************************/ + +int vchiq_is_connected(VCHIQ_INSTANCE_T instance) +{ + return instance->connected; +} + +/**************************************************************************** +* +* vchiq_connect +* +***************************************************************************/ + +VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance) +{ + VCHIQ_STATUS_T status; + VCHIQ_STATE_T *state = instance->state; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p) called", __func__, instance); + + if (mutex_lock_interruptible(&state->mutex) != 0) { + vchiq_log_trace(vchiq_core_log_level, + "%s: call to mutex_lock failed", __func__); + status = VCHIQ_RETRY; + goto failed; + } + status = vchiq_connect_internal(state, instance); + + if (status == VCHIQ_SUCCESS) + instance->connected = 1; + + mutex_unlock(&state->mutex); + +failed: + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + return status; +} +EXPORT_SYMBOL(vchiq_connect); + +/**************************************************************************** +* +* vchiq_add_service +* +***************************************************************************/ + +VCHIQ_STATUS_T vchiq_add_service( + VCHIQ_INSTANCE_T instance, + const VCHIQ_SERVICE_PARAMS_T *params, + VCHIQ_SERVICE_HANDLE_T *phandle) +{ + VCHIQ_STATUS_T status; + VCHIQ_STATE_T *state = instance->state; + VCHIQ_SERVICE_T *service = NULL; + int srvstate; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p) called", __func__, instance); + + *phandle = VCHIQ_SERVICE_HANDLE_INVALID; + + srvstate = vchiq_is_connected(instance) + ? VCHIQ_SRVSTATE_LISTENING + : VCHIQ_SRVSTATE_HIDDEN; + + service = vchiq_add_service_internal( + state, + params, + srvstate, + instance, + NULL); + + if (service) { + *phandle = service->handle; + status = VCHIQ_SUCCESS; + } else + status = VCHIQ_ERROR; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + return status; +} +EXPORT_SYMBOL(vchiq_add_service); + +/**************************************************************************** +* +* vchiq_open_service +* +***************************************************************************/ + +VCHIQ_STATUS_T vchiq_open_service( + VCHIQ_INSTANCE_T instance, + const VCHIQ_SERVICE_PARAMS_T *params, + VCHIQ_SERVICE_HANDLE_T *phandle) +{ + VCHIQ_STATUS_T status = VCHIQ_ERROR; + VCHIQ_STATE_T *state = instance->state; + VCHIQ_SERVICE_T *service = NULL; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p) called", __func__, instance); + + *phandle = VCHIQ_SERVICE_HANDLE_INVALID; + + if (!vchiq_is_connected(instance)) + goto failed; + + service = vchiq_add_service_internal(state, + params, + VCHIQ_SRVSTATE_OPENING, + instance, + NULL); + + if (service) { + *phandle = service->handle; + status = vchiq_open_service_internal(service, current->pid); + if (status != VCHIQ_SUCCESS) { + vchiq_remove_service(service->handle); + *phandle = VCHIQ_SERVICE_HANDLE_INVALID; + } + } + +failed: + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + return status; +} +EXPORT_SYMBOL(vchiq_open_service); + +VCHIQ_STATUS_T +vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, + const void *data, unsigned int size, void *userdata) +{ + return vchiq_bulk_transfer(handle, + VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, + VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT); +} +EXPORT_SYMBOL(vchiq_queue_bulk_transmit); + +VCHIQ_STATUS_T +vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, + unsigned int size, void *userdata) +{ + return vchiq_bulk_transfer(handle, + VCHI_MEM_HANDLE_INVALID, data, size, userdata, + VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE); +} +EXPORT_SYMBOL(vchiq_queue_bulk_receive); + +VCHIQ_STATUS_T +vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data, + unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode) +{ + VCHIQ_STATUS_T status; + + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + status = vchiq_bulk_transfer(handle, + VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, + mode, VCHIQ_BULK_TRANSMIT); + break; + case VCHIQ_BULK_MODE_BLOCKING: + status = vchiq_blocking_bulk_transfer(handle, + (void *)data, size, VCHIQ_BULK_TRANSMIT); + break; + default: + return VCHIQ_ERROR; + } + + return status; +} +EXPORT_SYMBOL(vchiq_bulk_transmit); + +VCHIQ_STATUS_T +vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, + unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode) +{ + VCHIQ_STATUS_T status; + + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + status = vchiq_bulk_transfer(handle, + VCHI_MEM_HANDLE_INVALID, data, size, userdata, + mode, VCHIQ_BULK_RECEIVE); + break; + case VCHIQ_BULK_MODE_BLOCKING: + status = vchiq_blocking_bulk_transfer(handle, + (void *)data, size, VCHIQ_BULK_RECEIVE); + break; + default: + return VCHIQ_ERROR; + } + + return status; +} +EXPORT_SYMBOL(vchiq_bulk_receive); + +static VCHIQ_STATUS_T +vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, + unsigned int size, VCHIQ_BULK_DIR_T dir) +{ + VCHIQ_INSTANCE_T instance; + VCHIQ_SERVICE_T *service; + VCHIQ_STATUS_T status; + struct bulk_waiter_node *waiter = NULL; + struct list_head *pos; + + service = find_service_by_handle(handle); + if (!service) + return VCHIQ_ERROR; + + instance = service->instance; + + unlock_service(service); + + mutex_lock(&instance->bulk_waiter_list_mutex); + list_for_each(pos, &instance->bulk_waiter_list) { + if (list_entry(pos, struct bulk_waiter_node, + list)->pid == current->pid) { + waiter = list_entry(pos, + struct bulk_waiter_node, + list); + list_del(pos); + break; + } + } + mutex_unlock(&instance->bulk_waiter_list_mutex); + + if (waiter) { + VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; + if (bulk) { + /* This thread has an outstanding bulk transfer. */ + if ((bulk->data != data) || + (bulk->size != size)) { + /* This is not a retry of the previous one. + ** Cancel the signal when the transfer + ** completes. */ + spin_lock(&bulk_waiter_spinlock); + bulk->userdata = NULL; + spin_unlock(&bulk_waiter_spinlock); + } + } + } + + if (!waiter) { + waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL); + if (!waiter) { + vchiq_log_error(vchiq_core_log_level, + "%s - out of memory", __func__); + return VCHIQ_ERROR; + } + } + + status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID, + data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING, + dir); + if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || + !waiter->bulk_waiter.bulk) { + VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; + if (bulk) { + /* Cancel the signal when the transfer + ** completes. */ + spin_lock(&bulk_waiter_spinlock); + bulk->userdata = NULL; + spin_unlock(&bulk_waiter_spinlock); + } + kfree(waiter); + } else { + waiter->pid = current->pid; + mutex_lock(&instance->bulk_waiter_list_mutex); + list_add(&waiter->list, &instance->bulk_waiter_list); + mutex_unlock(&instance->bulk_waiter_list_mutex); + vchiq_log_info(vchiq_arm_log_level, + "saved bulk_waiter %x for pid %d", + (unsigned int)waiter, current->pid); + } + + return status; +} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h new file mode 100644 index 000000000000..335446e05476 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_KILLABLE_H +#define VCHIQ_KILLABLE_H + +#include +#include + +#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTRAP) | sigmask(SIGSTOP) | sigmask(SIGCONT)) + +static inline int __must_check down_interruptible_killable(struct semaphore *sem) +{ + /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ + int ret; + sigset_t blocked, oldset; + siginitsetinv(&blocked, SHUTDOWN_SIGS); + sigprocmask(SIG_SETMASK, &blocked, &oldset); + ret = down_interruptible(sem); + sigprocmask(SIG_SETMASK, &oldset, NULL); + return ret; +} +#define down_interruptible down_interruptible_killable + + +static inline int __must_check mutex_lock_interruptible_killable(struct mutex *lock) +{ + /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ + int ret; + sigset_t blocked, oldset; + siginitsetinv(&blocked, SHUTDOWN_SIGS); + sigprocmask(SIG_SETMASK, &blocked, &oldset); + ret = mutex_lock_interruptible(lock); + sigprocmask(SIG_SETMASK, &oldset, NULL); + return ret; +} +#define mutex_lock_interruptible mutex_lock_interruptible_killable + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h new file mode 100644 index 000000000000..d02e7764bd0d --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_MEMDRV_H +#define VCHIQ_MEMDRV_H + +/* ---- Include Files ----------------------------------------------------- */ + +#include +#include "vchiq_if.h" + +/* ---- Constants and Types ---------------------------------------------- */ + +typedef struct { + void *armSharedMemVirt; + dma_addr_t armSharedMemPhys; + size_t armSharedMemSize; + + void *vcSharedMemVirt; + dma_addr_t vcSharedMemPhys; + size_t vcSharedMemSize; +} VCHIQ_SHARED_MEM_INFO_T; + +/* ---- Variable Externs ------------------------------------------------- */ + +/* ---- Function Prototypes ---------------------------------------------- */ + +void vchiq_get_shared_mem_info(VCHIQ_SHARED_MEM_INFO_T *info); + +VCHIQ_STATUS_T vchiq_memdrv_initialise(void); + +VCHIQ_STATUS_T vchiq_userdrv_create_instance( + const VCHIQ_PLATFORM_DATA_T * platform_data); + +VCHIQ_STATUS_T vchiq_userdrv_suspend( + const VCHIQ_PLATFORM_DATA_T * platform_data); + +VCHIQ_STATUS_T vchiq_userdrv_resume( + const VCHIQ_PLATFORM_DATA_T * platform_data); + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h new file mode 100644 index 000000000000..54a3ecec69ef --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_PAGELIST_H +#define VCHIQ_PAGELIST_H + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif +#define CACHE_LINE_SIZE 32 +#define PAGELIST_WRITE 0 +#define PAGELIST_READ 1 +#define PAGELIST_READ_WITH_FRAGMENTS 2 + +typedef struct pagelist_struct { + unsigned long length; + unsigned short type; + unsigned short offset; + unsigned long addrs[1]; /* N.B. 12 LSBs hold the number of following + pages at consecutive addresses. */ +} PAGELIST_T; + +typedef struct fragments_struct { + char headbuf[CACHE_LINE_SIZE]; + char tailbuf[CACHE_LINE_SIZE]; +} FRAGMENTS_T; + +#endif /* VCHIQ_PAGELIST_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c new file mode 100644 index 000000000000..8072ff613636 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c @@ -0,0 +1,860 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#include "interface/vchi/vchi.h" +#include "vchiq.h" +#include "vchiq_core.h" + +#include "vchiq_util.h" + +#include + +#define vchiq_status_to_vchi(status) ((int32_t)status) + +typedef struct { + VCHIQ_SERVICE_HANDLE_T handle; + + VCHIU_QUEUE_T queue; + + VCHI_CALLBACK_T callback; + void *callback_param; +} SHIM_SERVICE_T; + +/* ---------------------------------------------------------------------- + * return pointer to the mphi message driver function table + * -------------------------------------------------------------------- */ +const VCHI_MESSAGE_DRIVER_T * +vchi_mphi_message_driver_func_table(void) +{ + return NULL; +} + +/* ---------------------------------------------------------------------- + * return a pointer to the 'single' connection driver fops + * -------------------------------------------------------------------- */ +const VCHI_CONNECTION_API_T * +single_get_func_table(void) +{ + return NULL; +} + +VCHI_CONNECTION_T *vchi_create_connection( + const VCHI_CONNECTION_API_T *function_table, + const VCHI_MESSAGE_DRIVER_T *low_level) +{ + (void)function_table; + (void)low_level; + return NULL; +} + +/*********************************************************** + * Name: vchi_msg_peek + * + * Arguments: const VCHI_SERVICE_HANDLE_T handle, + * void **data, + * uint32_t *msg_size, + + + * VCHI_FLAGS_T flags + * + * Description: Routine to return a pointer to the current message (to allow in + * place processing). The message can be removed using + * vchi_msg_remove when you're finished + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_HEADER_T *header; + + WARN_ON((flags != VCHI_FLAGS_NONE) && + (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); + + if (flags == VCHI_FLAGS_NONE) + if (vchiu_queue_is_empty(&service->queue)) + return -1; + + header = vchiu_queue_peek(&service->queue); + + *data = header->data; + *msg_size = header->size; + + return 0; +} +EXPORT_SYMBOL(vchi_msg_peek); + +/*********************************************************** + * Name: vchi_msg_remove + * + * Arguments: const VCHI_SERVICE_HANDLE_T handle, + * + * Description: Routine to remove a message (after it has been read with + * vchi_msg_peek) + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_HEADER_T *header; + + header = vchiu_queue_pop(&service->queue); + + vchiq_release_message(service->handle, header); + + return 0; +} +EXPORT_SYMBOL(vchi_msg_remove); + +/*********************************************************** + * Name: vchi_msg_queue + * + * Arguments: VCHI_SERVICE_HANDLE_T handle, + * const void *data, + * uint32_t data_size, + * VCHI_FLAGS_T flags, + * void *msg_handle, + * + * Description: Thin wrapper to queue a message onto a connection + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, + const void *data, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *msg_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_ELEMENT_T element = {data, data_size}; + VCHIQ_STATUS_T status; + + (void)msg_handle; + + WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); + + status = vchiq_queue_message(service->handle, &element, 1); + + /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to + ** implement a retry mechanism since this function is supposed + ** to block until queued + */ + while (status == VCHIQ_RETRY) { + msleep(1); + status = vchiq_queue_message(service->handle, &element, 1); + } + + return vchiq_status_to_vchi(status); +} +EXPORT_SYMBOL(vchi_msg_queue); + +/*********************************************************** + * Name: vchi_bulk_queue_receive + * + * Arguments: VCHI_BULK_HANDLE_T handle, + * void *data_dst, + * const uint32_t data_size, + * VCHI_FLAGS_T flags + * void *bulk_handle + * + * Description: Routine to setup a rcv buffer + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, + void *data_dst, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *bulk_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_BULK_MODE_T mode; + VCHIQ_STATUS_T status; + + switch ((int)flags) { + case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE + | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: + WARN_ON(!service->callback); + mode = VCHIQ_BULK_MODE_CALLBACK; + break; + case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: + mode = VCHIQ_BULK_MODE_BLOCKING; + break; + case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: + case VCHI_FLAGS_NONE: + mode = VCHIQ_BULK_MODE_NOCALLBACK; + break; + default: + WARN(1, "unsupported message\n"); + return vchiq_status_to_vchi(VCHIQ_ERROR); + } + + status = vchiq_bulk_receive(service->handle, data_dst, data_size, + bulk_handle, mode); + + /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to + ** implement a retry mechanism since this function is supposed + ** to block until queued + */ + while (status == VCHIQ_RETRY) { + msleep(1); + status = vchiq_bulk_receive(service->handle, data_dst, + data_size, bulk_handle, mode); + } + + return vchiq_status_to_vchi(status); +} +EXPORT_SYMBOL(vchi_bulk_queue_receive); + +/*********************************************************** + * Name: vchi_bulk_queue_transmit + * + * Arguments: VCHI_BULK_HANDLE_T handle, + * const void *data_src, + * uint32_t data_size, + * VCHI_FLAGS_T flags, + * void *bulk_handle + * + * Description: Routine to transmit some data + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, + const void *data_src, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *bulk_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_BULK_MODE_T mode; + VCHIQ_STATUS_T status; + + switch ((int)flags) { + case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE + | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: + WARN_ON(!service->callback); + mode = VCHIQ_BULK_MODE_CALLBACK; + break; + case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: + case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: + mode = VCHIQ_BULK_MODE_BLOCKING; + break; + case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: + case VCHI_FLAGS_NONE: + mode = VCHIQ_BULK_MODE_NOCALLBACK; + break; + default: + WARN(1, "unsupported message\n"); + return vchiq_status_to_vchi(VCHIQ_ERROR); + } + + status = vchiq_bulk_transmit(service->handle, data_src, data_size, + bulk_handle, mode); + + /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to + ** implement a retry mechanism since this function is supposed + ** to block until queued + */ + while (status == VCHIQ_RETRY) { + msleep(1); + status = vchiq_bulk_transmit(service->handle, data_src, + data_size, bulk_handle, mode); + } + + return vchiq_status_to_vchi(status); +} +EXPORT_SYMBOL(vchi_bulk_queue_transmit); + +/*********************************************************** + * Name: vchi_msg_dequeue + * + * Arguments: VCHI_SERVICE_HANDLE_T handle, + * void *data, + * uint32_t max_data_size_to_read, + * uint32_t *actual_msg_size + * VCHI_FLAGS_T flags + * + * Description: Routine to dequeue a message into the supplied buffer + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, + void *data, + uint32_t max_data_size_to_read, + uint32_t *actual_msg_size, + VCHI_FLAGS_T flags) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_HEADER_T *header; + + WARN_ON((flags != VCHI_FLAGS_NONE) && + (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); + + if (flags == VCHI_FLAGS_NONE) + if (vchiu_queue_is_empty(&service->queue)) + return -1; + + header = vchiu_queue_pop(&service->queue); + + memcpy(data, header->data, header->size < max_data_size_to_read ? + header->size : max_data_size_to_read); + + *actual_msg_size = header->size; + + vchiq_release_message(service->handle, header); + + return 0; +} +EXPORT_SYMBOL(vchi_msg_dequeue); + +/*********************************************************** + * Name: vchi_msg_queuev + * + * Arguments: VCHI_SERVICE_HANDLE_T handle, + * VCHI_MSG_VECTOR_T *vector, + * uint32_t count, + * VCHI_FLAGS_T flags, + * void *msg_handle + * + * Description: Thin wrapper to queue a message onto a connection + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ + +vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T)); +vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == + offsetof(VCHIQ_ELEMENT_T, data)); +vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == + offsetof(VCHIQ_ELEMENT_T, size)); + +int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle, + VCHI_MSG_VECTOR_T *vector, + uint32_t count, + VCHI_FLAGS_T flags, + void *msg_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + + (void)msg_handle; + + WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); + + return vchiq_status_to_vchi(vchiq_queue_message(service->handle, + (const VCHIQ_ELEMENT_T *)vector, count)); +} +EXPORT_SYMBOL(vchi_msg_queuev); + +/*********************************************************** + * Name: vchi_held_msg_release + * + * Arguments: VCHI_HELD_MSG_T *message + * + * Description: Routine to release a held message (after it has been read with + * vchi_msg_hold) + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) +{ + vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service, + (VCHIQ_HEADER_T *)message->message); + + return 0; +} +EXPORT_SYMBOL(vchi_held_msg_release); + +/*********************************************************** + * Name: vchi_msg_hold + * + * Arguments: VCHI_SERVICE_HANDLE_T handle, + * void **data, + * uint32_t *msg_size, + * VCHI_FLAGS_T flags, + * VCHI_HELD_MSG_T *message_handle + * + * Description: Routine to return a pointer to the current message (to allow + * in place processing). The message is dequeued - don't forget + * to release the message using vchi_held_msg_release when you're + * finished. + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags, + VCHI_HELD_MSG_T *message_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_HEADER_T *header; + + WARN_ON((flags != VCHI_FLAGS_NONE) && + (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); + + if (flags == VCHI_FLAGS_NONE) + if (vchiu_queue_is_empty(&service->queue)) + return -1; + + header = vchiu_queue_pop(&service->queue); + + *data = header->data; + *msg_size = header->size; + + message_handle->service = + (struct opaque_vchi_service_t *)service->handle; + message_handle->message = header; + + return 0; +} +EXPORT_SYMBOL(vchi_msg_hold); + +/*********************************************************** + * Name: vchi_initialise + * + * Arguments: VCHI_INSTANCE_T *instance_handle + * + * Description: Initialises the hardware but does not transmit anything + * When run as a Host App this will be called twice hence the need + * to malloc the state information + * + * Returns: 0 if successful, failure otherwise + * + ***********************************************************/ + +int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle) +{ + VCHIQ_INSTANCE_T instance; + VCHIQ_STATUS_T status; + + status = vchiq_initialise(&instance); + + *instance_handle = (VCHI_INSTANCE_T)instance; + + return vchiq_status_to_vchi(status); +} +EXPORT_SYMBOL(vchi_initialise); + +/*********************************************************** + * Name: vchi_connect + * + * Arguments: VCHI_CONNECTION_T **connections + * const uint32_t num_connections + * VCHI_INSTANCE_T instance_handle) + * + * Description: Starts the command service on each connection, + * causing INIT messages to be pinged back and forth + * + * Returns: 0 if successful, failure otherwise + * + ***********************************************************/ +int32_t vchi_connect(VCHI_CONNECTION_T **connections, + const uint32_t num_connections, + VCHI_INSTANCE_T instance_handle) +{ + VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; + + (void)connections; + (void)num_connections; + + return vchiq_connect(instance); +} +EXPORT_SYMBOL(vchi_connect); + + +/*********************************************************** + * Name: vchi_disconnect + * + * Arguments: VCHI_INSTANCE_T instance_handle + * + * Description: Stops the command service on each connection, + * causing DE-INIT messages to be pinged back and forth + * + * Returns: 0 if successful, failure otherwise + * + ***********************************************************/ +int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle) +{ + VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; + return vchiq_status_to_vchi(vchiq_shutdown(instance)); +} +EXPORT_SYMBOL(vchi_disconnect); + + +/*********************************************************** + * Name: vchi_service_open + * Name: vchi_service_create + * + * Arguments: VCHI_INSTANCE_T *instance_handle + * SERVICE_CREATION_T *setup, + * VCHI_SERVICE_HANDLE_T *handle + * + * Description: Routine to open a service + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ + +static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, + VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user) +{ + SHIM_SERVICE_T *service = + (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle); + + if (!service->callback) + goto release; + + switch (reason) { + case VCHIQ_MESSAGE_AVAILABLE: + vchiu_queue_push(&service->queue, header); + + service->callback(service->callback_param, + VCHI_CALLBACK_MSG_AVAILABLE, NULL); + + goto done; + break; + + case VCHIQ_BULK_TRANSMIT_DONE: + service->callback(service->callback_param, + VCHI_CALLBACK_BULK_SENT, bulk_user); + break; + + case VCHIQ_BULK_RECEIVE_DONE: + service->callback(service->callback_param, + VCHI_CALLBACK_BULK_RECEIVED, bulk_user); + break; + + case VCHIQ_SERVICE_CLOSED: + service->callback(service->callback_param, + VCHI_CALLBACK_SERVICE_CLOSED, NULL); + break; + + case VCHIQ_SERVICE_OPENED: + /* No equivalent VCHI reason */ + break; + + case VCHIQ_BULK_TRANSMIT_ABORTED: + service->callback(service->callback_param, + VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, + bulk_user); + break; + + case VCHIQ_BULK_RECEIVE_ABORTED: + service->callback(service->callback_param, + VCHI_CALLBACK_BULK_RECEIVE_ABORTED, + bulk_user); + break; + + default: + WARN(1, "not supported\n"); + break; + } + +release: + vchiq_release_message(service->handle, header); +done: + return VCHIQ_SUCCESS; +} + +static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance, + SERVICE_CREATION_T *setup) +{ + SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL); + + (void)instance; + + if (service) { + if (vchiu_queue_init(&service->queue, 64)) { + service->callback = setup->callback; + service->callback_param = setup->callback_param; + } else { + kfree(service); + service = NULL; + } + } + + return service; +} + +static void service_free(SHIM_SERVICE_T *service) +{ + if (service) { + vchiu_queue_delete(&service->queue); + kfree(service); + } +} + +int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, + SERVICE_CREATION_T *setup, + VCHI_SERVICE_HANDLE_T *handle) +{ + VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; + SHIM_SERVICE_T *service = service_alloc(instance, setup); + + *handle = (VCHI_SERVICE_HANDLE_T)service; + + if (service) { + VCHIQ_SERVICE_PARAMS_T params; + VCHIQ_STATUS_T status; + + memset(¶ms, 0, sizeof(params)); + params.fourcc = setup->service_id; + params.callback = shim_callback; + params.userdata = service; + params.version = setup->version.version; + params.version_min = setup->version.version_min; + + status = vchiq_open_service(instance, ¶ms, + &service->handle); + if (status != VCHIQ_SUCCESS) { + service_free(service); + service = NULL; + *handle = NULL; + } + } + + return (service != NULL) ? 0 : -1; +} +EXPORT_SYMBOL(vchi_service_open); + +int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, + SERVICE_CREATION_T *setup, + VCHI_SERVICE_HANDLE_T *handle) +{ + VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; + SHIM_SERVICE_T *service = service_alloc(instance, setup); + + *handle = (VCHI_SERVICE_HANDLE_T)service; + + if (service) { + VCHIQ_SERVICE_PARAMS_T params; + VCHIQ_STATUS_T status; + + memset(¶ms, 0, sizeof(params)); + params.fourcc = setup->service_id; + params.callback = shim_callback; + params.userdata = service; + params.version = setup->version.version; + params.version_min = setup->version.version_min; + status = vchiq_add_service(instance, ¶ms, &service->handle); + + if (status != VCHIQ_SUCCESS) { + service_free(service); + service = NULL; + *handle = NULL; + } + } + + return (service != NULL) ? 0 : -1; +} +EXPORT_SYMBOL(vchi_service_create); + +int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if (service) { + VCHIQ_STATUS_T status = vchiq_close_service(service->handle); + if (status == VCHIQ_SUCCESS) { + service_free(service); + service = NULL; + } + + ret = vchiq_status_to_vchi(status); + } + return ret; +} +EXPORT_SYMBOL(vchi_service_close); + +int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if (service) { + VCHIQ_STATUS_T status = vchiq_remove_service(service->handle); + if (status == VCHIQ_SUCCESS) { + service_free(service); + service = NULL; + } + + ret = vchiq_status_to_vchi(status); + } + return ret; +} +EXPORT_SYMBOL(vchi_service_destroy); + +int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle, + VCHI_SERVICE_OPTION_T option, + int value) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_SERVICE_OPTION_T vchiq_option; + switch (option) { + case VCHI_SERVICE_OPTION_TRACE: + vchiq_option = VCHIQ_SERVICE_OPTION_TRACE; + break; + case VCHI_SERVICE_OPTION_SYNCHRONOUS: + vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS; + break; + default: + service = NULL; + break; + } + if (service) { + VCHIQ_STATUS_T status = + vchiq_set_service_option(service->handle, + vchiq_option, + value); + + ret = vchiq_status_to_vchi(status); + } + return ret; +} +EXPORT_SYMBOL(vchi_service_set_option); + +int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version ) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if(service) + { + VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version); + ret = vchiq_status_to_vchi( status ); + } + return ret; +} +EXPORT_SYMBOL(vchi_get_peer_version); + +/* ---------------------------------------------------------------------- + * read a uint32_t from buffer. + * network format is defined to be little endian + * -------------------------------------------------------------------- */ +uint32_t +vchi_readbuf_uint32(const void *_ptr) +{ + const unsigned char *ptr = _ptr; + return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); +} + +/* ---------------------------------------------------------------------- + * write a uint32_t to buffer. + * network format is defined to be little endian + * -------------------------------------------------------------------- */ +void +vchi_writebuf_uint32(void *_ptr, uint32_t value) +{ + unsigned char *ptr = _ptr; + ptr[0] = (unsigned char)((value >> 0) & 0xFF); + ptr[1] = (unsigned char)((value >> 8) & 0xFF); + ptr[2] = (unsigned char)((value >> 16) & 0xFF); + ptr[3] = (unsigned char)((value >> 24) & 0xFF); +} + +/* ---------------------------------------------------------------------- + * read a uint16_t from buffer. + * network format is defined to be little endian + * -------------------------------------------------------------------- */ +uint16_t +vchi_readbuf_uint16(const void *_ptr) +{ + const unsigned char *ptr = _ptr; + return ptr[0] | (ptr[1] << 8); +} + +/* ---------------------------------------------------------------------- + * write a uint16_t into the buffer. + * network format is defined to be little endian + * -------------------------------------------------------------------- */ +void +vchi_writebuf_uint16(void *_ptr, uint16_t value) +{ + unsigned char *ptr = _ptr; + ptr[0] = (value >> 0) & 0xFF; + ptr[1] = (value >> 8) & 0xFF; +} + +/*********************************************************** + * Name: vchi_service_use + * + * Arguments: const VCHI_SERVICE_HANDLE_T handle + * + * Description: Routine to increment refcount on a service + * + * Returns: void + * + ***********************************************************/ +int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if (service) + ret = vchiq_status_to_vchi(vchiq_use_service(service->handle)); + return ret; +} +EXPORT_SYMBOL(vchi_service_use); + +/*********************************************************** + * Name: vchi_service_release + * + * Arguments: const VCHI_SERVICE_HANDLE_T handle + * + * Description: Routine to decrement refcount on a service + * + * Returns: void + * + ***********************************************************/ +int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if (service) + ret = vchiq_status_to_vchi( + vchiq_release_service(service->handle)); + return ret; +} +EXPORT_SYMBOL(vchi_service_release); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c new file mode 100644 index 000000000000..384acb8d2eae --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vchiq_util.h" +#include "vchiq_killable.h" + +static inline int is_pow2(int i) +{ + return i && !(i & (i - 1)); +} + +int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size) +{ + WARN_ON(!is_pow2(size)); + + queue->size = size; + queue->read = 0; + queue->write = 0; + queue->initialized = 1; + + sema_init(&queue->pop, 0); + sema_init(&queue->push, 0); + + queue->storage = kzalloc(size * sizeof(VCHIQ_HEADER_T *), GFP_KERNEL); + if (queue->storage == NULL) { + vchiu_queue_delete(queue); + return 0; + } + return 1; +} + +void vchiu_queue_delete(VCHIU_QUEUE_T *queue) +{ + if (queue->storage != NULL) + kfree(queue->storage); +} + +int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue) +{ + return queue->read == queue->write; +} + +int vchiu_queue_is_full(VCHIU_QUEUE_T *queue) +{ + return queue->write == queue->read + queue->size; +} + +void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header) +{ + if (!queue->initialized) + return; + + while (queue->write == queue->read + queue->size) { + if (down_interruptible(&queue->pop) != 0) { + flush_signals(current); + } + } + + /* + * Write to queue->storage must be visible after read from + * queue->read + */ + smp_mb(); + + queue->storage[queue->write & (queue->size - 1)] = header; + + /* + * Write to queue->storage must be visible before write to + * queue->write + */ + smp_wmb(); + + queue->write++; + + up(&queue->push); +} + +VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue) +{ + while (queue->write == queue->read) { + if (down_interruptible(&queue->push) != 0) { + flush_signals(current); + } + } + + up(&queue->push); // We haven't removed anything from the queue. + + /* + * Read from queue->storage must be visible after read from + * queue->write + */ + smp_rmb(); + + return queue->storage[queue->read & (queue->size - 1)]; +} + +VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue) +{ + VCHIQ_HEADER_T *header; + + while (queue->write == queue->read) { + if (down_interruptible(&queue->push) != 0) { + flush_signals(current); + } + } + + /* + * Read from queue->storage must be visible after read from + * queue->write + */ + smp_rmb(); + + header = queue->storage[queue->read & (queue->size - 1)]; + + /* + * Read from queue->storage must be visible before write to + * queue->read + */ + smp_mb(); + + queue->read++; + + up(&queue->pop); + + return header; +} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h new file mode 100644 index 000000000000..4055d4bf9f74 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_UTIL_H +#define VCHIQ_UTIL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for time_t */ +#include +#include + +#include "vchiq_if.h" + +typedef struct { + int size; + int read; + int write; + int initialized; + + struct semaphore pop; + struct semaphore push; + + VCHIQ_HEADER_T **storage; +} VCHIU_QUEUE_T; + +extern int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size); +extern void vchiu_queue_delete(VCHIU_QUEUE_T *queue); + +extern int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue); +extern int vchiu_queue_is_full(VCHIU_QUEUE_T *queue); + +extern void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header); + +extern VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue); +extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue); + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_version.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_version.c new file mode 100644 index 000000000000..b6bfa21155e4 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_version.c @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2010-2012 Broadcom. 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, + * without modification. + * 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. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "vchiq_build_info.h" +#include + +VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_hostname, "dc4-arm-01" ); +VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_version, "9245b4c35b99b3870e1f7dc598c5692b3c66a6f0 (tainted)" ); +VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_time, __TIME__ ); +VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_date, __DATE__ ); + +const char *vchiq_get_build_hostname( void ) +{ + return vchiq_build_hostname; +} + +const char *vchiq_get_build_version( void ) +{ + return vchiq_build_version; +} + +const char *vchiq_get_build_date( void ) +{ + return vchiq_build_date; +} + +const char *vchiq_get_build_time( void ) +{ + return vchiq_build_time; +} diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c index 28a45689e2f4..8e66a520266c 100644 --- a/drivers/staging/vme/devices/vme_pio2_core.c +++ b/drivers/staging/vme/devices/vme_pio2_core.c @@ -466,23 +466,23 @@ static void __exit pio2_exit(void) /* These are required for each board */ MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected"); -module_param_array(bus, int, &bus_num, S_IRUGO); +module_param_array(bus, int, &bus_num, 0444); MODULE_PARM_DESC(base, "Base VME address for PIO2 Registers"); -module_param_array(base, long, &base_num, S_IRUGO); +module_param_array(base, long, &base_num, 0444); MODULE_PARM_DESC(vector, "VME IRQ Vector (Lower 4 bits masked)"); -module_param_array(vector, int, &vector_num, S_IRUGO); +module_param_array(vector, int, &vector_num, 0444); MODULE_PARM_DESC(level, "VME IRQ Level"); -module_param_array(level, int, &level_num, S_IRUGO); +module_param_array(level, int, &level_num, 0444); MODULE_PARM_DESC(variant, "Last 4 characters of PIO2 board variant"); -module_param_array(variant, charp, &variant_num, S_IRUGO); +module_param_array(variant, charp, &variant_num, 0444); /* This is for debugging */ MODULE_PARM_DESC(loopback, "Enable loopback mode on all cards"); -module_param(loopback, bool, S_IRUGO); +module_param(loopback, bool, 0444); MODULE_DESCRIPTION("GE PIO2 6U VME I/O Driver"); MODULE_AUTHOR("Martyn Welch RATE_54M) diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index afb1e8bde975..dbcea4434725 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -619,7 +619,7 @@ CARDvSafeResetRx( static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv, unsigned short wRateIdx) { - unsigned int ui = (unsigned int) wRateIdx; + unsigned int ui = (unsigned int)wRateIdx; while (ui > RATE_1M) { if (priv->basic_rates & ((u32)0x1 << ui)) @@ -645,7 +645,7 @@ static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv, static unsigned short CARDwGetOFDMControlRate(struct vnt_private *priv, unsigned short wRateIdx) { - unsigned int ui = (unsigned int) wRateIdx; + unsigned int ui = (unsigned int)wRateIdx; pr_debug("BASIC RATE: %X\n", priv->basic_rates); diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index b7d43a5622ba..029a8df4ca1c 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -193,7 +193,8 @@ bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) MACvRegBitsOn(priv->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV); /* TX_PE will reserve 3 us for MAX2829 A mode only, - it is for better TX throughput */ + * it is for better TX throughput + */ if (priv->byRFType == RF_AIROHA7230) RFbAL7230SelectChannelPostProcess(priv, priv->byCurrentCh, diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 494164045a0f..f109eeac358d 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -113,10 +113,10 @@ DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); /* BasebandType[] baseband type selected - 0: indicate 802.11a type - 1: indicate 802.11b type - 2: indicate 802.11g type -*/ + * 0: indicate 802.11a type + * 1: indicate 802.11b type + * 2: indicate 802.11g type + */ #define BBP_TYPE_MIN 0 #define BBP_TYPE_MAX 2 #define BBP_TYPE_DEF 2 @@ -477,7 +477,7 @@ static bool device_init_rings(struct vnt_private *priv) CB_MAX_BUF_SIZE, &priv->tx_bufs_dma0, GFP_ATOMIC); - if (priv->tx0_bufs == NULL) { + if (!priv->tx0_bufs) { dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n"); dma_free_coherent(&priv->pcid->dev, @@ -735,7 +735,7 @@ static bool device_alloc_rx_buf(struct vnt_private *priv, struct vnt_rd_info *rd_info = rd->rd_info; rd_info->skb = dev_alloc_skb((int)priv->rx_buf_sz); - if (rd_info->skb == NULL) + if (!rd_info->skb) return false; rd_info->skb_dma = diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index ffcaf25fdd8b..e161d5d9aebb 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -31,16 +31,6 @@ #include "key.h" #include "mac.h" -int vnt_key_init_table(struct vnt_private *priv) -{ - u32 i; - - for (i = 0; i < MAX_KEY_TABLE; i++) - MACvDisableKeyEntry(priv, i); - - return 0; -} - static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, struct ieee80211_key_conf *key, u32 key_type, u32 mode, bool onfly_latch) diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h index 261f8181d410..d72719741a56 100644 --- a/drivers/staging/vt6655/key.h +++ b/drivers/staging/vt6655/key.h @@ -61,8 +61,6 @@ struct vnt_private; -int vnt_key_init_table(struct vnt_private *); - int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct ieee80211_vif *vif, struct ieee80211_key_conf *key); diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index bc8ca981a629..7d6e7464ae51 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -52,7 +52,7 @@ /*--------------------- Export Functions --------------------------*/ -/*+ +/* * * Routine Description: * Enable hw power saving functions @@ -60,7 +60,7 @@ * Return Value: * None. * - -*/ + */ void PSvEnablePowerSaving( @@ -104,7 +104,7 @@ PSvEnablePowerSaving( pr_debug("PS:Power Saving Mode Enable...\n"); } -/*+ +/* * * Routine Description: * Disable hw power saving functions @@ -112,7 +112,7 @@ PSvEnablePowerSaving( * Return Value: * None. * - -*/ + */ void PSvDisablePowerSaving( @@ -134,7 +134,7 @@ PSvDisablePowerSaving( } -/*+ +/* * * Routine Description: * Check if Next TBTT must wake up @@ -142,7 +142,7 @@ PSvDisablePowerSaving( * Return Value: * None. * - -*/ + */ bool PSbIsNextTBTTWakeUp( diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index ae10da21ddd0..447882c7a6be 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -169,7 +169,8 @@ static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { }; /* 40MHz reference frequency - * Need to Pull PLLON(PE3) low when writing channel registers through 3-wire.*/ + * Need to Pull PLLON(PE3) low when writing channel registers through 3-wire. + */ static const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = { 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ @@ -463,7 +464,8 @@ static bool s_bAL7230Init(struct vnt_private *priv) } /* Need to Pull PLLON low when writing channel registers through - * 3-wire interface */ + * 3-wire interface + */ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byChannel) { void __iomem *dwIoBase = priv->PortOffset; @@ -873,7 +875,8 @@ bool RFbRawSetPower( case RF_AIROHA7230: /* 0x080F1B00 for 3 wire control TxGain(D10) - * and 0x31 as TX Gain value */ + * and 0x31 as TX Gain value + */ dwMax7230Pwr = 0x080C0B00 | ((byPwr) << 12) | (BY_AL7230_REG_LEN << 3) | IFREGCTL_REGW; @@ -886,7 +889,7 @@ bool RFbRawSetPower( return ret; } -/*+ +/* * * Routine Description: * Translate RSSI to dBm @@ -900,7 +903,7 @@ bool RFbRawSetPower( * * Return Value: none * - -*/ + */ void RFvRSSITodBm( struct vnt_private *priv, @@ -927,7 +930,8 @@ RFvRSSITodBm( } /* Post processing for the 11b/g and 11a. - * for save time on changing Reg2,3,5,7,10,12,15 */ + * for save time on changing Reg2,3,5,7,10,12,15 + */ bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, u16 byOldChannel, u16 byNewChannel) @@ -938,7 +942,8 @@ bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, /* if change between 11 b/g and 11a need to update the following * register - * Channel Index 1~14 */ + * Channel Index 1~14 + */ if ((byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G)) { /* Change from 2.4G to 5G [Reg] */ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[2]); diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index e4c3165ae027..7e69bc99d60f 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -64,8 +64,10 @@ /*--------------------- Static Functions --------------------------*/ /*--------------------- Static Definitions -------------------------*/ -#define CRITICAL_PACKET_LEN 256 /* if packet size < 256 -> in-direct send - packet size >= 256 -> direct send */ +/* if packet size < 256 -> in-direct send + * vpacket size >= 256 -> direct send + */ +#define CRITICAL_PACKET_LEN 256 static const unsigned short wTimeStampOff[2][MAX_RATE] = { {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, /* Long Preamble */ @@ -158,11 +160,11 @@ static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate) [rate % MAX_RATE]); } -/*byPktType : PK_TYPE_11A 0 - PK_TYPE_11B 1 - PK_TYPE_11GB 2 - PK_TYPE_11GA 3 -*/ +/* byPktType : PK_TYPE_11A 0 + * PK_TYPE_11B 1 + * PK_TYPE_11GB 2 + * PK_TYPE_11GA 3 + */ static unsigned int s_uGetTxRsvTime( @@ -502,7 +504,7 @@ s_uFillDataHead( ) { - if (pTxDataHead == NULL) + if (!pTxDataHead) return 0; @@ -646,17 +648,20 @@ s_vFillRTSHead( { unsigned int uRTSFrameLen = 20; - if (pvRTS == NULL) + if (!pvRTS) return; if (bDisCRC) { - /* When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame, - in this case we need to decrease its length by 4. */ + /* When CRCDIS bit is on, H/W forgot to generate FCS for + * RTS frame, in this case we need to decrease its length by 4. + */ uRTSFrameLen -= 4; } - /* Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, so we don't need to take them into account. - Otherwise, we need to modify codes for them. */ + /* Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, + * so we don't need to take them into account. + * Otherwise, we need to modify codes for them. + */ if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { if (byFBOption == AUTO_FB_NONE) { struct vnt_rts_g *buf = pvRTS; @@ -838,12 +843,13 @@ s_vFillCTSHead( { unsigned int uCTSFrameLen = 14; - if (pvCTS == NULL) + if (!pvCTS) return; if (bDisCRC) { - /* When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame, - in this case we need to decrease its length by 4. */ + /* When CRCDIS bit is on, H/W forgot to generate FCS for + * CTS frame, in this case we need to decrease its length by 4. + */ uCTSFrameLen -= 4; } @@ -915,7 +921,7 @@ s_vFillCTSHead( } } -/*+ +/* * * Description: * Generate FIFO control for MAC & Baseband controller @@ -937,7 +943,8 @@ s_vFillCTSHead( * Return Value: none * - - * unsigned int cbFrameSize, Hdr+Payload+FCS */ + * unsigned int cbFrameSize, Hdr+Payload+FCS + */ static void s_vGenerateTxParameter( @@ -972,8 +979,8 @@ s_vGenerateTxParameter( return; if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { - if (pvRTS != NULL) { /* RTS_need - Fill RsvTime */ + if (pvRTS != NULL) { /* RTS_need */ + /* Fill RsvTime */ struct vnt_rrv_time_rts *buf = pvRrvTime; buf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); @@ -1002,7 +1009,7 @@ s_vGenerateTxParameter( /* Fill RTS */ s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); - } else if (pvRTS == NULL) {/* RTS_needless, non PCF mode */ + } else if (!pvRTS) {/* RTS_needless, non PCF mode */ struct vnt_rrv_time_ab *buf = pvRrvTime; buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK); diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h index 807a5809b5d9..7cc13874f8f1 100644 --- a/drivers/staging/vt6656/baseband.h +++ b/drivers/staging/vt6656/baseband.h @@ -84,10 +84,10 @@ struct vnt_phy_field { } __packed; unsigned int vnt_get_frame_time(u8 preamble_type, u8 pkt_type, - unsigned int frame_length, u16 tx_rate); + unsigned int frame_length, u16 tx_rate); void vnt_get_phy_field(struct vnt_private *, u32 frame_length, - u16 tx_rate, u8 pkt_type, struct vnt_phy_field *); + u16 tx_rate, u8 pkt_type, struct vnt_phy_field *); void vnt_set_short_slot_time(struct vnt_private *); void vnt_set_vga_gain_offset(struct vnt_private *, u8); diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index a382fc6aa9d3..53b469c71dc2 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -46,10 +46,11 @@ #include "key.h" #include "usbpipe.h" -/* const u16 cwRXBCNTSFOff[MAX_RATE] = - {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; */ +/* const u16 cw_rxbcntsf_off[MAX_RATE] = + * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; + */ -static const u16 cwRXBCNTSFOff[MAX_RATE] = { +static const u16 cw_rxbcntsf_off[MAX_RATE] = { 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3 }; @@ -65,7 +66,6 @@ static const u16 cwRXBCNTSFOff[MAX_RATE] = { */ void vnt_set_channel(struct vnt_private *priv, u32 connection_channel) { - if (connection_channel > CB_MAX_CHANNEL || !connection_channel) return; @@ -76,10 +76,10 @@ void vnt_set_channel(struct vnt_private *priv, u32 connection_channel) vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL, 0xb0); vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL, - connection_channel, 0, 0, NULL); + connection_channel, 0, 0, NULL); vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL, - (u8)(connection_channel | 0x80)); + (u8)(connection_channel | 0x80)); } /* @@ -126,11 +126,11 @@ static u16 vnt_get_ofdm_rate(struct vnt_private *priv, u16 rate_idx) u16 ui = rate_idx; dev_dbg(&priv->usb->dev, "%s basic rate: %d\n", - __func__, priv->basic_rates); + __func__, priv->basic_rates); if (!vnt_ofdm_min_rate(priv)) { dev_dbg(&priv->usb->dev, "%s (NO OFDM) %d\n", - __func__, rate_idx); + __func__, rate_idx); if (rate_idx > RATE_24M) rate_idx = RATE_24M; return rate_idx; @@ -139,7 +139,7 @@ static u16 vnt_get_ofdm_rate(struct vnt_private *priv, u16 rate_idx) while (ui > RATE_11M) { if (priv->basic_rates & (1 << ui)) { dev_dbg(&priv->usb->dev, "%s rate: %d\n", - __func__, ui); + __func__, ui); return ui; } ui--; @@ -165,9 +165,8 @@ static u16 vnt_get_ofdm_rate(struct vnt_private *priv, u16 rate_idx) * */ static void vnt_calculate_ofdm_rate(u16 rate, u8 bb_type, - u8 *tx_rate, u8 *rsv_time) + u8 *tx_rate, u8 *rsv_time) { - switch (rate) { case RATE_6M: if (bb_type == BB_TYPE_11A) { @@ -267,20 +266,20 @@ void vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) int i; /*RSPINF_b_1*/ - vnt_get_phy_field(priv, 14, - vnt_get_cck_rate(priv, RATE_1M), PK_TYPE_11B, &phy[0]); + vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_1M), + PK_TYPE_11B, &phy[0]); /*RSPINF_b_2*/ - vnt_get_phy_field(priv, 14, - vnt_get_cck_rate(priv, RATE_2M), PK_TYPE_11B, &phy[1]); + vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_2M), + PK_TYPE_11B, &phy[1]); /*RSPINF_b_5*/ - vnt_get_phy_field(priv, 14, - vnt_get_cck_rate(priv, RATE_5M), PK_TYPE_11B, &phy[2]); + vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_5M), + PK_TYPE_11B, &phy[2]); /*RSPINF_b_11*/ - vnt_get_phy_field(priv, 14, - vnt_get_cck_rate(priv, RATE_11M), PK_TYPE_11B, &phy[3]); + vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_11M), + PK_TYPE_11B, &phy[3]); /*RSPINF_a_6*/ vnt_calculate_ofdm_rate(RATE_6M, bb_type, &tx_rate[0], &rsv_time[0]); @@ -299,19 +298,19 @@ void vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) /*RSPINF_a_36*/ vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_36M), - bb_type, &tx_rate[5], &rsv_time[5]); + bb_type, &tx_rate[5], &rsv_time[5]); /*RSPINF_a_48*/ vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_48M), - bb_type, &tx_rate[6], &rsv_time[6]); + bb_type, &tx_rate[6], &rsv_time[6]); /*RSPINF_a_54*/ vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_54M), - bb_type, &tx_rate[7], &rsv_time[7]); + bb_type, &tx_rate[7], &rsv_time[7]); /*RSPINF_a_72*/ vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_54M), - bb_type, &tx_rate[8], &rsv_time[8]); + bb_type, &tx_rate[8], &rsv_time[8]); put_unaligned(phy[0].len, (u16 *)&data[0]); data[2] = phy[0].signal; @@ -334,8 +333,8 @@ void vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) data[16 + i * 2 + 1] = rsv_time[i]; } - vnt_control_out(priv, MESSAGE_TYPE_WRITE, - MAC_REG_RSPINF_B_1, MESSAGE_REQUEST_MACREG, 34, &data[0]); + vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1, + MESSAGE_REQUEST_MACREG, 34, &data[0]); } /* @@ -429,12 +428,12 @@ void vnt_update_ifs(struct vnt_private *priv) data[3] = (u8)priv->slot; vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS, - MESSAGE_REQUEST_MACREG, 4, &data[0]); + MESSAGE_REQUEST_MACREG, 4, &data[0]); max_min |= 0xa0; vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0, - MESSAGE_REQUEST_MACREG, 1, &max_min); + MESSAGE_REQUEST_MACREG, 1, &max_min); } void vnt_update_top_rates(struct vnt_private *priv) @@ -478,7 +477,6 @@ int vnt_ofdm_min_rate(struct vnt_private *priv) u8 vnt_get_pkt_type(struct vnt_private *priv) { - if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B) return (u8)priv->bb_type; else if (vnt_ofdm_min_rate(priv)) @@ -506,7 +504,7 @@ u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) u64 tsf_offset = 0; u16 rx_bcn_offset; - rx_bcn_offset = cwRXBCNTSFOff[rx_rate % MAX_RATE]; + rx_bcn_offset = cw_rxbcntsf_off[rx_rate % MAX_RATE]; tsf2 += (u64)rx_bcn_offset; @@ -531,7 +529,7 @@ u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) * */ void vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, - u64 time_stamp, u64 local_tsf) + u64 time_stamp, u64 local_tsf) { u64 tsf_offset = 0; u8 data[8]; @@ -548,8 +546,9 @@ void vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, data[7] = (u8)(tsf_offset >> 56); vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, - MESSAGE_REQUEST_TSF, 0, 8, data); + MESSAGE_REQUEST_TSF, 0, 8, data); } + /* * Description: Read NIC TSF counter * Get local TSF counter @@ -565,7 +564,6 @@ void vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, */ bool vnt_get_current_tsf(struct vnt_private *priv, u64 *current_tsf) { - *current_tsf = priv->current_tsf; return true; @@ -584,7 +582,6 @@ bool vnt_get_current_tsf(struct vnt_private *priv, u64 *current_tsf) */ bool vnt_clear_current_tsf(struct vnt_private *priv) { - vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); priv->current_tsf = 0; @@ -657,7 +654,7 @@ void vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval) data[7] = (u8)(next_tbtt >> 56); vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, - MESSAGE_REQUEST_TBTT, 0, 8, data); + MESSAGE_REQUEST_TBTT, 0, 8, data); } /* @@ -676,7 +673,7 @@ void vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval) * */ void vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf, - u16 beacon_interval) + u16 beacon_interval) { u8 data[8]; @@ -721,7 +718,7 @@ int vnt_radio_power_off(struct vnt_private *priv) case RF_VT3226D0: case RF_VT3342A0: vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL, - (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); + (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); break; } @@ -762,7 +759,7 @@ int vnt_radio_power_on(struct vnt_private *priv) case RF_VT3226D0: case RF_VT3342A0: vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL, - (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); + (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); break; } @@ -795,7 +792,7 @@ void vnt_set_bss_mode(struct vnt_private *priv) priv->bb_vga[0] = 0x20; vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, - 0xe7, priv->bb_vga[0]); + 0xe7, priv->bb_vga[0]); } priv->bb_vga[2] = 0x10; @@ -805,7 +802,7 @@ void vnt_set_bss_mode(struct vnt_private *priv) priv->bb_vga[0] = 0x1c; vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, - 0xe7, priv->bb_vga[0]); + 0xe7, priv->bb_vga[0]); } priv->bb_vga[2] = 0x0; diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 6019aac8bdd5..655f0002f880 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -34,7 +34,7 @@ #include "rf.h" int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, - unsigned long bytes_received) + unsigned long bytes_received) { struct ieee80211_hw *hw = priv->hw; struct ieee80211_supported_band *sband; @@ -46,7 +46,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, __le64 *tsf_time; u32 frame_size; int ii, r; - u8 *rx_sts, *rx_rate, *sq, *sq_3; + u8 *rx_rate, *sq, *sq_3; u32 wbk_status; u8 *skb_data; u16 *pay_load_len; @@ -75,22 +75,21 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, skb_data = (u8 *)skb->data; - rx_sts = skb_data+4; - rx_rate = skb_data+5; + rx_rate = skb_data + 5; /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */ /* -8TSF - 4RSR - 4SQ3 - ?Padding */ /* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */ - pay_load_len = (u16 *) (skb_data + 6); + pay_load_len = (u16 *)(skb_data + 6); /*Fix hardware bug => PLCP_Length error */ if (((bytes_received - (*pay_load_len)) > 27) || - ((bytes_received - (*pay_load_len)) < 24) || - (bytes_received < (*pay_load_len))) { + ((bytes_received - (*pay_load_len)) < 24) || + (bytes_received < (*pay_load_len))) { dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n", - *pay_load_len); + *pay_load_len); return false; } diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h index 5a92bd86cee2..ff1850c4a927 100644 --- a/drivers/staging/vt6656/dpc.h +++ b/drivers/staging/vt6656/dpc.h @@ -29,6 +29,6 @@ #include "device.h" int vnt_rx_data(struct vnt_private *, struct vnt_rcb *, - unsigned long bytes_received); + unsigned long bytes_received); #endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index ac4fecb30d0e..0594828bdabf 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -440,10 +440,8 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) /* allocate URBs */ tx_context->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!tx_context->urb) { - dev_err(&priv->usb->dev, "alloc tx urb failed\n"); + if (!tx_context->urb) goto free_tx; - } tx_context->in_use = false; } @@ -462,10 +460,8 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) /* allocate URBs */ rcb->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rcb->urb) { - dev_err(&priv->usb->dev, "Failed to alloc rx urb\n"); + if (!rcb->urb) goto free_rx_tx; - } rcb->skb = dev_alloc_skb(priv->rx_buf_sz); if (!rcb->skb) @@ -479,10 +475,8 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) } priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!priv->interrupt_urb) { - dev_err(&priv->usb->dev, "Failed to alloc int urb\n"); + if (!priv->interrupt_urb) goto free_rx_tx; - } priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL); if (!priv->int_buf.data_buf) { diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index f546553de66f..e9b6b21f7422 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -28,8 +28,9 @@ * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM * * Revision History: - * 04-05-2004 Jerry Chen: Initial release - * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte + * 04-05-2004 Jerry Chen: Initial release + * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte, + * ControlvMaskByte * */ diff --git a/drivers/staging/wilc1000/TODO b/drivers/staging/wilc1000/TODO index ec93b2ee0b08..ae61b55f14fd 100644 --- a/drivers/staging/wilc1000/TODO +++ b/drivers/staging/wilc1000/TODO @@ -3,7 +3,6 @@ TODO: - remove OS wrapper functions - remove custom debug and tracing functions - rework comments and function headers(also coding style) -- replace all semaphores with mutexes or completions - Move handling for each individual members of 'union message_body' out into a separate 'struct work_struct' and completely remove the multiplexer that is currently part of host_if_work(), allowing movement of the diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 076e06ac0d66..cff16984167b 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -70,11 +70,11 @@ enum connect_status { CONNECT_STS_FORCE_16_BIT = 0xFFFF }; -typedef struct { +struct tstrRSSI { u8 u8Full; u8 u8Index; s8 as8RSSI[NUM_RSSI]; -} tstrRSSI; +}; struct network_info { s8 rssi; @@ -93,7 +93,7 @@ struct network_info { u8 *ies; u16 ies_len; void *join_params; - tstrRSSI str_rssi; + struct tstrRSSI str_rssi; u64 tsf_hi; }; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 78f524fcd214..78f5613e9467 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3279,7 +3279,6 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *cfg_param) { - int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; @@ -3293,9 +3292,7 @@ int wilc_hif_set_cfg(struct wilc_vif *vif, msg.body.cfg_info = *cfg_param; msg.vif = vif; - result = wilc_enqueue_cmd(&msg); - - return result; + return wilc_enqueue_cmd(&msg); } static void GetPeriodicRSSI(unsigned long arg) @@ -3329,7 +3326,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) init_completion(&hif_wait_response); - hif_drv = kzalloc(sizeof(struct host_if_drv), GFP_KERNEL); + hif_drv = kzalloc(sizeof(*hif_drv), GFP_KERNEL); if (!hif_drv) { result = -ENOMEM; goto _fail_; @@ -3878,7 +3875,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pu8IEs = ptstrNetworkInfo->ies; u16IEsLen = ptstrNetworkInfo->ies_len; - pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL); + pNewJoinBssParam = kzalloc(sizeof(*pNewJoinBssParam), GFP_KERNEL); if (pNewJoinBssParam) { pNewJoinBssParam->dtim_period = ptstrNetworkInfo->dtim_period; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period; diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 32215110d597..6370a5efe343 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -21,7 +21,6 @@ #include #include #include -#include #include static int dev_state_ev_handler(struct notifier_block *this, diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index fcbc95d19d8e..802bb1d5e207 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -29,7 +29,7 @@ static struct dentry *wilc_dir; #define ERR BIT(3) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) -atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); +static atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); EXPORT_SYMBOL_GPL(WILC_DEBUG_LEVEL); /* @@ -102,35 +102,16 @@ static struct wilc_debugfs_info_t debugfs_info[] = { static int __init wilc_debugfs_init(void) { int i; - - struct dentry *debugfs_files; struct wilc_debugfs_info_t *info; wilc_dir = debugfs_create_dir("wilc_wifi", NULL); - if (wilc_dir == ERR_PTR(-ENODEV)) { - /* it's not error. the debugfs is just not being enabled. */ - printk("ERR, kernel has built without debugfs support\n"); - return 0; - } - - if (!wilc_dir) { - printk("ERR, debugfs create dir\n"); - return -1; - } - for (i = 0; i < ARRAY_SIZE(debugfs_info); i++) { info = &debugfs_info[i]; - debugfs_files = debugfs_create_file(info->name, - info->perm, - wilc_dir, - &info->data, - &info->fops); - - if (!debugfs_files) { - printk("ERR fail to create the debugfs file, %s\n", info->name); - debugfs_remove_recursive(wilc_dir); - return -1; - } + debugfs_create_file(info->name, + info->perm, + wilc_dir, + &info->data, + &info->fops); } return 0; } diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 22cf4b7857e5..f08cf6d9e1af 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -410,8 +410,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (len2 > ARRAY_SIZE(wb)) { dev_err(&spi->dev, "spi buffer size too small (%d) (%zu)\n", len2, ARRAY_SIZE(wb)); - result = N_FAIL; - return result; + return N_FAIL; } /* zero spi write buffers. */ for (wix = len; wix < len2; wix++) @@ -420,8 +419,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (wilc_spi_tx_rx(wilc, wb, rb, len2)) { dev_err(&spi->dev, "Failed cmd write, bus error...\n"); - result = N_FAIL; - return result; + return N_FAIL; } /** @@ -442,8 +440,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, dev_err(&spi->dev, "Failed cmd response, cmd (%02x), resp (%02x)\n", cmd, rsp); - result = N_FAIL; - return result; + return N_FAIL; } /** @@ -453,8 +450,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (rsp != 0x00) { dev_err(&spi->dev, "Failed cmd state response state (%02x)\n", rsp); - result = N_FAIL; - return result; + return N_FAIL; } if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ) @@ -481,8 +477,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (retry <= 0) { dev_err(&spi->dev, "Error, data read response (%02x)\n", rsp); - result = N_RESET; - return result; + return N_RESET; } if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) { @@ -497,8 +492,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, } else { dev_err(&spi->dev, "buffer overrun when reading data.\n"); - result = N_FAIL; - return result; + return N_FAIL; } if (!g_spi.crc_off) { @@ -510,8 +504,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, crc[1] = rb[rix++]; } else { dev_err(&spi->dev, "buffer overrun when reading crc.\n"); - result = N_FAIL; - return result; + return N_FAIL; } } } else if ((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { @@ -551,7 +544,6 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, } } - ix += nbytes; sz -= nbytes; } @@ -587,7 +579,6 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (result == N_FAIL) break; - /** * Read bytes **/ @@ -687,7 +678,6 @@ static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) sz -= nbytes; } while (sz); - return result; } @@ -850,7 +840,6 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) static int isinit; if (isinit) { - if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) { dev_err(&spi->dev, "Fail cmd read chip id...\n"); return 0; @@ -871,7 +860,7 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) /* Read failed. Try with CRC off. This might happen when module * is removed but chip isn't reset*/ g_spi.crc_off = 1; - dev_err(&spi->dev, "Failed internal read protocol with CRC on, retyring with CRC off...\n"); + dev_err(&spi->dev, "Failed internal read protocol with CRC on, retrying with CRC off...\n"); if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { /* Reaad failed with both CRC on and off, something went bad */ dev_err(&spi->dev, @@ -890,7 +879,6 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) g_spi.crc_off = 1; } - /** * make sure can read back chip id correctly **/ @@ -931,14 +919,10 @@ static int wilc_spi_read_size(struct wilc *wilc, u32 *size) *size = tmp; } - - _fail_: return ret; } - - static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status) { struct spi_device *spi = to_spi_device(wilc->dev); @@ -993,7 +977,6 @@ static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status) } *int_status = tmp; - } _fail_: diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 2c2e8aca8305..60d8b055bb2f 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2200,7 +2200,7 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, return ret; } -static struct cfg80211_ops wilc_cfg80211_ops = { +static const struct cfg80211_ops wilc_cfg80211_ops = { .set_monitor_channel = set_channel, .scan = scan, .connect = connect, diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 5cc6a82d8081..ec6b1674cf38 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -131,7 +131,7 @@ struct wilc_priv { struct wilc_wfi_key *wilc_gtk[MAX_NUM_STA]; struct wilc_wfi_key *wilc_ptk[MAX_NUM_STA]; u8 wilc_groupkey; - /* semaphores */ + /* mutexes */ struct mutex scan_req_lock; /* */ bool gbAutoRateAdjusted; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 19a580939dfc..bc5ad20af0a3 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -621,9 +621,9 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (!ret) break; - if ((reg & 0x1) == 0) { + if ((reg & 0x1) == 0) break; - } + counter++; if (counter > 200) { counter = 0; @@ -1001,8 +1001,7 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg); if (!ret) { release_bus(wilc, RELEASE_ONLY); - ret = -EIO; - return ret; + return -EIO; } reg = 0; if (wilc->io_type == HIF_SDIO && wilc->dev_irq_num) @@ -1034,8 +1033,7 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg); if (!ret) { release_bus(wilc, RELEASE_ONLY); - ret = -EIO; - return ret; + return -EIO; } wilc->hif_func->hif_sync_ext(wilc, NUM_INT_EXT); @@ -1043,8 +1041,7 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_read_reg(wilc, 0x1000, &chipid); if (!ret) { release_bus(wilc, RELEASE_ONLY); - ret = -EIO; - return ret; + return -EIO; } wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 30e5312ee87e..de6c4ddbf45a 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -192,7 +192,7 @@ #define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM) #define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM) -/*time for expiring the semaphores of cfg packets*/ +/*time for expiring the completion of cfg packets*/ #define CFG_PKTS_TIMEOUT 2000 /******************************************** * diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 410bfc034319..439ac6f8d533 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -10,7 +10,6 @@ #ifndef WILC_WLAN_IF_H #define WILC_WLAN_IF_H -#include #include /******************************************** diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index f46dfe6b24e8..182b2d564627 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -35,7 +35,7 @@ static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = { /* prism2 device private data */ struct prism2_wiphy_private { - wlandevice_t *wlandev; + struct wlandevice *wlandev; struct ieee80211_supported_band band; struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)]; @@ -69,11 +69,11 @@ static int prism2_result2err(int prism2_result) return err; } -static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) +static int prism2_domibset_uint32(struct wlandevice *wlandev, u32 did, u32 data) { struct p80211msg_dot11req_mibset msg; - p80211item_uint32_t *mibitem = - (p80211item_uint32_t *)&msg.mibattribute.data; + struct p80211item_uint32 *mibitem = + (struct p80211item_uint32 *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; @@ -82,12 +82,12 @@ static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) return p80211req_dorequest(wlandev, (u8 *)&msg); } -static int prism2_domibset_pstr32(wlandevice_t *wlandev, +static int prism2_domibset_pstr32(struct wlandevice *wlandev, u32 did, u8 len, const u8 *data) { struct p80211msg_dot11req_mibset msg; - p80211item_pstr32_t *mibitem = - (p80211item_pstr32_t *)&msg.mibattribute.data; + struct p80211item_pstr32 *mibitem = + (struct p80211item_pstr32 *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; @@ -103,7 +103,7 @@ static int prism2_change_virtual_intf(struct wiphy *wiphy, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; u32 data; int result; int err = 0; @@ -144,12 +144,15 @@ static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; u32 did; int err = 0; int result = 0; + if (key_index >= NUM_WEPKEYS) + return -EINVAL; + switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: @@ -160,27 +163,7 @@ static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, goto exit; /* send key to driver */ - switch (key_index) { - case 0: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - - case 1: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - - case 2: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - - case 3: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - - default: - err = -EINVAL; - goto exit; - } + did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(key_index + 1); result = prism2_domibset_pstr32(wlandev, did, params->key_len, params->key); @@ -205,7 +188,7 @@ static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params*)) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; struct key_params params; int len; @@ -233,7 +216,7 @@ static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool pairwise, const u8 *mac_addr) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; u32 did; int err = 0; int result = 0; @@ -242,36 +225,13 @@ static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, * a key, so we will cheat by setting the key to a bogus value */ + if (key_index >= NUM_WEPKEYS) + return -EINVAL; + /* send key to driver */ - switch (key_index) { - case 0: - did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - - case 1: - did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - - case 2: - did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - - case 3: - did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - - default: - err = -EINVAL; - goto exit; - } - + did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(key_index + 1); result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000"); -exit: if (result) err = -EFAULT; @@ -281,7 +241,7 @@ exit: static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool unicast, bool multicast) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; int err = 0; int result = 0; @@ -299,13 +259,13 @@ static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_info *sinfo) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; struct p80211msg_lnxreq_commsquality quality; int result; memset(sinfo, 0, sizeof(*sinfo)); - if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING)) + if (!wlandev || (wlandev->msdstate != WLAN_MSD_RUNNING)) return -EOPNOTSUPP; /* build request message */ @@ -314,7 +274,7 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, quality.dbm.status = P80211ENUM_msgitem_status_data_ok; /* send message to nsd */ - if (wlandev->mlmerequest == NULL) + if (!wlandev->mlmerequest) return -EOPNOTSUPP; result = wlandev->mlmerequest(wlandev, (struct p80211msg *)&quality); @@ -334,7 +294,7 @@ static int prism2_scan(struct wiphy *wiphy, { struct net_device *dev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev; + struct wlandevice *wlandev; struct p80211msg_dot11req_scan msg1; struct p80211msg_dot11req_scan_results msg2; struct cfg80211_bss *bss; @@ -374,7 +334,7 @@ static int prism2_scan(struct wiphy *wiphy, msg1.scantype.data = P80211ENUM_scantype_active; msg1.ssid.data.len = request->ssids->ssid_len; memcpy(msg1.ssid.data.data, - request->ssids->ssid, request->ssids->ssid_len); + request->ssids->ssid, request->ssids->ssid_len); } else { msg1.scantype.data = 0; } @@ -451,7 +411,7 @@ exit: static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev = priv->wlandev; + struct wlandevice *wlandev = priv->wlandev; u32 data; int result; int err = 0; @@ -493,7 +453,7 @@ exit: static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; struct ieee80211_channel *channel = sme->channel; struct p80211msg_lnxreq_autojoin msg_join; u32 did; @@ -516,11 +476,11 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, /* Set the authorization */ if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) || - ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep)) - msg_join.authtype.data = P80211ENUM_authalg_opensystem; + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep)) + msg_join.authtype.data = P80211ENUM_authalg_opensystem; else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) || - ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep)) - msg_join.authtype.data = P80211ENUM_authalg_sharedkey; + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep)) + msg_join.authtype.data = P80211ENUM_authalg_sharedkey; else netdev_warn(dev, "Unhandled authorisation type for connect (%d)\n", @@ -529,6 +489,11 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, /* Set the encryption - we only support wep */ if (is_wep) { if (sme->key) { + if (sme->key_idx >= NUM_WEPKEYS) { + err = -EINVAL; + goto exit; + } + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, sme->key_idx); @@ -536,28 +501,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, goto exit; /* send key to driver */ - switch (sme->key_idx) { - case 0: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - - case 1: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - - case 2: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - - case 3: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - - default: - err = -EINVAL; - goto exit; - } - + did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key( + sme->key_idx + 1); result = prism2_domibset_pstr32(wlandev, did, sme->key_len, (u8 *)sme->key); @@ -618,7 +563,7 @@ exit: static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; struct p80211msg_lnxreq_autojoin msg_join; int result; int err = 0; @@ -652,7 +597,7 @@ static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, enum nl80211_tx_power_setting type, int mbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev = priv->wlandev; + struct wlandevice *wlandev = priv->wlandev; u32 data; int result; int err = 0; @@ -679,13 +624,13 @@ static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev = priv->wlandev; + struct wlandevice *wlandev = priv->wlandev; struct p80211msg_dot11req_mibget msg; - p80211item_uint32_t *mibitem; + struct p80211item_uint32 *mibitem; int result; int err = 0; - mibitem = (p80211item_uint32_t *)&msg.mibattribute.data; + mibitem = (struct p80211item_uint32 *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibget; mibitem->did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; @@ -704,7 +649,7 @@ exit: } /* Interface callback functions, passing data back up to the cfg80211 layer */ -void prism2_connect_result(wlandevice_t *wlandev, u8 failed) +void prism2_connect_result(struct wlandevice *wlandev, u8 failed) { u16 status = failed ? WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS; @@ -713,13 +658,13 @@ void prism2_connect_result(wlandevice_t *wlandev, u8 failed) NULL, 0, NULL, 0, status, GFP_KERNEL); } -void prism2_disconnected(wlandevice_t *wlandev) +void prism2_disconnected(struct wlandevice *wlandev) { cfg80211_disconnected(wlandev->netdev, 0, NULL, - 0, false, GFP_KERNEL); + 0, false, GFP_KERNEL); } -void prism2_roamed(wlandevice_t *wlandev) +void prism2_roamed(struct wlandevice *wlandev) { cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid, NULL, 0, NULL, 0, GFP_KERNEL); @@ -744,7 +689,7 @@ static const struct cfg80211_ops prism2_usb_cfg_ops = { }; /* Functions to create/free wiphy interface */ -static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev) +static struct wiphy *wlan_create_wiphy(struct device *dev, struct wlandevice *wlandev) { struct wiphy *wiphy; struct prism2_wiphy_private *priv; diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index cec6d0ba3b65..43c299c3b631 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1,57 +1,57 @@ /* hfa384x.h -* -* Defines the constants and data structures for the hfa384x -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* [Implementation and usage notes] -* -* [References] -* CW10 Programmer's Manual v1.5 -* IEEE 802.11 D10.0 -* -* -------------------------------------------------------------------- -*/ + * + * Defines the constants and data structures for the hfa384x + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * [Implementation and usage notes] + * + * [References] + * CW10 Programmer's Manual v1.5 + * IEEE 802.11 D10.0 + * + * -------------------------------------------------------------------- + */ #ifndef _HFA384x_H #define _HFA384x_H @@ -63,7 +63,7 @@ /*--- Mins & Maxs -----------------------------------*/ #define HFA384x_PORTID_MAX ((u16)7) -#define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX+1)) +#define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX + 1)) #define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */ #define HFA384x_PDA_RECS_MAX ((u16)200) /* a guess */ #define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK*/ @@ -110,20 +110,21 @@ #define HFA384x_ADDR_FLAT_CMD_OFF_MASK (0x0000ffff) /* Mask bits for discarding unwanted pieces in AUX format - 16-bit address parts */ + * 16-bit address parts + */ #define HFA384x_ADDR_AUX_PAGE_MASK (0xffff) #define HFA384x_ADDR_AUX_OFF_MASK (0x007f) /* Make a 32-bit flat address from AUX format 16-bit page and offset */ #define HFA384x_ADDR_AUX_MKFLAT(p, o) \ - ((((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \ - ((u32)(((u16)(o))&HFA384x_ADDR_AUX_OFF_MASK))) + ((((u32)(((u16)(p)) & HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \ + ((u32)(((u16)(o)) & HFA384x_ADDR_AUX_OFF_MASK))) /* Make CMD format offset and page from a 32-bit flat address */ #define HFA384x_ADDR_CMD_MKPAGE(f) \ - ((u16)((((u32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) + ((u16)((((u32)(f)) & HFA384x_ADDR_FLAT_CMD_PAGE_MASK) >> 16)) #define HFA384x_ADDR_CMD_MKOFF(f) \ - ((u16)(((u32)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK)) + ((u16)(((u32)(f)) & HFA384x_ADDR_FLAT_CMD_OFF_MASK)) /*--- Controller Memory addresses -------------------*/ #define HFA3842_PDA_BASE (0x007f0000UL) @@ -173,11 +174,12 @@ #define HFA384x_CMD_ERR ((u16)(0x7F)) /*--- Programming Modes -------------------------- - MODE 0: Disable programming - MODE 1: Enable volatile memory programming - MODE 2: Enable non-volatile memory programming - MODE 3: Program non-volatile memory section ---------------------------------------------------*/ + * MODE 0: Disable programming + * MODE 1: Enable volatile memory programming + * MODE 2: Enable non-volatile memory programming + * MODE 3: Program non-volatile memory section + *------------------------------------------------- + */ #define HFA384x_PROGMODE_DISABLE ((u16)0x00) #define HFA384x_PROGMODE_RAM ((u16)0x01) #define HFA384x_PROGMODE_NV ((u16)0x02) @@ -185,8 +187,9 @@ /*--- Record ID Constants --------------------------*/ /*-------------------------------------------------------------------- -Configuration RIDs: Network Parameters, Static Configuration Entities ---------------------------------------------------------------------*/ + * Configuration RIDs: Network Parameters, Static Configuration Entities + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CNFPORTTYPE ((u16)0xFC00) #define HFA384x_RID_CNFOWNMACADDR ((u16)0xFC01) #define HFA384x_RID_CNFDESIREDSSID ((u16)0xFC02) @@ -195,17 +198,19 @@ Configuration RIDs: Network Parameters, Static Configuration Entities #define HFA384x_RID_CNFMAXDATALEN ((u16)0xFC07) /*-------------------------------------------------------------------- -Configuration RID lengths: Network Params, Static Config Entities - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ + * Configuration RID lengths: Network Params, Static Config Entities + * This is the length of JUST the DATA part of the RID (does not + * include the len or code fields) + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CNFOWNMACADDR_LEN ((u16)6) #define HFA384x_RID_CNFDESIREDSSID_LEN ((u16)34) #define HFA384x_RID_CNFOWNSSID_LEN ((u16)34) /*-------------------------------------------------------------------- -Configuration RIDs: Network Parameters, Dynamic Configuration Entities ---------------------------------------------------------------------*/ + * Configuration RIDs: Network Parameters, Dynamic Configuration Entities + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CREATEIBSS ((u16)0xFC81) #define HFA384x_RID_FRAGTHRESH ((u16)0xFC82) #define HFA384x_RID_RTSTHRESH ((u16)0xFC83) @@ -213,8 +218,9 @@ Configuration RIDs: Network Parameters, Dynamic Configuration Entities #define HFA384x_RID_PROMISCMODE ((u16)0xFC85) /*---------------------------------------------------------------------- -Information RIDs: NIC Information ---------------------------------------------------------------------*/ + * Information RIDs: NIC Information + *---------------------------------------------------------------------- + */ #define HFA384x_RID_MAXLOADTIME ((u16)0xFD00) #define HFA384x_RID_DOWNLOADBUFFER ((u16)0xFD01) #define HFA384x_RID_PRIIDENTITY ((u16)0xFD02) @@ -230,15 +236,17 @@ Information RIDs: NIC Information #define HFA384x_RID_STA_CFIACTRANGES ((u16)0xFD23) /*---------------------------------------------------------------------- -Information RID Lengths: NIC Information - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ + * Information RID Lengths: NIC Information + * This is the length of JUST the DATA part of the RID (does not + * include the len or code fields) + *--------------------------------------------------------------------- + */ #define HFA384x_RID_NICSERIALNUMBER_LEN ((u16)12) /*-------------------------------------------------------------------- -Information RIDs: MAC Information ---------------------------------------------------------------------*/ + * Information RIDs: MAC Information + *-------------------------------------------------------------------- + */ #define HFA384x_RID_PORTSTATUS ((u16)0xFD40) #define HFA384x_RID_CURRENTSSID ((u16)0xFD41) #define HFA384x_RID_CURRENTBSSID ((u16)0xFD42) @@ -250,23 +258,26 @@ Information RIDs: MAC Information #define HFA384x_RID_DBMCOMMSQUALITY ((u16)0xFD51) /*-------------------------------------------------------------------- -Information RID Lengths: MAC Information - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ + * Information RID Lengths: MAC Information + * This is the length of JUST the DATA part of the RID (does not + * include the len or code fields) + *-------------------------------------------------------------------- + */ #define HFA384x_RID_DBMCOMMSQUALITY_LEN \ - ((u16) sizeof(hfa384x_dbmcommsquality_t)) + ((u16)sizeof(struct hfa384x_dbmcommsquality)) #define HFA384x_RID_JOINREQUEST_LEN \ - ((u16)sizeof(hfa384x_JoinRequest_data_t)) + ((u16)sizeof(struct hfa384x_JoinRequest_data)) /*-------------------------------------------------------------------- -Information RIDs: Modem Information ---------------------------------------------------------------------*/ + * Information RIDs: Modem Information + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CURRENTCHANNEL ((u16)0xFDC1) /*-------------------------------------------------------------------- -API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) ---------------------------------------------------------------------*/ + * API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CNFWEPDEFAULTKEYID ((u16)0xFC23) #define HFA384x_RID_CNFWEPDEFAULTKEY0 ((u16)0xFC24) #define HFA384x_RID_CNFWEPDEFAULTKEY1 ((u16)0xFC25) @@ -290,8 +301,9 @@ API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) #define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((u16)14) /*-------------------------------------------------------------------- -PD Record codes ---------------------------------------------------------------------*/ + * PD Record codes + *-------------------------------------------------------------------- + */ #define HFA384x_PDR_PCB_PARTNUM ((u16)0x0001) #define HFA384x_PDR_PDAVER ((u16)0x0002) #define HFA384x_PDR_NIC_SERIAL ((u16)0x0003) @@ -355,31 +367,32 @@ struct hfa384x_bytestr { u8 data[0]; } __packed; -typedef struct hfa384x_bytestr32 { +struct hfa384x_bytestr32 { u16 len; u8 data[32]; -} __packed hfa384x_bytestr32_t; +} __packed; /*-------------------------------------------------------------------- -Configuration Record Structures: - Network Parameters, Static Configuration Entities ---------------------------------------------------------------------*/ + * Configuration Record Structures: + * Network Parameters, Static Configuration Entities + *-------------------------------------------------------------------- + */ /*-- Hardware/Firmware Component Information ----------*/ -typedef struct hfa384x_compident { +struct hfa384x_compident { u16 id; u16 variant; u16 major; u16 minor; -} __packed hfa384x_compident_t; +} __packed; -typedef struct hfa384x_caplevel { +struct hfa384x_caplevel { u16 role; u16 id; u16 variant; u16 bottom; u16 top; -} __packed hfa384x_caplevel_t; +} __packed; /*-- Configuration Record: cnfAuthentication --*/ #define HFA384x_CNFAUTHENTICATION_OPENSYSTEM 0x0001 @@ -387,77 +400,81 @@ typedef struct hfa384x_caplevel { #define HFA384x_CNFAUTHENTICATION_LEAP 0x0004 /*-------------------------------------------------------------------- -Configuration Record Structures: - Network Parameters, Dynamic Configuration Entities ---------------------------------------------------------------------*/ + * Configuration Record Structures: + * Network Parameters, Dynamic Configuration Entities + *-------------------------------------------------------------------- + */ #define HFA384x_CREATEIBSS_JOINCREATEIBSS 0 /*-- Configuration Record: HostScanRequest (data portion only) --*/ -typedef struct hfa384x_HostScanRequest_data { +struct hfa384x_HostScanRequest_data { u16 channelList; u16 txRate; - hfa384x_bytestr32_t ssid; -} __packed hfa384x_HostScanRequest_data_t; + struct hfa384x_bytestr32 ssid; +} __packed; /*-- Configuration Record: JoinRequest (data portion only) --*/ -typedef struct hfa384x_JoinRequest_data { +struct hfa384x_JoinRequest_data { u8 bssid[WLAN_BSSID_LEN]; u16 channel; -} __packed hfa384x_JoinRequest_data_t; +} __packed; /*-- Configuration Record: authenticateStation (data portion only) --*/ -typedef struct hfa384x_authenticateStation_data { +struct hfa384x_authenticateStation_data { u8 address[ETH_ALEN]; u16 status; u16 algorithm; -} __packed hfa384x_authenticateStation_data_t; +} __packed; /*-- Configuration Record: WPAData (data portion only) --*/ -typedef struct hfa384x_WPAData { +struct hfa384x_WPAData { u16 datalen; u8 data[0]; /* max 80 */ -} __packed hfa384x_WPAData_t; +} __packed; /*-------------------------------------------------------------------- -Information Record Structures: NIC Information ---------------------------------------------------------------------*/ + * Information Record Structures: NIC Information + *-------------------------------------------------------------------- + */ /*-- Information Record: DownLoadBuffer --*/ /* NOTE: The page and offset are in AUX format */ -typedef struct hfa384x_downloadbuffer { +struct hfa384x_downloadbuffer { u16 page; u16 offset; u16 len; -} __packed hfa384x_downloadbuffer_t; +} __packed; /*-------------------------------------------------------------------- -Information Record Structures: NIC Information ---------------------------------------------------------------------*/ + * Information Record Structures: NIC Information + *-------------------------------------------------------------------- + */ #define HFA384x_PSTATUS_CONN_IBSS ((u16)3) /*-- Information Record: commsquality --*/ -typedef struct hfa384x_commsquality { +struct hfa384x_commsquality { u16 CQ_currBSS; u16 ASL_currBSS; u16 ANL_currFC; -} __packed hfa384x_commsquality_t; +} __packed; /*-- Information Record: dmbcommsquality --*/ -typedef struct hfa384x_dbmcommsquality { +struct hfa384x_dbmcommsquality { u16 CQdbm_currBSS; u16 ASLdbm_currBSS; u16 ANLdbm_currFC; -} __packed hfa384x_dbmcommsquality_t; +} __packed; /*-------------------------------------------------------------------- -FRAME STRUCTURES: Communication Frames ----------------------------------------------------------------------- -Communication Frames: Transmit Frames ---------------------------------------------------------------------*/ + * FRAME STRUCTURES: Communication Frames + *-------------------------------------------------------------------- + * Communication Frames: Transmit Frames + *-------------------------------------------------------------------- + */ /*-- Communication Frame: Transmit Frame Structure --*/ -typedef struct hfa384x_tx_frame { +struct hfa384x_tx_frame { u16 status; u16 reserved1; u16 reserved2; @@ -482,10 +499,11 @@ typedef struct hfa384x_tx_frame { u8 dest_addr[6]; u8 src_addr[6]; u16 data_length; /* big endian format */ -} __packed hfa384x_tx_frame_t; +} __packed; /*-------------------------------------------------------------------- -Communication Frames: Field Masks for Transmit Frames ---------------------------------------------------------------------*/ + * Communication Frames: Field Masks for Transmit Frames + *-------------------------------------------------------------------- + */ /*-- Status Field --*/ #define HFA384x_TXSTATUS_ACKERR ((u16)BIT(5)) #define HFA384x_TXSTATUS_FORMERR ((u16)BIT(3)) @@ -499,16 +517,17 @@ Communication Frames: Field Masks for Transmit Frames #define HFA384x_TX_TXEX ((u16)BIT(2)) #define HFA384x_TX_TXOK ((u16)BIT(1)) /*-------------------------------------------------------------------- -Communication Frames: Test/Get/Set Field Values for Transmit Frames ---------------------------------------------------------------------*/ + * Communication Frames: Test/Get/Set Field Values for Transmit Frames + *-------------------------------------------------------------------- + */ /*-- Status Field --*/ #define HFA384x_TXSTATUS_ISERROR(v) \ - (((u16)(v))&\ - (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\ - HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\ + (((u16)(v)) & \ + (HFA384x_TXSTATUS_ACKERR | HFA384x_TXSTATUS_FORMERR | \ + HFA384x_TXSTATUS_DISCON | HFA384x_TXSTATUS_AGEDERR | \ HFA384x_TXSTATUS_RETRYERR)) -#define HFA384x_TX_SET(v, m, s) ((((u16)(v))<<((u16)(s)))&((u16)(m))) +#define HFA384x_TX_SET(v, m, s) ((((u16)(v)) << ((u16)(s))) & ((u16)(m))) #define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8) #define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, \ @@ -516,10 +535,11 @@ Communication Frames: Test/Get/Set Field Values for Transmit Frames #define HFA384x_TX_TXEX_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2) #define HFA384x_TX_TXOK_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1) /*-------------------------------------------------------------------- -Communication Frames: Receive Frames ---------------------------------------------------------------------*/ + * Communication Frames: Receive Frames + *-------------------------------------------------------------------- + */ /*-- Communication Frame: Receive Frame Structure --*/ -typedef struct hfa384x_rx_frame { +struct hfa384x_rx_frame { /*-- MAC rx descriptor (hfa384x byte order) --*/ u16 status; u32 time; @@ -544,10 +564,11 @@ typedef struct hfa384x_rx_frame { u8 dest_addr[6]; u8 src_addr[6]; u16 data_length; /* IEEE? (big endian) format */ -} __packed hfa384x_rx_frame_t; +} __packed; /*-------------------------------------------------------------------- -Communication Frames: Field Masks for Receive Frames ---------------------------------------------------------------------*/ + * Communication Frames: Field Masks for Receive Frames + *-------------------------------------------------------------------- + */ /*-- Status Fields --*/ #define HFA384x_RXSTATUS_MACPORT ((u16)(BIT(10) | \ @@ -555,17 +576,19 @@ Communication Frames: Field Masks for Receive Frames BIT(8))) #define HFA384x_RXSTATUS_FCSERR ((u16)BIT(0)) /*-------------------------------------------------------------------- -Communication Frames: Test/Get/Set Field Values for Receive Frames ---------------------------------------------------------------------*/ + * Communication Frames: Test/Get/Set Field Values for Receive Frames + *-------------------------------------------------------------------- + */ #define HFA384x_RXSTATUS_MACPORT_GET(value) ((u16)((((u16)(value)) \ & HFA384x_RXSTATUS_MACPORT) >> 8)) #define HFA384x_RXSTATUS_ISFCSERR(value) ((u16)(((u16)(value)) \ & HFA384x_RXSTATUS_FCSERR)) /*-------------------------------------------------------------------- - FRAME STRUCTURES: Information Types and Information Frame Structures ----------------------------------------------------------------------- -Information Types ---------------------------------------------------------------------*/ + * FRAME STRUCTURES: Information Types and Information Frame Structures + *-------------------------------------------------------------------- + * Information Types + *-------------------------------------------------------------------- + */ #define HFA384x_IT_HANDOVERADDR ((u16)0xF000UL) #define HFA384x_IT_COMMTALLIES ((u16)0xF100UL) #define HFA384x_IT_SCANRESULTS ((u16)0xF101UL) @@ -580,13 +603,14 @@ Information Types #define HFA384x_IT_MICFAILURE ((u16)0xF206UL) /*-------------------------------------------------------------------- -Information Frames Structures ----------------------------------------------------------------------- -Information Frames: Notification Frame Structures ---------------------------------------------------------------------*/ + * Information Frames Structures + *-------------------------------------------------------------------- + * Information Frames: Notification Frame Structures + *-------------------------------------------------------------------- + */ /*-- Inquiry Frame, Diagnose: Communication Tallies --*/ -typedef struct hfa384x_CommTallies16 { +struct hfa384x_CommTallies16 { u16 txunicastframes; u16 txmulticastframes; u16 txfragments; @@ -608,9 +632,9 @@ typedef struct hfa384x_CommTallies16 { u16 rxdiscardswepundecr; u16 rxmsginmsgfrag; u16 rxmsginbadmsgfrag; -} __packed hfa384x_CommTallies16_t; +} __packed; -typedef struct hfa384x_CommTallies32 { +struct hfa384x_CommTallies32 { u32 txunicastframes; u32 txmulticastframes; u32 txfragments; @@ -632,62 +656,62 @@ typedef struct hfa384x_CommTallies32 { u32 rxdiscardswepundecr; u32 rxmsginmsgfrag; u32 rxmsginbadmsgfrag; -} __packed hfa384x_CommTallies32_t; +} __packed; /*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/ -typedef struct hfa384x_ScanResultSub { +struct hfa384x_ScanResultSub { u16 chid; u16 anl; u16 sl; u8 bssid[WLAN_BSSID_LEN]; u16 bcnint; u16 capinfo; - hfa384x_bytestr32_t ssid; + struct hfa384x_bytestr32 ssid; u8 supprates[10]; /* 802.11 info element */ u16 proberesp_rate; -} __packed hfa384x_ScanResultSub_t; +} __packed; -typedef struct hfa384x_ScanResult { +struct hfa384x_ScanResult { u16 rsvd; u16 scanreason; - hfa384x_ScanResultSub_t result[HFA384x_SCANRESULT_MAX]; -} __packed hfa384x_ScanResult_t; + struct hfa384x_ScanResultSub result[HFA384x_SCANRESULT_MAX]; +} __packed; /*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ -typedef struct hfa384x_ChInfoResultSub { +struct hfa384x_ChInfoResultSub { u16 chid; u16 anl; u16 pnl; u16 active; -} __packed hfa384x_ChInfoResultSub_t; +} __packed; #define HFA384x_CHINFORESULT_BSSACTIVE BIT(0) #define HFA384x_CHINFORESULT_PCFACTIVE BIT(1) -typedef struct hfa384x_ChInfoResult { +struct hfa384x_ChInfoResult { u16 scanchannels; - hfa384x_ChInfoResultSub_t result[HFA384x_CHINFORESULT_MAX]; -} __packed hfa384x_ChInfoResult_t; + struct hfa384x_ChInfoResultSub result[HFA384x_CHINFORESULT_MAX]; +} __packed; /*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ -typedef struct hfa384x_HScanResultSub { +struct hfa384x_HScanResultSub { u16 chid; u16 anl; u16 sl; u8 bssid[WLAN_BSSID_LEN]; u16 bcnint; u16 capinfo; - hfa384x_bytestr32_t ssid; + struct hfa384x_bytestr32 ssid; u8 supprates[10]; /* 802.11 info element */ u16 proberesp_rate; u16 atim; -} __packed hfa384x_HScanResultSub_t; +} __packed; -typedef struct hfa384x_HScanResult { +struct hfa384x_HScanResult { u16 nresult; u16 rsvd; - hfa384x_HScanResultSub_t result[HFA384x_HSCANRESULT_MAX]; -} __packed hfa384x_HScanResult_t; + struct hfa384x_HScanResultSub result[HFA384x_HSCANRESULT_MAX]; +} __packed; /*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/ @@ -699,9 +723,9 @@ typedef struct hfa384x_HScanResult { #define HFA384x_LINK_AP_INRANGE ((u16)5) #define HFA384x_LINK_ASSOCFAIL ((u16)6) -typedef struct hfa384x_LinkStatus { +struct hfa384x_LinkStatus { u16 linkstatus; -} __packed hfa384x_LinkStatus_t; +} __packed; /*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/ @@ -709,56 +733,57 @@ typedef struct hfa384x_LinkStatus { #define HFA384x_ASSOCSTATUS_REASSOC ((u16)2) #define HFA384x_ASSOCSTATUS_AUTHFAIL ((u16)5) -typedef struct hfa384x_AssocStatus { +struct hfa384x_AssocStatus { u16 assocstatus; u8 sta_addr[ETH_ALEN]; /* old_ap_addr is only valid if assocstatus == 2 */ u8 old_ap_addr[ETH_ALEN]; u16 reason; u16 reserved; -} __packed hfa384x_AssocStatus_t; +} __packed; /*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/ -typedef struct hfa384x_AuthRequest { +struct hfa384x_AuthRequest { u8 sta_addr[ETH_ALEN]; u16 algorithm; -} __packed hfa384x_AuthReq_t; +} __packed; /*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/ -typedef struct hfa384x_PSUserCount { +struct hfa384x_PSUserCount { u16 usercnt; -} __packed hfa384x_PSUserCount_t; +} __packed; -typedef struct hfa384x_KeyIDChanged { +struct hfa384x_KeyIDChanged { u8 sta_addr[ETH_ALEN]; u16 keyid; -} __packed hfa384x_KeyIDChanged_t; +} __packed; /*-- Collection of all Inf frames ---------------*/ -typedef union hfa384x_infodata { - hfa384x_CommTallies16_t commtallies16; - hfa384x_CommTallies32_t commtallies32; - hfa384x_ScanResult_t scanresult; - hfa384x_ChInfoResult_t chinforesult; - hfa384x_HScanResult_t hscanresult; - hfa384x_LinkStatus_t linkstatus; - hfa384x_AssocStatus_t assocstatus; - hfa384x_AuthReq_t authreq; - hfa384x_PSUserCount_t psusercnt; - hfa384x_KeyIDChanged_t keyidchanged; -} __packed hfa384x_infodata_t; +union hfa384x_infodata { + struct hfa384x_CommTallies16 commtallies16; + struct hfa384x_CommTallies32 commtallies32; + struct hfa384x_ScanResult scanresult; + struct hfa384x_ChInfoResult chinforesult; + struct hfa384x_HScanResult hscanresult; + struct hfa384x_LinkStatus linkstatus; + struct hfa384x_AssocStatus assocstatus; + struct hfa384x_AuthRequest authreq; + struct hfa384x_PSUserCount psusercnt; + struct hfa384x_KeyIDChanged keyidchanged; +} __packed; -typedef struct hfa384x_InfFrame { +struct hfa384x_InfFrame { u16 framelen; u16 infotype; - hfa384x_infodata_t info; -} __packed hfa384x_InfFrame_t; + union hfa384x_infodata info; +} __packed; /*-------------------------------------------------------------------- -USB Packet structures and constants. ---------------------------------------------------------------------*/ + * USB Packet structures and constants. + *-------------------------------------------------------------------- + */ /* Should be sent to the bulkout endpoint */ #define HFA384x_USB_TXFRM 0 @@ -783,143 +808,140 @@ USB Packet structures and constants. /*------------------------------------*/ /* Request (bulk OUT) packet contents */ -typedef struct hfa384x_usb_txfrm { - hfa384x_tx_frame_t desc; +struct hfa384x_usb_txfrm { + struct hfa384x_tx_frame desc; u8 data[WLAN_DATA_MAXLEN]; -} __packed hfa384x_usb_txfrm_t; +} __packed; -typedef struct hfa384x_usb_cmdreq { +struct hfa384x_usb_cmdreq { u16 type; u16 cmd; u16 parm0; u16 parm1; u16 parm2; u8 pad[54]; -} __packed hfa384x_usb_cmdreq_t; +} __packed; -typedef struct hfa384x_usb_wridreq { +struct hfa384x_usb_wridreq { u16 type; u16 frmlen; u16 rid; u8 data[HFA384x_RIDDATA_MAXLEN]; -} __packed hfa384x_usb_wridreq_t; +} __packed; -typedef struct hfa384x_usb_rridreq { +struct hfa384x_usb_rridreq { u16 type; u16 frmlen; u16 rid; u8 pad[58]; -} __packed hfa384x_usb_rridreq_t; +} __packed; -typedef struct hfa384x_usb_wmemreq { +struct hfa384x_usb_wmemreq { u16 type; u16 frmlen; u16 offset; u16 page; u8 data[HFA384x_USB_RWMEM_MAXLEN]; -} __packed hfa384x_usb_wmemreq_t; +} __packed; -typedef struct hfa384x_usb_rmemreq { +struct hfa384x_usb_rmemreq { u16 type; u16 frmlen; u16 offset; u16 page; u8 pad[56]; -} __packed hfa384x_usb_rmemreq_t; +} __packed; /*------------------------------------*/ /* Response (bulk IN) packet contents */ -typedef struct hfa384x_usb_rxfrm { - hfa384x_rx_frame_t desc; +struct hfa384x_usb_rxfrm { + struct hfa384x_rx_frame desc; u8 data[WLAN_DATA_MAXLEN]; -} __packed hfa384x_usb_rxfrm_t; +} __packed; -typedef struct hfa384x_usb_infofrm { +struct hfa384x_usb_infofrm { u16 type; - hfa384x_InfFrame_t info; -} __packed hfa384x_usb_infofrm_t; + struct hfa384x_InfFrame info; +} __packed; -typedef struct hfa384x_usb_statusresp { +struct hfa384x_usb_statusresp { u16 type; u16 status; u16 resp0; u16 resp1; u16 resp2; -} __packed hfa384x_usb_cmdresp_t; +} __packed; -typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t; - -typedef struct hfa384x_usb_rridresp { +struct hfa384x_usb_rridresp { u16 type; u16 frmlen; u16 rid; u8 data[HFA384x_RIDDATA_MAXLEN]; -} __packed hfa384x_usb_rridresp_t; +} __packed; -typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t; - -typedef struct hfa384x_usb_rmemresp { +struct hfa384x_usb_rmemresp { u16 type; u16 frmlen; u8 data[HFA384x_USB_RWMEM_MAXLEN]; -} __packed hfa384x_usb_rmemresp_t; +} __packed; -typedef struct hfa384x_usb_bufavail { +struct hfa384x_usb_bufavail { u16 type; u16 frmlen; -} __packed hfa384x_usb_bufavail_t; +} __packed; -typedef struct hfa384x_usb_error { +struct hfa384x_usb_error { u16 type; u16 errortype; -} __packed hfa384x_usb_error_t; +} __packed; /*----------------------------------------------------------*/ /* Unions for packaging all the known packet types together */ -typedef union hfa384x_usbout { +union hfa384x_usbout { __le16 type; - hfa384x_usb_txfrm_t txfrm; - hfa384x_usb_cmdreq_t cmdreq; - hfa384x_usb_wridreq_t wridreq; - hfa384x_usb_rridreq_t rridreq; - hfa384x_usb_wmemreq_t wmemreq; - hfa384x_usb_rmemreq_t rmemreq; -} __packed hfa384x_usbout_t; + struct hfa384x_usb_txfrm txfrm; + struct hfa384x_usb_cmdreq cmdreq; + struct hfa384x_usb_wridreq wridreq; + struct hfa384x_usb_rridreq rridreq; + struct hfa384x_usb_wmemreq wmemreq; + struct hfa384x_usb_rmemreq rmemreq; +} __packed; -typedef union hfa384x_usbin { +union hfa384x_usbin { __le16 type; - hfa384x_usb_rxfrm_t rxfrm; - hfa384x_usb_txfrm_t txfrm; - hfa384x_usb_infofrm_t infofrm; - hfa384x_usb_cmdresp_t cmdresp; - hfa384x_usb_wridresp_t wridresp; - hfa384x_usb_rridresp_t rridresp; - hfa384x_usb_wmemresp_t wmemresp; - hfa384x_usb_rmemresp_t rmemresp; - hfa384x_usb_bufavail_t bufavail; - hfa384x_usb_error_t usberror; + struct hfa384x_usb_rxfrm rxfrm; + struct hfa384x_usb_txfrm txfrm; + struct hfa384x_usb_infofrm infofrm; + struct hfa384x_usb_statusresp cmdresp; + struct hfa384x_usb_statusresp wridresp; + struct hfa384x_usb_rridresp rridresp; + struct hfa384x_usb_statusresp wmemresp; + struct hfa384x_usb_rmemresp rmemresp; + struct hfa384x_usb_bufavail bufavail; + struct hfa384x_usb_error usberror; u8 boguspad[3000]; -} __packed hfa384x_usbin_t; +} __packed; /*-------------------------------------------------------------------- -PD record structures. ---------------------------------------------------------------------*/ + * PD record structures. + *-------------------------------------------------------------------- + */ -typedef struct hfa384x_pdr_pcb_partnum { +struct hfa384x_pdr_pcb_partnum { u8 num[8]; -} __packed hfa384x_pdr_pcb_partnum_t; +} __packed; -typedef struct hfa384x_pdr_pcb_tracenum { +struct hfa384x_pdr_pcb_tracenum { u8 num[8]; -} __packed hfa384x_pdr_pcb_tracenum_t; +} __packed; -typedef struct hfa384x_pdr_nic_serial { +struct hfa384x_pdr_nic_serial { u8 num[12]; -} __packed hfa384x_pdr_nic_serial_t; +} __packed; -typedef struct hfa384x_pdr_mkk_measurements { +struct hfa384x_pdr_mkk_measurements { double carrier_freq; double occupied_band; double power_density; @@ -935,192 +957,193 @@ typedef struct hfa384x_pdr_mkk_measurements { double rx_spur_f2; double rx_spur_l1; double rx_spur_l2; -} __packed hfa384x_pdr_mkk_measurements_t; +} __packed; -typedef struct hfa384x_pdr_nic_ramsize { +struct hfa384x_pdr_nic_ramsize { u8 size[12]; /* units of KB */ -} __packed hfa384x_pdr_nic_ramsize_t; +} __packed; -typedef struct hfa384x_pdr_mfisuprange { +struct hfa384x_pdr_mfisuprange { u16 id; u16 variant; u16 bottom; u16 top; -} __packed hfa384x_pdr_mfisuprange_t; +} __packed; -typedef struct hfa384x_pdr_cfisuprange { +struct hfa384x_pdr_cfisuprange { u16 id; u16 variant; u16 bottom; u16 top; -} __packed hfa384x_pdr_cfisuprange_t; +} __packed; -typedef struct hfa384x_pdr_nicid { +struct hfa384x_pdr_nicid { u16 id; u16 variant; u16 major; u16 minor; -} __packed hfa384x_pdr_nicid_t; +} __packed; -typedef struct hfa384x_pdr_refdac_measurements { +struct hfa384x_pdr_refdac_measurements { u16 value[0]; -} __packed hfa384x_pdr_refdac_measurements_t; +} __packed; -typedef struct hfa384x_pdr_vgdac_measurements { +struct hfa384x_pdr_vgdac_measurements { u16 value[0]; -} __packed hfa384x_pdr_vgdac_measurements_t; +} __packed; -typedef struct hfa384x_pdr_level_comp_measurements { +struct hfa384x_pdr_level_comp_measurements { u16 value[0]; -} __packed hfa384x_pdr_level_compc_measurements_t; +} __packed; -typedef struct hfa384x_pdr_mac_address { +struct hfa384x_pdr_mac_address { u8 addr[6]; -} __packed hfa384x_pdr_mac_address_t; +} __packed; -typedef struct hfa384x_pdr_mkk_callname { +struct hfa384x_pdr_mkk_callname { u8 callname[8]; -} __packed hfa384x_pdr_mkk_callname_t; +} __packed; -typedef struct hfa384x_pdr_regdomain { +struct hfa384x_pdr_regdomain { u16 numdomains; u16 domain[5]; -} __packed hfa384x_pdr_regdomain_t; +} __packed; -typedef struct hfa384x_pdr_allowed_channel { +struct hfa384x_pdr_allowed_channel { u16 ch_bitmap; -} __packed hfa384x_pdr_allowed_channel_t; +} __packed; -typedef struct hfa384x_pdr_default_channel { +struct hfa384x_pdr_default_channel { u16 channel; -} __packed hfa384x_pdr_default_channel_t; +} __packed; -typedef struct hfa384x_pdr_privacy_option { +struct hfa384x_pdr_privacy_option { u16 available; -} __packed hfa384x_pdr_privacy_option_t; +} __packed; -typedef struct hfa384x_pdr_temptype { +struct hfa384x_pdr_temptype { u16 type; -} __packed hfa384x_pdr_temptype_t; +} __packed; -typedef struct hfa384x_pdr_refdac_setup { +struct hfa384x_pdr_refdac_setup { u16 ch_value[14]; -} __packed hfa384x_pdr_refdac_setup_t; +} __packed; -typedef struct hfa384x_pdr_vgdac_setup { +struct hfa384x_pdr_vgdac_setup { u16 ch_value[14]; -} __packed hfa384x_pdr_vgdac_setup_t; +} __packed; -typedef struct hfa384x_pdr_level_comp_setup { +struct hfa384x_pdr_level_comp_setup { u16 ch_value[14]; -} __packed hfa384x_pdr_level_comp_setup_t; +} __packed; -typedef struct hfa384x_pdr_trimdac_setup { +struct hfa384x_pdr_trimdac_setup { u16 trimidac; u16 trimqdac; -} __packed hfa384x_pdr_trimdac_setup_t; +} __packed; -typedef struct hfa384x_pdr_ifr_setting { +struct hfa384x_pdr_ifr_setting { u16 value[3]; -} __packed hfa384x_pdr_ifr_setting_t; +} __packed; -typedef struct hfa384x_pdr_rfr_setting { +struct hfa384x_pdr_rfr_setting { u16 value[3]; -} __packed hfa384x_pdr_rfr_setting_t; +} __packed; -typedef struct hfa384x_pdr_hfa3861_baseline { +struct hfa384x_pdr_hfa3861_baseline { u16 value[50]; -} __packed hfa384x_pdr_hfa3861_baseline_t; +} __packed; -typedef struct hfa384x_pdr_hfa3861_shadow { +struct hfa384x_pdr_hfa3861_shadow { u32 value[32]; -} __packed hfa384x_pdr_hfa3861_shadow_t; +} __packed; -typedef struct hfa384x_pdr_hfa3861_ifrf { +struct hfa384x_pdr_hfa3861_ifrf { u32 value[20]; -} __packed hfa384x_pdr_hfa3861_ifrf_t; +} __packed; -typedef struct hfa384x_pdr_hfa3861_chcalsp { +struct hfa384x_pdr_hfa3861_chcalsp { u16 value[14]; -} __packed hfa384x_pdr_hfa3861_chcalsp_t; +} __packed; -typedef struct hfa384x_pdr_hfa3861_chcali { +struct hfa384x_pdr_hfa3861_chcali { u16 value[17]; -} __packed hfa384x_pdr_hfa3861_chcali_t; +} __packed; -typedef struct hfa384x_pdr_hfa3861_nic_config { +struct hfa384x_pdr_hfa3861_nic_config { u16 config_bitmap; -} __packed hfa384x_pdr_nic_config_t; +} __packed; -typedef struct hfa384x_pdr_hfo_delay { +struct hfa384x_pdr_hfo_delay { u8 hfo_delay; -} __packed hfa384x_hfo_delay_t; +} __packed; -typedef struct hfa384x_pdr_hfa3861_manf_testsp { +struct hfa384x_pdr_hfa3861_manf_testsp { u16 value[30]; -} __packed hfa384x_pdr_hfa3861_manf_testsp_t; +} __packed; -typedef struct hfa384x_pdr_hfa3861_manf_testi { +struct hfa384x_pdr_hfa3861_manf_testi { u16 value[30]; -} __packed hfa384x_pdr_hfa3861_manf_testi_t; +} __packed; -typedef struct hfa384x_end_of_pda { +struct hfa384x_pdr_end_of_pda { u16 crc; -} __packed hfa384x_pdr_end_of_pda_t; +} __packed; -typedef struct hfa384x_pdrec { +struct hfa384x_pdrec { u16 len; /* in words */ u16 code; union pdr { - hfa384x_pdr_pcb_partnum_t pcb_partnum; - hfa384x_pdr_pcb_tracenum_t pcb_tracenum; - hfa384x_pdr_nic_serial_t nic_serial; - hfa384x_pdr_mkk_measurements_t mkk_measurements; - hfa384x_pdr_nic_ramsize_t nic_ramsize; - hfa384x_pdr_mfisuprange_t mfisuprange; - hfa384x_pdr_cfisuprange_t cfisuprange; - hfa384x_pdr_nicid_t nicid; - hfa384x_pdr_refdac_measurements_t refdac_measurements; - hfa384x_pdr_vgdac_measurements_t vgdac_measurements; - hfa384x_pdr_level_compc_measurements_t level_compc_measurements; - hfa384x_pdr_mac_address_t mac_address; - hfa384x_pdr_mkk_callname_t mkk_callname; - hfa384x_pdr_regdomain_t regdomain; - hfa384x_pdr_allowed_channel_t allowed_channel; - hfa384x_pdr_default_channel_t default_channel; - hfa384x_pdr_privacy_option_t privacy_option; - hfa384x_pdr_temptype_t temptype; - hfa384x_pdr_refdac_setup_t refdac_setup; - hfa384x_pdr_vgdac_setup_t vgdac_setup; - hfa384x_pdr_level_comp_setup_t level_comp_setup; - hfa384x_pdr_trimdac_setup_t trimdac_setup; - hfa384x_pdr_ifr_setting_t ifr_setting; - hfa384x_pdr_rfr_setting_t rfr_setting; - hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; - hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; - hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; - hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; - hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; - hfa384x_pdr_nic_config_t nic_config; - hfa384x_hfo_delay_t hfo_delay; - hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; - hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; - hfa384x_pdr_end_of_pda_t end_of_pda; + struct hfa384x_pdr_pcb_partnum pcb_partnum; + struct hfa384x_pdr_pcb_tracenum pcb_tracenum; + struct hfa384x_pdr_nic_serial nic_serial; + struct hfa384x_pdr_mkk_measurements mkk_measurements; + struct hfa384x_pdr_nic_ramsize nic_ramsize; + struct hfa384x_pdr_mfisuprange mfisuprange; + struct hfa384x_pdr_cfisuprange cfisuprange; + struct hfa384x_pdr_nicid nicid; + struct hfa384x_pdr_refdac_measurements refdac_measurements; + struct hfa384x_pdr_vgdac_measurements vgdac_measurements; + struct hfa384x_pdr_level_comp_measurements level_compc_measurements; + struct hfa384x_pdr_mac_address mac_address; + struct hfa384x_pdr_mkk_callname mkk_callname; + struct hfa384x_pdr_regdomain regdomain; + struct hfa384x_pdr_allowed_channel allowed_channel; + struct hfa384x_pdr_default_channel default_channel; + struct hfa384x_pdr_privacy_option privacy_option; + struct hfa384x_pdr_temptype temptype; + struct hfa384x_pdr_refdac_setup refdac_setup; + struct hfa384x_pdr_vgdac_setup vgdac_setup; + struct hfa384x_pdr_level_comp_setup level_comp_setup; + struct hfa384x_pdr_trimdac_setup trimdac_setup; + struct hfa384x_pdr_ifr_setting ifr_setting; + struct hfa384x_pdr_rfr_setting rfr_setting; + struct hfa384x_pdr_hfa3861_baseline hfa3861_baseline; + struct hfa384x_pdr_hfa3861_shadow hfa3861_shadow; + struct hfa384x_pdr_hfa3861_ifrf hfa3861_ifrf; + struct hfa384x_pdr_hfa3861_chcalsp hfa3861_chcalsp; + struct hfa384x_pdr_hfa3861_chcali hfa3861_chcali; + struct hfa384x_pdr_hfa3861_nic_config nic_config; + struct hfa384x_pdr_hfo_delay hfo_delay; + struct hfa384x_pdr_hfa3861_manf_testsp hfa3861_manf_testsp; + struct hfa384x_pdr_hfa3861_manf_testi hfa3861_manf_testi; + struct hfa384x_pdr_end_of_pda end_of_pda; } data; -} __packed hfa384x_pdrec_t; +} __packed; #ifdef __KERNEL__ /*-------------------------------------------------------------------- ---- MAC state structure, argument to all functions -- ---- Also, a collection of support types -- ---------------------------------------------------------------------*/ -typedef struct hfa384x_statusresult { + * --- MAC state structure, argument to all functions -- + * --- Also, a collection of support types -- + *-------------------------------------------------------------------- + */ +struct hfa384x_cmdresult { u16 status; u16 resp0; u16 resp1; u16 resp2; -} hfa384x_cmdresult_t; +}; /* USB Control Exchange (CTLX): * A queue of the structure below is maintained for all of the @@ -1129,11 +1152,11 @@ typedef struct hfa384x_statusresult { /* The following hfa384x_* structures are arguments to * the usercb() for the different CTLX types. */ -typedef struct hfa384x_rridresult { +struct hfa384x_rridresult { u16 rid; const void *riddata; unsigned int riddata_len; -} hfa384x_rridresult_t; +}; enum ctlx_state { CTLX_START = 0, /* Start state, not queued */ @@ -1156,12 +1179,12 @@ typedef void (*ctlx_cmdcb_t) (struct hfa384x *, const struct hfa384x_usbctlx *); typedef void (*ctlx_usercb_t) (struct hfa384x *hw, void *ctlxresult, void *usercb_data); -typedef struct hfa384x_usbctlx { +struct hfa384x_usbctlx { struct list_head list; size_t outbufsize; - hfa384x_usbout_t outbuf; /* pkt buf for OUT */ - hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */ + union hfa384x_usbout outbuf; /* pkt buf for OUT */ + union hfa384x_usbin inbuf; /* pkt buf for IN(a copy) */ CTLX_STATE state; /* Tracks running state */ @@ -1173,25 +1196,25 @@ typedef struct hfa384x_usbctlx { void *usercb_data; /* at CTLX completion */ int variant; /* Identifies cmd variant */ -} hfa384x_usbctlx_t; +}; -typedef struct hfa384x_usbctlxq { +struct hfa384x_usbctlxq { spinlock_t lock; struct list_head pending; struct list_head active; struct list_head completing; struct list_head reapable; -} hfa384x_usbctlxq_t; +}; -typedef struct hfa484x_metacmd { +struct hfa384x_metacmd { u16 cmd; u16 parm0; u16 parm1; u16 parm2; - hfa384x_cmdresult_t result; -} hfa384x_metacmd_t; + struct hfa384x_cmdresult result; +}; #define MAX_GRP_ADDR 32 #define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */ @@ -1218,15 +1241,15 @@ struct prism2sta_accesslist { u8 addr1[WLAN_ACCESS_MAX][ETH_ALEN]; }; -typedef struct hfa384x { +struct hfa384x { /* USB support data */ struct usb_device *usb; struct urb rx_urb; struct sk_buff *rx_urb_skb; struct urb tx_urb; struct urb ctlx_urb; - hfa384x_usbout_t txbuff; - hfa384x_usbctlxq_t ctlxq; + union hfa384x_usbout txbuff; + struct hfa384x_usbctlxq ctlxq; struct timer_list reqtimer; struct timer_list resptimer; @@ -1265,20 +1288,20 @@ typedef struct hfa384x { /* Download support */ unsigned int dlstate; - hfa384x_downloadbuffer_t bufinfo; + struct hfa384x_downloadbuffer bufinfo; u16 dltimeout; int scanflag; /* to signal scan complete */ int join_ap; /* are we joined to a specific ap */ int join_retries; /* number of join retries till we fail */ - hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ + struct hfa384x_JoinRequest_data joinreq; /* join request saved data */ - wlandevice_t *wlandev; + struct wlandevice *wlandev; /* Timer to allow for the deferred processing of linkstatus messages */ struct work_struct link_bh; struct work_struct commsqual_bh; - hfa384x_commsquality_t qual; + struct hfa384x_commsquality qual; struct timer_list commsqual_timer; u16 link_status; @@ -1297,92 +1320,93 @@ typedef struct hfa384x { int dbmadjust; /* Group Addresses - right now, there are up to a total - of MAX_GRP_ADDR group addresses */ + * of MAX_GRP_ADDR group addresses + */ u8 dot11_grp_addr[MAX_GRP_ADDR][ETH_ALEN]; unsigned int dot11_grpcnt; /* Component Identities */ - hfa384x_compident_t ident_nic; - hfa384x_compident_t ident_pri_fw; - hfa384x_compident_t ident_sta_fw; - hfa384x_compident_t ident_ap_fw; + struct hfa384x_compident ident_nic; + struct hfa384x_compident ident_pri_fw; + struct hfa384x_compident ident_sta_fw; + struct hfa384x_compident ident_ap_fw; u16 mm_mods; /* Supplier compatibility ranges */ - hfa384x_caplevel_t cap_sup_mfi; - hfa384x_caplevel_t cap_sup_cfi; - hfa384x_caplevel_t cap_sup_pri; - hfa384x_caplevel_t cap_sup_sta; - hfa384x_caplevel_t cap_sup_ap; + struct hfa384x_caplevel cap_sup_mfi; + struct hfa384x_caplevel cap_sup_cfi; + struct hfa384x_caplevel cap_sup_pri; + struct hfa384x_caplevel cap_sup_sta; + struct hfa384x_caplevel cap_sup_ap; /* Actor compatibility ranges */ - hfa384x_caplevel_t cap_act_pri_cfi; /* - * pri f/w to controller - * interface - */ + struct hfa384x_caplevel cap_act_pri_cfi; /* + * pri f/w to controller + * interface + */ - hfa384x_caplevel_t cap_act_sta_cfi; /* - * sta f/w to controller - * interface - */ + struct hfa384x_caplevel cap_act_sta_cfi; /* + * sta f/w to controller + * interface + */ - hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */ + struct hfa384x_caplevel cap_act_sta_mfi; /* sta f/w to modem interface */ - hfa384x_caplevel_t cap_act_ap_cfi; /* + struct hfa384x_caplevel cap_act_ap_cfi; /* * ap f/w to controller * interface */ - hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */ + struct hfa384x_caplevel cap_act_ap_mfi; /* ap f/w to modem interface */ u32 psusercount; /* Power save user count. */ - hfa384x_CommTallies32_t tallies; /* Communication tallies. */ + struct hfa384x_CommTallies32 tallies; /* Communication tallies. */ u8 comment[WLAN_COMMENT_MAX + 1]; /* User comment */ /* Channel Info request results (AP only) */ struct { atomic_t done; u8 count; - hfa384x_ChInfoResult_t results; + struct hfa384x_ChInfoResult results; } channel_info; - hfa384x_InfFrame_t *scanresults; + struct hfa384x_InfFrame *scanresults; struct prism2sta_authlist authlist; /* Authenticated station list. */ unsigned int accessmode; /* Access mode. */ struct prism2sta_accesslist allow; /* Allowed station list. */ struct prism2sta_accesslist deny; /* Denied station list. */ -} hfa384x_t; +}; -void hfa384x_create(hfa384x_t *hw, struct usb_device *usb); -void hfa384x_destroy(hfa384x_t *hw); +void hfa384x_create(struct hfa384x *hw, struct usb_device *usb); +void hfa384x_destroy(struct hfa384x *hw); int -hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis); -int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport); -int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport); -int hfa384x_drvr_flashdl_enable(hfa384x_t *hw); -int hfa384x_drvr_flashdl_disable(hfa384x_t *hw); -int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len); -int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len); -int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr); -int hfa384x_drvr_ramdl_disable(hfa384x_t *hw); -int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len); -int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len); -int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len); +hfa384x_corereset(struct hfa384x *hw, int holdtime, int settletime, int genesis); +int hfa384x_drvr_disable(struct hfa384x *hw, u16 macport); +int hfa384x_drvr_enable(struct hfa384x *hw, u16 macport); +int hfa384x_drvr_flashdl_enable(struct hfa384x *hw); +int hfa384x_drvr_flashdl_disable(struct hfa384x *hw); +int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len); +int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len); +int hfa384x_drvr_ramdl_enable(struct hfa384x *hw, u32 exeaddr); +int hfa384x_drvr_ramdl_disable(struct hfa384x *hw); +int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len); +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); -static inline int hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val) +static inline int hfa384x_drvr_getconfig16(struct hfa384x *hw, u16 rid, void *val) { int result = 0; result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(u16)); if (result == 0) - *((u16 *) val) = le16_to_cpu(*((u16 *) val)); + *((u16 *)val) = le16_to_cpu(*((u16 *)val)); return result; } -static inline int hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val) +static inline int hfa384x_drvr_setconfig16(struct hfa384x *hw, u16 rid, u16 val) { u16 value = cpu_to_le16(val); @@ -1390,13 +1414,13 @@ static inline int hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val) } int -hfa384x_drvr_setconfig_async(hfa384x_t *hw, +hfa384x_drvr_setconfig_async(struct hfa384x *hw, u16 rid, void *buf, u16 len, ctlx_usercb_t usercb, void *usercb_data); static inline int -hfa384x_drvr_setconfig16_async(hfa384x_t *hw, u16 rid, u16 val) +hfa384x_drvr_setconfig16_async(struct hfa384x *hw, u16 rid, u16 val) { u16 value = cpu_to_le16(val); @@ -1404,21 +1428,21 @@ hfa384x_drvr_setconfig16_async(hfa384x_t *hw, u16 rid, u16 val) NULL, NULL); } -int hfa384x_drvr_start(hfa384x_t *hw); -int hfa384x_drvr_stop(hfa384x_t *hw); +int hfa384x_drvr_start(struct hfa384x *hw); +int hfa384x_drvr_stop(struct hfa384x *hw); int -hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, +hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep); -void hfa384x_tx_timeout(wlandevice_t *wlandev); +void hfa384x_tx_timeout(struct wlandevice *wlandev); -int hfa384x_cmd_initialize(hfa384x_t *hw); -int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport); -int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport); -int hfa384x_cmd_allocate(hfa384x_t *hw, u16 len); -int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable); +int hfa384x_cmd_initialize(struct hfa384x *hw); +int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport); +int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport); +int hfa384x_cmd_allocate(struct hfa384x *hw, u16 len); +int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable); int -hfa384x_cmd_download(hfa384x_t *hw, +hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, u16 highaddr, u16 codelen); #endif /*__KERNEL__ */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 337810750f2b..6a107f8a06e2 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -154,13 +154,13 @@ static void dbprint_urb(struct urb *urb); #endif static void -hfa384x_int_rxmonitor(wlandevice_t *wlandev, hfa384x_usb_rxfrm_t *rxfrm); +hfa384x_int_rxmonitor(struct wlandevice *wlandev, struct hfa384x_usb_rxfrm *rxfrm); static void hfa384x_usb_defer(struct work_struct *data); -static int submit_rx_urb(hfa384x_t *hw, gfp_t flags); +static int submit_rx_urb(struct hfa384x *hw, gfp_t flags); -static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t flags); +static int submit_tx_urb(struct hfa384x *hw, struct urb *tx_urb, gfp_t flags); /*---------------------------------------------------*/ /* Callbacks */ @@ -169,19 +169,19 @@ static void hfa384x_ctlxout_callback(struct urb *urb); static void hfa384x_usbin_callback(struct urb *urb); static void -hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); +hfa384x_usbin_txcompl(struct wlandevice *wlandev, union hfa384x_usbin *usbin); -static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb); +static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb); -static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); +static void hfa384x_usbin_info(struct wlandevice *wlandev, union hfa384x_usbin *usbin); -static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, +static void hfa384x_usbin_ctlx(struct hfa384x *hw, union hfa384x_usbin *usbin, int urb_status); /*---------------------------------------------------*/ /* Functions to support the prism2 usb command queue */ -static void hfa384x_usbctlxq_run(hfa384x_t *hw); +static void hfa384x_usbctlxq_run(struct hfa384x *hw); static void hfa384x_usbctlx_reqtimerfn(unsigned long data); @@ -193,42 +193,42 @@ static void hfa384x_usbctlx_completion_task(unsigned long data); static void hfa384x_usbctlx_reaper_task(unsigned long data); -static int hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); +static int hfa384x_usbctlx_submit(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); -static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); +static void unlocked_usbctlx_complete(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); struct usbctlx_completor { int (*complete)(struct usbctlx_completor *); }; static int -hfa384x_usbctlx_complete_sync(hfa384x_t *hw, - hfa384x_usbctlx_t *ctlx, +hfa384x_usbctlx_complete_sync(struct hfa384x *hw, + struct hfa384x_usbctlx *ctlx, struct usbctlx_completor *completor); static int -unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); +unlocked_usbctlx_cancel_async(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); -static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); +static void hfa384x_cb_status(struct hfa384x *hw, const struct hfa384x_usbctlx *ctlx); static int -usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, - hfa384x_cmdresult_t *result); +usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, + struct hfa384x_cmdresult *result); static void -usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, - hfa384x_rridresult_t *result); +usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, + struct hfa384x_rridresult *result); /*---------------------------------------------------*/ /* Low level req/resp CTLX formatters and submitters */ static int -hfa384x_docmd(hfa384x_t *hw, +hfa384x_docmd(struct hfa384x *hw, enum cmd_mode mode, - hfa384x_metacmd_t *cmd, + struct hfa384x_metacmd *cmd, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dorrid(hfa384x_t *hw, +hfa384x_dorrid(struct hfa384x *hw, enum cmd_mode mode, u16 rid, void *riddata, @@ -236,7 +236,7 @@ hfa384x_dorrid(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dowrid(hfa384x_t *hw, +hfa384x_dowrid(struct hfa384x *hw, enum cmd_mode mode, u16 rid, void *riddata, @@ -244,7 +244,7 @@ hfa384x_dowrid(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dormem(hfa384x_t *hw, +hfa384x_dormem(struct hfa384x *hw, enum cmd_mode mode, u16 page, u16 offset, @@ -253,7 +253,7 @@ hfa384x_dormem(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dowmem(hfa384x_t *hw, +hfa384x_dowmem(struct hfa384x *hw, enum cmd_mode mode, u16 page, u16 offset, @@ -278,9 +278,9 @@ static inline const char *ctlxstr(CTLX_STATE s) return ctlx_str[s]; }; -static inline hfa384x_usbctlx_t *get_active_ctlx(hfa384x_t *hw) +static inline struct hfa384x_usbctlx *get_active_ctlx(struct hfa384x *hw) { - return list_entry(hw->ctlxq.active.next, hfa384x_usbctlx_t, list); + return list_entry(hw->ctlxq.active.next, struct hfa384x_usbctlx, list); } #ifdef DEBUG_USB @@ -322,12 +322,12 @@ void dbprint_urb(struct urb *urb) * Call context: * Any ----------------------------------------------------------------*/ -static int submit_rx_urb(hfa384x_t *hw, gfp_t memflags) +static int submit_rx_urb(struct hfa384x *hw, gfp_t memflags) { struct sk_buff *skb; int result; - skb = dev_alloc_skb(sizeof(hfa384x_usbin_t)); + skb = dev_alloc_skb(sizeof(union hfa384x_usbin)); if (!skb) { result = -ENOMEM; goto done; @@ -336,7 +336,7 @@ static int submit_rx_urb(hfa384x_t *hw, gfp_t memflags) /* Post the IN urb */ usb_fill_bulk_urb(&hw->rx_urb, hw->usb, hw->endp_in, - skb->data, sizeof(hfa384x_usbin_t), + skb->data, sizeof(union hfa384x_usbin), hfa384x_usbin_callback, hw->wlandev); hw->rx_urb_skb = skb; @@ -384,7 +384,7 @@ done: * Call context: * Any ----------------------------------------------------------------*/ -static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) +static int submit_tx_urb(struct hfa384x *hw, struct urb *tx_urb, gfp_t memflags) { struct net_device *netdev = hw->wlandev->netdev; int result; @@ -429,7 +429,7 @@ static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) ----------------------------------------------------------------*/ static void hfa384x_usb_defer(struct work_struct *data) { - hfa384x_t *hw = container_of(data, struct hfa384x, usb_work); + struct hfa384x *hw = container_of(data, struct hfa384x, usb_work); struct net_device *netdev = hw->wlandev->netdev; /* Don't bother trying to reset anything if the plug @@ -503,7 +503,7 @@ static void hfa384x_usb_defer(struct work_struct *data) /*---------------------------------------------------------------- * hfa384x_create * -* Sets up the hfa384x_t data structure for use. Note this +* Sets up the struct hfa384x data structure for use. Note this * does _not_ initialize the actual hardware, just the data structures * we use to keep track of its state. * @@ -521,9 +521,9 @@ static void hfa384x_usb_defer(struct work_struct *data) * Call context: * process ----------------------------------------------------------------*/ -void hfa384x_create(hfa384x_t *hw, struct usb_device *usb) +void hfa384x_create(struct hfa384x *hw, struct usb_device *usb) { - memset(hw, 0, sizeof(hfa384x_t)); + memset(hw, 0, sizeof(struct hfa384x)); hw->usb = usb; /* set up the endpoints */ @@ -592,7 +592,7 @@ void hfa384x_create(hfa384x_t *hw, struct usb_device *usb) * Call context: * process ----------------------------------------------------------------*/ -void hfa384x_destroy(hfa384x_t *hw) +void hfa384x_destroy(struct hfa384x *hw) { struct sk_buff *skb; @@ -608,9 +608,9 @@ void hfa384x_destroy(hfa384x_t *hw) dev_kfree_skb(skb); } -static hfa384x_usbctlx_t *usbctlx_alloc(void) +static struct hfa384x_usbctlx *usbctlx_alloc(void) { - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = kzalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); @@ -621,8 +621,8 @@ static hfa384x_usbctlx_t *usbctlx_alloc(void) } static int -usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, - hfa384x_cmdresult_t *result) +usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, + struct hfa384x_cmdresult *result) { result->status = le16_to_cpu(cmdresp->status); result->resp0 = le16_to_cpu(cmdresp->resp0); @@ -636,8 +636,8 @@ usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, } static void -usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, - hfa384x_rridresult_t *result) +usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, + struct hfa384x_rridresult *result) { result->rid = le16_to_cpu(rridresp->rid); result->riddata = rridresp->data; @@ -647,13 +647,13 @@ usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, /*---------------------------------------------------------------- * Completor object: * This completor must be passed to hfa384x_usbctlx_complete_sync() -* when processing a CTLX that returns a hfa384x_cmdresult_t structure. +* when processing a CTLX that returns a struct hfa384x_cmdresult structure. ----------------------------------------------------------------*/ struct usbctlx_cmd_completor { struct usbctlx_completor head; - const hfa384x_usb_cmdresp_t *cmdresp; - hfa384x_cmdresult_t *result; + const struct hfa384x_usb_statusresp *cmdresp; + struct hfa384x_cmdresult *result; }; static inline int usbctlx_cmd_completor_fn(struct usbctlx_completor *head) @@ -667,9 +667,9 @@ static inline int usbctlx_cmd_completor_fn(struct usbctlx_completor *head) static inline struct usbctlx_completor *init_cmd_completor( struct usbctlx_cmd_completor *completor, - const hfa384x_usb_cmdresp_t + const struct hfa384x_usb_statusresp *cmdresp, - hfa384x_cmdresult_t *result) + struct hfa384x_cmdresult *result) { completor->head.complete = usbctlx_cmd_completor_fn; completor->cmdresp = cmdresp; @@ -685,7 +685,7 @@ static inline struct usbctlx_completor *init_cmd_completor( struct usbctlx_rrid_completor { struct usbctlx_completor head; - const hfa384x_usb_rridresp_t *rridresp; + const struct hfa384x_usb_rridresp *rridresp; void *riddata; unsigned int riddatalen; }; @@ -693,7 +693,7 @@ struct usbctlx_rrid_completor { static int usbctlx_rrid_completor_fn(struct usbctlx_completor *head) { struct usbctlx_rrid_completor *complete; - hfa384x_rridresult_t rridresult; + struct hfa384x_rridresult rridresult; complete = (struct usbctlx_rrid_completor *)head; usbctlx_get_rridresult(complete->rridresp, &rridresult); @@ -713,7 +713,7 @@ static int usbctlx_rrid_completor_fn(struct usbctlx_completor *head) static inline struct usbctlx_completor *init_rrid_completor( struct usbctlx_rrid_completor *completor, - const hfa384x_usb_rridresp_t + const struct hfa384x_usb_rridresp *rridresp, void *riddata, unsigned int riddatalen) @@ -744,7 +744,7 @@ static inline struct usbctlx_completor *init_rrid_completor( struct usbctlx_rmem_completor { struct usbctlx_completor head; - const hfa384x_usb_rmemresp_t *rmemresp; + const struct hfa384x_usb_rmemresp *rmemresp; void *data; unsigned int len; }; @@ -762,7 +762,7 @@ static int usbctlx_rmem_completor_fn(struct usbctlx_completor *head) static inline struct usbctlx_completor *init_rmem_completor( struct usbctlx_rmem_completor *completor, - hfa384x_usb_rmemresp_t + struct hfa384x_usb_rmemresp *rmemresp, void *data, unsigned int len) @@ -795,10 +795,10 @@ static inline struct usbctlx_completor *init_rmem_completor( * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) +static void hfa384x_cb_status(struct hfa384x *hw, const struct hfa384x_usbctlx *ctlx) { if (ctlx->usercb) { - hfa384x_cmdresult_t cmdresult; + struct hfa384x_cmdresult cmdresult; if (ctlx->state != CTLX_COMPLETE) { memset(&cmdresult, 0, sizeof(cmdresult)); @@ -812,21 +812,21 @@ static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) } } -static inline int hfa384x_docmd_wait(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +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(hfa384x_t *hw, - hfa384x_metacmd_t *cmd, +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(hfa384x_t *hw, u16 rid, void *riddata, +hfa384x_dorrid_wait(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen) { return hfa384x_dorrid(hw, DOWAIT, @@ -834,7 +834,7 @@ hfa384x_dorrid_wait(hfa384x_t *hw, u16 rid, void *riddata, } static inline int -hfa384x_dorrid_async(hfa384x_t *hw, +hfa384x_dorrid_async(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) @@ -845,7 +845,7 @@ hfa384x_dorrid_async(hfa384x_t *hw, } static inline int -hfa384x_dowrid_wait(hfa384x_t *hw, u16 rid, void *riddata, +hfa384x_dowrid_wait(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen) { return hfa384x_dowrid(hw, DOWAIT, @@ -853,7 +853,7 @@ hfa384x_dowrid_wait(hfa384x_t *hw, u16 rid, void *riddata, } static inline int -hfa384x_dowrid_async(hfa384x_t *hw, +hfa384x_dowrid_async(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) @@ -864,7 +864,7 @@ hfa384x_dowrid_async(hfa384x_t *hw, } static inline int -hfa384x_dormem_wait(hfa384x_t *hw, +hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) { return hfa384x_dormem(hw, DOWAIT, @@ -872,7 +872,7 @@ hfa384x_dormem_wait(hfa384x_t *hw, } static inline int -hfa384x_dormem_async(hfa384x_t *hw, +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) @@ -883,7 +883,7 @@ hfa384x_dormem_async(hfa384x_t *hw, } static inline int -hfa384x_dowmem_wait(hfa384x_t *hw, +hfa384x_dowmem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) { return hfa384x_dowmem(hw, DOWAIT, @@ -891,7 +891,7 @@ hfa384x_dowmem_wait(hfa384x_t *hw, } static inline int -hfa384x_dowmem_async(hfa384x_t *hw, +hfa384x_dowmem_async(struct hfa384x *hw, u16 page, u16 offset, void *data, @@ -923,11 +923,11 @@ hfa384x_dowmem_async(hfa384x_t *hw, * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_initialize(hfa384x_t *hw) +int hfa384x_cmd_initialize(struct hfa384x *hw) { int result = 0; int i; - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; cmd.cmd = HFA384x_CMDCODE_INIT; cmd.parm0 = 0; @@ -969,9 +969,9 @@ int hfa384x_cmd_initialize(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) +int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport) { - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | HFA384x_CMD_MACPORT_SET(macport); @@ -1002,9 +1002,9 @@ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) +int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport) { - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(macport); @@ -1044,9 +1044,9 @@ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) +int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable) { - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | HFA384x_CMD_AINFO_SET(enable); @@ -1095,10 +1095,10 @@ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, +int hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, u16 highaddr, u16 codelen) { - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; pr_debug("mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n", mode, lowaddr, highaddr, codelen); @@ -1136,7 +1136,7 @@ int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) +int hfa384x_corereset(struct hfa384x *hw, int holdtime, int settletime, int genesis) { int result; @@ -1173,8 +1173,8 @@ int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) * Call context: * process ----------------------------------------------------------------*/ -static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, - hfa384x_usbctlx_t *ctlx, +static int hfa384x_usbctlx_complete_sync(struct hfa384x *hw, + struct hfa384x_usbctlx *ctlx, struct usbctlx_completor *completor) { unsigned long flags; @@ -1289,13 +1289,13 @@ cleanup: * process ----------------------------------------------------------------*/ static int -hfa384x_docmd(hfa384x_t *hw, +hfa384x_docmd(struct hfa384x *hw, enum cmd_mode mode, - hfa384x_metacmd_t *cmd, + struct hfa384x_metacmd *cmd, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = usbctlx_alloc(); if (!ctlx) { @@ -1377,7 +1377,7 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dorrid(hfa384x_t *hw, +hfa384x_dorrid(struct hfa384x *hw, enum cmd_mode mode, u16 rid, void *riddata, @@ -1385,7 +1385,7 @@ hfa384x_dorrid(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = usbctlx_alloc(); if (!ctlx) { @@ -1458,7 +1458,7 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dowrid(hfa384x_t *hw, +hfa384x_dowrid(struct hfa384x *hw, enum cmd_mode mode, u16 rid, void *riddata, @@ -1466,7 +1466,7 @@ hfa384x_dowrid(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = usbctlx_alloc(); if (!ctlx) { @@ -1497,7 +1497,7 @@ hfa384x_dowrid(hfa384x_t *hw, kfree(ctlx); } else if (mode == DOWAIT) { struct usbctlx_cmd_completor completor; - hfa384x_cmdresult_t wridresult; + struct hfa384x_cmdresult wridresult; result = hfa384x_usbctlx_complete_sync(hw, ctlx, @@ -1545,7 +1545,7 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dormem(hfa384x_t *hw, +hfa384x_dormem(struct hfa384x *hw, enum cmd_mode mode, u16 page, u16 offset, @@ -1554,7 +1554,7 @@ hfa384x_dormem(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = usbctlx_alloc(); if (!ctlx) { @@ -1636,7 +1636,7 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dowmem(hfa384x_t *hw, +hfa384x_dowmem(struct hfa384x *hw, enum cmd_mode mode, u16 page, u16 offset, @@ -1645,7 +1645,7 @@ hfa384x_dowmem(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; pr_debug("page=0x%04x offset=0x%04x len=%d\n", page, offset, len); @@ -1679,7 +1679,7 @@ hfa384x_dowmem(hfa384x_t *hw, kfree(ctlx); } else if (mode == DOWAIT) { struct usbctlx_cmd_completor completor; - hfa384x_cmdresult_t wmemresult; + struct hfa384x_cmdresult wmemresult; result = hfa384x_usbctlx_complete_sync(hw, ctlx, @@ -1715,7 +1715,7 @@ done: * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport) +int hfa384x_drvr_disable(struct hfa384x *hw, u16 macport) { int result = 0; @@ -1753,7 +1753,7 @@ int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport) +int hfa384x_drvr_enable(struct hfa384x *hw, u16 macport) { int result = 0; @@ -1790,7 +1790,7 @@ int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) +int hfa384x_drvr_flashdl_enable(struct hfa384x *hw) { int result = 0; int i; @@ -1849,7 +1849,7 @@ int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) +int hfa384x_drvr_flashdl_disable(struct hfa384x *hw) { /* Check that we're already in the download state */ if (hw->dlstate != HFA384x_DLSTATE_FLASHENABLED) @@ -1894,7 +1894,7 @@ int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) +int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) { int result = 0; u32 dlbufaddr; @@ -2032,7 +2032,7 @@ exit_proc: * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) +int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { return hfa384x_dorrid_wait(hw, rid, buf, len); } @@ -2061,7 +2061,7 @@ int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) * process ----------------------------------------------------------------*/ int -hfa384x_drvr_setconfig_async(hfa384x_t *hw, +hfa384x_drvr_setconfig_async(struct hfa384x *hw, u16 rid, void *buf, u16 len, ctlx_usercb_t usercb, void *usercb_data) @@ -2088,7 +2088,7 @@ hfa384x_drvr_setconfig_async(hfa384x_t *hw, * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_disable(hfa384x_t *hw) +int hfa384x_drvr_ramdl_disable(struct hfa384x *hw) { /* Check that we're already in the download state */ if (hw->dlstate != HFA384x_DLSTATE_RAMENABLED) @@ -2128,7 +2128,7 @@ int hfa384x_drvr_ramdl_disable(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr) +int hfa384x_drvr_ramdl_enable(struct hfa384x *hw, u32 exeaddr) { int result = 0; u16 lowaddr; @@ -2196,7 +2196,7 @@ int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) +int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) { int result = 0; int nwrites; @@ -2276,7 +2276,7 @@ int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) * Call context: * process or non-card interrupt. ----------------------------------------------------------------*/ -int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len) +int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) { int result = 0; u16 *pda = buf; @@ -2386,7 +2386,7 @@ int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) +int hfa384x_drvr_setconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { return hfa384x_dowrid_wait(hw, rid, buf, len); } @@ -2411,7 +2411,7 @@ int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) * process ----------------------------------------------------------------*/ -int hfa384x_drvr_start(hfa384x_t *hw) +int hfa384x_drvr_start(struct hfa384x *hw) { int result, result1, result2; u16 status; @@ -2512,7 +2512,7 @@ done: * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_stop(hfa384x_t *hw) +int hfa384x_drvr_stop(struct hfa384x *hw) { int i; @@ -2562,11 +2562,11 @@ int hfa384x_drvr_stop(hfa384x_t *hw) * Call context: * interrupt ----------------------------------------------------------------*/ -int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, +int hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { - int usbpktlen = sizeof(hfa384x_tx_frame_t); + int usbpktlen = sizeof(struct hfa384x_tx_frame); int result; int ret; char *ptr; @@ -2656,9 +2656,9 @@ exit: return result; } -void hfa384x_tx_timeout(wlandevice_t *wlandev) +void hfa384x_tx_timeout(struct wlandevice *wlandev) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -2681,7 +2681,7 @@ void hfa384x_tx_timeout(wlandevice_t *wlandev) * Tasklet to delete dead CTLX objects * * Arguments: -* data ptr to a hfa384x_t +* data ptr to a struct hfa384x * * Returns: * @@ -2690,8 +2690,8 @@ void hfa384x_tx_timeout(wlandevice_t *wlandev) ----------------------------------------------------------------*/ static void hfa384x_usbctlx_reaper_task(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; - hfa384x_usbctlx_t *ctlx, *temp; + struct hfa384x *hw = (struct hfa384x *)data; + struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -2713,7 +2713,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) * Tasklet to call completion handlers for returned CTLXs * * Arguments: -* data ptr to hfa384x_t +* data ptr to struct hfa384x * * Returns: * Nothing @@ -2723,8 +2723,8 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) ----------------------------------------------------------------*/ static void hfa384x_usbctlx_completion_task(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; - hfa384x_usbctlx_t *ctlx, *temp; + struct hfa384x *hw = (struct hfa384x *)data; + struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; int reap = 0; @@ -2787,7 +2787,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) * next command on the queue is run afterwards. * * Arguments: -* hw ptr to the hfa384x_t structure +* hw ptr to the struct hfa384x structure * ctlx ptr to a CTLX structure * * Returns: @@ -2797,8 +2797,8 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) * Call context: * Either process or interrupt, but presumably interrupt ----------------------------------------------------------------*/ -static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, - hfa384x_usbctlx_t *ctlx) +static int unlocked_usbctlx_cancel_async(struct hfa384x *hw, + struct hfa384x_usbctlx *ctlx) { int ret; @@ -2836,7 +2836,7 @@ static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, * tasklet is scheduled. * * Arguments: -* hw ptr to a hfa384x_t structure +* hw ptr to a struct hfa384x structure * ctlx ptr to a ctlx structure * * Returns: @@ -2847,7 +2847,7 @@ static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, * Call context: * Either, assume interrupt ----------------------------------------------------------------*/ -static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +static void unlocked_usbctlx_complete(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) { /* Timers have been stopped, and ctlx should be in * a terminal state. Retire it from the "active" @@ -2876,7 +2876,7 @@ static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) * Checks to see if the head item is running. If not, starts it. * * Arguments: -* hw ptr to hfa384x_t +* hw ptr to struct hfa384x * * Returns: * nothing @@ -2886,7 +2886,7 @@ static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) * Call context: * any ----------------------------------------------------------------*/ -static void hfa384x_usbctlxq_run(hfa384x_t *hw) +static void hfa384x_usbctlxq_run(struct hfa384x *hw) { unsigned long flags; @@ -2905,12 +2905,12 @@ static void hfa384x_usbctlxq_run(hfa384x_t *hw) goto unlock; while (!list_empty(&hw->ctlxq.pending)) { - hfa384x_usbctlx_t *head; + struct hfa384x_usbctlx *head; int result; /* This is the first pending command */ head = list_entry(hw->ctlxq.pending.next, - hfa384x_usbctlx_t, list); + struct hfa384x_usbctlx, list); /* We need to split this off to avoid a race condition */ list_move_tail(&head->list, &hw->ctlxq.active); @@ -2988,9 +2988,9 @@ unlock: ----------------------------------------------------------------*/ static void hfa384x_usbin_callback(struct urb *urb) { - wlandevice_t *wlandev = urb->context; - hfa384x_t *hw; - hfa384x_usbin_t *usbin = (hfa384x_usbin_t *)urb->transfer_buffer; + struct wlandevice *wlandev = urb->context; + struct hfa384x *hw; + union hfa384x_usbin *usbin = (union hfa384x_usbin *)urb->transfer_buffer; struct sk_buff *skb = NULL; int result; int urb_status; @@ -3154,7 +3154,7 @@ exit: * queue and our state updated accordingly. * * Arguments: -* hw ptr to hfa384x_t +* hw ptr to struct hfa384x * usbin ptr to USB IN packet * urb_status status of this Bulk-In URB * @@ -3166,10 +3166,10 @@ exit: * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, +static void hfa384x_usbin_ctlx(struct hfa384x *hw, union hfa384x_usbin *usbin, int urb_status) { - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; int run_queue = 0; unsigned long flags; @@ -3285,8 +3285,8 @@ unlock: * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, - hfa384x_usbin_t *usbin) +static void hfa384x_usbin_txcompl(struct wlandevice *wlandev, + union hfa384x_usbin *usbin) { u16 status; @@ -3316,10 +3316,10 @@ static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) +static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) { - hfa384x_usbin_t *usbin = (hfa384x_usbin_t *)skb->data; - hfa384x_t *hw = wlandev->priv; + union hfa384x_usbin *usbin = (union hfa384x_usbin *)skb->data; + struct hfa384x *hw = wlandev->priv; int hdrlen; struct p80211_rxmeta *rxmeta; u16 data_len; @@ -3346,7 +3346,7 @@ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) hdrlen = p80211_headerlen(fc); /* Pull off the descriptor */ - skb_pull(skb, sizeof(hfa384x_rx_frame_t)); + skb_pull(skb, sizeof(struct hfa384x_rx_frame)); /* Now shunt the header block up against the data block * with an "overlapping" copy @@ -3416,17 +3416,17 @@ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_int_rxmonitor(wlandevice_t *wlandev, - hfa384x_usb_rxfrm_t *rxfrm) +static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, + struct hfa384x_usb_rxfrm *rxfrm) { - hfa384x_rx_frame_t *rxdesc = &(rxfrm->desc); + struct hfa384x_rx_frame *rxdesc = &(rxfrm->desc); unsigned int hdrlen = 0; unsigned int datalen = 0; unsigned int skblen = 0; u8 *datap; u16 fc; struct sk_buff *skb; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; /* Remember the status, time, and data_len fields are in host order */ /* Figure out how big the frame is */ @@ -3517,7 +3517,8 @@ static void hfa384x_int_rxmonitor(wlandevice_t *wlandev, * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) +static void hfa384x_usbin_info(struct wlandevice *wlandev, + union hfa384x_usbin *usbin) { usbin->infofrm.info.framelen = le16_to_cpu(usbin->infofrm.info.framelen); @@ -3542,7 +3543,7 @@ static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) ----------------------------------------------------------------*/ static void hfa384x_usbout_callback(struct urb *urb) { - wlandevice_t *wlandev = urb->context; + struct wlandevice *wlandev = urb->context; #ifdef DEBUG_USB dbprint_urb(urb); @@ -3556,7 +3557,7 @@ static void hfa384x_usbout_callback(struct urb *urb) case -EPIPE: { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; netdev_warn(hw->wlandev->netdev, "%s tx pipe stalled: requesting reset\n", @@ -3572,7 +3573,7 @@ static void hfa384x_usbout_callback(struct urb *urb) case -ETIMEDOUT: case -EILSEQ: { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; if (!test_and_set_bit (THROTTLE_TX, &hw->usb_flags) && @@ -3617,11 +3618,11 @@ static void hfa384x_usbout_callback(struct urb *urb) ----------------------------------------------------------------*/ static void hfa384x_ctlxout_callback(struct urb *urb) { - hfa384x_t *hw = urb->context; + struct hfa384x *hw = urb->context; int delete_resptimer = 0; int timer_ok = 1; int run_queue = 0; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; unsigned long flags; pr_debug("urb->status=%d\n", urb->status); @@ -3736,7 +3737,7 @@ delresp: * URB containing a Prism2.x XXX_Request was never called. * * Arguments: -* data a ptr to the hfa384x_t +* data a ptr to the struct hfa384x * * Returns: * nothing @@ -3748,7 +3749,7 @@ delresp: ----------------------------------------------------------------*/ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3765,7 +3766,7 @@ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) */ hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK; if (usb_unlink_urb(&hw->ctlx_urb) == -EINPROGRESS) { - hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); + struct hfa384x_usbctlx *ctlx = get_active_ctlx(hw); ctlx->state = CTLX_REQ_FAILED; @@ -3794,7 +3795,7 @@ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) * URB containing a Prism2.x XXX_Response was never called. * * Arguments: -* data a ptr to the hfa384x_t +* data a ptr to the struct hfa384x * * Returns: * nothing @@ -3806,7 +3807,7 @@ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) ----------------------------------------------------------------*/ static void hfa384x_usbctlx_resptimerfn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3817,7 +3818,7 @@ static void hfa384x_usbctlx_resptimerfn(unsigned long data) * adapter has been unplugged ... */ if (!list_empty(&hw->ctlxq.active)) { - hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); + struct hfa384x_usbctlx *ctlx = get_active_ctlx(hw); if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); @@ -3845,7 +3846,7 @@ static void hfa384x_usbctlx_resptimerfn(unsigned long data) ----------------------------------------------------------------*/ static void hfa384x_usb_throttlefn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3885,7 +3886,7 @@ static void hfa384x_usb_throttlefn(unsigned long data) * Call context: * process or interrupt ----------------------------------------------------------------*/ -static int hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +static int hfa384x_usbctlx_submit(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) { unsigned long flags; diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 6354036ffb42..0247cbc29145 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -104,7 +104,7 @@ static const u8 oui_8021h[] = { 0x00, 0x00, 0xf8 }; * May be called in interrupt or non-interrupt context *---------------------------------------------------------------- */ -int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, +int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { @@ -232,7 +232,7 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, } /* jkriegl: from orinoco, modified */ -static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, +static void orinoco_spy_gather(struct wlandevice *wlandev, char *mac, struct p80211_rxmeta *rxmeta) { int i; @@ -274,10 +274,10 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, * May be called in interrupt or non-interrupt context *---------------------------------------------------------------- */ -int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, +int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv, struct sk_buff *skb) { - netdevice_t *netdev = wlandev->netdev; + struct net_device *netdev = wlandev->netdev; u16 fc; unsigned int payload_length; unsigned int payload_offset; diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index 0ccfba1294de..b0d3567ca0ad 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -155,22 +155,9 @@ #define DIDmib_dot11smt_dot11WEPDefaultKeysTable \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4)) -#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(1) | 0x0c000000) -#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(2) | 0x0c000000) -#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(3) | 0x0c000000) -#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(4) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(_i) \ + (DIDmib_dot11smt_dot11WEPDefaultKeysTable | \ + P80211DID_MKITEM(_i) | 0x0c000000) #define DIDmib_dot11smt_dot11PrivacyTable \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(6)) diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index c501162c3020..850d897fc163 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -51,221 +51,221 @@ struct p80211msg_dot11req_mibget { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_unk392_t mibattribute; - p80211item_uint32_t resultcode; + struct p80211item_unk392 mibattribute; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_dot11req_mibset { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_unk392_t mibattribute; - p80211item_uint32_t resultcode; + struct p80211item_unk392 mibattribute; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_dot11req_scan { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t bsstype; - p80211item_pstr6_t bssid; + struct p80211item_uint32 bsstype; + struct p80211item_pstr6 bssid; u8 pad_0C[1]; - p80211item_pstr32_t ssid; + struct p80211item_pstr32 ssid; u8 pad_1D[3]; - p80211item_uint32_t scantype; - p80211item_uint32_t probedelay; - p80211item_pstr14_t channellist; + struct p80211item_uint32 scantype; + struct p80211item_uint32 probedelay; + struct p80211item_pstr14 channellist; u8 pad_2C[1]; - p80211item_uint32_t minchanneltime; - p80211item_uint32_t maxchanneltime; - p80211item_uint32_t resultcode; - p80211item_uint32_t numbss; - p80211item_uint32_t append; + struct p80211item_uint32 minchanneltime; + struct p80211item_uint32 maxchanneltime; + struct p80211item_uint32 resultcode; + struct p80211item_uint32 numbss; + struct p80211item_uint32 append; } __packed; struct p80211msg_dot11req_scan_results { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t bssindex; - p80211item_uint32_t resultcode; - p80211item_uint32_t signal; - p80211item_uint32_t noise; - p80211item_pstr6_t bssid; + struct p80211item_uint32 bssindex; + struct p80211item_uint32 resultcode; + struct p80211item_uint32 signal; + struct p80211item_uint32 noise; + struct p80211item_pstr6 bssid; u8 pad_3C[1]; - p80211item_pstr32_t ssid; + struct p80211item_pstr32 ssid; u8 pad_4D[3]; - p80211item_uint32_t bsstype; - p80211item_uint32_t beaconperiod; - p80211item_uint32_t dtimperiod; - p80211item_uint32_t timestamp; - p80211item_uint32_t localtime; - p80211item_uint32_t fhdwelltime; - p80211item_uint32_t fhhopset; - p80211item_uint32_t fhhoppattern; - p80211item_uint32_t fhhopindex; - p80211item_uint32_t dschannel; - p80211item_uint32_t cfpcount; - p80211item_uint32_t cfpperiod; - p80211item_uint32_t cfpmaxduration; - p80211item_uint32_t cfpdurremaining; - p80211item_uint32_t ibssatimwindow; - p80211item_uint32_t cfpollable; - p80211item_uint32_t cfpollreq; - p80211item_uint32_t privacy; - p80211item_uint32_t capinfo; - p80211item_uint32_t basicrate1; - p80211item_uint32_t basicrate2; - p80211item_uint32_t basicrate3; - p80211item_uint32_t basicrate4; - p80211item_uint32_t basicrate5; - p80211item_uint32_t basicrate6; - p80211item_uint32_t basicrate7; - p80211item_uint32_t basicrate8; - p80211item_uint32_t supprate1; - p80211item_uint32_t supprate2; - p80211item_uint32_t supprate3; - p80211item_uint32_t supprate4; - p80211item_uint32_t supprate5; - p80211item_uint32_t supprate6; - p80211item_uint32_t supprate7; - p80211item_uint32_t supprate8; + struct p80211item_uint32 bsstype; + struct p80211item_uint32 beaconperiod; + struct p80211item_uint32 dtimperiod; + struct p80211item_uint32 timestamp; + struct p80211item_uint32 localtime; + struct p80211item_uint32 fhdwelltime; + struct p80211item_uint32 fhhopset; + struct p80211item_uint32 fhhoppattern; + struct p80211item_uint32 fhhopindex; + struct p80211item_uint32 dschannel; + struct p80211item_uint32 cfpcount; + struct p80211item_uint32 cfpperiod; + struct p80211item_uint32 cfpmaxduration; + struct p80211item_uint32 cfpdurremaining; + struct p80211item_uint32 ibssatimwindow; + struct p80211item_uint32 cfpollable; + struct p80211item_uint32 cfpollreq; + struct p80211item_uint32 privacy; + struct p80211item_uint32 capinfo; + struct p80211item_uint32 basicrate1; + struct p80211item_uint32 basicrate2; + struct p80211item_uint32 basicrate3; + struct p80211item_uint32 basicrate4; + struct p80211item_uint32 basicrate5; + struct p80211item_uint32 basicrate6; + struct p80211item_uint32 basicrate7; + struct p80211item_uint32 basicrate8; + struct p80211item_uint32 supprate1; + struct p80211item_uint32 supprate2; + struct p80211item_uint32 supprate3; + struct p80211item_uint32 supprate4; + struct p80211item_uint32 supprate5; + struct p80211item_uint32 supprate6; + struct p80211item_uint32 supprate7; + struct p80211item_uint32 supprate8; } __packed; struct p80211msg_dot11req_start { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_pstr32_t ssid; + struct p80211item_pstr32 ssid; u8 pad_12D[3]; - p80211item_uint32_t bsstype; - p80211item_uint32_t beaconperiod; - p80211item_uint32_t dtimperiod; - p80211item_uint32_t cfpperiod; - p80211item_uint32_t cfpmaxduration; - p80211item_uint32_t fhdwelltime; - p80211item_uint32_t fhhopset; - p80211item_uint32_t fhhoppattern; - p80211item_uint32_t dschannel; - p80211item_uint32_t ibssatimwindow; - p80211item_uint32_t probedelay; - p80211item_uint32_t cfpollable; - p80211item_uint32_t cfpollreq; - p80211item_uint32_t basicrate1; - p80211item_uint32_t basicrate2; - p80211item_uint32_t basicrate3; - p80211item_uint32_t basicrate4; - p80211item_uint32_t basicrate5; - p80211item_uint32_t basicrate6; - p80211item_uint32_t basicrate7; - p80211item_uint32_t basicrate8; - p80211item_uint32_t operationalrate1; - p80211item_uint32_t operationalrate2; - p80211item_uint32_t operationalrate3; - p80211item_uint32_t operationalrate4; - p80211item_uint32_t operationalrate5; - p80211item_uint32_t operationalrate6; - p80211item_uint32_t operationalrate7; - p80211item_uint32_t operationalrate8; - p80211item_uint32_t resultcode; + struct p80211item_uint32 bsstype; + struct p80211item_uint32 beaconperiod; + struct p80211item_uint32 dtimperiod; + struct p80211item_uint32 cfpperiod; + struct p80211item_uint32 cfpmaxduration; + struct p80211item_uint32 fhdwelltime; + struct p80211item_uint32 fhhopset; + struct p80211item_uint32 fhhoppattern; + struct p80211item_uint32 dschannel; + struct p80211item_uint32 ibssatimwindow; + struct p80211item_uint32 probedelay; + struct p80211item_uint32 cfpollable; + struct p80211item_uint32 cfpollreq; + struct p80211item_uint32 basicrate1; + struct p80211item_uint32 basicrate2; + struct p80211item_uint32 basicrate3; + struct p80211item_uint32 basicrate4; + struct p80211item_uint32 basicrate5; + struct p80211item_uint32 basicrate6; + struct p80211item_uint32 basicrate7; + struct p80211item_uint32 basicrate8; + struct p80211item_uint32 operationalrate1; + struct p80211item_uint32 operationalrate2; + struct p80211item_uint32 operationalrate3; + struct p80211item_uint32 operationalrate4; + struct p80211item_uint32 operationalrate5; + struct p80211item_uint32 operationalrate6; + struct p80211item_uint32 operationalrate7; + struct p80211item_uint32 operationalrate8; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_lnxreq_ifstate { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t ifstate; - p80211item_uint32_t resultcode; + struct p80211item_uint32 ifstate; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_lnxreq_wlansniff { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t enable; - p80211item_uint32_t channel; - p80211item_uint32_t prismheader; - p80211item_uint32_t wlanheader; - p80211item_uint32_t keepwepflags; - p80211item_uint32_t stripfcs; - p80211item_uint32_t packet_trunc; - p80211item_uint32_t resultcode; + struct p80211item_uint32 enable; + struct p80211item_uint32 channel; + struct p80211item_uint32 prismheader; + struct p80211item_uint32 wlanheader; + struct p80211item_uint32 keepwepflags; + struct p80211item_uint32 stripfcs; + struct p80211item_uint32 packet_trunc; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_lnxreq_hostwep { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t resultcode; - p80211item_uint32_t decrypt; - p80211item_uint32_t encrypt; + struct p80211item_uint32 resultcode; + struct p80211item_uint32 decrypt; + struct p80211item_uint32 encrypt; } __packed; struct p80211msg_lnxreq_commsquality { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t resultcode; - p80211item_uint32_t dbm; - p80211item_uint32_t link; - p80211item_uint32_t level; - p80211item_uint32_t noise; - p80211item_uint32_t txrate; + struct p80211item_uint32 resultcode; + struct p80211item_uint32 dbm; + struct p80211item_uint32 link; + struct p80211item_uint32 level; + struct p80211item_uint32 noise; + struct p80211item_uint32 txrate; } __packed; struct p80211msg_lnxreq_autojoin { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_pstr32_t ssid; + struct p80211item_pstr32 ssid; u8 pad_19D[3]; - p80211item_uint32_t authtype; - p80211item_uint32_t resultcode; + struct p80211item_uint32 authtype; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_readpda { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_unk1024_t pda; - p80211item_uint32_t resultcode; + struct p80211item_unk1024 pda; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_ramdl_state { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t enable; - p80211item_uint32_t exeaddr; - p80211item_uint32_t resultcode; + struct p80211item_uint32 enable; + struct p80211item_uint32 exeaddr; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_ramdl_write { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t addr; - p80211item_uint32_t len; - p80211item_unk4096_t data; - p80211item_uint32_t resultcode; + struct p80211item_uint32 addr; + struct p80211item_uint32 len; + struct p80211item_unk4096 data; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_flashdl_state { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t enable; - p80211item_uint32_t resultcode; + struct p80211item_uint32 enable; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_flashdl_write { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t addr; - p80211item_uint32_t len; - p80211item_unk4096_t data; - p80211item_uint32_t resultcode; + struct p80211item_uint32 addr; + struct p80211item_uint32 len; + struct p80211item_unk4096 data; + struct p80211item_uint32 resultcode; } __packed; #endif diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 90cc8cdcf969..825a63a7c0e3 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -91,17 +91,17 @@ #include "cfg80211.c" /* netdevice method functions */ -static int p80211knetdev_init(netdevice_t *netdev); -static int p80211knetdev_open(netdevice_t *netdev); -static int p80211knetdev_stop(netdevice_t *netdev); +static int p80211knetdev_init(struct net_device *netdev); +static int p80211knetdev_open(struct net_device *netdev); +static int p80211knetdev_stop(struct net_device *netdev); static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, - netdevice_t *netdev); -static void p80211knetdev_set_multicast_list(netdevice_t *dev); -static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, + struct net_device *netdev); +static void p80211knetdev_set_multicast_list(struct net_device *dev); +static int p80211knetdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr); -static void p80211knetdev_tx_timeout(netdevice_t *netdev); -static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc); +static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr); +static void p80211knetdev_tx_timeout(struct net_device *netdev); +static int p80211_rx_typedrop(struct wlandevice *wlandev, u16 fc); int wlan_watchdog = 5000; module_param(wlan_watchdog, int, 0644); @@ -123,7 +123,7 @@ MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions"); * Returns: * nothing ----------------------------------------------------------------*/ -static int p80211knetdev_init(netdevice_t *netdev) +static int p80211knetdev_init(struct net_device *netdev) { /* Called in response to register_netdev */ /* This is usually the probe function, but the probe has */ @@ -146,10 +146,10 @@ static int p80211knetdev_init(netdevice_t *netdev) * Returns: * zero on success, non-zero otherwise ----------------------------------------------------------------*/ -static int p80211knetdev_open(netdevice_t *netdev) +static int p80211knetdev_open(struct net_device *netdev) { int result = 0; /* success */ - wlandevice_t *wlandev = netdev->ml_priv; + struct wlandevice *wlandev = netdev->ml_priv; /* Check to make sure the MSD is running */ if (wlandev->msdstate != WLAN_MSD_RUNNING) @@ -181,10 +181,10 @@ static int p80211knetdev_open(netdevice_t *netdev) * Returns: * zero on success, non-zero otherwise ----------------------------------------------------------------*/ -static int p80211knetdev_stop(netdevice_t *netdev) +static int p80211knetdev_stop(struct net_device *netdev) { int result = 0; - wlandevice_t *wlandev = netdev->ml_priv; + struct wlandevice *wlandev = netdev->ml_priv; if (wlandev->close) result = wlandev->close(wlandev); @@ -208,7 +208,7 @@ static int p80211knetdev_stop(netdevice_t *netdev) * Side effects: * ----------------------------------------------------------------*/ -void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb) +void p80211netdev_rx(struct wlandevice *wlandev, struct sk_buff *skb) { /* Enqueue for post-irq processing */ skb_queue_tail(&wlandev->nsd_rxq, skb); @@ -227,11 +227,11 @@ void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb) * CONV_TO_ETHER_FAILED if conversion failed * CONV_TO_ETHER_SKIPPED if frame is ignored */ -static int p80211_convert_to_ether(wlandevice_t *wlandev, struct sk_buff *skb) +static int p80211_convert_to_ether(struct wlandevice *wlandev, struct sk_buff *skb) { struct p80211_hdr_a3 *hdr; - hdr = (struct p80211_hdr_a3 *) skb->data; + hdr = (struct p80211_hdr_a3 *)skb->data; if (p80211_rx_typedrop(wlandev, hdr->fc)) return CONV_TO_ETHER_SKIPPED; @@ -265,9 +265,9 @@ static int p80211_convert_to_ether(wlandevice_t *wlandev, struct sk_buff *skb) */ static void p80211netdev_rx_bh(unsigned long arg) { - wlandevice_t *wlandev = (wlandevice_t *) arg; + struct wlandevice *wlandev = (struct wlandevice *)arg; struct sk_buff *skb = NULL; - netdevice_t *dev = wlandev->netdev; + struct net_device *dev = wlandev->netdev; /* Let's empty our our queue */ while ((skb = skb_dequeue(&wlandev->nsd_rxq))) { @@ -318,11 +318,11 @@ static void p80211netdev_rx_bh(unsigned long arg) * zero on success, non-zero on failure. ----------------------------------------------------------------*/ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, - netdevice_t *netdev) + struct net_device *netdev) { int result = 0; int txresult = -1; - wlandevice_t *wlandev = netdev->ml_priv; + struct wlandevice *wlandev = netdev->ml_priv; union p80211_hdr p80211_hdr; struct p80211_metawep p80211_wep; @@ -446,9 +446,9 @@ failed: * Returns: * nothing ----------------------------------------------------------------*/ -static void p80211knetdev_set_multicast_list(netdevice_t *dev) +static void p80211knetdev_set_multicast_list(struct net_device *dev) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; /* TODO: real multicast support as well */ @@ -459,7 +459,7 @@ static void p80211knetdev_set_multicast_list(netdevice_t *dev) #ifdef SIOCETHTOOL -static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr) +static int p80211netdev_ethtool(struct wlandevice *wlandev, void __user *useraddr) { u32 ethcmd; struct ethtool_drvinfo info; @@ -531,11 +531,11 @@ static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr) * Process thread (ioctl caller). TODO: SMP support may require * locks. ----------------------------------------------------------------*/ -static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) +static int p80211knetdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int result = 0; - struct p80211ioctl_req *req = (struct p80211ioctl_req *) ifr; - wlandevice_t *wlandev = dev->ml_priv; + struct p80211ioctl_req *req = (struct p80211ioctl_req *)ifr; + struct wlandevice *wlandev = dev->ml_priv; u8 *msgbuf; netdev_dbg(dev, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); @@ -610,13 +610,13 @@ bail: * * by: Collin R. Mulliner ----------------------------------------------------------------*/ -static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) +static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *new_addr = addr; struct p80211msg_dot11req_mibset dot11req; - p80211item_unk392_t *mibattr; - p80211item_pstr6_t *macaddr; - p80211item_uint32_t *resultcode; + struct p80211item_unk392 *mibattr; + struct p80211item_pstr6 *macaddr; + struct p80211item_uint32 *resultcode; int result; /* If we're running, we don't allow MAC address changes */ @@ -625,7 +625,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) /* Set up some convenience pointers. */ mibattr = &dot11req.mibattribute; - macaddr = (p80211item_pstr6_t *) &mibattr->data; + macaddr = (struct p80211item_pstr6 *)&mibattr->data; resultcode = &dot11req.resultcode; /* Set up a dot11req_mibset */ @@ -633,7 +633,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) dot11req.msgcode = DIDmsg_dot11req_mibset; dot11req.msglen = sizeof(struct p80211msg_dot11req_mibset); memcpy(dot11req.devname, - ((wlandevice_t *) dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1); + ((struct wlandevice *)dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1); /* Set up the mibattribute argument */ mibattr->did = DIDmsg_dot11req_mibset_mibattribute; @@ -653,7 +653,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) resultcode->data = 0; /* now fire the request */ - result = p80211req_dorequest(dev->ml_priv, (u8 *) &dot11req); + result = p80211req_dorequest(dev->ml_priv, (u8 *)&dot11req); /* If the request wasn't successful, report an error and don't * change the netdev address @@ -669,7 +669,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) return result; } -static int wlan_change_mtu(netdevice_t *dev, int new_mtu) +static int wlan_change_mtu(struct net_device *dev, int new_mtu) { /* 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap) and another 8 for wep. */ @@ -717,10 +717,10 @@ static const struct net_device_ops p80211_netdev_ops = { * compiled drivers, this function will be called in the * context of the kernel startup code. ----------------------------------------------------------------*/ -int wlan_setup(wlandevice_t *wlandev, struct device *physdev) +int wlan_setup(struct wlandevice *wlandev, struct device *physdev) { int result = 0; - netdevice_t *netdev; + struct net_device *netdev; struct wiphy *wiphy; struct wireless_dev *wdev; @@ -783,7 +783,7 @@ int wlan_setup(wlandevice_t *wlandev, struct device *physdev) * compiled drivers, this function will be called in the * context of the kernel startup code. ----------------------------------------------------------------*/ -void wlan_unsetup(wlandevice_t *wlandev) +void wlan_unsetup(struct wlandevice *wlandev) { struct wireless_dev *wdev; @@ -817,7 +817,7 @@ void wlan_unsetup(wlandevice_t *wlandev) * Call Context: * Can be either interrupt or not. ----------------------------------------------------------------*/ -int register_wlandev(wlandevice_t *wlandev) +int register_wlandev(struct wlandevice *wlandev) { return register_netdev(wlandev->netdev); } @@ -839,7 +839,7 @@ int register_wlandev(wlandevice_t *wlandev) * Call Context: * Can be either interrupt or not. ----------------------------------------------------------------*/ -int unregister_wlandev(wlandevice_t *wlandev) +int unregister_wlandev(struct wlandevice *wlandev) { struct sk_buff *skb; @@ -882,7 +882,7 @@ int unregister_wlandev(wlandevice_t *wlandev) * Call context: * Usually interrupt. ----------------------------------------------------------------*/ -void p80211netdev_hwremoved(wlandevice_t *wlandev) +void p80211netdev_hwremoved(struct wlandevice *wlandev) { wlandev->hwremoved = 1; if (wlandev->state == WLAN_DEVICE_OPEN) @@ -912,7 +912,7 @@ void p80211netdev_hwremoved(wlandevice_t *wlandev) * Call context: * interrupt ----------------------------------------------------------------*/ -static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc) +static int p80211_rx_typedrop(struct wlandevice *wlandev, u16 fc) { u16 ftype; u16 fstype; @@ -1071,9 +1071,9 @@ static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc) return drop; } -static void p80211knetdev_tx_timeout(netdevice_t *netdev) +static void p80211knetdev_tx_timeout(struct net_device *netdev) { - wlandevice_t *wlandev = netdev->ml_priv; + struct wlandevice *wlandev = netdev->ml_priv; if (wlandev->tx_timeout) { wlandev->tx_timeout(wlandev); diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 820a0e20a941..1e6a774fc7c5 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -57,9 +57,6 @@ #include #include -#undef netdevice_t -typedef struct net_device netdevice_t; - #define WLAN_RELEASE "0.3.0-staging" #define WLAN_DEVICE_CLOSED 0 @@ -101,7 +98,7 @@ typedef struct net_device netdevice_t; #define P80211_NSDCAP_NOSCAN 0x200 /* nsd can scan */ /* Received frame statistics */ -typedef struct p80211_frmrx_t { +struct p80211_frmrx { u32 mgmt; u32 assocreq; u32 assocresp; @@ -135,10 +132,10 @@ typedef struct p80211_frmrx_t { u32 data_unknown; u32 decrypt; u32 decrypt_err; -} p80211_frmrx_t; +}; /* called by /proc/net/wireless */ -struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev); +struct iw_statistics *p80211wext_get_wireless_stats(struct net_device *dev); /* wireless extensions' ioctls */ extern struct iw_handler_def p80211wext_handler_def; @@ -157,7 +154,7 @@ extern int wlan_watchdog; extern int wlan_wext_write; /* WLAN device type */ -typedef struct wlandevice { +struct wlandevice { void *priv; /* private data for MSD */ /* Subsystem State */ @@ -186,12 +183,12 @@ typedef struct wlandevice { struct p80211_metawep *p80211_wep); int (*mlmerequest)(struct wlandevice *wlandev, struct p80211msg *msg); int (*set_multicast_list)(struct wlandevice *wlandev, - netdevice_t *dev); + struct net_device *dev); void (*tx_timeout)(struct wlandevice *wlandev); /* 802.11 State */ u8 bssid[WLAN_BSSID_LEN]; - p80211pstr32_t ssid; + struct p80211pstr32 ssid; u32 macmode; int linkstatus; @@ -206,7 +203,7 @@ typedef struct wlandevice { /* netlink socket */ /* queue for indications waiting for cmd completion */ /* Linux netdevice and support */ - netdevice_t *netdev; /* ptr to linux netdevice */ + struct net_device *netdev; /* ptr to linux netdevice */ /* Rx bottom half */ struct tasklet_struct rx_bh; @@ -214,7 +211,7 @@ typedef struct wlandevice { struct sk_buff_head nsd_rxq; /* 802.11 device statistics */ - struct p80211_frmrx_t rx; + struct p80211_frmrx rx; struct iw_statistics wstats; @@ -222,19 +219,19 @@ typedef struct wlandevice { u8 spy_number; char spy_address[IW_MAX_SPY][ETH_ALEN]; struct iw_quality spy_stat[IW_MAX_SPY]; -} wlandevice_t; +}; /* WEP stuff */ -int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen); -int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, - u8 *iv, u8 *icv); -int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, +int wep_change_key(struct wlandevice *wlandev, int keynum, u8 *key, int keylen); +int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv); +int wep_encrypt(struct wlandevice *wlandev, u8 *buf, u8 *dst, u32 len, + int keynum, u8 *iv, u8 *icv); -int wlan_setup(wlandevice_t *wlandev, struct device *physdev); -void wlan_unsetup(wlandevice_t *wlandev); -int register_wlandev(wlandevice_t *wlandev); -int unregister_wlandev(wlandevice_t *wlandev); -void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); -void p80211netdev_hwremoved(wlandevice_t *wlandev); +int wlan_setup(struct wlandevice *wlandev, struct device *physdev); +void wlan_unsetup(struct wlandevice *wlandev); +int register_wlandev(struct wlandevice *wlandev); +int unregister_wlandev(struct wlandevice *wlandev); +void p80211netdev_rx(struct wlandevice *wlandev, struct sk_buff *skb); +void p80211netdev_hwremoved(struct wlandevice *wlandev); #endif diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 4b84b568f6ca..d43e85b5d49b 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -72,11 +72,26 @@ #include "p80211metastruct.h" #include "p80211req.h" -static void p80211req_handlemsg(wlandevice_t *wlandev, struct p80211msg *msg); -static void p80211req_mibset_mibget(wlandevice_t *wlandev, +static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *msg); +static void p80211req_mibset_mibget(struct wlandevice *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget); +static void p80211req_handle_action(struct wlandevice *wlandev, u32 *data, + int isget, u32 flag) +{ + if (isget) { + if (wlandev->hostwep & flag) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= ~flag; + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= flag; + } +} + /*---------------------------------------------------------------- * p80211req_dorequest * @@ -93,9 +108,9 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, * Potentially blocks the caller, so it's a good idea to * not call this function from an interrupt context. ----------------------------------------------------------------*/ -int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf) +int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf) { - struct p80211msg *msg = (struct p80211msg *) msgbuf; + struct p80211msg *msg = (struct p80211msg *)msgbuf; /* Check to make sure the MSD is running */ if (!((wlandev->msdstate == WLAN_MSD_HWPRESENT && @@ -149,13 +164,13 @@ int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf) * Call context: * Process thread ----------------------------------------------------------------*/ -static void p80211req_handlemsg(wlandevice_t *wlandev, struct p80211msg *msg) +static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *msg) { switch (msg->msgcode) { case DIDmsg_lnxreq_hostwep:{ struct p80211msg_lnxreq_hostwep *req = - (struct p80211msg_lnxreq_hostwep *) msg; + (struct p80211msg_lnxreq_hostwep *)msg; wlandev->hostwep &= ~(HOSTWEP_DECRYPT | HOSTWEP_ENCRYPT); if (req->decrypt.data == P80211ENUM_truth_true) @@ -169,44 +184,34 @@ static void p80211req_handlemsg(wlandevice_t *wlandev, struct p80211msg *msg) case DIDmsg_dot11req_mibset:{ int isget = (msg->msgcode == DIDmsg_dot11req_mibget); struct p80211msg_dot11req_mibget *mib_msg = - (struct p80211msg_dot11req_mibget *) msg; + (struct p80211msg_dot11req_mibget *)msg; p80211req_mibset_mibget(wlandev, mib_msg, isget); break; } } /* switch msg->msgcode */ } -static void p80211req_mibset_mibget(wlandevice_t *wlandev, +static void p80211req_mibset_mibget(struct wlandevice *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget) { - p80211itemd_t *mibitem = (p80211itemd_t *) mib_msg->mibattribute.data; - p80211pstrd_t *pstr = (p80211pstrd_t *) mibitem->data; - u8 *key = mibitem->data + sizeof(p80211pstrd_t); + struct p80211itemd *mibitem = (struct p80211itemd *)mib_msg->mibattribute.data; + struct p80211pstrd *pstr = (struct p80211pstrd *)mibitem->data; + u8 *key = mibitem->data + sizeof(struct p80211pstrd); switch (mibitem->did) { - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0:{ + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1): + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(2): + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(3): + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(4): if (!isget) - wep_change_key(wlandev, 0, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1:{ - if (!isget) - wep_change_key(wlandev, 1, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2:{ - if (!isget) - wep_change_key(wlandev, 2, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3:{ - if (!isget) - wep_change_key(wlandev, 3, key, pstr->len); - break; - } + wep_change_key(wlandev, + P80211DID_ITEM(mibitem->did) - 1, + key, pstr->len); + break; + case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID:{ - u32 *data = (u32 *) mibitem->data; + u32 *data = (u32 *)mibitem->data; if (isget) { *data = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; @@ -217,33 +222,17 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, break; } case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked:{ - u32 *data = (u32 *) mibitem->data; + u32 *data = (u32 *)mibitem->data; - if (isget) { - if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) - *data = P80211ENUM_truth_true; - else - *data = P80211ENUM_truth_false; - } else { - wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED); - if (*data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_PRIVACYINVOKED; - } + p80211req_handle_action(wlandev, data, isget, + HOSTWEP_PRIVACYINVOKED); break; } case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted:{ - u32 *data = (u32 *) mibitem->data; + u32 *data = (u32 *)mibitem->data; - if (isget) { - if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) - *data = P80211ENUM_truth_true; - else - *data = P80211ENUM_truth_false; - } else { - wlandev->hostwep &= ~(HOSTWEP_EXCLUDEUNENCRYPTED); - if (*data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_EXCLUDEUNENCRYPTED; - } + p80211req_handle_action(wlandev, data, isget, + HOSTWEP_EXCLUDEUNENCRYPTED); break; } } diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h index a95a45a6814d..8d3054c22a05 100644 --- a/drivers/staging/wlan-ng/p80211req.h +++ b/drivers/staging/wlan-ng/p80211req.h @@ -48,6 +48,6 @@ #ifndef _LINUX_P80211REQ_H #define _LINUX_P80211REQ_H -int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf); +int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf); #endif diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 8cb4fc6448a0..263ef2ddb197 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -1,58 +1,59 @@ -/* p80211types.h -* -* Macros, constants, types, and funcs for p80211 data types -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file declares some of the constants and types used in various -* parts of the linux-wlan system. -* -* Notes: -* - Constant values are always in HOST byte order. -* -* All functions and statics declared here are implemented in p80211types.c -* -------------------------------------------------------------------- -*/ +/* + * p80211types.h + * + * Macros, constants, types, and funcs for p80211 data types + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file declares some of the constants and types used in various + * parts of the linux-wlan system. + * + * Notes: + * - Constant values are always in HOST byte order. + * + * All functions and statics declared here are implemented in p80211types.c + * -------------------------------------------------------------------- + */ #ifndef _P80211TYPES_H #define _P80211TYPES_H @@ -123,18 +124,18 @@ #define MKENUMNAME(name) p80211enum_ ## name /*---------------------------------------------------------------- -* The following constants and macros are used to construct and -* deconstruct the Data ID codes. The coding is as follows: -* -* ...rwtnnnnnnnniiiiiiggggggssssss s - Section -* g - Group -* i - Item -* n - Index -* t - Table flag -* w - Write flag -* r - Read flag -* . - Unused -*/ + * The following constants and macros are used to construct and + * deconstruct the Data ID codes. The coding is as follows: + * + * ...rwtnnnnnnnniiiiiiggggggssssss s - Section + * g - Group + * i - Item + * n - Index + * t - Table flag + * w - Write flag + * r - Read flag + * . - Unused + */ #define P80211DID_LSB_SECTION (0) #define P80211DID_LSB_GROUP (6) @@ -200,138 +201,138 @@ /* The following structure types are used for the representation */ /* of ENUMint type metadata. */ -typedef struct p80211enumpair { +struct p80211enumpair { u32 val; char *name; -} p80211enumpair_t; +}; -typedef struct p80211enum { +struct p80211enum { int nitems; - p80211enumpair_t *list; -} p80211enum_t; + struct p80211enumpair *list; +}; /*----------------------------------------------------------------*/ /* The following structure types are used to store data items in */ /* messages. */ /* Template pascal string */ -typedef struct p80211pstr { +struct p80211pstr { u8 len; -} __packed p80211pstr_t; +} __packed; -typedef struct p80211pstrd { +struct p80211pstrd { u8 len; u8 data[0]; -} __packed p80211pstrd_t; +} __packed; /* Maximum pascal string */ -typedef struct p80211pstr255 { +struct p80211pstr255 { u8 len; u8 data[MAXLEN_PSTR255]; -} __packed p80211pstr255_t; +} __packed; /* pascal string for macaddress and bssid */ -typedef struct p80211pstr6 { +struct p80211pstr6 { u8 len; u8 data[MAXLEN_PSTR6]; -} __packed p80211pstr6_t; +} __packed; /* pascal string for channel list */ -typedef struct p80211pstr14 { +struct p80211pstr14 { u8 len; u8 data[MAXLEN_PSTR14]; -} __packed p80211pstr14_t; +} __packed; /* pascal string for ssid */ -typedef struct p80211pstr32 { +struct p80211pstr32 { u8 len; u8 data[MAXLEN_PSTR32]; -} __packed p80211pstr32_t; +} __packed; /* MAC address array */ -typedef struct p80211macarray { +struct p80211macarray { u32 cnt; u8 data[1][MAXLEN_PSTR6]; -} __packed p80211macarray_t; +} __packed; /* prototype template */ -typedef struct p80211item { +struct p80211item { u32 did; u16 status; u16 len; -} __packed p80211item_t; +} __packed; /* prototype template w/ data item */ -typedef struct p80211itemd { +struct p80211itemd { u32 did; u16 status; u16 len; u8 data[0]; -} __packed p80211itemd_t; +} __packed; /* message data item for int, BOUNDEDINT, ENUMINT */ -typedef struct p80211item_uint32 { +struct p80211item_uint32 { u32 did; u16 status; u16 len; u32 data; -} __packed p80211item_uint32_t; +} __packed; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr6 { +struct p80211item_pstr6 { u32 did; u16 status; u16 len; - p80211pstr6_t data; -} __packed p80211item_pstr6_t; + struct p80211pstr6 data; +} __packed; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr14 { +struct p80211item_pstr14 { u32 did; u16 status; u16 len; - p80211pstr14_t data; -} __packed p80211item_pstr14_t; + struct p80211pstr14 data; +} __packed; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr32 { +struct p80211item_pstr32 { u32 did; u16 status; u16 len; - p80211pstr32_t data; -} __packed p80211item_pstr32_t; + struct p80211pstr32 data; +} __packed; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr255 { +struct p80211item_pstr255 { u32 did; u16 status; u16 len; - p80211pstr255_t data; -} __packed p80211item_pstr255_t; + struct p80211pstr255 data; +} __packed; /* message data item for UNK 392, namely mib items */ -typedef struct p80211item_unk392 { +struct p80211item_unk392 { u32 did; u16 status; u16 len; u8 data[MAXLEN_MIBATTRIBUTE]; -} __packed p80211item_unk392_t; +} __packed; /* message data item for UNK 1025, namely p2 pdas */ -typedef struct p80211item_unk1024 { +struct p80211item_unk1024 { u32 did; u16 status; u16 len; u8 data[1024]; -} __packed p80211item_unk1024_t; +} __packed; /* message data item for UNK 4096, namely p2 download chunks */ -typedef struct p80211item_unk4096 { +struct p80211item_unk4096 { u32 did; u16 status; u16 len; u8 data[4096]; -} __packed p80211item_unk4096_t; +} __packed; struct catlistitem; @@ -351,25 +352,25 @@ typedef u32(*p80211_valid_t) (struct catlistitem *, u32 did, u8 *itembuf); /* The following are the external declarations */ /* for all enumerations */ -extern p80211enum_t MKENUMNAME(truth); -extern p80211enum_t MKENUMNAME(ifstate); -extern p80211enum_t MKENUMNAME(powermgmt); -extern p80211enum_t MKENUMNAME(bsstype); -extern p80211enum_t MKENUMNAME(authalg); -extern p80211enum_t MKENUMNAME(phytype); -extern p80211enum_t MKENUMNAME(temptype); -extern p80211enum_t MKENUMNAME(regdomain); -extern p80211enum_t MKENUMNAME(ccamode); -extern p80211enum_t MKENUMNAME(diversity); -extern p80211enum_t MKENUMNAME(scantype); -extern p80211enum_t MKENUMNAME(resultcode); -extern p80211enum_t MKENUMNAME(reason); -extern p80211enum_t MKENUMNAME(status); -extern p80211enum_t MKENUMNAME(msgcode); -extern p80211enum_t MKENUMNAME(msgitem_status); +extern struct p80211enum MKENUMNAME(truth); +extern struct p80211enum MKENUMNAME(ifstate); +extern struct p80211enum MKENUMNAME(powermgmt); +extern struct p80211enum MKENUMNAME(bsstype); +extern struct p80211enum MKENUMNAME(authalg); +extern struct p80211enum MKENUMNAME(phytype); +extern struct p80211enum MKENUMNAME(temptype); +extern struct p80211enum MKENUMNAME(regdomain); +extern struct p80211enum MKENUMNAME(ccamode); +extern struct p80211enum MKENUMNAME(diversity); +extern struct p80211enum MKENUMNAME(scantype); +extern struct p80211enum MKENUMNAME(resultcode); +extern struct p80211enum MKENUMNAME(reason); +extern struct p80211enum MKENUMNAME(status); +extern struct p80211enum MKENUMNAME(msgcode); +extern struct p80211enum MKENUMNAME(msgitem_status); -extern p80211enum_t MKENUMNAME(lnxroam_reason); +extern struct p80211enum MKENUMNAME(lnxroam_reason); -extern p80211enum_t MKENUMNAME(p2preamble); +extern struct p80211enum MKENUMNAME(p2preamble); #endif /* _P80211TYPES_H */ diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 22c79703e328..23b183738037 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -119,7 +119,7 @@ static const u32 wep_crc32_table[256] = { /* keylen in bytes! */ -int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen) +int wep_change_key(struct wlandevice *wlandev, int keynum, u8 *key, int keylen) { if (keylen < 0) return -1; @@ -143,7 +143,7 @@ int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen) * 4-byte IV at start of buffer, 4-byte ICV at end of buffer. * if successful, buf start is payload begin, length -= 8; */ -int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, +int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv) { u32 i, j, k, crc, keylen; @@ -217,7 +217,7 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, } /* encrypts in-place. */ -int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, +int wep_encrypt(struct wlandevice *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv) { u32 i, j, k, crc, keylen; diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 56bffd93c982..96aa21188669 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -96,16 +96,16 @@ struct s3inforec { u16 len; u16 type; union { - hfa384x_compident_t version; - hfa384x_caplevel_t compat; + struct hfa384x_compident version; + struct hfa384x_caplevel compat; u16 buildseq; - hfa384x_compident_t platform; + struct hfa384x_compident platform; } info; }; struct pda { u8 buf[HFA384x_PDA_LEN_MAX]; - hfa384x_pdrec_t *rec[HFA384x_PDA_RECS_MAX]; + struct hfa384x_pdrec *rec[HFA384x_PDA_RECS_MAX]; unsigned int nrec; }; @@ -152,22 +152,22 @@ static struct imgchunk fchunk[CHUNKS_MAX]; /* PDA, built from [card|newfile]+[addfile1+addfile2...] */ static struct pda pda; -static hfa384x_compident_t nicid; -static hfa384x_caplevel_t rfid; -static hfa384x_caplevel_t macid; -static hfa384x_caplevel_t priid; +static struct hfa384x_compident nicid; +static struct hfa384x_caplevel rfid; +static struct hfa384x_caplevel macid; +static struct hfa384x_caplevel priid; /*================================================================*/ /* Local Function Declarations */ static int prism2_fwapply(const struct ihex_binrec *rfptr, -wlandevice_t *wlandev); +struct wlandevice *wlandev); static int read_fwfile(const struct ihex_binrec *rfptr); static int mkimage(struct imgchunk *clist, unsigned int *ccnt); -static int read_cardpda(struct pda *pda, wlandevice_t *wlandev); +static int read_cardpda(struct pda *pda, struct wlandevice *wlandev); static int mkpdrlist(struct pda *pda); @@ -177,7 +177,7 @@ static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks, struct s3crcrec *s3crc, unsigned int ns3crc); -static int writeimage(wlandevice_t *wlandev, struct imgchunk *fchunk, +static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk, unsigned int nfchunks); static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks); @@ -201,7 +201,7 @@ static int validate_identity(void); * 0 - success * ~0 - failure ----------------------------------------------------------------*/ -static int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) +static int prism2_fwtry(struct usb_device *udev, struct wlandevice *wlandev) { const struct firmware *fw_entry = NULL; @@ -239,11 +239,11 @@ static int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) * ~0 - failure ----------------------------------------------------------------*/ static int prism2_fwapply(const struct ihex_binrec *rfptr, - wlandevice_t *wlandev) + struct wlandevice *wlandev) { signed int result = 0; struct p80211msg_dot11req_mibget getmsg; - p80211itemd_t *item; + struct p80211itemd *item; u32 *data; /* Initialize the data structures */ @@ -266,7 +266,7 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, /* clear the pda and add an initial END record */ memset(&pda, 0, sizeof(pda)); - pda.rec[0] = (hfa384x_pdrec_t *) pda.buf; + pda.rec[0] = (struct hfa384x_pdrec *)pda.buf; pda.rec[0]->len = cpu_to_le16(2); /* len in words */ pda.rec[0]->code = cpu_to_le16(HFA384x_PDR_END_OF_PDA); pda.nrec = 1; @@ -293,11 +293,11 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, getmsg.resultcode.did = DIDmsg_dot11req_mibget_resultcode; getmsg.resultcode.status = P80211ENUM_msgitem_status_no_value; - item = (p80211itemd_t *) getmsg.mibattribute.data; + item = (struct p80211itemd *)getmsg.mibattribute.data; item->did = DIDmib_p2_p2NIC_p2PRISupRange; item->status = P80211ENUM_msgitem_status_no_value; - data = (u32 *) item->data; + data = (u32 *)item->data; /* DIDmsg_dot11req_mibget */ prism2mgmt_mibset_mibget(wlandev, &getmsg); @@ -592,14 +592,14 @@ static int mkimage(struct imgchunk *clist, unsigned int *ccnt) ----------------------------------------------------------------*/ static int mkpdrlist(struct pda *pda) { - u16 *pda16 = (u16 *) pda->buf; + u16 *pda16 = (u16 *)pda->buf; int curroff; /* in 'words' */ pda->nrec = 0; curroff = 0; while (curroff < (HFA384x_PDA_LEN_MAX / 2 - 1) && le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) { - pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]); + pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&(pda16[curroff]); if (le16_to_cpu(pda->rec[pda->nrec]->code) == HFA384x_PDR_NICID) { @@ -638,7 +638,7 @@ static int mkpdrlist(struct pda *pda) curroff, pda->nrec); return 1; } - pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]); + pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&(pda16[curroff]); (pda->nrec)++; return 0; } @@ -766,7 +766,7 @@ static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, * 0 - success * ~0 - failure (probably an errno) ----------------------------------------------------------------*/ -static int read_cardpda(struct pda *pda, wlandevice_t *wlandev) +static int read_cardpda(struct pda *pda, struct wlandevice *wlandev) { int result = 0; struct p80211msg_p2req_readpda *msg; @@ -879,8 +879,8 @@ static int read_fwfile(const struct ihex_binrec *record) addr = be32_to_cpu(record->addr); /* Point into data for different word lengths */ - ptr32 = (u32 *) record->data; - ptr16 = (u16 *) record->data; + ptr32 = (u32 *)record->data; + ptr16 = (u16 *)record->data; /* parse what was an S3 srec and put it in the right array */ switch (addr) { @@ -954,7 +954,7 @@ static int read_fwfile(const struct ihex_binrec *record) default: /* Data record */ s3data[ns3data].addr = addr; s3data[ns3data].len = len; - s3data[ns3data].data = (uint8_t *) record->data; + s3data[ns3data].data = (uint8_t *)record->data; ns3data++; if (ns3data == S3DATA_MAX) { pr_err("S3 datarec limit reached - aborting\n"); @@ -982,7 +982,7 @@ static int read_fwfile(const struct ihex_binrec *record) * 0 success * ~0 failure ----------------------------------------------------------------*/ -static int writeimage(wlandevice_t *wlandev, struct imgchunk *fchunk, +static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk, unsigned int nfchunks) { int result = 0; diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index d8ed9a05789c..170de1c9eac4 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -113,16 +113,16 @@ * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_dot11req_scan *msg = msgp; u16 roamingmode, word; int i, timeout; int istmpenable = 0; - hfa384x_HostScanRequest_data_t scanreq; + struct hfa384x_HostScanRequest_data scanreq; /* gatekeeper check */ if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, @@ -292,7 +292,7 @@ int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) result = hfa384x_drvr_setconfig(hw, HFA384x_RID_HOSTSCAN, &scanreq, - sizeof(hfa384x_HostScanRequest_data_t)); + sizeof(struct hfa384x_HostScanRequest_data)); if (result) { netdev_err(wlandev->netdev, "setconfig(SCANREQUEST) failed. result=%d\n", @@ -366,12 +366,12 @@ exit: * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp) { int result = 0; struct p80211msg_dot11req_scan_results *req; - hfa384x_t *hw = wlandev->priv; - hfa384x_HScanResultSub_t *item = NULL; + struct hfa384x *hw = wlandev->priv; + struct hfa384x_HScanResultSub *item = NULL; int count; @@ -525,15 +525,15 @@ exit: * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_dot11req_start *msg = msgp; - p80211pstrd_t *pstr; + struct p80211pstrd *pstr; u8 bytebuf[80]; - struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf; + struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf; u16 word; wlandev->macmode = WLAN_MACMODE_NONE; @@ -558,7 +558,7 @@ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) /*** STATION ***/ /* Set the REQUIRED config items */ /* SSID */ - pstr = (p80211pstrd_t *) &(msg->ssid.data); + pstr = (struct p80211pstrd *)&(msg->ssid.data); prism2mgmt_pstr2bytestr(p2bytestr, pstr); result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, bytebuf, HFA384x_RID_CNFOWNSSID_LEN); @@ -685,9 +685,7 @@ failed: msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; done: - result = 0; - - return result; + return 0; } /*---------------------------------------------------------------- @@ -708,9 +706,9 @@ done: * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_readpda *msg = msgp; int result; @@ -774,9 +772,9 @@ int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_ramdl_state *msg = msgp; if (wlandev->msdstate != WLAN_MSD_FWLOAD) { @@ -829,9 +827,9 @@ int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_ramdl_write *msg = msgp; u32 addr; u32 len; @@ -890,10 +888,10 @@ int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_flashdl_state *msg = msgp; if (wlandev->msdstate != WLAN_MSD_FWLOAD) { @@ -961,9 +959,9 @@ int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_flashdl_write *msg = msgp; u32 addr; u32 len; @@ -1021,16 +1019,16 @@ int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int result = 0; u16 reg; u16 port_type; struct p80211msg_lnxreq_autojoin *msg = msgp; - p80211pstrd_t *pstr; + struct p80211pstrd *pstr; u8 bytebuf[256]; - struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf; + struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf; wlandev->macmode = WLAN_MACMODE_NONE; @@ -1054,7 +1052,7 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) /* Set the ssid */ memset(bytebuf, 0, 256); - pstr = (p80211pstrd_t *) &(msg->ssid.data); + pstr = (struct p80211pstrd *)&(msg->ssid.data); prism2mgmt_pstr2bytestr(p2bytestr, pstr); result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, bytebuf, @@ -1092,12 +1090,12 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp) { int result = 0; struct p80211msg_lnxreq_wlansniff *msg = msgp; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u16 word; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index e6472034da33..cc1ac7a60dfe 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -63,43 +63,44 @@ extern int prism2_reset_holdtime; extern int prism2_reset_settletime; -u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate); +u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate); -void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status); -void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status); -void prism2sta_ev_alloc(wlandevice_t *wlandev); +void prism2sta_ev_info(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf); +void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status); +void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status); +void prism2sta_ev_alloc(struct wlandevice *wlandev); -int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_start(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_start(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp); /*--------------------------------------------------------------- * conversion functions going between wlan message data types and * Prism2 data types ---------------------------------------------------------------*/ /* byte area conversion functions*/ -void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len); +void prism2mgmt_bytearea2pstr(u8 *bytearea, struct p80211pstrd *pstr, int len); /* byte string conversion functions*/ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, - p80211pstrd_t *pstr); + struct p80211pstrd *pstr); void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, - p80211pstrd_t *pstr); + struct p80211pstrd *pstr); /* functions to convert Group Addresses */ -void prism2mgmt_get_grpaddr(u32 did, p80211pstrd_t *pstr, hfa384x_t *priv); +void prism2mgmt_get_grpaddr(u32 did, struct p80211pstrd *pstr, + struct hfa384x *priv); int prism2mgmt_set_grpaddr(u32 did, - u8 *prism2buf, p80211pstrd_t *pstr, - hfa384x_t *priv); + u8 *prism2buf, struct p80211pstrd *pstr, + struct hfa384x *priv); int prism2mgmt_get_grpaddr_index(u32 did); void prism2sta_processing_defer(struct work_struct *data); @@ -108,8 +109,8 @@ void prism2sta_commsqual_defer(struct work_struct *data); void prism2sta_commsqual_timer(unsigned long data); /* Interface callback functions, passing data back up to the cfg80211 layer */ -void prism2_connect_result(wlandevice_t *wlandev, u8 failed); -void prism2_disconnected(wlandevice_t *wlandev); -void prism2_roamed(wlandevice_t *wlandev); +void prism2_connect_result(struct wlandevice *wlandev, u8 failed); +void prism2_disconnected(struct wlandevice *wlandev); +void prism2_roamed(struct wlandevice *wlandev); #endif diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index fe914b1f904b..63ab6bc88654 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -87,80 +87,80 @@ struct mibrec { u16 parm3; int (*func)(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); }; static int prism2mib_bytearea2pstr(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_uint32(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_flag(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_wepdefaultkey(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_privacyinvoked(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_excludeunencrypted(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_priv(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static struct mibrec mibtab[] = { /* dot11smt MIB's */ - {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1), F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, prism2mib_wepdefaultkey}, - {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(2), F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, prism2mib_wepdefaultkey}, - {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(3), F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, prism2mib_wepdefaultkey}, - {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(4), F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, prism2mib_wepdefaultkey}, @@ -237,36 +237,36 @@ static struct mibrec mibtab[] = { {0, 0, 0, 0, 0, NULL} }; -/*---------------------------------------------------------------- -* prism2mgmt_mibset_mibget -* -* Set the value of a mib item. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -* interrupt -----------------------------------------------------------------*/ +/* + * prism2mgmt_mibset_mibget + * + * Set the value of a mib item. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + * interrupt + */ -int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int result, isget; struct mibrec *mib; u16 which; struct p80211msg_dot11req_mibset *msg = msgp; - p80211itemd_t *mibitem; + struct p80211itemd *mibitem; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; msg->resultcode.data = P80211ENUM_resultcode_success; @@ -284,7 +284,7 @@ int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp) ** MIB table. */ - mibitem = (p80211itemd_t *) msg->mibattribute.data; + mibitem = (struct p80211itemd *)msg->mibattribute.data; for (mib = mibtab; mib->did != 0; mib++) if (mib->did == mibitem->did && (mib->flag & which)) @@ -346,40 +346,40 @@ done: return 0; } -/*---------------------------------------------------------------- -* prism2mib_bytearea2pstr -* -* Get/set pstr data to/from a byte area. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Number of bytes of RID data. -* 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. -* -----------------------------------------------------------------*/ +/* + * prism2mib_bytearea2pstr + * + * Get/set pstr data to/from a byte area. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Number of bytes of RID data. + * 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_bytearea2pstr(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { int result; - p80211pstrd_t *pstr = data; + struct p80211pstrd *pstr = data; u8 bytebuf[MIB_TMP_MAXLEN]; if (isget) { @@ -396,41 +396,41 @@ static int prism2mib_bytearea2pstr(struct mibrec *mib, return result; } -/*---------------------------------------------------------------- -* prism2mib_uint32 -* -* Get/set uint32 data. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Not used. -* 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. -* -----------------------------------------------------------------*/ +/* + * prism2mib_uint32 + * + * Get/set uint32 data. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Not used. + * 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_uint32(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { int result; u32 *uint32 = data; u8 bytebuf[MIB_TMP_MAXLEN]; - u16 *wordbuf = (u16 *) bytebuf; + u16 *wordbuf = (u16 *)bytebuf; if (isget) { result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); @@ -443,41 +443,41 @@ static int prism2mib_uint32(struct mibrec *mib, return result; } -/*---------------------------------------------------------------- -* prism2mib_flag -* -* Get/set a flag. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Bit to get/set. -* 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. -* -----------------------------------------------------------------*/ +/* + * prism2mib_flag + * + * Get/set a flag. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Bit to get/set. + * 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_flag(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { int result; u32 *uint32 = data; u8 bytebuf[MIB_TMP_MAXLEN]; - u16 *wordbuf = (u16 *) bytebuf; + u16 *wordbuf = (u16 *)bytebuf; u32 flags; result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); @@ -500,40 +500,40 @@ static int prism2mib_flag(struct mibrec *mib, return result; } -/*---------------------------------------------------------------- -* prism2mib_wepdefaultkey -* -* Get/set WEP default keys. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Number of bytes of RID data. -* 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. -* -----------------------------------------------------------------*/ +/* + * prism2mib_wepdefaultkey + * + * Get/set WEP default keys. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Number of bytes of RID data. + * 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_wepdefaultkey(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { int result; - p80211pstrd_t *pstr = data; + struct p80211pstrd *pstr = data; u8 bytebuf[MIB_TMP_MAXLEN]; u16 len; @@ -550,35 +550,35 @@ static int prism2mib_wepdefaultkey(struct mibrec *mib, return result; } -/*---------------------------------------------------------------- -* prism2mib_privacyinvoked -* -* Get/set the dot11PrivacyInvoked value. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Bit value for PrivacyInvoked 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. -* -----------------------------------------------------------------*/ +/* + * prism2mib_privacyinvoked + * + * Get/set the dot11PrivacyInvoked value. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Bit value for PrivacyInvoked 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_privacyinvoked(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -592,35 +592,35 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, return prism2mib_flag(mib, isget, wlandev, hw, msg, data); } -/*---------------------------------------------------------------- -* 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. -* -----------------------------------------------------------------*/ +/* + * 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, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -628,35 +628,35 @@ static int prism2mib_excludeunencrypted(struct mibrec *mib, return prism2mib_flag(mib, isget, wlandev, hw, msg, data); } -/*---------------------------------------------------------------- -* prism2mib_fragmentationthreshold -* -* Get/set the fragmentation threshold. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Not used. -* 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. -* -----------------------------------------------------------------*/ +/* + * prism2mib_fragmentationthreshold + * + * Get/set the fragmentation threshold. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Not used. + * 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_fragmentationthreshold(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -674,47 +674,47 @@ static int prism2mib_fragmentationthreshold(struct mibrec *mib, return prism2mib_uint32(mib, isget, wlandev, hw, msg, data); } -/*---------------------------------------------------------------- -* prism2mib_priv -* -* Get/set values in the "priv" data structure. -* -* MIB record parameters: -* parm1 Not used. -* parm2 Not used. -* 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. -* -----------------------------------------------------------------*/ +/* + * prism2mib_priv + * + * Get/set values in the "priv" data structure. + * + * MIB record parameters: + * parm1 Not used. + * parm2 Not used. + * 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_priv(struct mibrec *mib, int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, + struct wlandevice *wlandev, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { - p80211pstrd_t *pstr = data; + struct p80211pstrd *pstr = data; switch (mib->did) { case DIDmib_lnx_lnxConfigTable_lnxRSNAIE:{ - hfa384x_WPAData_t wpa; + struct hfa384x_WPAData wpa; if (isget) { hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFWPADATA, - (u8 *) &wpa, + (u8 *)&wpa, sizeof(wpa)); pstr->len = le16_to_cpu(wpa.datalen); memcpy(pstr->data, wpa.data, pstr->len); @@ -724,7 +724,7 @@ static int prism2mib_priv(struct mibrec *mib, hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFWPADATA, - (u8 *) &wpa, + (u8 *)&wpa, sizeof(wpa)); } break; @@ -736,67 +736,67 @@ static int prism2mib_priv(struct mibrec *mib, return 0; } -/*---------------------------------------------------------------- -* prism2mgmt_pstr2bytestr -* -* Convert the pstr data in the WLAN message structure into an hfa384x -* byte string format. -* -* Arguments: -* bytestr hfa384x byte string data type -* pstr wlan message data -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ +/* + * prism2mgmt_pstr2bytestr + * + * Convert the pstr data in the WLAN message structure into an hfa384x + * byte string format. + * + * Arguments: + * bytestr hfa384x byte string data type + * pstr wlan message data + * + * Returns: + * Nothing + * + */ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, - p80211pstrd_t *pstr) + struct p80211pstrd *pstr) { - bytestr->len = cpu_to_le16((u16) (pstr->len)); + bytestr->len = cpu_to_le16((u16)(pstr->len)); memcpy(bytestr->data, pstr->data, pstr->len); } -/*---------------------------------------------------------------- -* prism2mgmt_bytestr2pstr -* -* Convert the data in an hfa384x byte string format into a -* pstr in the WLAN message. -* -* Arguments: -* bytestr hfa384x byte string data type -* msg wlan message -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ +/* + * prism2mgmt_bytestr2pstr + * + * Convert the data in an hfa384x byte string format into a + * pstr in the WLAN message. + * + * Arguments: + * bytestr hfa384x byte string data type + * msg wlan message + * + * Returns: + * Nothing + * + */ void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, - p80211pstrd_t *pstr) + struct p80211pstrd *pstr) { - pstr->len = (u8) (le16_to_cpu((u16) (bytestr->len))); + pstr->len = (u8)(le16_to_cpu((u16)(bytestr->len))); memcpy(pstr->data, bytestr->data, pstr->len); } -/*---------------------------------------------------------------- -* prism2mgmt_bytearea2pstr -* -* Convert the data in an hfa384x byte area format into a pstr -* in the WLAN message. -* -* Arguments: -* bytearea hfa384x byte area data type -* msg wlan message -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ +/* + * prism2mgmt_bytearea2pstr + * + * Convert the data in an hfa384x byte area format into a pstr + * in the WLAN message. + * + * Arguments: + * bytearea hfa384x byte area data type + * msg wlan message + * + * Returns: + * Nothing + * + */ -void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len) +void prism2mgmt_bytearea2pstr(u8 *bytearea, struct p80211pstrd *pstr, int len) { - pstr->len = (u8) len; + pstr->len = (u8)len; memcpy(pstr->data, bytearea, len); } diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 64f90722b01b..e1b4a94292ff 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -81,7 +81,7 @@ #include "prism2mgmt.h" static char *dev_info = "prism2_usb"; -static wlandevice_t *create_wlan(void); +static struct wlandevice *create_wlan(void); int prism2_reset_holdtime = 30; /* Reset hold time in ms */ int prism2_reset_settletime = 100; /* Reset settle time in ms */ @@ -98,37 +98,38 @@ MODULE_PARM_DESC(prism2_reset_settletime, "reset settle time in ms"); MODULE_LICENSE("Dual MPL/GPL"); -static int prism2sta_open(wlandevice_t *wlandev); -static int prism2sta_close(wlandevice_t *wlandev); -static void prism2sta_reset(wlandevice_t *wlandev); -static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, +static int prism2sta_open(struct wlandevice *wlandev); +static int prism2sta_close(struct wlandevice *wlandev); +static void prism2sta_reset(struct wlandevice *wlandev); +static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep); -static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg); -static int prism2sta_getcardinfo(wlandevice_t *wlandev); -static int prism2sta_globalsetup(wlandevice_t *wlandev); -static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev); +static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *msg); +static int prism2sta_getcardinfo(struct wlandevice *wlandev); +static int prism2sta_globalsetup(struct wlandevice *wlandev); +static int prism2sta_setmulticast(struct wlandevice *wlandev, + struct net_device *dev); -static void prism2sta_inf_handover(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_tallies(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_scanresults(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_authreq(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); -static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf); +static void prism2sta_inf_handover(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_tallies(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_scanresults(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_authreq(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); +static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf); /* * prism2sta_open @@ -151,7 +152,7 @@ static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, * Call context: * process thread */ -static int prism2sta_open(wlandevice_t *wlandev) +static int prism2sta_open(struct wlandevice *wlandev) { /* We don't currently have to do anything else. * The setup of the MAC should be subsequently completed via @@ -185,7 +186,7 @@ static int prism2sta_open(wlandevice_t *wlandev) * Call context: * process thread */ -static int prism2sta_close(wlandevice_t *wlandev) +static int prism2sta_close(struct wlandevice *wlandev) { /* We don't currently have to do anything else. * Higher layers know we're not ready from dev->start==0 and @@ -213,7 +214,7 @@ static int prism2sta_close(wlandevice_t *wlandev) * Call context: * process thread */ -static void prism2sta_reset(wlandevice_t *wlandev) +static void prism2sta_reset(struct wlandevice *wlandev) { } @@ -238,11 +239,11 @@ static void prism2sta_reset(wlandevice_t *wlandev) * Call context: * process thread */ -static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, +static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; /* If necessary, set the 802.11 WEP bit */ if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) == @@ -277,9 +278,9 @@ static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, * Call context: * process thread */ -static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg) +static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *msg) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int result = 0; @@ -337,7 +338,7 @@ static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg) struct p80211msg_lnxreq_ifstate *ifstatemsg; pr_debug("Received mlme ifstate request\n"); - ifstatemsg = (struct p80211msg_lnxreq_ifstate *) msg; + ifstatemsg = (struct p80211msg_lnxreq_ifstate *)msg; result = prism2sta_ifstate(wlandev, ifstatemsg->ifstate.data); @@ -360,7 +361,7 @@ static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg) pr_debug("Received commsquality request\n"); - qualmsg = (struct p80211msg_lnxreq_commsquality *) msg; + qualmsg = (struct p80211msg_lnxreq_commsquality *)msg; qualmsg->link.status = P80211ENUM_msgitem_status_data_ok; @@ -407,9 +408,9 @@ static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg) * process thread (usually) * interrupt */ -u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) +u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u32 result; result = P80211ENUM_resultcode_implementation_failure; @@ -580,10 +581,10 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) * Call context: * Either. */ -static int prism2sta_getcardinfo(wlandevice_t *wlandev) +static int prism2sta_getcardinfo(struct wlandevice *wlandev) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u16 temp; u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN]; @@ -592,7 +593,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* NIC identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY, &hw->ident_nic, - sizeof(hfa384x_compident_t)); + sizeof(struct hfa384x_compident)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve NICIDENTITY\n"); goto failed; @@ -611,7 +612,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Primary f/w identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY, &hw->ident_pri_fw, - sizeof(hfa384x_compident_t)); + sizeof(struct hfa384x_compident)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve PRIIDENTITY\n"); goto failed; @@ -630,7 +631,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Station (Secondary?) f/w identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY, &hw->ident_sta_fw, - sizeof(hfa384x_compident_t)); + sizeof(struct hfa384x_compident)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve STAIDENTITY\n"); goto failed; @@ -651,7 +652,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* strip out the 'special' variant bits */ hw->mm_mods = hw->ident_sta_fw.variant & (BIT(14) | BIT(15)); - hw->ident_sta_fw.variant &= ~((u16) (BIT(14) | BIT(15))); + hw->ident_sta_fw.variant &= ~((u16)(BIT(14) | BIT(15))); if (hw->ident_sta_fw.id == 0x1f) { netdev_info(wlandev->netdev, @@ -670,7 +671,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Compatibility range, Modem supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE, &hw->cap_sup_mfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve MFISUPRANGE\n"); goto failed; @@ -694,7 +695,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Compatibility range, Controller supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE, &hw->cap_sup_cfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve CFISUPRANGE\n"); goto failed; @@ -718,7 +719,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Compatibility range, Primary f/w supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE, &hw->cap_sup_pri, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve PRISUPRANGE\n"); goto failed; @@ -742,7 +743,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Compatibility range, Station f/w supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE, &hw->cap_sup_sta, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve STASUPRANGE\n"); goto failed; @@ -774,7 +775,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Compatibility range, primary f/w actor, CFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES, &hw->cap_act_pri_cfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve PRI_CFIACTRANGES\n"); goto failed; @@ -798,7 +799,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Compatibility range, sta f/w actor, CFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES, &hw->cap_act_sta_cfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve STA_CFIACTRANGES\n"); goto failed; @@ -822,7 +823,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) /* Compatibility range, sta f/w actor, MFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES, &hw->cap_act_sta_mfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve STA_MFIACTRANGES\n"); goto failed; @@ -909,19 +910,20 @@ done: * Call context: * process thread */ -static int prism2sta_globalsetup(wlandevice_t *wlandev) +static int prism2sta_globalsetup(struct wlandevice *wlandev) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; /* Set the maximum frame size */ return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, WLAN_DATA_MAXLEN); } -static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev) +static int prism2sta_setmulticast(struct wlandevice *wlandev, + struct net_device *dev) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u16 promisc; @@ -959,8 +961,8 @@ exit: * Call context: * interrupt */ -static void prism2sta_inf_handover(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_handover(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { pr_debug("received infoframe:HANDOVER (unhandled)\n"); } @@ -982,10 +984,10 @@ static void prism2sta_inf_handover(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_tallies(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_tallies(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u16 *src16; u32 *dst; u32 *src32; @@ -997,15 +999,15 @@ static void prism2sta_inf_tallies(wlandevice_t *wlandev, * record length of the info record. */ - cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(u32); + cnt = sizeof(struct hfa384x_CommTallies32) / sizeof(u32); if (inf->framelen > 22) { - dst = (u32 *) &hw->tallies; - src32 = (u32 *) &inf->info.commtallies32; + dst = (u32 *)&hw->tallies; + src32 = (u32 *)&inf->info.commtallies32; for (i = 0; i < cnt; i++, dst++, src32++) *dst += le32_to_cpu(*src32); } else { - dst = (u32 *) &hw->tallies; - src16 = (u16 *) &inf->info.commtallies16; + dst = (u32 *)&hw->tallies; + src16 = (u16 *)&inf->info.commtallies16; for (i = 0; i < cnt; i++, dst++, src16++) *dst += le16_to_cpu(*src16); } @@ -1028,21 +1030,20 @@ static void prism2sta_inf_tallies(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_scanresults(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_scanresults(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int nbss; - hfa384x_ScanResult_t *sr = &(inf->info.scanresult); + struct hfa384x_ScanResult *sr = &(inf->info.scanresult); int i; - hfa384x_JoinRequest_data_t joinreq; + struct hfa384x_JoinRequest_data joinreq; int result; /* Get the number of results, first in bytes, then in results */ nbss = (inf->framelen * sizeof(u16)) - sizeof(inf->infotype) - sizeof(inf->info.scanresult.scanreason); - nbss /= sizeof(hfa384x_ScanResultSub_t); + nbss /= sizeof(struct hfa384x_ScanResultSub); /* Print em */ pr_debug("rx scanresults, reason=%d, nbss=%d:\n", @@ -1084,10 +1085,10 @@ static void prism2sta_inf_scanresults(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int nbss; nbss = (inf->framelen - 3) / 32; @@ -1098,7 +1099,7 @@ static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, kfree(hw->scanresults); - hw->scanresults = kmemdup(inf, sizeof(hfa384x_InfFrame_t), GFP_ATOMIC); + hw->scanresults = kmemdup(inf, sizeof(struct hfa384x_InfFrame), GFP_ATOMIC); if (nbss == 0) nbss = -1; @@ -1125,18 +1126,18 @@ static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; unsigned int i, n; hw->channel_info.results.scanchannels = le16_to_cpu(inf->info.chinforesult.scanchannels); for (i = 0, n = 0; i < HFA384x_CHINFORESULT_MAX; i++) { - hfa384x_ChInfoResultSub_t *result; - hfa384x_ChInfoResultSub_t *chinforesult; + struct hfa384x_ChInfoResultSub *result; + struct hfa384x_ChInfoResultSub *chinforesult; int chan; if (!(hw->channel_info.results.scanchannels & (1 << i))) @@ -1170,18 +1171,18 @@ static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, void prism2sta_processing_defer(struct work_struct *data) { - hfa384x_t *hw = container_of(data, struct hfa384x, link_bh); - wlandevice_t *wlandev = hw->wlandev; - hfa384x_bytestr32_t ssid; + struct hfa384x *hw = container_of(data, struct hfa384x, link_bh); + struct wlandevice *wlandev = hw->wlandev; + struct hfa384x_bytestr32 ssid; int result; /* First let's process the auth frames */ { struct sk_buff *skb; - hfa384x_InfFrame_t *inf; + struct hfa384x_InfFrame *inf; while ((skb = skb_dequeue(&hw->authq))) { - inf = (hfa384x_InfFrame_t *) skb->data; + inf = (struct hfa384x_InfFrame *)skb->data; prism2sta_inf_authreq_defer(wlandev, inf); } @@ -1256,8 +1257,8 @@ void prism2sta_processing_defer(struct work_struct *data) return; } prism2mgmt_bytestr2pstr( - (struct hfa384x_bytestr *) &ssid, - (p80211pstrd_t *) &wlandev->ssid); + (struct hfa384x_bytestr *)&ssid, + (struct p80211pstrd *)&wlandev->ssid); /* Collect the port status */ result = hfa384x_drvr_getconfig16(hw, @@ -1337,8 +1338,8 @@ void prism2sta_processing_defer(struct work_struct *data) HFA384x_RID_CURRENTSSID, result); return; } - prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *) &ssid, - (p80211pstrd_t *) &wlandev->ssid); + prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, + (struct p80211pstrd *)&wlandev->ssid); hw->link_status = HFA384x_LINK_CONNECTED; netif_carrier_on(wlandev->netdev); @@ -1390,7 +1391,7 @@ void prism2sta_processing_defer(struct work_struct *data) * Disable Transmits, Ignore receives of data frames */ if (hw->join_ap && --hw->join_retries > 0) { - hfa384x_JoinRequest_data_t joinreq; + struct hfa384x_JoinRequest_data joinreq; joinreq = hw->joinreq; /* Send the join request */ @@ -1438,10 +1439,10 @@ void prism2sta_processing_defer(struct work_struct *data) * Call context: * interrupt */ -static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; hw->link_status_new = le16_to_cpu(inf->info.linkstatus.linkstatus); @@ -1466,11 +1467,11 @@ static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; - hfa384x_AssocStatus_t rec; + struct hfa384x *hw = wlandev->priv; + struct hfa384x_AssocStatus rec; int i; memcpy(&rec, &inf->info.assocstatus, sizeof(rec)); @@ -1527,10 +1528,10 @@ static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, * interrupt * */ -static void prism2sta_inf_authreq(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_authreq(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct sk_buff *skb; skb = dev_alloc_skb(sizeof(*inf)); @@ -1542,11 +1543,11 @@ static void prism2sta_inf_authreq(wlandevice_t *wlandev, } } -static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; - hfa384x_authenticateStation_data_t rec; + struct hfa384x *hw = wlandev->priv; + struct hfa384x_authenticateStation_data rec; int i, added, result, cnt; u8 *addr; @@ -1716,10 +1717,10 @@ static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, - hfa384x_InfFrame_t *inf) +static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, + struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; hw->psusercount = le16_to_cpu(inf->info.psusercnt.usercnt); } @@ -1741,7 +1742,7 @@ static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, * Call context: * interrupt */ -void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +void prism2sta_ev_info(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { inf->infotype = le16_to_cpu(inf->infotype); /* Dispatch */ @@ -1808,7 +1809,7 @@ void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) * Call context: * interrupt */ -void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status) +void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status) { pr_debug("TxExc status=0x%x.\n", status); } @@ -1829,7 +1830,7 @@ void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status) * Call context: * interrupt */ -void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status) +void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status) { pr_debug("Tx Complete, status=0x%04x\n", status); /* update linux network stats */ @@ -1852,7 +1853,7 @@ void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status) * Call context: * interrupt */ -void prism2sta_ev_alloc(wlandevice_t *wlandev) +void prism2sta_ev_alloc(struct wlandevice *wlandev) { netif_wake_queue(wlandev->netdev); } @@ -1860,14 +1861,14 @@ void prism2sta_ev_alloc(wlandevice_t *wlandev) /* * create_wlan * -* Called at module init time. This creates the wlandevice_t structure +* Called at module init time. This creates the struct wlandevice structure * and initializes it with relevant bits. * * Arguments: * none * * Returns: -* the created wlandevice_t structure. +* the created struct wlandevice structure. * * Side effects: * also allocates the priv/hw structures. @@ -1876,14 +1877,14 @@ void prism2sta_ev_alloc(wlandevice_t *wlandev) * process thread * */ -static wlandevice_t *create_wlan(void) +static struct wlandevice *create_wlan(void) { - wlandevice_t *wlandev = NULL; - hfa384x_t *hw = NULL; + struct wlandevice *wlandev = NULL; + struct hfa384x *hw = NULL; /* Alloc our structures */ - wlandev = kzalloc(sizeof(wlandevice_t), GFP_KERNEL); - hw = kzalloc(sizeof(hfa384x_t), GFP_KERNEL); + wlandev = kzalloc(sizeof(struct wlandevice), GFP_KERNEL); + hw = kzalloc(sizeof(struct hfa384x), GFP_KERNEL); if (!wlandev || !hw) { kfree(wlandev); @@ -1913,11 +1914,11 @@ static wlandevice_t *create_wlan(void) void prism2sta_commsqual_defer(struct work_struct *data) { - hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); - wlandevice_t *wlandev = hw->wlandev; - hfa384x_bytestr32_t ssid; + struct hfa384x *hw = container_of(data, struct hfa384x, commsqual_bh); + struct wlandevice *wlandev = hw->wlandev; + struct hfa384x_bytestr32 ssid; struct p80211msg_dot11req_mibget msg; - p80211item_uint32_t *mibitem = (p80211item_uint32_t *) + struct p80211item_uint32 *mibitem = (struct p80211item_uint32 *) &msg.mibattribute.data; int result = 0; @@ -1950,7 +1951,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) /* Get the signal rate */ msg.msgcode = DIDmsg_dot11req_mibget; mibitem->did = DIDmib_p2_p2MAC_p2CurrentTxRate; - result = p80211req_dorequest(wlandev, (u8 *) &msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { pr_debug("get signal rate failed, result = %d\n", @@ -1993,8 +1994,8 @@ void prism2sta_commsqual_defer(struct work_struct *data) HFA384x_RID_CURRENTSSID, result); return; } - prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *) &ssid, - (p80211pstrd_t *) &wlandev->ssid); + prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, + (struct p80211pstrd *)&wlandev->ssid); /* Reschedule timer */ mod_timer(&hw->commsqual_timer, jiffies + HZ); @@ -2002,7 +2003,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) void prism2sta_commsqual_timer(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *) data; + struct hfa384x *hw = (struct hfa384x *)data; schedule_work(&hw->commsqual_bh); } diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index b26d09ff840c..bfb6b0a6528d 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -47,11 +47,11 @@ static const struct usb_device_id usb_prism_tbl[] = { PRISM_DEV(0x0bb2, 0x0302, "Ambit Microsystems Corp."), PRISM_DEV(0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter"), PRISM_DEV(0x0543, 0x0f01, - "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)"), + "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)"), PRISM_DEV(0x067c, 0x1022, - "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter"), + "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter"), PRISM_DEV(0x049f, 0x0033, - "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter"), + "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter"), { } /* terminator */ }; MODULE_DEVICE_TABLE(usb, usb_prism_tbl); @@ -61,8 +61,8 @@ static int prism2sta_probe_usb(struct usb_interface *interface, { struct usb_device *dev; - wlandevice_t *wlandev = NULL; - hfa384x_t *hw = NULL; + struct wlandevice *wlandev = NULL; + struct hfa384x *hw = NULL; int result = 0; dev = interface_to_usbdev(interface); @@ -74,7 +74,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface, } hw = wlandev->priv; - if (wlan_setup(wlandev, &(interface->dev)) != 0) { + if (wlan_setup(wlandev, &interface->dev) != 0) { dev_err(&interface->dev, "wlan_setup() failed.\n"); result = -EIO; goto failed; @@ -87,7 +87,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface, /* Register the wlandev, this gets us a name and registers the * linux netdevice. */ - SET_NETDEV_DEV(wlandev->netdev, &(interface->dev)); + SET_NETDEV_DEV(wlandev->netdev, &interface->dev); /* Do a chip-level reset on the MAC */ if (prism2_doreset) { @@ -134,15 +134,15 @@ done: static void prism2sta_disconnect_usb(struct usb_interface *interface) { - wlandevice_t *wlandev; + struct wlandevice *wlandev; - wlandev = (wlandevice_t *)usb_get_intfdata(interface); - if (wlandev != NULL) { + wlandev = (struct wlandevice *)usb_get_intfdata(interface); + if (wlandev) { LIST_HEAD(cleanlist); - hfa384x_usbctlx_t *ctlx, *temp; + struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; if (!hw) goto exit; @@ -216,12 +216,12 @@ exit: #ifdef CONFIG_PM static int prism2sta_suspend(struct usb_interface *interface, - pm_message_t message) + pm_message_t message) { - hfa384x_t *hw = NULL; - wlandevice_t *wlandev; + struct hfa384x *hw = NULL; + struct wlandevice *wlandev; - wlandev = (wlandevice_t *)usb_get_intfdata(interface); + wlandev = (struct wlandevice *)usb_get_intfdata(interface); if (!wlandev) return -ENODEV; @@ -241,10 +241,10 @@ static int prism2sta_suspend(struct usb_interface *interface, static int prism2sta_resume(struct usb_interface *interface) { int result = 0; - hfa384x_t *hw = NULL; - wlandevice_t *wlandev; + struct hfa384x *hw = NULL; + struct wlandevice *wlandev; - wlandev = (wlandevice_t *)usb_get_intfdata(interface); + wlandev = (struct wlandevice *)usb_get_intfdata(interface); if (!wlandev) return -ENODEV; diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index d56ef1425f6b..0c78491ff5a1 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -62,7 +62,6 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, unsigned short ModeNo = modeno; unsigned short ModeIdIndex = 0, ClockIndex = 0; unsigned short RefreshRateTableIndex = 0; - int Clock; InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr); @@ -73,9 +72,7 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, ClockIndex = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; - Clock = XGI_VCLKData[ClockIndex].CLOCK * 1000; - - return Clock; + return XGI_VCLKData[ClockIndex].CLOCK * 1000; } static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr, @@ -1227,7 +1224,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) unsigned int vtotal = 0; unsigned int drate = 0, hrate = 0; int found_mode = 0; - int refresh_rate, search_idx; + int search_idx; if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { vtotal = var->upper_margin + var->yres + var->lower_margin @@ -1263,10 +1260,6 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) xgifb_info->refresh_rate = 60; } - /* Calculation wrong for 1024x600 - force it to 60Hz */ - if ((var->xres == 1024) && (var->yres == 600)) - refresh_rate = 60; - search_idx = 0; while ((XGIbios_mode[search_idx].mode_no != 0) && (XGIbios_mode[search_idx].xres <= var->xres)) { @@ -2085,7 +2078,7 @@ static int __init xgifb_init(void) { char *option = NULL; - if (forcecrt2type != NULL) + if (forcecrt2type) XGIfb_search_crt2type(forcecrt2type); if (fb_get_options("xgifb", &option)) return -ENODEV; diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 50c8ea4f5ab7..d8010c5c1a70 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -214,7 +214,7 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeIdIndex, if (!(pVBInfo->VBInfo & TVSetPAL) && (modeflag & NoSupportSimuTV) && (pVBInfo->VBInfo & SetInSlaveMode) && - (!(pVBInfo->VBInfo & SetNotSimuMode))) + !(pVBInfo->VBInfo & SetNotSimuMode)) return 0; } @@ -1647,7 +1647,6 @@ static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1, static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { - unsigned short index, modeflag; unsigned char tempal; @@ -1655,7 +1654,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag; if ((pVBInfo->SetFlag & ProgrammingCRT2) && - (!(pVBInfo->LCDInfo & EnableScalingLCD))) { /* {LCDA/LCDB} */ + !(pVBInfo->LCDInfo & EnableScalingLCD)) { /* {LCDA/LCDB} */ index = XGI_GetLCDCapPtr(pVBInfo); tempal = pVBInfo->LCDCapList[index].LCD_VCLK; @@ -1678,7 +1677,6 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, if (!(modeflag & Charx8Dot)) tempal = TVCLKBASE_315 + HiTVTextVCLK; - } return tempal; } @@ -1716,7 +1714,7 @@ static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0, { if (pVBInfo->VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { - if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && + if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && (pVBInfo->SetFlag & ProgrammingCRT2)) { *di_0 = XGI_VBVCLKData[tempal].Part4_A; *di_1 = XGI_VBVCLKData[tempal].Part4_B; @@ -1741,8 +1739,8 @@ static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex, for (i = 0; i < 4; i++) { xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30, (unsigned short) (0x10 * i)); - if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) - && (!(pVBInfo->VBInfo & SetInSlaveMode))) { + if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && + !(pVBInfo->VBInfo & SetInSlaveMode)) { xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0); xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1); } else { @@ -1915,7 +1913,7 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex, } } - if (pVBInfo->VBType & (VB_SIS301LV|VB_SIS302LV|VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { if (temp & SetYPbPr) { /* shampoo add for new scratch */ temp = xgifb_reg_get(pVBInfo->P3d4, 0x35); @@ -1986,7 +1984,7 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex, } if (!(tempbx & DisableCRT2Display)) { - if ((!(tempbx & DriverMode)) || (!(modeflag & CRT2Mode))) { + if (!(tempbx & DriverMode) || !(modeflag & CRT2Mode)) { if (!(tempbx & XGI_SetCRT2ToLCDA)) tempbx |= (SetInSlaveMode | SetSimuScanMode); } @@ -2132,7 +2130,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex, if ((pVBInfo->LCDResInfo == Panel_1400x1050) && (pVBInfo->VBInfo & SetCRT2ToLCD) && (resinfo == 9) && - (!(tempbx & EnableScalingLCD))) + !(tempbx & EnableScalingLCD)) /* * set to center in 1280x1024 LCDB * for Panel_1400x1050 @@ -2245,7 +2243,6 @@ static void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, /* CR B4[1] */ xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp); - } temp = xgifb_reg_get(pVBInfo->P3d4, 0x48); @@ -2274,7 +2271,6 @@ static void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, /* CR B4[1] */ xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp); - } xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0); @@ -2291,7 +2287,6 @@ static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, struct xgi_hw_device_info *pXGIHWDE, struct vb_device_info *pVBInfo) { - xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x00); if (pXGIHWDE->jChipType == XG21) { if (pVBInfo->IF_DEF_LVDS == 1) { @@ -2310,7 +2305,6 @@ static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, /* DVO/DVI signal on */ XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo); } - } if (pXGIHWDE->jChipType == XG27) { @@ -2330,7 +2324,6 @@ static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, /* DVO/DVI signal on */ XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo); } - } } @@ -2338,7 +2331,6 @@ void XGI_DisplayOff(struct xgifb_video_info *xgifb_info, struct xgi_hw_device_info *pXGIHWDE, struct vb_device_info *pVBInfo) { - if (pXGIHWDE->jChipType == XG21) { if (pVBInfo->IF_DEF_LVDS == 1) { /* LVDS backlight off */ @@ -2455,7 +2447,6 @@ exit: static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo) { - if ((pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) && (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */ return 1; @@ -3922,7 +3913,7 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo) xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]); if ((pVBInfo->VBInfo & SetCRT2ToTV) && - (!(pVBInfo->VBInfo & SetCRT2ToHiVision))) { + !(pVBInfo->VBInfo & SetCRT2ToHiVision)) { /* Set Vertical Scaling */ Tap4TimingPtr = XGI_GetTap4Ptr(1, pVBInfo); for (i = 0xC0, j = 0; i < 0xFF; i++, j++) @@ -3932,7 +3923,7 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo) } if ((pVBInfo->VBInfo & SetCRT2ToTV) && - (!(pVBInfo->VBInfo & SetCRT2ToHiVision))) + !(pVBInfo->VBInfo & SetCRT2ToHiVision)) /* Enable V.Scaling */ xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x04); else @@ -4132,7 +4123,6 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex, if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVision)) { if (pVBInfo->VGAHDE > 800) xgifb_reg_or(pVBInfo->Part4Port, 0x1E, 0x08); - } temp = 0x0036; @@ -4141,9 +4131,9 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex, | TVSetYPbPr525p | TVSetYPbPr750p | TVSetHiVision))) { temp |= 0x0001; - if ((pVBInfo->VBInfo & SetInSlaveMode) - && (!(pVBInfo->TVInfo - & TVSimuMode))) + if ((pVBInfo->VBInfo & SetInSlaveMode) && + !(pVBInfo->TVInfo + & TVSimuMode)) temp &= (~0x0001); } } @@ -4389,7 +4379,6 @@ static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info, (value << 2) & 0x7C); for (temp = 0, value = 0; temp < 3; temp++) { - xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value); xgifb_reg_set(pVBInfo->P3c4, 0x2B, xgifb_info->lvds_data.VCLKData1); @@ -4409,7 +4398,6 @@ static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info, inb(pVBInfo->P3da); /* reset 3da */ } - } /* --------------------------------------------------------------------- */ @@ -4476,7 +4464,7 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, if ((pVBInfo->VBInfo & (DisableCRT2Display | SetSimuScanMode)) || - ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && + (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV)))) xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80); @@ -4587,7 +4575,7 @@ static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl, if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { - if ((!(pVBInfo->VBInfo & SetInSlaveMode)) || (pVBInfo->TVInfo + if (!(pVBInfo->VBInfo & SetInSlaveMode) || (pVBInfo->TVInfo & TVSimuMode)) { *tempbx += 8; *tempcl += 1; @@ -4988,8 +4976,8 @@ reg_and_or: if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { tempah &= (~0x08); - if ((pVBInfo->ModeType == ModeVGA) && (!(pVBInfo->VBInfo - & SetInSlaveMode))) { + if ((pVBInfo->ModeType == ModeVGA) && !(pVBInfo->VBInfo + & SetInSlaveMode)) { tempah |= 0x010; } tempah |= 0x080; @@ -5416,7 +5404,6 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, if (HwDeviceExtension->jChipType >= XG21) { temp = xgifb_reg_get(pVBInfo->P3d4, 0x38); if (temp & 0xA0) { - if (HwDeviceExtension->jChipType == XG27) XGI_SetXG27CRTC(RefreshRateTableIndex, pVBInfo); else @@ -5486,7 +5473,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo); if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA) || - (!(pVBInfo->VBInfo & SwitchCRT2))) { + !(pVBInfo->VBInfo & SwitchCRT2)) { XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h index c02b5ce6c5cd..dd85f3503410 100644 --- a/include/linux/hid-sensor-hub.h +++ b/include/linux/hid-sensor-hub.h @@ -236,6 +236,7 @@ struct hid_sensor_common { struct hid_sensor_hub_attribute_info report_state; struct hid_sensor_hub_attribute_info power_state; struct hid_sensor_hub_attribute_info sensitivity; + struct work_struct work; }; /* Convert from hid unit expo to regular exponent */ diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 3d672f72e7ec..9edccfba1ffb 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -164,6 +164,18 @@ void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff); struct iio_channel *iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer); +/** + * iio_channel_cb_get_iio_dev() - get access to the underlying device. + * @cb_buffer: The callback buffer from whom we want the device + * information. + * + * This function allows one to obtain information about the device. + * The primary aim is to allow drivers that are consuming a device to query + * things like current trigger. + */ +struct iio_dev +*iio_channel_cb_get_iio_dev(const struct iio_cb_buffer *cb_buffer); + /** * iio_read_channel_raw() - read from a given channel * @chan: The channel being queried. diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 854e2dad1e0d..b4a0679e4a49 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -483,6 +483,7 @@ struct iio_buffer_setup_ops { * @scan_timestamp: [INTERN] set if any buffers have requested timestamp * @scan_index_timestamp:[INTERN] cache of the index to the timestamp * @trig: [INTERN] current device trigger (buffer modes) + * @trig_readonly [INTERN] mark the current trigger immutable * @pollfunc: [DRIVER] function run on trigger being received * @pollfunc_event: [DRIVER] function run on events trigger being received * @channels: [DRIVER] channel specification structure table @@ -523,6 +524,7 @@ struct iio_dev { bool scan_timestamp; unsigned scan_index_timestamp; struct iio_trigger *trig; + bool trig_readonly; struct iio_poll_func *pollfunc; struct iio_poll_func *pollfunc_event; @@ -642,6 +644,7 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) } void iio_device_free(struct iio_dev *indio_dev); +int devm_iio_device_match(struct device *dev, void *res, void *data); struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv); void devm_iio_device_free(struct device *dev, struct iio_dev *indio_dev); struct iio_trigger *devm_iio_trigger_alloc(struct device *dev, diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index 1c9e028e0d4a..4f1154f7a33c 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -56,6 +56,9 @@ struct iio_trigger_ops { * @subirqs: [INTERN] information about the 'child' irqs. * @pool: [INTERN] bitmap of irqs currently in use. * @pool_lock: [INTERN] protection of the irq pool. + * @attached_own_device:[INTERN] if we are using our own device as trigger, + * i.e. if we registered a poll function to the same + * device as the one providing the trigger. **/ struct iio_trigger { const struct iio_trigger_ops *ops; @@ -73,6 +76,7 @@ struct iio_trigger { struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER]; unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; struct mutex pool_lock; + bool attached_own_device; }; @@ -125,12 +129,27 @@ static inline void *iio_trigger_get_drvdata(struct iio_trigger *trig) **/ int iio_trigger_register(struct iio_trigger *trig_info); +int devm_iio_trigger_register(struct device *dev, + struct iio_trigger *trig_info); + /** * iio_trigger_unregister() - unregister a trigger from the core * @trig_info: trigger to be unregistered **/ void iio_trigger_unregister(struct iio_trigger *trig_info); +void devm_iio_trigger_unregister(struct device *dev, + struct iio_trigger *trig_info); + +/** + * iio_trigger_set_immutable() - set an immutable trigger on destination + * + * @indio_dev - IIO device structure containing the device + * @trig - trigger to assign to device + * + **/ +int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig); + /** * iio_trigger_poll() - called on a trigger occurring * @trig: trigger which occurred @@ -145,6 +164,13 @@ irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); __printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...); void iio_trigger_free(struct iio_trigger *trig); +/** + * iio_trigger_using_own() - tells us if we use our own HW trigger ourselves + * @indio_dev: device to check + */ +bool iio_trigger_using_own(struct iio_dev *indio_dev); + + #else struct iio_trigger; struct iio_trigger_ops; diff --git a/include/linux/iio/triggered_buffer.h b/include/linux/iio/triggered_buffer.h index f72f70d5a97b..30145616773d 100644 --- a/include/linux/iio/triggered_buffer.h +++ b/include/linux/iio/triggered_buffer.h @@ -12,4 +12,12 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, const struct iio_buffer_setup_ops *setup_ops); void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev); +int devm_iio_triggered_buffer_setup(struct device *dev, + struct iio_dev *indio_dev, + irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + const struct iio_buffer_setup_ops *ops); +void devm_iio_triggered_buffer_cleanup(struct device *dev, + struct iio_dev *indio_dev); + #endif diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c index 5eb6793f3972..7a6d61c6c012 100644 --- a/tools/iio/iio_utils.c +++ b/tools/iio/iio_utils.c @@ -121,10 +121,6 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used, ret = -ENOENT; while (ent = readdir(dp), ent) - /* - * Do we allow devices to override a generic name with - * a specific one? - */ if ((strcmp(builtname, ent->d_name) == 0) || (strcmp(builtname_generic, ent->d_name) == 0)) { ret = asprintf(&filename, @@ -178,6 +174,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used, sysfsfp = 0; free(filename); filename = 0; + + /* + * Avoid having a more generic entry overwriting + * the settings. + */ + if (strcmp(builtname, ent->d_name) == 0) + break; } error_close_sysfsfp: diff --git a/tools/iio/lsiio.c b/tools/iio/lsiio.c index 3d650e668252..ab0f5cf16025 100644 --- a/tools/iio/lsiio.c +++ b/tools/iio/lsiio.c @@ -51,7 +51,8 @@ static int dump_channels(const char *dev_dir_name) while (ent = readdir(dp), ent) if (check_prefix(ent->d_name, "in_") && - check_postfix(ent->d_name, "_raw")) + (check_postfix(ent->d_name, "_raw") || + check_postfix(ent->d_name, "_input"))) printf(" %-10s\n", ent->d_name); return (closedir(dp) == -1) ? -errno : 0;