summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bus/Kconfig9
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/ti-pwmss.c (renamed from drivers/pwm/pwm-tipwmss.c)0
-rw-r--r--drivers/counter/104-quad-8.c33
-rw-r--r--drivers/counter/Kconfig11
-rw-r--r--drivers/counter/Makefile1
-rw-r--r--drivers/counter/counter.c101
-rw-r--r--drivers/counter/ftm-quaddec.c14
-rw-r--r--drivers/counter/stm32-lptimer-cnt.c7
-rw-r--r--drivers/counter/stm32-timer-cnt.c23
-rw-r--r--drivers/counter/ti-eqep.c466
-rw-r--r--drivers/hwmon/Kconfig3
-rw-r--r--drivers/hwmon/ab8500.c65
-rw-r--r--drivers/iio/accel/st_accel_core.c1
-rw-r--r--drivers/iio/adc/Kconfig25
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c1218
-rw-r--r--drivers/iio/adc/ad7949.c33
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c3
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c4
-rw-r--r--drivers/iio/adc/cpcap-adc.c2
-rw-r--r--drivers/iio/adc/exynos_adc.c6
-rw-r--r--drivers/iio/adc/hx711.c22
-rw-r--r--drivers/iio/adc/ingenic-adc.c149
-rw-r--r--drivers/iio/adc/intel_mrfld_adc.c262
-rw-r--r--drivers/iio/adc/max1027.c180
-rw-r--r--drivers/iio/adc/mcp320x.c2
-rw-r--r--drivers/iio/adc/meson_saradc.c4
-rw-r--r--drivers/iio/adc/sc27xx_adc.c16
-rw-r--r--drivers/iio/adc/stm32-adc-core.c11
-rw-r--r--drivers/iio/adc/stm32-adc.c21
-rw-r--r--drivers/iio/adc/stmpe-adc.c2
-rw-r--r--drivers/iio/adc/twl4030-madc.c18
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c4
-rw-r--r--drivers/iio/chemical/atlas-ph-sensor.c8
-rw-r--r--drivers/iio/chemical/sgp30.c2
-rw-r--r--drivers/iio/chemical/sps30.c2
-rw-r--r--drivers/iio/dac/ad7303.c13
-rw-r--r--drivers/iio/dac/stm32-dac-core.c138
-rw-r--r--drivers/iio/dac/stm32-dac.c94
-rw-r--r--drivers/iio/gyro/adis16080.c8
-rw-r--r--drivers/iio/gyro/adis16130.c2
-rw-r--r--drivers/iio/gyro/itg3200_core.c2
-rw-r--r--drivers/iio/gyro/mpu3050-core.c2
-rw-r--r--drivers/iio/gyro/st_gyro_core.c1
-rw-r--r--drivers/iio/imu/Kconfig27
-rw-r--r--drivers/iio/imu/Makefile5
-rw-r--r--drivers/iio/imu/fxos8700.h10
-rw-r--r--drivers/iio/imu/fxos8700_core.c649
-rw-r--r--drivers/iio/imu/fxos8700_i2c.c71
-rw-r--r--drivers/iio/imu/fxos8700_spi.c59
-rw-r--r--drivers/iio/imu/inv_mpu6050/Makefile7
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_aux.c204
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_aux.h19
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c152
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c60
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h70
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c356
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h36
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c11
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c86
-rw-r--r--drivers/iio/imu/st_lsm6dsx/Kconfig3
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h79
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c100
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c821
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c10
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c10
-rw-r--r--drivers/iio/industrialio-core.c17
-rw-r--r--drivers/iio/light/Kconfig11
-rw-r--r--drivers/iio/light/Makefile1
-rw-r--r--drivers/iio/light/adux1020.c849
-rw-r--r--drivers/iio/light/bh1750.c4
-rw-r--r--drivers/iio/light/cm36651.c2
-rw-r--r--drivers/iio/light/tcs3414.c30
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c1
-rw-r--r--drivers/iio/pressure/bmp280-core.c130
-rw-r--r--drivers/iio/pressure/bmp280-i2c.c6
-rw-r--r--drivers/iio/pressure/bmp280-spi.c6
-rw-r--r--drivers/iio/pressure/bmp280.h1
-rw-r--r--drivers/iio/pressure/st_pressure_core.c1
-rw-r--r--drivers/iio/pressure/zpa2326.c16
-rw-r--r--drivers/iio/proximity/pulsedlight-lidar-lite-v2.c5
-rw-r--r--drivers/iio/proximity/sx9500.c16
-rw-r--r--drivers/iio/temperature/Kconfig11
-rw-r--r--drivers/iio/temperature/Makefile1
-rw-r--r--drivers/iio/temperature/ltc2983.c1557
-rw-r--r--drivers/iio/temperature/max31856.c2
-rw-r--r--drivers/iio/temperature/maxim_thermocouple.c2
-rw-r--r--drivers/mfd/Kconfig7
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/ab8500-debugfs.c715
-rw-r--r--drivers/mfd/ab8500-gpadc.c1075
-rw-r--r--drivers/power/supply/Kconfig2
-rw-r--r--drivers/power/supply/ab8500_btemp.c41
-rw-r--r--drivers/power/supply/ab8500_charger.c78
-rw-r--r--drivers/power/supply/ab8500_fg.c23
-rw-r--r--drivers/pwm/Kconfig9
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.c301
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.txt18
-rw-r--r--drivers/staging/board/armadillo800eva.c12
-rw-r--r--drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c4
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c3
-rw-r--r--drivers/staging/comedi/drivers/ni_routes.c2
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.c27
-rw-r--r--drivers/staging/exfat/TODO9
-rw-r--r--drivers/staging/exfat/exfat.h10
-rw-r--r--drivers/staging/exfat/exfat_cache.c48
-rw-r--r--drivers/staging/exfat/exfat_core.c87
-rw-r--r--drivers/staging/exfat/exfat_super.c340
-rw-r--r--drivers/staging/fbtft/Kconfig7
-rw-r--r--drivers/staging/fbtft/Makefile1
-rw-r--r--drivers/staging/fbtft/fb_seps525.c213
-rw-r--r--drivers/staging/fbtft/fb_uc1611.c22
-rw-r--r--drivers/staging/fbtft/fbtft-core.c2
-rw-r--r--drivers/staging/fieldbus/anybuss/anybuss-client.h11
-rw-r--r--drivers/staging/fieldbus/anybuss/arcx-anybus.c8
-rw-r--r--drivers/staging/fieldbus/anybuss/hms-profinet.c2
-rw-r--r--drivers/staging/fieldbus/anybuss/host.c6
-rw-r--r--drivers/staging/fieldbus/dev_core.c3
-rw-r--r--drivers/staging/fieldbus/fieldbus_dev.h6
-rw-r--r--drivers/staging/gasket/gasket_ioctl.c16
-rw-r--r--drivers/staging/iio/accel/adis16240.c1
-rw-r--r--drivers/staging/iio/adc/ad7192.c79
-rw-r--r--drivers/staging/iio/frequency/ad9834.c4
-rw-r--r--drivers/staging/isdn/avm/b1.c41
-rw-r--r--drivers/staging/isdn/gigaset/interface.c2
-rw-r--r--drivers/staging/kpc2000/kpc2000_i2c.c204
-rw-r--r--drivers/staging/kpc2000/kpc2000_spi.c24
-rw-r--r--drivers/staging/media/allegro-dvt/nal-h264.c2
-rw-r--r--drivers/staging/most/configfs.c6
-rw-r--r--drivers/staging/most/core.c18
-rw-r--r--drivers/staging/mt7621-dma/mtk-hsdma.c21
-rw-r--r--drivers/staging/mt7621-pci/pci-mt7621.c23
-rw-r--r--drivers/staging/netlogic/TODO2
-rw-r--r--drivers/staging/netlogic/xlr_net.c3
-rw-r--r--drivers/staging/octeon-usb/octeon-hcd.c3
-rw-r--r--drivers/staging/octeon/ethernet-mdio.c6
-rw-r--r--drivers/staging/octeon/ethernet-rgmii.c4
-rw-r--r--drivers/staging/octeon/ethernet-rx.c6
-rw-r--r--drivers/staging/octeon/ethernet-tx.c6
-rw-r--r--drivers/staging/octeon/ethernet.c6
-rw-r--r--drivers/staging/octeon/octeon-ethernet.h4
-rw-r--r--drivers/staging/octeon/octeon-stubs.h73
-rw-r--r--drivers/staging/olpc_dcon/Kconfig21
-rw-r--r--drivers/staging/olpc_dcon/Makefile4
-rw-r--r--drivers/staging/olpc_dcon/TODO1
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c6
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.h5
-rw-r--r--drivers/staging/qlge/TODO3
-rw-r--r--drivers/staging/qlge/qlge.h145
-rw-r--r--drivers/staging/qlge/qlge_dbg.c291
-rw-r--r--drivers/staging/qlge/qlge_main.c909
-rw-r--r--drivers/staging/qlge/qlge_mpi.c1
-rw-r--r--drivers/staging/ralink-gdma/ralink-gdma.c4
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c43
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_efuse.c5
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme.c4
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme_ext.c2
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_pwrctrl.c4
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_sta_mgt.c167
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_wlan_util.c26
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_xmit.c4
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c55
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c1
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_efuse.h1
-rw-r--r--drivers/staging/rtl8188eu/include/sta_info.h2
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c30
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c9
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c8
-rw-r--r--drivers/staging/rtl8192u/r8190_rtl8256.c4
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c127
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c2
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c40
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c8
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.c103
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_ap.c11
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_cmd.c20
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme.c174
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme_ext.c23
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_pwrctrl.c1
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_recv.c9
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_security.c145
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_sta_mgt.c3
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_wlan_util.c19
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_xmit.c98
-rw-r--r--drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c2
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_btcoex.c2
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com.c1
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com_phycfg.c1076
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DIG.c1
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_dm.c3
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c6
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c77
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c41
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c2
-rw-r--r--drivers/staging/rtl8723bs/hal/sdio_ops.c127
-rw-r--r--drivers/staging/rtl8723bs/include/drv_types.h4
-rw-r--r--drivers/staging/rtl8723bs/include/hal_com_phycfg.h26
-rw-r--r--drivers/staging/rtl8723bs/include/hal_data.h21
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_service.h4
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_service_linux.h7
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_hal.h15
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mlme_ext.h1
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c41
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_linux.c59
-rw-r--r--drivers/staging/rtl8723bs/os_dep/os_intfs.c23
-rw-r--r--drivers/staging/rtl8723bs/os_dep/osdep_service.c136
-rw-r--r--drivers/staging/rtl8723bs/os_dep/sdio_intf.c1
-rw-r--r--drivers/staging/rts5208/ms.c86
-rw-r--r--drivers/staging/rts5208/ms.h70
-rw-r--r--drivers/staging/rts5208/rtsx.c3
-rw-r--r--drivers/staging/rts5208/rtsx_transport.c4
-rw-r--r--drivers/staging/rts5208/sd.h2
-rw-r--r--drivers/staging/rts5208/xd.c8
-rw-r--r--drivers/staging/rts5208/xd.h6
-rw-r--r--drivers/staging/sm750fb/ddk750_chip.c41
-rw-r--r--drivers/staging/sm750fb/ddk750_chip.h18
-rw-r--r--drivers/staging/sm750fb/ddk750_display.c4
-rw-r--r--drivers/staging/sm750fb/ddk750_mode.c16
-rw-r--r--drivers/staging/sm750fb/ddk750_sii164.c28
-rw-r--r--drivers/staging/sm750fb/ddk750_sii164.h11
-rw-r--r--drivers/staging/sm750fb/sm750_accel.c94
-rw-r--r--drivers/staging/sm750fb/sm750_accel.h83
-rw-r--r--drivers/staging/sm750fb/sm750_cursor.h17
-rw-r--r--drivers/staging/uwb/rsv.c4
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c9
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835.h2
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c4
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c6
-rw-r--r--drivers/staging/vc04_services/interface/vchi/vchi.h102
-rw-r--r--drivers/staging/vc04_services/interface/vchi/vchi_cfg.h172
-rw-r--r--drivers/staging/vc04_services/interface/vchi/vchi_common.h28
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c18
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c198
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h32
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c127
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h92
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c14
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h4
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h96
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h6
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c164
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c4
-rw-r--r--drivers/staging/vt6655/card.c24
-rw-r--r--drivers/staging/vt6655/card.h2
-rw-r--r--drivers/staging/vt6655/device_main.c14
-rw-r--r--drivers/staging/vt6655/power.c10
-rw-r--r--drivers/staging/vt6655/rf.c5
-rw-r--r--drivers/staging/vt6655/rf.h19
-rw-r--r--drivers/staging/vt6655/rxtx.c5
-rw-r--r--drivers/staging/vt6656/main_usb.c9
-rw-r--r--drivers/staging/vt6656/rxtx.c8
-rw-r--r--drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt97
-rw-r--r--drivers/staging/wfx/Kconfig8
-rw-r--r--drivers/staging/wfx/Makefile24
-rw-r--r--drivers/staging/wfx/TODO17
-rw-r--r--drivers/staging/wfx/bh.c321
-rw-r--r--drivers/staging/wfx/bh.h32
-rw-r--r--drivers/staging/wfx/bus.h36
-rw-r--r--drivers/staging/wfx/bus_sdio.c269
-rw-r--r--drivers/staging/wfx/bus_spi.c267
-rw-r--r--drivers/staging/wfx/data_rx.c213
-rw-r--r--drivers/staging/wfx/data_rx.h18
-rw-r--r--drivers/staging/wfx/data_tx.c837
-rw-r--r--drivers/staging/wfx/data_tx.h93
-rw-r--r--drivers/staging/wfx/debug.c306
-rw-r--r--drivers/staging/wfx/debug.h19
-rw-r--r--drivers/staging/wfx/fwio.c388
-rw-r--r--drivers/staging/wfx/fwio.h15
-rw-r--r--drivers/staging/wfx/hif_api_cmd.h681
-rw-r--r--drivers/staging/wfx/hif_api_general.h437
-rw-r--r--drivers/staging/wfx/hif_api_mib.h558
-rw-r--r--drivers/staging/wfx/hif_rx.c336
-rw-r--r--drivers/staging/wfx/hif_rx.h18
-rw-r--r--drivers/staging/wfx/hif_tx.c470
-rw-r--r--drivers/staging/wfx/hif_tx.h67
-rw-r--r--drivers/staging/wfx/hif_tx_mib.h290
-rw-r--r--drivers/staging/wfx/hwio.c338
-rw-r--r--drivers/staging/wfx/hwio.h75
-rw-r--r--drivers/staging/wfx/key.c258
-rw-r--r--drivers/staging/wfx/key.h22
-rw-r--r--drivers/staging/wfx/main.c470
-rw-r--r--drivers/staging/wfx/main.h47
-rw-r--r--drivers/staging/wfx/queue.c608
-rw-r--r--drivers/staging/wfx/queue.h59
-rw-r--r--drivers/staging/wfx/scan.c289
-rw-r--r--drivers/staging/wfx/scan.h42
-rw-r--r--drivers/staging/wfx/secure_link.h55
-rw-r--r--drivers/staging/wfx/sta.c1636
-rw-r--r--drivers/staging/wfx/sta.h101
-rw-r--r--drivers/staging/wfx/traces.h434
-rw-r--r--drivers/staging/wfx/wfx.h206
-rw-r--r--drivers/staging/wilc1000/Makefile8
-rw-r--r--drivers/staging/wilc1000/cfg80211.c (renamed from drivers/staging/wilc1000/wilc_wfi_cfgoperations.c)246
-rw-r--r--drivers/staging/wilc1000/cfg80211.h (renamed from drivers/staging/wilc1000/wilc_wfi_cfgoperations.h)8
-rw-r--r--drivers/staging/wilc1000/hif.c (renamed from drivers/staging/wilc1000/wilc_hif.c)20
-rw-r--r--drivers/staging/wilc1000/hif.h (renamed from drivers/staging/wilc1000/wilc_hif.h)6
-rw-r--r--drivers/staging/wilc1000/mon.c (renamed from drivers/staging/wilc1000/wilc_mon.c)4
-rw-r--r--drivers/staging/wilc1000/netdev.c (renamed from drivers/staging/wilc1000/wilc_netdev.c)146
-rw-r--r--drivers/staging/wilc1000/netdev.h (renamed from drivers/staging/wilc1000/wilc_wfi_netdevice.h)34
-rw-r--r--drivers/staging/wilc1000/sdio.c (renamed from drivers/staging/wilc1000/wilc_sdio.c)4
-rw-r--r--drivers/staging/wilc1000/spi.c (renamed from drivers/staging/wilc1000/wilc_spi.c)15
-rw-r--r--drivers/staging/wilc1000/wlan.c (renamed from drivers/staging/wilc1000/wilc_wlan.c)4
-rw-r--r--drivers/staging/wilc1000/wlan.h (renamed from drivers/staging/wilc1000/wilc_wlan.h)2
-rw-r--r--drivers/staging/wilc1000/wlan_cfg.c (renamed from drivers/staging/wilc1000/wilc_wlan_cfg.c)30
-rw-r--r--drivers/staging/wilc1000/wlan_cfg.h (renamed from drivers/staging/wilc1000/wilc_wlan_cfg.h)0
-rw-r--r--drivers/staging/wilc1000/wlan_if.h (renamed from drivers/staging/wilc1000/wilc_wlan_if.h)8
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h18
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c2
-rw-r--r--drivers/staging/wlan-ng/p80211wep.c64
-rw-r--r--drivers/staging/wlan-ng/prism2usb.c6
315 files changed, 21677 insertions, 7448 deletions
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 6b331061d34b..97ab5ad171d4 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -150,6 +150,15 @@ config TEGRA_GMI
Driver for the Tegra Generic Memory Interface bus which can be used
to attach devices such as NOR, UART, FPGA and more.
+config TI_PWMSS
+ bool
+ default y if (ARCH_OMAP2PLUS) && (PWM_TIECAP || PWM_TIEHRPWM || TI_EQEP)
+ help
+ PWM Subsystem driver support for AM33xx SOC.
+
+ PWM submodules require PWM config space access from submodule
+ drivers and require common parent driver support.
+
config TI_SYSC
bool "TI sysc interconnect target module driver"
depends on ARCH_OMAP2PLUS
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 16b43d3468c6..1320bcf9fa9d 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
obj-$(CONFIG_TEGRA_GMI) += tegra-gmi.o
+obj-$(CONFIG_TI_PWMSS) += ti-pwmss.o
obj-$(CONFIG_TI_SYSC) += ti-sysc.o
obj-$(CONFIG_TS_NBUS) += ts-nbus.o
obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
diff --git a/drivers/pwm/pwm-tipwmss.c b/drivers/bus/ti-pwmss.c
index e9c26c94251b..e9c26c94251b 100644
--- a/drivers/pwm/pwm-tipwmss.c
+++ b/drivers/bus/ti-pwmss.c
diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
index 00b113f4b958..17e67a84777d 100644
--- a/drivers/counter/104-quad-8.c
+++ b/drivers/counter/104-quad-8.c
@@ -562,11 +562,10 @@ static const struct iio_chan_spec quad8_channels[] = {
};
static int quad8_signal_read(struct counter_device *counter,
- struct counter_signal *signal, struct counter_signal_read_value *val)
+ struct counter_signal *signal, enum counter_signal_value *val)
{
const struct quad8_iio *const priv = counter->priv;
unsigned int state;
- enum counter_signal_level level;
/* Only Index signal levels can be read */
if (signal->id < 16)
@@ -575,22 +574,19 @@ static int quad8_signal_read(struct counter_device *counter,
state = inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS)
& BIT(signal->id - 16);
- level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
-
- counter_signal_read_value_set(val, COUNTER_SIGNAL_LEVEL, &level);
+ *val = (state) ? COUNTER_SIGNAL_HIGH : COUNTER_SIGNAL_LOW;
return 0;
}
static int quad8_count_read(struct counter_device *counter,
- struct counter_count *count, struct counter_count_read_value *val)
+ struct counter_count *count, unsigned long *val)
{
const struct quad8_iio *const priv = counter->priv;
const int base_offset = priv->base + 2 * count->id;
unsigned int flags;
unsigned int borrow;
unsigned int carry;
- unsigned long position;
int i;
flags = inb(base_offset + 1);
@@ -598,36 +594,27 @@ static int quad8_count_read(struct counter_device *counter,
carry = !!(flags & QUAD8_FLAG_CT);
/* Borrow XOR Carry effectively doubles count range */
- position = (unsigned long)(borrow ^ carry) << 24;
+ *val = (unsigned long)(borrow ^ carry) << 24;
/* Reset Byte Pointer; transfer Counter to Output Latch */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
base_offset + 1);
for (i = 0; i < 3; i++)
- position |= (unsigned long)inb(base_offset) << (8 * i);
-
- counter_count_read_value_set(val, COUNTER_COUNT_POSITION, &position);
+ *val |= (unsigned long)inb(base_offset) << (8 * i);
return 0;
}
static int quad8_count_write(struct counter_device *counter,
- struct counter_count *count, struct counter_count_write_value *val)
+ struct counter_count *count, unsigned long val)
{
const struct quad8_iio *const priv = counter->priv;
const int base_offset = priv->base + 2 * count->id;
- int err;
- unsigned long position;
int i;
- err = counter_count_write_value_get(&position, COUNTER_COUNT_POSITION,
- val);
- if (err)
- return err;
-
/* Only 24-bit values are supported */
- if (position > 0xFFFFFF)
+ if (val > 0xFFFFFF)
return -EINVAL;
/* Reset Byte Pointer */
@@ -635,7 +622,7 @@ static int quad8_count_write(struct counter_device *counter,
/* Counter can only be set via Preset Register */
for (i = 0; i < 3; i++)
- outb(position >> (8 * i), base_offset);
+ outb(val >> (8 * i), base_offset);
/* Transfer Preset Register to Counter */
outb(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1);
@@ -644,9 +631,9 @@ static int quad8_count_write(struct counter_device *counter,
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
/* Set Preset Register back to original value */
- position = priv->preset[count->id];
+ val = priv->preset[count->id];
for (i = 0; i < 3; i++)
- outb(position >> (8 * i), base_offset);
+ outb(val >> (8 * i), base_offset);
/* Reset Borrow, Carry, Compare, and Sign flags */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
index 2967d0a9ff91..c80fa76bb531 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -49,6 +49,17 @@ config STM32_LPTIMER_CNT
To compile this driver as a module, choose M here: the
module will be called stm32-lptimer-cnt.
+config TI_EQEP
+ tristate "TI eQEP counter driver"
+ depends on (SOC_AM33XX || COMPILE_TEST)
+ select REGMAP_MMIO
+ help
+ Select this option to enable the Texas Instruments Enhanced Quadrature
+ Encoder Pulse (eQEP) counter driver.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ti-eqep.
+
config FTM_QUADDEC
tristate "Flex Timer Module Quadrature decoder driver"
depends on HAS_IOMEM && OF
diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
index 40d35522937d..55142d1f4c43 100644
--- a/drivers/counter/Makefile
+++ b/drivers/counter/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_COUNTER) += counter.o
obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o
obj-$(CONFIG_STM32_TIMER_CNT) += stm32-timer-cnt.o
obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o
+obj-$(CONFIG_TI_EQEP) += ti-eqep.o
obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o
diff --git a/drivers/counter/counter.c b/drivers/counter/counter.c
index 106bc7180cd8..6a683d086008 100644
--- a/drivers/counter/counter.c
+++ b/drivers/counter/counter.c
@@ -220,86 +220,6 @@ ssize_t counter_device_enum_available_read(struct counter_device *counter,
}
EXPORT_SYMBOL_GPL(counter_device_enum_available_read);
-static const char *const counter_signal_level_str[] = {
- [COUNTER_SIGNAL_LEVEL_LOW] = "low",
- [COUNTER_SIGNAL_LEVEL_HIGH] = "high"
-};
-
-/**
- * counter_signal_read_value_set - set counter_signal_read_value data
- * @val: counter_signal_read_value structure to set
- * @type: property Signal data represents
- * @data: Signal data
- *
- * This function sets an opaque counter_signal_read_value structure with the
- * provided Signal data.
- */
-void counter_signal_read_value_set(struct counter_signal_read_value *const val,
- const enum counter_signal_value_type type,
- void *const data)
-{
- if (type == COUNTER_SIGNAL_LEVEL)
- val->len = sprintf(val->buf, "%s\n",
- counter_signal_level_str[*(enum counter_signal_level *)data]);
- else
- val->len = 0;
-}
-EXPORT_SYMBOL_GPL(counter_signal_read_value_set);
-
-/**
- * counter_count_read_value_set - set counter_count_read_value data
- * @val: counter_count_read_value structure to set
- * @type: property Count data represents
- * @data: Count data
- *
- * This function sets an opaque counter_count_read_value structure with the
- * provided Count data.
- */
-void counter_count_read_value_set(struct counter_count_read_value *const val,
- const enum counter_count_value_type type,
- void *const data)
-{
- switch (type) {
- case COUNTER_COUNT_POSITION:
- val->len = sprintf(val->buf, "%lu\n", *(unsigned long *)data);
- break;
- default:
- val->len = 0;
- }
-}
-EXPORT_SYMBOL_GPL(counter_count_read_value_set);
-
-/**
- * counter_count_write_value_get - get counter_count_write_value data
- * @data: Count data
- * @type: property Count data represents
- * @val: counter_count_write_value structure containing data
- *
- * This function extracts Count data from the provided opaque
- * counter_count_write_value structure and stores it at the address provided by
- * @data.
- *
- * RETURNS:
- * 0 on success, negative error number on failure.
- */
-int counter_count_write_value_get(void *const data,
- const enum counter_count_value_type type,
- const struct counter_count_write_value *const val)
-{
- int err;
-
- switch (type) {
- case COUNTER_COUNT_POSITION:
- err = kstrtoul(val->buf, 0, data);
- if (err)
- return err;
- break;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(counter_count_write_value_get);
-
struct counter_attr_parm {
struct counter_device_attr_group *group;
const char *prefix;
@@ -369,6 +289,11 @@ struct counter_signal_unit {
struct counter_signal *signal;
};
+static const char *const counter_signal_value_str[] = {
+ [COUNTER_SIGNAL_LOW] = "low",
+ [COUNTER_SIGNAL_HIGH] = "high"
+};
+
static ssize_t counter_signal_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -377,13 +302,13 @@ static ssize_t counter_signal_show(struct device *dev,
const struct counter_signal_unit *const component = devattr->component;
struct counter_signal *const signal = component->signal;
int err;
- struct counter_signal_read_value val = { .buf = buf };
+ enum counter_signal_value val;
err = counter->ops->signal_read(counter, signal, &val);
if (err)
return err;
- return val.len;
+ return sprintf(buf, "%s\n", counter_signal_value_str[val]);
}
struct counter_name_unit {
@@ -788,13 +713,13 @@ static ssize_t counter_count_show(struct device *dev,
const struct counter_count_unit *const component = devattr->component;
struct counter_count *const count = component->count;
int err;
- struct counter_count_read_value val = { .buf = buf };
+ unsigned long val;
err = counter->ops->count_read(counter, count, &val);
if (err)
return err;
- return val.len;
+ return sprintf(buf, "%lu\n", val);
}
static ssize_t counter_count_store(struct device *dev,
@@ -806,9 +731,13 @@ static ssize_t counter_count_store(struct device *dev,
const struct counter_count_unit *const component = devattr->component;
struct counter_count *const count = component->count;
int err;
- struct counter_count_write_value val = { .buf = buf };
+ unsigned long val;
+
+ err = kstrtoul(buf, 0, &val);
+ if (err)
+ return err;
- err = counter->ops->count_write(counter, count, &val);
+ err = counter->ops->count_write(counter, count, val);
if (err)
return err;
diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c
index 4046aa9f9234..c2b3fdfd8b77 100644
--- a/drivers/counter/ftm-quaddec.c
+++ b/drivers/counter/ftm-quaddec.c
@@ -178,31 +178,25 @@ static const enum counter_count_function ftm_quaddec_count_functions[] = {
static int ftm_quaddec_count_read(struct counter_device *counter,
struct counter_count *count,
- struct counter_count_read_value *val)
+ unsigned long *val)
{
struct ftm_quaddec *const ftm = counter->priv;
uint32_t cntval;
ftm_read(ftm, FTM_CNT, &cntval);
- counter_count_read_value_set(val, COUNTER_COUNT_POSITION, &cntval);
+ *val = cntval;
return 0;
}
static int ftm_quaddec_count_write(struct counter_device *counter,
struct counter_count *count,
- struct counter_count_write_value *val)
+ const unsigned long val)
{
struct ftm_quaddec *const ftm = counter->priv;
- u32 cnt;
- int err;
- err = counter_count_write_value_get(&cnt, COUNTER_COUNT_POSITION, val);
- if (err)
- return err;
-
- if (cnt != 0) {
+ if (val != 0) {
dev_warn(&ftm->pdev->dev, "Can only accept '0' as new counter value\n");
return -EINVAL;
}
diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c
index bbc930a5962c..8e276eb655f5 100644
--- a/drivers/counter/stm32-lptimer-cnt.c
+++ b/drivers/counter/stm32-lptimer-cnt.c
@@ -347,7 +347,7 @@ static const struct iio_chan_spec stm32_lptim_cnt_channels = {
};
/**
- * stm32_lptim_cnt_function - enumerates stm32 LPTimer counter & encoder modes
+ * enum stm32_lptim_cnt_function - enumerates LPTimer counter & encoder modes
* @STM32_LPTIM_COUNTER_INCREASE: up count on IN1 rising, falling or both edges
* @STM32_LPTIM_ENCODER_BOTH_EDGE: count on both edges (IN1 & IN2 quadrature)
*/
@@ -377,8 +377,7 @@ static enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = {
};
static int stm32_lptim_cnt_read(struct counter_device *counter,
- struct counter_count *count,
- struct counter_count_read_value *val)
+ struct counter_count *count, unsigned long *val)
{
struct stm32_lptim_cnt *const priv = counter->priv;
u32 cnt;
@@ -388,7 +387,7 @@ static int stm32_lptim_cnt_read(struct counter_device *counter,
if (ret)
return ret;
- counter_count_read_value_set(val, COUNTER_COUNT_POSITION, &cnt);
+ *val = cnt;
return 0;
}
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 644ba18a72ad..3eafccec3beb 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -28,7 +28,7 @@ struct stm32_timer_cnt {
};
/**
- * stm32_count_function - enumerates stm32 timer counter encoder modes
+ * enum stm32_count_function - enumerates stm32 timer counter encoder modes
* @STM32_COUNT_SLAVE_MODE_DISABLED: counts on internal clock when CEN=1
* @STM32_COUNT_ENCODER_MODE_1: counts TI1FP1 edges, depending on TI2FP2 level
* @STM32_COUNT_ENCODER_MODE_2: counts TI2FP2 edges, depending on TI1FP1 level
@@ -48,34 +48,27 @@ static enum counter_count_function stm32_count_functions[] = {
};
static int stm32_count_read(struct counter_device *counter,
- struct counter_count *count,
- struct counter_count_read_value *val)
+ struct counter_count *count, unsigned long *val)
{
struct stm32_timer_cnt *const priv = counter->priv;
u32 cnt;
regmap_read(priv->regmap, TIM_CNT, &cnt);
- counter_count_read_value_set(val, COUNTER_COUNT_POSITION, &cnt);
+ *val = cnt;
return 0;
}
static int stm32_count_write(struct counter_device *counter,
struct counter_count *count,
- struct counter_count_write_value *val)
+ const unsigned long val)
{
struct stm32_timer_cnt *const priv = counter->priv;
- u32 cnt;
- int err;
-
- err = counter_count_write_value_get(&cnt, COUNTER_COUNT_POSITION, val);
- if (err)
- return err;
- if (cnt > priv->ceiling)
+ if (val > priv->ceiling)
return -EINVAL;
- return regmap_write(priv->regmap, TIM_CNT, cnt);
+ return regmap_write(priv->regmap, TIM_CNT, val);
}
static int stm32_count_function_get(struct counter_device *counter,
@@ -219,8 +212,8 @@ static ssize_t stm32_count_enable_write(struct counter_device *counter,
if (enable) {
regmap_read(priv->regmap, TIM_CR1, &cr1);
- if (!(cr1 & TIM_CR1_CEN))
- clk_enable(priv->clk);
+ if (!(cr1 & TIM_CR1_CEN))
+ clk_enable(priv->clk);
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
TIM_CR1_CEN);
diff --git a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c
new file mode 100644
index 000000000000..1ff07faef27f
--- /dev/null
+++ b/drivers/counter/ti-eqep.c
@@ -0,0 +1,466 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 David Lechner <david@lechnology.com>
+ *
+ * Counter driver for Texas Instruments Enhanced Quadrature Encoder Pulse (eQEP)
+ */
+
+#include <linux/bitops.h>
+#include <linux/counter.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+/* 32-bit registers */
+#define QPOSCNT 0x0
+#define QPOSINIT 0x4
+#define QPOSMAX 0x8
+#define QPOSCMP 0xc
+#define QPOSILAT 0x10
+#define QPOSSLAT 0x14
+#define QPOSLAT 0x18
+#define QUTMR 0x1c
+#define QUPRD 0x20
+
+/* 16-bit registers */
+#define QWDTMR 0x0 /* 0x24 */
+#define QWDPRD 0x2 /* 0x26 */
+#define QDECCTL 0x4 /* 0x28 */
+#define QEPCTL 0x6 /* 0x2a */
+#define QCAPCTL 0x8 /* 0x2c */
+#define QPOSCTL 0xa /* 0x2e */
+#define QEINT 0xc /* 0x30 */
+#define QFLG 0xe /* 0x32 */
+#define QCLR 0x10 /* 0x34 */
+#define QFRC 0x12 /* 0x36 */
+#define QEPSTS 0x14 /* 0x38 */
+#define QCTMR 0x16 /* 0x3a */
+#define QCPRD 0x18 /* 0x3c */
+#define QCTMRLAT 0x1a /* 0x3e */
+#define QCPRDLAT 0x1c /* 0x40 */
+
+#define QDECCTL_QSRC_SHIFT 14
+#define QDECCTL_QSRC GENMASK(15, 14)
+#define QDECCTL_SOEN BIT(13)
+#define QDECCTL_SPSEL BIT(12)
+#define QDECCTL_XCR BIT(11)
+#define QDECCTL_SWAP BIT(10)
+#define QDECCTL_IGATE BIT(9)
+#define QDECCTL_QAP BIT(8)
+#define QDECCTL_QBP BIT(7)
+#define QDECCTL_QIP BIT(6)
+#define QDECCTL_QSP BIT(5)
+
+#define QEPCTL_FREE_SOFT GENMASK(15, 14)
+#define QEPCTL_PCRM GENMASK(13, 12)
+#define QEPCTL_SEI GENMASK(11, 10)
+#define QEPCTL_IEI GENMASK(9, 8)
+#define QEPCTL_SWI BIT(7)
+#define QEPCTL_SEL BIT(6)
+#define QEPCTL_IEL GENMASK(5, 4)
+#define QEPCTL_PHEN BIT(3)
+#define QEPCTL_QCLM BIT(2)
+#define QEPCTL_UTE BIT(1)
+#define QEPCTL_WDE BIT(0)
+
+/* EQEP Inputs */
+enum {
+ TI_EQEP_SIGNAL_QEPA, /* QEPA/XCLK */
+ TI_EQEP_SIGNAL_QEPB, /* QEPB/XDIR */
+};
+
+/* Position Counter Input Modes */
+enum {
+ TI_EQEP_COUNT_FUNC_QUAD_COUNT,
+ TI_EQEP_COUNT_FUNC_DIR_COUNT,
+ TI_EQEP_COUNT_FUNC_UP_COUNT,
+ TI_EQEP_COUNT_FUNC_DOWN_COUNT,
+};
+
+enum {
+ TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES,
+ TI_EQEP_SYNAPSE_ACTION_RISING_EDGE,
+ TI_EQEP_SYNAPSE_ACTION_NONE,
+};
+
+struct ti_eqep_cnt {
+ struct counter_device counter;
+ struct regmap *regmap32;
+ struct regmap *regmap16;
+};
+
+static int ti_eqep_count_read(struct counter_device *counter,
+ struct counter_count *count, unsigned long *val)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ u32 cnt;
+
+ regmap_read(priv->regmap32, QPOSCNT, &cnt);
+ *val = cnt;
+
+ return 0;
+}
+
+static int ti_eqep_count_write(struct counter_device *counter,
+ struct counter_count *count, unsigned long val)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ u32 max;
+
+ regmap_read(priv->regmap32, QPOSMAX, &max);
+ if (val > max)
+ return -EINVAL;
+
+ return regmap_write(priv->regmap32, QPOSCNT, val);
+}
+
+static int ti_eqep_function_get(struct counter_device *counter,
+ struct counter_count *count, size_t *function)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ u32 qdecctl;
+
+ regmap_read(priv->regmap16, QDECCTL, &qdecctl);
+ *function = (qdecctl & QDECCTL_QSRC) >> QDECCTL_QSRC_SHIFT;
+
+ return 0;
+}
+
+static int ti_eqep_function_set(struct counter_device *counter,
+ struct counter_count *count, size_t function)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+
+ return regmap_write_bits(priv->regmap16, QDECCTL, QDECCTL_QSRC,
+ function << QDECCTL_QSRC_SHIFT);
+}
+
+static int ti_eqep_action_get(struct counter_device *counter,
+ struct counter_count *count,
+ struct counter_synapse *synapse, size_t *action)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ size_t function;
+ u32 qdecctl;
+ int err;
+
+ err = ti_eqep_function_get(counter, count, &function);
+ if (err)
+ return err;
+
+ switch (function) {
+ case TI_EQEP_COUNT_FUNC_QUAD_COUNT:
+ /* In quadrature mode, the rising and falling edge of both
+ * QEPA and QEPB trigger QCLK.
+ */
+ *action = TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES;
+ break;
+ case TI_EQEP_COUNT_FUNC_DIR_COUNT:
+ /* In direction-count mode only rising edge of QEPA is counted
+ * and QEPB gives direction.
+ */
+ switch (synapse->signal->id) {
+ case TI_EQEP_SIGNAL_QEPA:
+ *action = TI_EQEP_SYNAPSE_ACTION_RISING_EDGE;
+ break;
+ default:
+ *action = TI_EQEP_SYNAPSE_ACTION_NONE;
+ break;
+ }
+ break;
+ case TI_EQEP_COUNT_FUNC_UP_COUNT:
+ case TI_EQEP_COUNT_FUNC_DOWN_COUNT:
+ /* In up/down-count modes only QEPA is counted and QEPB is not
+ * used.
+ */
+ switch (synapse->signal->id) {
+ case TI_EQEP_SIGNAL_QEPA:
+ err = regmap_read(priv->regmap16, QDECCTL, &qdecctl);
+ if (err)
+ return err;
+
+ if (qdecctl & QDECCTL_XCR)
+ *action = TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES;
+ else
+ *action = TI_EQEP_SYNAPSE_ACTION_RISING_EDGE;
+ break;
+ default:
+ *action = TI_EQEP_SYNAPSE_ACTION_NONE;
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static const struct counter_ops ti_eqep_counter_ops = {
+ .count_read = ti_eqep_count_read,
+ .count_write = ti_eqep_count_write,
+ .function_get = ti_eqep_function_get,
+ .function_set = ti_eqep_function_set,
+ .action_get = ti_eqep_action_get,
+};
+
+static ssize_t ti_eqep_position_ceiling_read(struct counter_device *counter,
+ struct counter_count *count,
+ void *ext_priv, char *buf)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ u32 qposmax;
+
+ regmap_read(priv->regmap32, QPOSMAX, &qposmax);
+
+ return sprintf(buf, "%u\n", qposmax);
+}
+
+static ssize_t ti_eqep_position_ceiling_write(struct counter_device *counter,
+ struct counter_count *count,
+ void *ext_priv, const char *buf,
+ size_t len)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ int err;
+ u32 res;
+
+ err = kstrtouint(buf, 0, &res);
+ if (err < 0)
+ return err;
+
+ regmap_write(priv->regmap32, QPOSMAX, res);
+
+ return len;
+}
+
+static ssize_t ti_eqep_position_floor_read(struct counter_device *counter,
+ struct counter_count *count,
+ void *ext_priv, char *buf)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ u32 qposinit;
+
+ regmap_read(priv->regmap32, QPOSINIT, &qposinit);
+
+ return sprintf(buf, "%u\n", qposinit);
+}
+
+static ssize_t ti_eqep_position_floor_write(struct counter_device *counter,
+ struct counter_count *count,
+ void *ext_priv, const char *buf,
+ size_t len)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ int err;
+ u32 res;
+
+ err = kstrtouint(buf, 0, &res);
+ if (err < 0)
+ return err;
+
+ regmap_write(priv->regmap32, QPOSINIT, res);
+
+ return len;
+}
+
+static ssize_t ti_eqep_position_enable_read(struct counter_device *counter,
+ struct counter_count *count,
+ void *ext_priv, char *buf)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ u32 qepctl;
+
+ regmap_read(priv->regmap16, QEPCTL, &qepctl);
+
+ return sprintf(buf, "%u\n", !!(qepctl & QEPCTL_PHEN));
+}
+
+static ssize_t ti_eqep_position_enable_write(struct counter_device *counter,
+ struct counter_count *count,
+ void *ext_priv, const char *buf,
+ size_t len)
+{
+ struct ti_eqep_cnt *priv = counter->priv;
+ int err;
+ bool res;
+
+ err = kstrtobool(buf, &res);
+ if (err < 0)
+ return err;
+
+ regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, res ? -1 : 0);
+
+ return len;
+}
+
+static struct counter_count_ext ti_eqep_position_ext[] = {
+ {
+ .name = "ceiling",
+ .read = ti_eqep_position_ceiling_read,
+ .write = ti_eqep_position_ceiling_write,
+ },
+ {
+ .name = "floor",
+ .read = ti_eqep_position_floor_read,
+ .write = ti_eqep_position_floor_write,
+ },
+ {
+ .name = "enable",
+ .read = ti_eqep_position_enable_read,
+ .write = ti_eqep_position_enable_write,
+ },
+};
+
+static struct counter_signal ti_eqep_signals[] = {
+ [TI_EQEP_SIGNAL_QEPA] = {
+ .id = TI_EQEP_SIGNAL_QEPA,
+ .name = "QEPA"
+ },
+ [TI_EQEP_SIGNAL_QEPB] = {
+ .id = TI_EQEP_SIGNAL_QEPB,
+ .name = "QEPB"
+ },
+};
+
+static const enum counter_count_function ti_eqep_position_functions[] = {
+ [TI_EQEP_COUNT_FUNC_QUAD_COUNT] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
+ [TI_EQEP_COUNT_FUNC_DIR_COUNT] = COUNTER_COUNT_FUNCTION_PULSE_DIRECTION,
+ [TI_EQEP_COUNT_FUNC_UP_COUNT] = COUNTER_COUNT_FUNCTION_INCREASE,
+ [TI_EQEP_COUNT_FUNC_DOWN_COUNT] = COUNTER_COUNT_FUNCTION_DECREASE,
+};
+
+static const enum counter_synapse_action ti_eqep_position_synapse_actions[] = {
+ [TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
+ [TI_EQEP_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE,
+ [TI_EQEP_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
+};
+
+static struct counter_synapse ti_eqep_position_synapses[] = {
+ {
+ .actions_list = ti_eqep_position_synapse_actions,
+ .num_actions = ARRAY_SIZE(ti_eqep_position_synapse_actions),
+ .signal = &ti_eqep_signals[TI_EQEP_SIGNAL_QEPA],
+ },
+ {
+ .actions_list = ti_eqep_position_synapse_actions,
+ .num_actions = ARRAY_SIZE(ti_eqep_position_synapse_actions),
+ .signal = &ti_eqep_signals[TI_EQEP_SIGNAL_QEPB],
+ },
+};
+
+static struct counter_count ti_eqep_counts[] = {
+ {
+ .id = 0,
+ .name = "QPOSCNT",
+ .functions_list = ti_eqep_position_functions,
+ .num_functions = ARRAY_SIZE(ti_eqep_position_functions),
+ .synapses = ti_eqep_position_synapses,
+ .num_synapses = ARRAY_SIZE(ti_eqep_position_synapses),
+ .ext = ti_eqep_position_ext,
+ .num_ext = ARRAY_SIZE(ti_eqep_position_ext),
+ },
+};
+
+static const struct regmap_config ti_eqep_regmap32_config = {
+ .name = "32-bit",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x24,
+};
+
+static const struct regmap_config ti_eqep_regmap16_config = {
+ .name = "16-bit",
+ .reg_bits = 16,
+ .val_bits = 16,
+ .reg_stride = 2,
+ .max_register = 0x1e,
+};
+
+static int ti_eqep_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ti_eqep_cnt *priv;
+ void __iomem *base;
+ int err;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->regmap32 = devm_regmap_init_mmio(dev, base,
+ &ti_eqep_regmap32_config);
+ if (IS_ERR(priv->regmap32))
+ return PTR_ERR(priv->regmap32);
+
+ priv->regmap16 = devm_regmap_init_mmio(dev, base + 0x24,
+ &ti_eqep_regmap16_config);
+ if (IS_ERR(priv->regmap16))
+ return PTR_ERR(priv->regmap16);
+
+ priv->counter.name = dev_name(dev);
+ priv->counter.parent = dev;
+ priv->counter.ops = &ti_eqep_counter_ops;
+ priv->counter.counts = ti_eqep_counts;
+ priv->counter.num_counts = ARRAY_SIZE(ti_eqep_counts);
+ priv->counter.signals = ti_eqep_signals;
+ priv->counter.num_signals = ARRAY_SIZE(ti_eqep_signals);
+ priv->counter.priv = priv;
+
+ platform_set_drvdata(pdev, priv);
+
+ /*
+ * Need to make sure power is turned on. On AM33xx, this comes from the
+ * parent PWMSS bus driver. On AM17xx, this comes from the PSC power
+ * domain.
+ */
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+
+ err = counter_register(&priv->counter);
+ if (err < 0) {
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+ return err;
+ }
+
+ return 0;
+}
+
+static int ti_eqep_remove(struct platform_device *pdev)
+{
+ struct ti_eqep_cnt *priv = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+
+ counter_unregister(&priv->counter);
+ pm_runtime_put_sync(dev),
+ pm_runtime_disable(dev);
+
+ return 0;
+}
+
+static const struct of_device_id ti_eqep_of_match[] = {
+ { .compatible = "ti,am3352-eqep", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ti_eqep_of_match);
+
+static struct platform_driver ti_eqep_driver = {
+ .probe = ti_eqep_probe,
+ .remove = ti_eqep_remove,
+ .driver = {
+ .name = "ti-eqep-cnt",
+ .of_match_table = ti_eqep_of_match,
+ },
+};
+module_platform_driver(ti_eqep_driver);
+
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_DESCRIPTION("TI eQEP counter driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 13a6b4afb4b3..5308c59d7001 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -40,7 +40,8 @@ comment "Native drivers"
config SENSORS_AB8500
tristate "AB8500 thermal monitoring"
- depends on AB8500_GPADC && AB8500_BM
+ depends on AB8500_GPADC && AB8500_BM && (IIO = y)
+ default n
help
If you say yes here you get support for the thermal sensor part
of the AB8500 chip. The driver includes thermal management for
diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c
index 207f77f85a40..53f3379d799d 100644
--- a/drivers/hwmon/ab8500.c
+++ b/drivers/hwmon/ab8500.c
@@ -17,20 +17,24 @@
#include <linux/hwmon-sysfs.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/power/ab8500.h>
#include <linux/reboot.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/iio/consumer.h>
#include "abx500.h"
#define DEFAULT_POWER_OFF_DELAY (HZ * 10)
#define THERMAL_VCC 1800
#define PULL_UP_RESISTOR 47000
-/* Number of monitored sensors should not greater than NUM_SENSORS */
-#define NUM_MONITORED_SENSORS 4
+
+#define AB8500_SENSOR_AUX1 0
+#define AB8500_SENSOR_AUX2 1
+#define AB8500_SENSOR_BTEMP_BALL 2
+#define AB8500_SENSOR_BAT_CTRL 3
+#define NUM_MONITORED_SENSORS 4
struct ab8500_gpadc_cfg {
const struct abx500_res_to_temp *temp_tbl;
@@ -40,7 +44,8 @@ struct ab8500_gpadc_cfg {
};
struct ab8500_temp {
- struct ab8500_gpadc *gpadc;
+ struct iio_channel *aux1;
+ struct iio_channel *aux2;
struct ab8500_btemp *btemp;
struct delayed_work power_off_work;
struct ab8500_gpadc_cfg cfg;
@@ -82,15 +87,21 @@ static int ab8500_read_sensor(struct abx500_temp *data, u8 sensor, int *temp)
int voltage, ret;
struct ab8500_temp *ab8500_data = data->plat_data;
- if (sensor == BAT_CTRL) {
- *temp = ab8500_btemp_get_batctrl_temp(ab8500_data->btemp);
- } else if (sensor == BTEMP_BALL) {
+ if (sensor == AB8500_SENSOR_BTEMP_BALL) {
*temp = ab8500_btemp_get_temp(ab8500_data->btemp);
- } else {
- voltage = ab8500_gpadc_convert(ab8500_data->gpadc, sensor);
- if (voltage < 0)
- return voltage;
-
+ } else if (sensor == AB8500_SENSOR_BAT_CTRL) {
+ *temp = ab8500_btemp_get_batctrl_temp(ab8500_data->btemp);
+ } else if (sensor == AB8500_SENSOR_AUX1) {
+ ret = iio_read_channel_processed(ab8500_data->aux1, &voltage);
+ if (ret < 0)
+ return ret;
+ ret = ab8500_voltage_to_temp(&ab8500_data->cfg, voltage, temp);
+ if (ret < 0)
+ return ret;
+ } else if (sensor == AB8500_SENSOR_AUX2) {
+ ret = iio_read_channel_processed(ab8500_data->aux2, &voltage);
+ if (ret < 0)
+ return ret;
ret = ab8500_voltage_to_temp(&ab8500_data->cfg, voltage, temp);
if (ret < 0)
return ret;
@@ -164,10 +175,6 @@ int abx500_hwmon_init(struct abx500_temp *data)
if (!ab8500_data)
return -ENOMEM;
- ab8500_data->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- if (IS_ERR(ab8500_data->gpadc))
- return PTR_ERR(ab8500_data->gpadc);
-
ab8500_data->btemp = ab8500_btemp_get();
if (IS_ERR(ab8500_data->btemp))
return PTR_ERR(ab8500_data->btemp);
@@ -181,15 +188,25 @@ int abx500_hwmon_init(struct abx500_temp *data)
ab8500_data->cfg.tbl_sz = ab8500_temp_tbl_a_size;
data->plat_data = ab8500_data;
+ ab8500_data->aux1 = devm_iio_channel_get(&data->pdev->dev, "aux1");
+ if (IS_ERR(ab8500_data->aux1)) {
+ if (PTR_ERR(ab8500_data->aux1) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&data->pdev->dev, "failed to get AUX1 ADC channel\n");
+ return PTR_ERR(ab8500_data->aux1);
+ }
+ ab8500_data->aux2 = devm_iio_channel_get(&data->pdev->dev, "aux2");
+ if (IS_ERR(ab8500_data->aux2)) {
+ if (PTR_ERR(ab8500_data->aux2) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&data->pdev->dev, "failed to get AUX2 ADC channel\n");
+ return PTR_ERR(ab8500_data->aux2);
+ }
- /*
- * ADC_AUX1 and ADC_AUX2, connected to external NTC
- * BTEMP_BALL and BAT_CTRL, fixed usage
- */
- data->gpadc_addr[0] = ADC_AUX1;
- data->gpadc_addr[1] = ADC_AUX2;
- data->gpadc_addr[2] = BTEMP_BALL;
- data->gpadc_addr[3] = BAT_CTRL;
+ data->gpadc_addr[0] = AB8500_SENSOR_AUX1;
+ data->gpadc_addr[1] = AB8500_SENSOR_AUX2;
+ data->gpadc_addr[2] = AB8500_SENSOR_BTEMP_BALL;
+ data->gpadc_addr[3] = AB8500_SENSOR_BAT_CTRL;
data->monitored_sensors = NUM_MONITORED_SENSORS;
data->ops.read_sensor = ab8500_read_sensor;
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 2e37f8a6d8cf..7b837641f166 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -15,7 +15,6 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index f0af3a42f53c..9554890a3200 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -6,6 +6,16 @@
menu "Analog to digital converters"
+config AB8500_GPADC
+ bool "ST-Ericsson AB8500 GPADC driver"
+ depends on AB8500_CORE && REGULATOR_AB8500
+ default y
+ help
+ AB8500 Analog Baseband, mixed signal integrated circuit GPADC
+ (General Purpose Analog to Digital Converter) driver used to monitor
+ internal voltages, convert accessory and battery, AC (charger, mains)
+ and USB voltages integral to the U8500 platform.
+
config AD_SIGMA_DELTA
tristate
select IIO_BUFFER
@@ -432,6 +442,17 @@ config INGENIC_ADC
This driver can also be built as a module. If so, the module will be
called ingenic_adc.
+config INTEL_MRFLD_ADC
+ tristate "Intel Merrifield Basin Cove ADC driver"
+ depends on INTEL_SOC_PMIC_MRFLD
+ help
+ Say yes here to have support for Basin Cove power management IC (PMIC) ADC
+ device. Depending on platform configuration, this general purpose ADC can
+ be used for sampling sensors such as thermal resistors.
+
+ To compile this driver as a module, choose M here: the module will be
+ called intel_mrfld_adc.
+
config IMX7D_ADC
tristate "Freescale IMX7D ADC driver"
depends on ARCH_MXC || COMPILE_TEST
@@ -508,8 +529,8 @@ config MAX1027
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
- Say yes here to build support for Maxim SPI ADC models
- max1027, max1029 and max1031.
+ Say yes here to build support for Maxim SPI {10,12}-bit ADC models:
+ max1027, max1029, max1031, max1227, max1229 and max1231.
To compile this driver as a module, choose M here: the module will be
called max1027.
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ef9cc485fb67..5ecc481c2967 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -4,6 +4,7 @@
#
# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7124) += ad7124.o
obj-$(CONFIG_AD7266) += ad7266.o
@@ -42,6 +43,7 @@ obj-$(CONFIG_HX711) += hx711.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_INGENIC_ADC) += ingenic-adc.o
+obj-$(CONFIG_INTEL_MRFLD_ADC) += intel_mrfld_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
new file mode 100644
index 000000000000..fd5b18d7f0c2
--- /dev/null
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -0,0 +1,1218 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Arun R Murthy <arun.murthy@stericsson.com>
+ * Author: Daniel Willerud <daniel.willerud@stericsson.com>
+ * Author: Johan Palsson <johan.palsson@stericsson.com>
+ * Author: M'boumba Cedric Madianga
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * AB8500 General Purpose ADC driver. The AB8500 uses reference voltages:
+ * VinVADC, and VADC relative to GND to do its job. It monitors main and backup
+ * battery voltages, AC (mains) voltage, USB cable voltage, as well as voltages
+ * representing the temperature of the chip die and battery, accessory
+ * detection by resistance measurements using relative voltages and GSM burst
+ * information.
+ *
+ * Some of the voltages are measured on external pins on the IC, such as
+ * battery temperature or "ADC aux" 1 and 2. Other voltages are internal rails
+ * from other parts of the ASIC such as main charger voltage, main and battery
+ * backup voltage or USB VBUS voltage. For this reason drivers for other
+ * parts of the system are required to obtain handles to the ADC to do work
+ * for them and the IIO driver provides arbitration among these consumers.
+ */
+#include <linux/init.h>
+#include <linux/bits.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/regulator/consumer.h>
+#include <linux/random.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+
+/* GPADC register offsets and bit definitions */
+
+#define AB8500_GPADC_CTRL1_REG 0x00
+/* GPADC control register 1 bits */
+#define AB8500_GPADC_CTRL1_DISABLE 0x00
+#define AB8500_GPADC_CTRL1_ENABLE BIT(0)
+#define AB8500_GPADC_CTRL1_TRIG_ENA BIT(1)
+#define AB8500_GPADC_CTRL1_START_SW_CONV BIT(2)
+#define AB8500_GPADC_CTRL1_BTEMP_PULL_UP BIT(3)
+/* 0 = use rising edge, 1 = use falling edge */
+#define AB8500_GPADC_CTRL1_TRIG_EDGE BIT(4)
+/* 0 = use VTVOUT, 1 = use VRTC as pull-up supply for battery temp NTC */
+#define AB8500_GPADC_CTRL1_PUPSUPSEL BIT(5)
+#define AB8500_GPADC_CTRL1_BUF_ENA BIT(6)
+#define AB8500_GPADC_CTRL1_ICHAR_ENA BIT(7)
+
+#define AB8500_GPADC_CTRL2_REG 0x01
+#define AB8500_GPADC_CTRL3_REG 0x02
+/*
+ * GPADC control register 2 and 3 bits
+ * the bit layout is the same for SW and HW conversion set-up
+ */
+#define AB8500_GPADC_CTRL2_AVG_1 0x00
+#define AB8500_GPADC_CTRL2_AVG_4 BIT(5)
+#define AB8500_GPADC_CTRL2_AVG_8 BIT(6)
+#define AB8500_GPADC_CTRL2_AVG_16 (BIT(5) | BIT(6))
+
+enum ab8500_gpadc_channel {
+ AB8500_GPADC_CHAN_UNUSED = 0x00,
+ AB8500_GPADC_CHAN_BAT_CTRL = 0x01,
+ AB8500_GPADC_CHAN_BAT_TEMP = 0x02,
+ /* This is not used on AB8505 */
+ AB8500_GPADC_CHAN_MAIN_CHARGER = 0x03,
+ AB8500_GPADC_CHAN_ACC_DET_1 = 0x04,
+ AB8500_GPADC_CHAN_ACC_DET_2 = 0x05,
+ AB8500_GPADC_CHAN_ADC_AUX_1 = 0x06,
+ AB8500_GPADC_CHAN_ADC_AUX_2 = 0x07,
+ AB8500_GPADC_CHAN_VBAT_A = 0x08,
+ AB8500_GPADC_CHAN_VBUS = 0x09,
+ AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT = 0x0a,
+ AB8500_GPADC_CHAN_USB_CHARGER_CURRENT = 0x0b,
+ AB8500_GPADC_CHAN_BACKUP_BAT = 0x0c,
+ /* Only on AB8505 */
+ AB8505_GPADC_CHAN_DIE_TEMP = 0x0d,
+ AB8500_GPADC_CHAN_ID = 0x0e,
+ AB8500_GPADC_CHAN_INTERNAL_TEST_1 = 0x0f,
+ AB8500_GPADC_CHAN_INTERNAL_TEST_2 = 0x10,
+ AB8500_GPADC_CHAN_INTERNAL_TEST_3 = 0x11,
+ /* FIXME: Applicable to all ASIC variants? */
+ AB8500_GPADC_CHAN_XTAL_TEMP = 0x12,
+ AB8500_GPADC_CHAN_VBAT_TRUE_MEAS = 0x13,
+ /* FIXME: Doesn't seem to work with pure AB8500 */
+ AB8500_GPADC_CHAN_BAT_CTRL_AND_IBAT = 0x1c,
+ AB8500_GPADC_CHAN_VBAT_MEAS_AND_IBAT = 0x1d,
+ AB8500_GPADC_CHAN_VBAT_TRUE_MEAS_AND_IBAT = 0x1e,
+ AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT = 0x1f,
+ /*
+ * Virtual channel used only for ibat conversion to ampere.
+ * Battery current conversion (ibat) cannot be requested as a
+ * single conversion but it is always requested in combination
+ * with other input requests.
+ */
+ AB8500_GPADC_CHAN_IBAT_VIRTUAL = 0xFF,
+};
+
+#define AB8500_GPADC_AUTO_TIMER_REG 0x03
+
+#define AB8500_GPADC_STAT_REG 0x04
+#define AB8500_GPADC_STAT_BUSY BIT(0)
+
+#define AB8500_GPADC_MANDATAL_REG 0x05
+#define AB8500_GPADC_MANDATAH_REG 0x06
+#define AB8500_GPADC_AUTODATAL_REG 0x07
+#define AB8500_GPADC_AUTODATAH_REG 0x08
+#define AB8500_GPADC_MUX_CTRL_REG 0x09
+#define AB8540_GPADC_MANDATA2L_REG 0x09
+#define AB8540_GPADC_MANDATA2H_REG 0x0A
+#define AB8540_GPADC_APEAAX_REG 0x10
+#define AB8540_GPADC_APEAAT_REG 0x11
+#define AB8540_GPADC_APEAAM_REG 0x12
+#define AB8540_GPADC_APEAAH_REG 0x13
+#define AB8540_GPADC_APEAAL_REG 0x14
+
+/*
+ * OTP register offsets
+ * Bank : 0x15
+ */
+#define AB8500_GPADC_CAL_1 0x0F
+#define AB8500_GPADC_CAL_2 0x10
+#define AB8500_GPADC_CAL_3 0x11
+#define AB8500_GPADC_CAL_4 0x12
+#define AB8500_GPADC_CAL_5 0x13
+#define AB8500_GPADC_CAL_6 0x14
+#define AB8500_GPADC_CAL_7 0x15
+/* New calibration for 8540 */
+#define AB8540_GPADC_OTP4_REG_7 0x38
+#define AB8540_GPADC_OTP4_REG_6 0x39
+#define AB8540_GPADC_OTP4_REG_5 0x3A
+
+#define AB8540_GPADC_DIS_ZERO 0x00
+#define AB8540_GPADC_EN_VBIAS_XTAL_TEMP 0x02
+
+/* GPADC constants from AB8500 spec, UM0836 */
+#define AB8500_ADC_RESOLUTION 1024
+#define AB8500_ADC_CH_BTEMP_MIN 0
+#define AB8500_ADC_CH_BTEMP_MAX 1350
+#define AB8500_ADC_CH_DIETEMP_MIN 0
+#define AB8500_ADC_CH_DIETEMP_MAX 1350
+#define AB8500_ADC_CH_CHG_V_MIN 0
+#define AB8500_ADC_CH_CHG_V_MAX 20030
+#define AB8500_ADC_CH_ACCDET2_MIN 0
+#define AB8500_ADC_CH_ACCDET2_MAX 2500
+#define AB8500_ADC_CH_VBAT_MIN 2300
+#define AB8500_ADC_CH_VBAT_MAX 4800
+#define AB8500_ADC_CH_CHG_I_MIN 0
+#define AB8500_ADC_CH_CHG_I_MAX 1500
+#define AB8500_ADC_CH_BKBAT_MIN 0
+#define AB8500_ADC_CH_BKBAT_MAX 3200
+
+/* GPADC constants from AB8540 spec */
+#define AB8500_ADC_CH_IBAT_MIN (-6000) /* mA range measured by ADC for ibat */
+#define AB8500_ADC_CH_IBAT_MAX 6000
+#define AB8500_ADC_CH_IBAT_MIN_V (-60) /* mV range measured by ADC for ibat */
+#define AB8500_ADC_CH_IBAT_MAX_V 60
+#define AB8500_GPADC_IBAT_VDROP_L (-56) /* mV */
+#define AB8500_GPADC_IBAT_VDROP_H 56
+
+/* This is used to not lose precision when dividing to get gain and offset */
+#define AB8500_GPADC_CALIB_SCALE 1000
+/*
+ * Number of bits shift used to not lose precision
+ * when dividing to get ibat gain.
+ */
+#define AB8500_GPADC_CALIB_SHIFT_IBAT 20
+
+/* Time in ms before disabling regulator */
+#define AB8500_GPADC_AUTOSUSPEND_DELAY 1
+
+#define AB8500_GPADC_CONVERSION_TIME 500 /* ms */
+
+enum ab8500_cal_channels {
+ AB8500_CAL_VMAIN = 0,
+ AB8500_CAL_BTEMP,
+ AB8500_CAL_VBAT,
+ AB8500_CAL_IBAT,
+ AB8500_CAL_NR,
+};
+
+/**
+ * struct ab8500_adc_cal_data - Table for storing gain and offset for the
+ * calibrated ADC channels
+ * @gain: Gain of the ADC channel
+ * @offset: Offset of the ADC channel
+ * @otp_calib_hi: Calibration from OTP
+ * @otp_calib_lo: Calibration from OTP
+ */
+struct ab8500_adc_cal_data {
+ s64 gain;
+ s64 offset;
+ u16 otp_calib_hi;
+ u16 otp_calib_lo;
+};
+
+/**
+ * struct ab8500_gpadc_chan_info - per-channel GPADC info
+ * @name: name of the channel
+ * @id: the internal AB8500 ID number for the channel
+ * @hardware_control: indicate that we want to use hardware ADC control
+ * on this channel, the default is software ADC control. Hardware control
+ * is normally only used to test the battery voltage during GSM bursts
+ * and needs a hardware trigger on the GPADCTrig pin of the ASIC.
+ * @falling_edge: indicate that we want to trigger on falling edge
+ * rather than rising edge, rising edge is the default
+ * @avg_sample: how many samples to average: must be 1, 4, 8 or 16.
+ * @trig_timer: how long to wait for the trigger, in 32kHz periods:
+ * 0 .. 255 periods
+ */
+struct ab8500_gpadc_chan_info {
+ const char *name;
+ u8 id;
+ bool hardware_control;
+ bool falling_edge;
+ u8 avg_sample;
+ u8 trig_timer;
+};
+
+/**
+ * struct ab8500_gpadc - AB8500 GPADC device information
+ * @dev: pointer to the containing device
+ * @ab8500: pointer to the parent AB8500 device
+ * @chans: internal per-channel information container
+ * @nchans: number of channels
+ * @complete: pointer to the completion that indicates
+ * the completion of an gpadc conversion cycle
+ * @vddadc: pointer to the regulator supplying VDDADC
+ * @irq_sw: interrupt number that is used by gpadc for software ADC conversion
+ * @irq_hw: interrupt number that is used by gpadc for hardware ADC conversion
+ * @cal_data: array of ADC calibration data structs
+ */
+struct ab8500_gpadc {
+ struct device *dev;
+ struct ab8500 *ab8500;
+ struct ab8500_gpadc_chan_info *chans;
+ unsigned int nchans;
+ struct completion complete;
+ struct regulator *vddadc;
+ int irq_sw;
+ int irq_hw;
+ struct ab8500_adc_cal_data cal_data[AB8500_CAL_NR];
+};
+
+static struct ab8500_gpadc_chan_info *
+ab8500_gpadc_get_channel(struct ab8500_gpadc *gpadc, u8 chan)
+{
+ struct ab8500_gpadc_chan_info *ch;
+ int i;
+
+ for (i = 0; i < gpadc->nchans; i++) {
+ ch = &gpadc->chans[i];
+ if (ch->id == chan)
+ break;
+ }
+ if (i == gpadc->nchans)
+ return NULL;
+
+ return ch;
+}
+
+/**
+ * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage
+ * @gpadc: GPADC instance
+ * @ch: the sampled channel this raw value is coming from
+ * @ad_value: the raw value
+ */
+static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc,
+ enum ab8500_gpadc_channel ch,
+ int ad_value)
+{
+ int res;
+
+ switch (ch) {
+ case AB8500_GPADC_CHAN_MAIN_CHARGER:
+ /* No calibration data available: just interpolate */
+ if (!gpadc->cal_data[AB8500_CAL_VMAIN].gain) {
+ res = AB8500_ADC_CH_CHG_V_MIN + (AB8500_ADC_CH_CHG_V_MAX -
+ AB8500_ADC_CH_CHG_V_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+ }
+ /* Here we can use calibration */
+ res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_VMAIN].gain +
+ gpadc->cal_data[AB8500_CAL_VMAIN].offset) / AB8500_GPADC_CALIB_SCALE;
+ break;
+
+ case AB8500_GPADC_CHAN_BAT_CTRL:
+ case AB8500_GPADC_CHAN_BAT_TEMP:
+ case AB8500_GPADC_CHAN_ACC_DET_1:
+ case AB8500_GPADC_CHAN_ADC_AUX_1:
+ case AB8500_GPADC_CHAN_ADC_AUX_2:
+ case AB8500_GPADC_CHAN_XTAL_TEMP:
+ /* No calibration data available: just interpolate */
+ if (!gpadc->cal_data[AB8500_CAL_BTEMP].gain) {
+ res = AB8500_ADC_CH_BTEMP_MIN + (AB8500_ADC_CH_BTEMP_MAX -
+ AB8500_ADC_CH_BTEMP_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+ }
+ /* Here we can use calibration */
+ res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_BTEMP].gain +
+ gpadc->cal_data[AB8500_CAL_BTEMP].offset) / AB8500_GPADC_CALIB_SCALE;
+ break;
+
+ case AB8500_GPADC_CHAN_VBAT_A:
+ case AB8500_GPADC_CHAN_VBAT_TRUE_MEAS:
+ /* No calibration data available: just interpolate */
+ if (!gpadc->cal_data[AB8500_CAL_VBAT].gain) {
+ res = AB8500_ADC_CH_VBAT_MIN + (AB8500_ADC_CH_VBAT_MAX -
+ AB8500_ADC_CH_VBAT_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+ }
+ /* Here we can use calibration */
+ res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_VBAT].gain +
+ gpadc->cal_data[AB8500_CAL_VBAT].offset) / AB8500_GPADC_CALIB_SCALE;
+ break;
+
+ case AB8505_GPADC_CHAN_DIE_TEMP:
+ res = AB8500_ADC_CH_DIETEMP_MIN +
+ (AB8500_ADC_CH_DIETEMP_MAX - AB8500_ADC_CH_DIETEMP_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+
+ case AB8500_GPADC_CHAN_ACC_DET_2:
+ res = AB8500_ADC_CH_ACCDET2_MIN +
+ (AB8500_ADC_CH_ACCDET2_MAX - AB8500_ADC_CH_ACCDET2_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+
+ case AB8500_GPADC_CHAN_VBUS:
+ res = AB8500_ADC_CH_CHG_V_MIN +
+ (AB8500_ADC_CH_CHG_V_MAX - AB8500_ADC_CH_CHG_V_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+
+ case AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT:
+ case AB8500_GPADC_CHAN_USB_CHARGER_CURRENT:
+ res = AB8500_ADC_CH_CHG_I_MIN +
+ (AB8500_ADC_CH_CHG_I_MAX - AB8500_ADC_CH_CHG_I_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+
+ case AB8500_GPADC_CHAN_BACKUP_BAT:
+ res = AB8500_ADC_CH_BKBAT_MIN +
+ (AB8500_ADC_CH_BKBAT_MAX - AB8500_ADC_CH_BKBAT_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+
+ case AB8500_GPADC_CHAN_IBAT_VIRTUAL:
+ /* No calibration data available: just interpolate */
+ if (!gpadc->cal_data[AB8500_CAL_IBAT].gain) {
+ res = AB8500_ADC_CH_IBAT_MIN + (AB8500_ADC_CH_IBAT_MAX -
+ AB8500_ADC_CH_IBAT_MIN) * ad_value /
+ AB8500_ADC_RESOLUTION;
+ break;
+ }
+ /* Here we can use calibration */
+ res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_IBAT].gain +
+ gpadc->cal_data[AB8500_CAL_IBAT].offset)
+ >> AB8500_GPADC_CALIB_SHIFT_IBAT;
+ break;
+
+ default:
+ dev_err(gpadc->dev,
+ "unknown channel ID: %d, not possible to convert\n",
+ ch);
+ res = -EINVAL;
+ break;
+
+ }
+
+ return res;
+}
+
+static int ab8500_gpadc_read(struct ab8500_gpadc *gpadc,
+ const struct ab8500_gpadc_chan_info *ch,
+ int *ibat)
+{
+ int ret;
+ int looplimit = 0;
+ unsigned long completion_timeout;
+ u8 val;
+ u8 low_data, high_data, low_data2, high_data2;
+ u8 ctrl1;
+ u8 ctrl23;
+ unsigned int delay_min = 0;
+ unsigned int delay_max = 0;
+ u8 data_low_addr, data_high_addr;
+
+ if (!gpadc)
+ return -ENODEV;
+
+ /* check if conversion is supported */
+ if ((gpadc->irq_sw <= 0) && !ch->hardware_control)
+ return -ENOTSUPP;
+ if ((gpadc->irq_hw <= 0) && ch->hardware_control)
+ return -ENOTSUPP;
+
+ /* Enable vddadc by grabbing PM runtime */
+ pm_runtime_get_sync(gpadc->dev);
+
+ /* Check if ADC is not busy, lock and proceed */
+ do {
+ ret = abx500_get_register_interruptible(gpadc->dev,
+ AB8500_GPADC, AB8500_GPADC_STAT_REG, &val);
+ if (ret < 0)
+ goto out;
+ if (!(val & AB8500_GPADC_STAT_BUSY))
+ break;
+ msleep(20);
+ } while (++looplimit < 10);
+ if (looplimit >= 10 && (val & AB8500_GPADC_STAT_BUSY)) {
+ dev_err(gpadc->dev, "gpadc_conversion: GPADC busy");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Enable GPADC */
+ ctrl1 = AB8500_GPADC_CTRL1_ENABLE;
+
+ /* Select the channel source and set average samples */
+ switch (ch->avg_sample) {
+ case 1:
+ ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_1;
+ break;
+ case 4:
+ ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_4;
+ break;
+ case 8:
+ ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_8;
+ break;
+ default:
+ ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_16;
+ break;
+ }
+
+ if (ch->hardware_control) {
+ ret = abx500_set_register_interruptible(gpadc->dev,
+ AB8500_GPADC, AB8500_GPADC_CTRL3_REG, ctrl23);
+ ctrl1 |= AB8500_GPADC_CTRL1_TRIG_ENA;
+ if (ch->falling_edge)
+ ctrl1 |= AB8500_GPADC_CTRL1_TRIG_EDGE;
+ } else {
+ ret = abx500_set_register_interruptible(gpadc->dev,
+ AB8500_GPADC, AB8500_GPADC_CTRL2_REG, ctrl23);
+ }
+ if (ret < 0) {
+ dev_err(gpadc->dev,
+ "gpadc_conversion: set avg samples failed\n");
+ goto out;
+ }
+
+ /*
+ * Enable ADC, buffering, select rising edge and enable ADC path
+ * charging current sense if it needed, ABB 3.0 needs some special
+ * treatment too.
+ */
+ switch (ch->id) {
+ case AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT:
+ case AB8500_GPADC_CHAN_USB_CHARGER_CURRENT:
+ ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA |
+ AB8500_GPADC_CTRL1_ICHAR_ENA;
+ break;
+ case AB8500_GPADC_CHAN_BAT_TEMP:
+ if (!is_ab8500_2p0_or_earlier(gpadc->ab8500)) {
+ ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA |
+ AB8500_GPADC_CTRL1_BTEMP_PULL_UP;
+ /*
+ * Delay might be needed for ABB8500 cut 3.0, if not,
+ * remove when hardware will be available
+ */
+ delay_min = 1000; /* Delay in micro seconds */
+ delay_max = 10000; /* large range optimises sleepmode */
+ break;
+ }
+ /* Fall through */
+ default:
+ ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA;
+ break;
+ }
+
+ /* Write configuration to control register 1 */
+ ret = abx500_set_register_interruptible(gpadc->dev,
+ AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ctrl1);
+ if (ret < 0) {
+ dev_err(gpadc->dev,
+ "gpadc_conversion: set Control register failed\n");
+ goto out;
+ }
+
+ if (delay_min != 0)
+ usleep_range(delay_min, delay_max);
+
+ if (ch->hardware_control) {
+ /* Set trigger delay timer */
+ ret = abx500_set_register_interruptible(gpadc->dev,
+ AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG,
+ ch->trig_timer);
+ if (ret < 0) {
+ dev_err(gpadc->dev,
+ "gpadc_conversion: trig timer failed\n");
+ goto out;
+ }
+ completion_timeout = 2 * HZ;
+ data_low_addr = AB8500_GPADC_AUTODATAL_REG;
+ data_high_addr = AB8500_GPADC_AUTODATAH_REG;
+ } else {
+ /* Start SW conversion */
+ ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
+ AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
+ AB8500_GPADC_CTRL1_START_SW_CONV,
+ AB8500_GPADC_CTRL1_START_SW_CONV);
+ if (ret < 0) {
+ dev_err(gpadc->dev,
+ "gpadc_conversion: start s/w conv failed\n");
+ goto out;
+ }
+ completion_timeout = msecs_to_jiffies(AB8500_GPADC_CONVERSION_TIME);
+ data_low_addr = AB8500_GPADC_MANDATAL_REG;
+ data_high_addr = AB8500_GPADC_MANDATAH_REG;
+ }
+
+ /* Wait for completion of conversion */
+ if (!wait_for_completion_timeout(&gpadc->complete,
+ completion_timeout)) {
+ dev_err(gpadc->dev,
+ "timeout didn't receive GPADC conv interrupt\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Read the converted RAW data */
+ ret = abx500_get_register_interruptible(gpadc->dev,
+ AB8500_GPADC, data_low_addr, &low_data);
+ if (ret < 0) {
+ dev_err(gpadc->dev,
+ "gpadc_conversion: read low data failed\n");
+ goto out;
+ }
+
+ ret = abx500_get_register_interruptible(gpadc->dev,
+ AB8500_GPADC, data_high_addr, &high_data);
+ if (ret < 0) {
+ dev_err(gpadc->dev,
+ "gpadc_conversion: read high data failed\n");
+ goto out;
+ }
+
+ /* Check if double conversion is required */
+ if ((ch->id == AB8500_GPADC_CHAN_BAT_CTRL_AND_IBAT) ||
+ (ch->id == AB8500_GPADC_CHAN_VBAT_MEAS_AND_IBAT) ||
+ (ch->id == AB8500_GPADC_CHAN_VBAT_TRUE_MEAS_AND_IBAT) ||
+ (ch->id == AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT)) {
+
+ if (ch->hardware_control) {
+ /* not supported */
+ ret = -ENOTSUPP;
+ dev_err(gpadc->dev,
+ "gpadc_conversion: only SW double conversion supported\n");
+ goto out;
+ } else {
+ /* Read the converted RAW data 2 */
+ ret = abx500_get_register_interruptible(gpadc->dev,
+ AB8500_GPADC, AB8540_GPADC_MANDATA2L_REG,
+ &low_data2);
+ if (ret < 0) {
+ dev_err(gpadc->dev,
+ "gpadc_conversion: read sw low data 2 failed\n");
+ goto out;
+ }
+
+ ret = abx500_get_register_interruptible(gpadc->dev,
+ AB8500_GPADC, AB8540_GPADC_MANDATA2H_REG,
+ &high_data2);
+ if (ret < 0) {
+ dev_err(gpadc->dev,
+ "gpadc_conversion: read sw high data 2 failed\n");
+ goto out;
+ }
+ if (ibat != NULL) {
+ *ibat = (high_data2 << 8) | low_data2;
+ } else {
+ dev_warn(gpadc->dev,
+ "gpadc_conversion: ibat not stored\n");
+ }
+
+ }
+ }
+
+ /* Disable GPADC */
+ ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
+ AB8500_GPADC_CTRL1_REG, AB8500_GPADC_CTRL1_DISABLE);
+ if (ret < 0) {
+ dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n");
+ goto out;
+ }
+
+ /* This eventually drops the regulator */
+ pm_runtime_mark_last_busy(gpadc->dev);
+ pm_runtime_put_autosuspend(gpadc->dev);
+
+ return (high_data << 8) | low_data;
+
+out:
+ /*
+ * It has shown to be needed to turn off the GPADC if an error occurs,
+ * otherwise we might have problem when waiting for the busy bit in the
+ * GPADC status register to go low. In V1.1 there wait_for_completion
+ * seems to timeout when waiting for an interrupt.. Not seen in V2.0
+ */
+ (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
+ AB8500_GPADC_CTRL1_REG, AB8500_GPADC_CTRL1_DISABLE);
+ pm_runtime_put(gpadc->dev);
+ dev_err(gpadc->dev,
+ "gpadc_conversion: Failed to AD convert channel %d\n", ch->id);
+
+ return ret;
+}
+
+/**
+ * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion
+ * @irq: irq number
+ * @data: pointer to the data passed during request irq
+ *
+ * This is a interrupt service routine for gpadc conversion completion.
+ * Notifies the gpadc completion is completed and the converted raw value
+ * can be read from the registers.
+ * Returns IRQ status(IRQ_HANDLED)
+ */
+static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *data)
+{
+ struct ab8500_gpadc *gpadc = data;
+
+ complete(&gpadc->complete);
+
+ return IRQ_HANDLED;
+}
+
+static int otp_cal_regs[] = {
+ AB8500_GPADC_CAL_1,
+ AB8500_GPADC_CAL_2,
+ AB8500_GPADC_CAL_3,
+ AB8500_GPADC_CAL_4,
+ AB8500_GPADC_CAL_5,
+ AB8500_GPADC_CAL_6,
+ AB8500_GPADC_CAL_7,
+};
+
+static int otp4_cal_regs[] = {
+ AB8540_GPADC_OTP4_REG_7,
+ AB8540_GPADC_OTP4_REG_6,
+ AB8540_GPADC_OTP4_REG_5,
+};
+
+static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
+{
+ int i;
+ int ret[ARRAY_SIZE(otp_cal_regs)];
+ u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)];
+ int ret_otp4[ARRAY_SIZE(otp4_cal_regs)];
+ u8 gpadc_otp4[ARRAY_SIZE(otp4_cal_regs)];
+ int vmain_high, vmain_low;
+ int btemp_high, btemp_low;
+ int vbat_high, vbat_low;
+ int ibat_high, ibat_low;
+ s64 V_gain, V_offset, V2A_gain, V2A_offset;
+
+ /* First we read all OTP registers and store the error code */
+ for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) {
+ ret[i] = abx500_get_register_interruptible(gpadc->dev,
+ AB8500_OTP_EMUL, otp_cal_regs[i], &gpadc_cal[i]);
+ if (ret[i] < 0) {
+ /* Continue anyway: maybe the other registers are OK */
+ dev_err(gpadc->dev, "%s: read otp reg 0x%02x failed\n",
+ __func__, otp_cal_regs[i]);
+ } else {
+ /* Put this in the entropy pool as device-unique */
+ add_device_randomness(&ret[i], sizeof(ret[i]));
+ }
+ }
+
+ /*
+ * The ADC calibration data is stored in OTP registers.
+ * The layout of the calibration data is outlined below and a more
+ * detailed description can be found in UM0836
+ *
+ * vm_h/l = vmain_high/low
+ * bt_h/l = btemp_high/low
+ * vb_h/l = vbat_high/low
+ *
+ * Data bits 8500/9540:
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | | vm_h9 | vm_h8
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ *
+ * Data bits 8540:
+ * OTP2
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * |
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | vm_h9 | vm_h8 | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ *
+ * Data bits 8540:
+ * OTP4
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | | ib_h9 | ib_h8 | ib_h7
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | ib_h6 | ib_h5 | ib_h4 | ib_h3 | ib_h2 | ib_h1 | ib_h0 | ib_l5
+ * |.......|.......|.......|.......|.......|.......|.......|.......
+ * | ib_l4 | ib_l3 | ib_l2 | ib_l1 | ib_l0 |
+ *
+ *
+ * Ideal output ADC codes corresponding to injected input voltages
+ * during manufacturing is:
+ *
+ * vmain_high: Vin = 19500mV / ADC ideal code = 997
+ * vmain_low: Vin = 315mV / ADC ideal code = 16
+ * btemp_high: Vin = 1300mV / ADC ideal code = 985
+ * btemp_low: Vin = 21mV / ADC ideal code = 16
+ * vbat_high: Vin = 4700mV / ADC ideal code = 982
+ * vbat_low: Vin = 2380mV / ADC ideal code = 33
+ */
+
+ if (is_ab8540(gpadc->ab8500)) {
+ /* Calculate gain and offset for VMAIN if all reads succeeded*/
+ if (!(ret[1] < 0 || ret[2] < 0)) {
+ vmain_high = (((gpadc_cal[1] & 0xFF) << 2) |
+ ((gpadc_cal[2] & 0xC0) >> 6));
+ vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
+
+ gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_hi =
+ (u16)vmain_high;
+ gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_lo =
+ (u16)vmain_low;
+
+ gpadc->cal_data[AB8500_CAL_VMAIN].gain = AB8500_GPADC_CALIB_SCALE *
+ (19500 - 315) / (vmain_high - vmain_low);
+ gpadc->cal_data[AB8500_CAL_VMAIN].offset = AB8500_GPADC_CALIB_SCALE *
+ 19500 - (AB8500_GPADC_CALIB_SCALE * (19500 - 315) /
+ (vmain_high - vmain_low)) * vmain_high;
+ } else {
+ gpadc->cal_data[AB8500_CAL_VMAIN].gain = 0;
+ }
+
+ /* Read IBAT calibration Data */
+ for (i = 0; i < ARRAY_SIZE(otp4_cal_regs); i++) {
+ ret_otp4[i] = abx500_get_register_interruptible(
+ gpadc->dev, AB8500_OTP_EMUL,
+ otp4_cal_regs[i], &gpadc_otp4[i]);
+ if (ret_otp4[i] < 0)
+ dev_err(gpadc->dev,
+ "%s: read otp4 reg 0x%02x failed\n",
+ __func__, otp4_cal_regs[i]);
+ }
+
+ /* Calculate gain and offset for IBAT if all reads succeeded */
+ if (!(ret_otp4[0] < 0 || ret_otp4[1] < 0 || ret_otp4[2] < 0)) {
+ ibat_high = (((gpadc_otp4[0] & 0x07) << 7) |
+ ((gpadc_otp4[1] & 0xFE) >> 1));
+ ibat_low = (((gpadc_otp4[1] & 0x01) << 5) |
+ ((gpadc_otp4[2] & 0xF8) >> 3));
+
+ gpadc->cal_data[AB8500_CAL_IBAT].otp_calib_hi =
+ (u16)ibat_high;
+ gpadc->cal_data[AB8500_CAL_IBAT].otp_calib_lo =
+ (u16)ibat_low;
+
+ V_gain = ((AB8500_GPADC_IBAT_VDROP_H - AB8500_GPADC_IBAT_VDROP_L)
+ << AB8500_GPADC_CALIB_SHIFT_IBAT) / (ibat_high - ibat_low);
+
+ V_offset = (AB8500_GPADC_IBAT_VDROP_H << AB8500_GPADC_CALIB_SHIFT_IBAT) -
+ (((AB8500_GPADC_IBAT_VDROP_H - AB8500_GPADC_IBAT_VDROP_L) <<
+ AB8500_GPADC_CALIB_SHIFT_IBAT) / (ibat_high - ibat_low))
+ * ibat_high;
+ /*
+ * Result obtained is in mV (at a scale factor),
+ * we need to calculate gain and offset to get mA
+ */
+ V2A_gain = (AB8500_ADC_CH_IBAT_MAX - AB8500_ADC_CH_IBAT_MIN)/
+ (AB8500_ADC_CH_IBAT_MAX_V - AB8500_ADC_CH_IBAT_MIN_V);
+ V2A_offset = ((AB8500_ADC_CH_IBAT_MAX_V * AB8500_ADC_CH_IBAT_MIN -
+ AB8500_ADC_CH_IBAT_MAX * AB8500_ADC_CH_IBAT_MIN_V)
+ << AB8500_GPADC_CALIB_SHIFT_IBAT)
+ / (AB8500_ADC_CH_IBAT_MAX_V - AB8500_ADC_CH_IBAT_MIN_V);
+
+ gpadc->cal_data[AB8500_CAL_IBAT].gain =
+ V_gain * V2A_gain;
+ gpadc->cal_data[AB8500_CAL_IBAT].offset =
+ V_offset * V2A_gain + V2A_offset;
+ } else {
+ gpadc->cal_data[AB8500_CAL_IBAT].gain = 0;
+ }
+ } else {
+ /* Calculate gain and offset for VMAIN if all reads succeeded */
+ if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) {
+ vmain_high = (((gpadc_cal[0] & 0x03) << 8) |
+ ((gpadc_cal[1] & 0x3F) << 2) |
+ ((gpadc_cal[2] & 0xC0) >> 6));
+ vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
+
+ gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_hi =
+ (u16)vmain_high;
+ gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_lo =
+ (u16)vmain_low;
+
+ gpadc->cal_data[AB8500_CAL_VMAIN].gain = AB8500_GPADC_CALIB_SCALE *
+ (19500 - 315) / (vmain_high - vmain_low);
+
+ gpadc->cal_data[AB8500_CAL_VMAIN].offset = AB8500_GPADC_CALIB_SCALE *
+ 19500 - (AB8500_GPADC_CALIB_SCALE * (19500 - 315) /
+ (vmain_high - vmain_low)) * vmain_high;
+ } else {
+ gpadc->cal_data[AB8500_CAL_VMAIN].gain = 0;
+ }
+ }
+
+ /* Calculate gain and offset for BTEMP if all reads succeeded */
+ if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) {
+ btemp_high = (((gpadc_cal[2] & 0x01) << 9) |
+ (gpadc_cal[3] << 1) | ((gpadc_cal[4] & 0x80) >> 7));
+ btemp_low = ((gpadc_cal[4] & 0x7C) >> 2);
+
+ gpadc->cal_data[AB8500_CAL_BTEMP].otp_calib_hi = (u16)btemp_high;
+ gpadc->cal_data[AB8500_CAL_BTEMP].otp_calib_lo = (u16)btemp_low;
+
+ gpadc->cal_data[AB8500_CAL_BTEMP].gain =
+ AB8500_GPADC_CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low);
+ gpadc->cal_data[AB8500_CAL_BTEMP].offset = AB8500_GPADC_CALIB_SCALE * 1300 -
+ (AB8500_GPADC_CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low))
+ * btemp_high;
+ } else {
+ gpadc->cal_data[AB8500_CAL_BTEMP].gain = 0;
+ }
+
+ /* Calculate gain and offset for VBAT if all reads succeeded */
+ if (!(ret[4] < 0 || ret[5] < 0 || ret[6] < 0)) {
+ vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]);
+ vbat_low = ((gpadc_cal[6] & 0xFC) >> 2);
+
+ gpadc->cal_data[AB8500_CAL_VBAT].otp_calib_hi = (u16)vbat_high;
+ gpadc->cal_data[AB8500_CAL_VBAT].otp_calib_lo = (u16)vbat_low;
+
+ gpadc->cal_data[AB8500_CAL_VBAT].gain = AB8500_GPADC_CALIB_SCALE *
+ (4700 - 2380) / (vbat_high - vbat_low);
+ gpadc->cal_data[AB8500_CAL_VBAT].offset = AB8500_GPADC_CALIB_SCALE * 4700 -
+ (AB8500_GPADC_CALIB_SCALE * (4700 - 2380) /
+ (vbat_high - vbat_low)) * vbat_high;
+ } else {
+ gpadc->cal_data[AB8500_CAL_VBAT].gain = 0;
+ }
+}
+
+static int ab8500_gpadc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
+ const struct ab8500_gpadc_chan_info *ch;
+ int raw_val;
+ int processed;
+
+ ch = ab8500_gpadc_get_channel(gpadc, chan->address);
+ if (!ch) {
+ dev_err(gpadc->dev, "no such channel %lu\n",
+ chan->address);
+ return -EINVAL;
+ }
+
+ raw_val = ab8500_gpadc_read(gpadc, ch, NULL);
+ if (raw_val < 0)
+ return raw_val;
+
+ if (mask == IIO_CHAN_INFO_RAW) {
+ *val = raw_val;
+ return IIO_VAL_INT;
+ }
+
+ if (mask == IIO_CHAN_INFO_PROCESSED) {
+ processed = ab8500_gpadc_ad_to_voltage(gpadc, ch->id, raw_val);
+ if (processed < 0)
+ return processed;
+
+ /* Return millivolt or milliamps or millicentigrades */
+ *val = processed * 1000;
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int ab8500_gpadc_of_xlate(struct iio_dev *indio_dev,
+ const struct of_phandle_args *iiospec)
+{
+ int i;
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ if (indio_dev->channels[i].channel == iiospec->args[0])
+ return i;
+
+ return -EINVAL;
+}
+
+static const struct iio_info ab8500_gpadc_info = {
+ .of_xlate = ab8500_gpadc_of_xlate,
+ .read_raw = ab8500_gpadc_read_raw,
+};
+
+#ifdef CONFIG_PM
+static int ab8500_gpadc_runtime_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
+
+ regulator_disable(gpadc->vddadc);
+
+ return 0;
+}
+
+static int ab8500_gpadc_runtime_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
+ int ret;
+
+ ret = regulator_enable(gpadc->vddadc);
+ if (ret)
+ dev_err(dev, "Failed to enable vddadc: %d\n", ret);
+
+ return ret;
+}
+#endif
+
+/**
+ * ab8500_gpadc_parse_channel() - process devicetree channel configuration
+ * @dev: pointer to containing device
+ * @np: device tree node for the channel to configure
+ * @ch: channel info to fill in
+ * @iio_chan: IIO channel specification to fill in
+ *
+ * The devicetree will set up the channel for use with the specific device,
+ * and define usage for things like AUX GPADC inputs more precisely.
+ */
+static int ab8500_gpadc_parse_channel(struct device *dev,
+ struct device_node *np,
+ struct ab8500_gpadc_chan_info *ch,
+ struct iio_chan_spec *iio_chan)
+{
+ const char *name = np->name;
+ u32 chan;
+ int ret;
+
+ ret = of_property_read_u32(np, "reg", &chan);
+ if (ret) {
+ dev_err(dev, "invalid channel number %s\n", name);
+ return ret;
+ }
+ if (chan > AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT) {
+ dev_err(dev, "%s channel number out of range %d\n", name, chan);
+ return -EINVAL;
+ }
+
+ iio_chan->channel = chan;
+ iio_chan->datasheet_name = name;
+ iio_chan->indexed = 1;
+ iio_chan->address = chan;
+ iio_chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_PROCESSED);
+ /* Most are voltages (also temperatures), some are currents */
+ if ((chan == AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT) ||
+ (chan == AB8500_GPADC_CHAN_USB_CHARGER_CURRENT))
+ iio_chan->type = IIO_CURRENT;
+ else
+ iio_chan->type = IIO_VOLTAGE;
+
+ ch->id = chan;
+
+ /* Sensible defaults */
+ ch->avg_sample = 16;
+ ch->hardware_control = false;
+ ch->falling_edge = false;
+ ch->trig_timer = 0;
+
+ return 0;
+}
+
+/**
+ * ab8500_gpadc_parse_channels() - Parse the GPADC channels from DT
+ * @gpadc: the GPADC to configure the channels for
+ * @np: device tree node containing the channel configurations
+ * @chans: the IIO channels we parsed
+ * @nchans: the number of IIO channels we parsed
+ */
+static int ab8500_gpadc_parse_channels(struct ab8500_gpadc *gpadc,
+ struct device_node *np,
+ struct iio_chan_spec **chans_parsed,
+ unsigned int *nchans_parsed)
+{
+ struct device_node *child;
+ struct ab8500_gpadc_chan_info *ch;
+ struct iio_chan_spec *iio_chans;
+ unsigned int nchans;
+ int i;
+
+ nchans = of_get_available_child_count(np);
+ if (!nchans) {
+ dev_err(gpadc->dev, "no channel children\n");
+ return -ENODEV;
+ }
+ dev_info(gpadc->dev, "found %d ADC channels\n", nchans);
+
+ iio_chans = devm_kcalloc(gpadc->dev, nchans,
+ sizeof(*iio_chans), GFP_KERNEL);
+ if (!iio_chans)
+ return -ENOMEM;
+
+ gpadc->chans = devm_kcalloc(gpadc->dev, nchans,
+ sizeof(*gpadc->chans), GFP_KERNEL);
+ if (!gpadc->chans)
+ return -ENOMEM;
+
+ i = 0;
+ for_each_available_child_of_node(np, child) {
+ struct iio_chan_spec *iio_chan;
+ int ret;
+
+ ch = &gpadc->chans[i];
+ iio_chan = &iio_chans[i];
+
+ ret = ab8500_gpadc_parse_channel(gpadc->dev, child, ch,
+ iio_chan);
+ if (ret) {
+ of_node_put(child);
+ return ret;
+ }
+ i++;
+ }
+ gpadc->nchans = nchans;
+ *chans_parsed = iio_chans;
+ *nchans_parsed = nchans;
+
+ return 0;
+}
+
+static int ab8500_gpadc_probe(struct platform_device *pdev)
+{
+ struct ab8500_gpadc *gpadc;
+ struct iio_dev *indio_dev;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+ struct iio_chan_spec *iio_chans;
+ unsigned int n_iio_chans;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, indio_dev);
+ gpadc = iio_priv(indio_dev);
+
+ gpadc->dev = dev;
+ gpadc->ab8500 = dev_get_drvdata(dev->parent);
+
+ ret = ab8500_gpadc_parse_channels(gpadc, np, &iio_chans, &n_iio_chans);
+ if (ret)
+ return ret;
+
+ gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END");
+ if (gpadc->irq_sw < 0) {
+ dev_err(dev, "failed to get platform sw_conv_end irq\n");
+ return gpadc->irq_sw;
+ }
+
+ gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END");
+ if (gpadc->irq_hw < 0) {
+ dev_err(dev, "failed to get platform hw_conv_end irq\n");
+ return gpadc->irq_hw;
+ }
+
+ /* Initialize completion used to notify completion of conversion */
+ init_completion(&gpadc->complete);
+
+ /* Request interrupts */
+ ret = devm_request_threaded_irq(dev, gpadc->irq_sw, NULL,
+ ab8500_bm_gpadcconvend_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ "ab8500-gpadc-sw", gpadc);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to request sw conversion irq %d\n",
+ gpadc->irq_sw);
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(dev, gpadc->irq_hw, NULL,
+ ab8500_bm_gpadcconvend_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ "ab8500-gpadc-hw", gpadc);
+ if (ret < 0) {
+ dev_err(dev,
+ "Failed to request hw conversion irq: %d\n",
+ gpadc->irq_hw);
+ return ret;
+ }
+
+ /* The VTVout LDO used to power the AB8500 GPADC */
+ gpadc->vddadc = devm_regulator_get(dev, "vddadc");
+ if (IS_ERR(gpadc->vddadc)) {
+ ret = PTR_ERR(gpadc->vddadc);
+ dev_err(dev, "failed to get vddadc\n");
+ return ret;
+ }
+
+ ret = regulator_enable(gpadc->vddadc);
+ if (ret) {
+ dev_err(dev, "failed to enable vddadc: %d\n", ret);
+ return ret;
+ }
+
+ /* Enable runtime PM */
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(dev, AB8500_GPADC_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(dev);
+
+ ab8500_gpadc_read_calibration_data(gpadc);
+
+ pm_runtime_put(dev);
+
+ indio_dev->dev.parent = dev;
+ indio_dev->dev.of_node = np;
+ indio_dev->name = "ab8500-gpadc";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &ab8500_gpadc_info;
+ indio_dev->channels = iio_chans;
+ indio_dev->num_channels = n_iio_chans;
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ goto out_dis_pm;
+
+ return 0;
+
+out_dis_pm:
+ pm_runtime_get_sync(dev);
+ pm_runtime_put_noidle(dev);
+ pm_runtime_disable(dev);
+ regulator_disable(gpadc->vddadc);
+
+ return ret;
+}
+
+static int ab8500_gpadc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
+
+ pm_runtime_get_sync(gpadc->dev);
+ pm_runtime_put_noidle(gpadc->dev);
+ pm_runtime_disable(gpadc->dev);
+ regulator_disable(gpadc->vddadc);
+
+ return 0;
+}
+
+static const struct dev_pm_ops ab8500_gpadc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend,
+ ab8500_gpadc_runtime_resume,
+ NULL)
+};
+
+static struct platform_driver ab8500_gpadc_driver = {
+ .probe = ab8500_gpadc_probe,
+ .remove = ab8500_gpadc_remove,
+ .driver = {
+ .name = "ab8500-gpadc",
+ .pm = &ab8500_gpadc_pm_ops,
+ },
+};
+builtin_platform_driver(ab8500_gpadc_driver);
diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c
index ac0ffff6c5ae..5c2b3446fa4a 100644
--- a/drivers/iio/adc/ad7949.c
+++ b/drivers/iio/adc/ad7949.c
@@ -54,38 +54,20 @@ struct ad7949_adc_chip {
u8 resolution;
u16 cfg;
unsigned int current_channel;
- u32 buffer ____cacheline_aligned;
+ u16 buffer ____cacheline_aligned;
};
-static bool ad7949_spi_cfg_is_read_back(struct ad7949_adc_chip *ad7949_adc)
-{
- if (!(ad7949_adc->cfg & AD7949_CFG_READ_BACK))
- return true;
-
- return false;
-}
-
-static int ad7949_spi_bits_per_word(struct ad7949_adc_chip *ad7949_adc)
-{
- int ret = ad7949_adc->resolution;
-
- if (ad7949_spi_cfg_is_read_back(ad7949_adc))
- ret += AD7949_CFG_REG_SIZE_BITS;
-
- return ret;
-}
-
static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val,
u16 mask)
{
int ret;
- int bits_per_word = ad7949_spi_bits_per_word(ad7949_adc);
+ int bits_per_word = ad7949_adc->resolution;
int shift = bits_per_word - AD7949_CFG_REG_SIZE_BITS;
struct spi_message msg;
struct spi_transfer tx[] = {
{
.tx_buf = &ad7949_adc->buffer,
- .len = 4,
+ .len = 2,
.bits_per_word = bits_per_word,
},
};
@@ -107,13 +89,13 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
unsigned int channel)
{
int ret;
- int bits_per_word = ad7949_spi_bits_per_word(ad7949_adc);
+ int bits_per_word = ad7949_adc->resolution;
int mask = GENMASK(ad7949_adc->resolution, 0);
struct spi_message msg;
struct spi_transfer tx[] = {
{
.rx_buf = &ad7949_adc->buffer,
- .len = 4,
+ .len = 2,
.bits_per_word = bits_per_word,
},
};
@@ -138,10 +120,7 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
ad7949_adc->current_channel = channel;
- if (ad7949_spi_cfg_is_read_back(ad7949_adc))
- *val = (ad7949_adc->buffer >> AD7949_CFG_REG_SIZE_BITS) & mask;
- else
- *val = ad7949_adc->buffer & mask;
+ *val = ad7949_adc->buffer & mask;
return 0;
}
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index 2640b75fb774..8ba90486c787 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -205,7 +205,7 @@ int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
}
EXPORT_SYMBOL_GPL(ad_sd_reset);
-static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
+int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
unsigned int mode, unsigned int channel)
{
int ret;
@@ -242,6 +242,7 @@ out:
return ret;
}
+EXPORT_SYMBOL_GPL(ad_sd_calibrate);
/**
* ad_sd_calibrate_all() - Performs channel calibration
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index a2837a0e7cba..e1850f3d5cf3 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1483,7 +1483,7 @@ dma_free_area:
st->dma_st.rx_buf, st->dma_st.rx_dma_buf);
dma_chan_disable:
dma_release_channel(st->dma_st.dma_chan);
- st->dma_st.dma_chan = 0;
+ st->dma_st.dma_chan = NULL;
dma_exit:
dev_info(&pdev->dev, "continuing without DMA support\n");
}
@@ -1506,7 +1506,7 @@ static void at91_adc_dma_disable(struct platform_device *pdev)
dma_free_coherent(st->dma_st.dma_chan->device->dev, pages * PAGE_SIZE,
st->dma_st.rx_buf, st->dma_st.rx_dma_buf);
dma_release_channel(st->dma_st.dma_chan);
- st->dma_st.dma_chan = 0;
+ st->dma_st.dma_chan = NULL;
dev_info(&pdev->dev, "continuing without DMA support\n");
}
diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c
index 2d616cafe75f..5086a337f4c9 100644
--- a/drivers/iio/adc/cpcap-adc.c
+++ b/drivers/iio/adc/cpcap-adc.c
@@ -1008,7 +1008,7 @@ static int cpcap_adc_probe(struct platform_device *pdev)
error = devm_request_threaded_irq(&pdev->dev, ddata->irq, NULL,
cpcap_adc_irq_thread,
- IRQF_TRIGGER_NONE,
+ IRQF_TRIGGER_NONE | IRQF_ONESHOT,
"cpcap-adc", indio_dev);
if (error) {
dev_err(&pdev->dev, "could not get irq: %i\n",
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 42a3ced11fbd..2df7d057b249 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -651,7 +651,7 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
input_sync(info->input);
usleep_range(1000, 1100);
- };
+ }
writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
@@ -769,7 +769,6 @@ static int exynos_adc_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct s3c2410_ts_mach_info *pdata = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = NULL;
- struct resource *mem;
bool has_ts = false;
int ret = -ENODEV;
int irq;
@@ -788,8 +787,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
return -EINVAL;
}
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- info->regs = devm_ioremap_resource(&pdev->dev, mem);
+ info->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(info->regs))
return PTR_ERR(info->regs);
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 62e6c8badd22..c8686558429b 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -23,6 +23,7 @@
/* gain to pulse and scale conversion */
#define HX711_GAIN_MAX 3
+#define HX711_RESET_GAIN 128
struct hx711_gain_to_scale {
int gain;
@@ -185,8 +186,7 @@ static int hx711_wait_for_ready(struct hx711_data *hx711_data)
static int hx711_reset(struct hx711_data *hx711_data)
{
- int ret;
- int val = gpiod_get_value(hx711_data->gpiod_dout);
+ int val = hx711_wait_for_ready(hx711_data);
if (val) {
/*
@@ -202,22 +202,10 @@ static int hx711_reset(struct hx711_data *hx711_data)
msleep(10);
gpiod_set_value(hx711_data->gpiod_pd_sck, 0);
- ret = hx711_wait_for_ready(hx711_data);
- if (ret)
- return ret;
- /*
- * after a reset the gain is 128 so we do a dummy read
- * to set the gain for the next read
- */
- ret = hx711_read(hx711_data);
- if (ret < 0)
- return ret;
-
- /*
- * after a dummy read we need to wait vor readiness
- * for not mixing gain pulses with the clock
- */
val = hx711_wait_for_ready(hx711_data);
+
+ /* after a reset the gain is 128 */
+ hx711_data->gain_set = HX711_RESET_GAIN;
}
return val;
diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
index e234970b7150..7a53c2f8d438 100644
--- a/drivers/iio/adc/ingenic-adc.c
+++ b/drivers/iio/adc/ingenic-adc.c
@@ -25,9 +25,13 @@
#define JZ_ADC_REG_ADSDAT 0x20
#define JZ_ADC_REG_ADCLK 0x28
+#define JZ_ADC_REG_ENABLE_PD BIT(7)
+#define JZ_ADC_REG_CFG_AUX_MD (BIT(0) | BIT(1))
#define JZ_ADC_REG_CFG_BAT_MD BIT(4)
#define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0
-#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB 16
+#define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB 16
+#define JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB 8
+#define JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB 16
#define JZ_ADC_AUX_VREF 3300
#define JZ_ADC_AUX_VREF_BITS 12
@@ -37,6 +41,8 @@
#define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS 10
#define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986)
#define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12
+#define JZ4770_ADC_BATTERY_VREF 6600
+#define JZ4770_ADC_BATTERY_VREF_BITS 12
struct ingenic_adc;
@@ -47,6 +53,8 @@ struct ingenic_adc_soc_data {
size_t battery_raw_avail_size;
const int *battery_scale_avail;
size_t battery_scale_avail_size;
+ unsigned int battery_vref_mode: 1;
+ unsigned int has_aux2: 1;
int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
};
@@ -54,6 +62,7 @@ struct ingenic_adc {
void __iomem *base;
struct clk *clk;
struct mutex lock;
+ struct mutex aux_lock;
const struct ingenic_adc_soc_data *soc_data;
bool low_vref_mode;
};
@@ -120,6 +129,8 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->channel) {
case INGENIC_ADC_BATTERY:
+ if (!adc->soc_data->battery_vref_mode)
+ return -EINVAL;
if (val > JZ_ADC_BATTERY_LOW_VREF) {
ingenic_adc_set_config(adc,
JZ_ADC_REG_CFG_BAT_MD,
@@ -158,6 +169,14 @@ static const int jz4740_adc_battery_scale_avail[] = {
JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
};
+static const int jz4770_adc_battery_raw_avail[] = {
+ 0, 1, (1 << JZ4770_ADC_BATTERY_VREF_BITS) - 1,
+};
+
+static const int jz4770_adc_battery_scale_avail[] = {
+ JZ4770_ADC_BATTERY_VREF, JZ4770_ADC_BATTERY_VREF_BITS,
+};
+
static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
{
struct clk *parent_clk;
@@ -187,7 +206,45 @@ static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
/* We also need a divider that produces a 10us clock. */
div_10us = DIV_ROUND_UP(rate, 100000);
- writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
+ writel(((div_10us - 1) << JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB) |
+ (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
+ adc->base + JZ_ADC_REG_ADCLK);
+
+ return 0;
+}
+
+static int jz4770_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
+{
+ struct clk *parent_clk;
+ unsigned long parent_rate, rate;
+ unsigned int div_main, div_ms, div_10us;
+
+ parent_clk = clk_get_parent(adc->clk);
+ if (!parent_clk) {
+ dev_err(dev, "ADC clock has no parent\n");
+ return -ENODEV;
+ }
+ parent_rate = clk_get_rate(parent_clk);
+
+ /*
+ * The JZ4770 ADC works at 20 kHz to 200 kHz.
+ * We pick the highest rate possible.
+ */
+ div_main = DIV_ROUND_UP(parent_rate, 200000);
+ div_main = clamp(div_main, 1u, 256u);
+ rate = parent_rate / div_main;
+ if (rate < 20000 || rate > 200000) {
+ dev_err(dev, "No valid divider for ADC main clock\n");
+ return -EINVAL;
+ }
+
+ /* We also need a divider that produces a 10us clock. */
+ div_10us = DIV_ROUND_UP(rate, 10000);
+ /* And another, which produces a 1ms clock. */
+ div_ms = DIV_ROUND_UP(rate, 1000);
+
+ writel(((div_ms - 1) << JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB) |
+ ((div_10us - 1) << JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB) |
(div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
adc->base + JZ_ADC_REG_ADCLK);
@@ -201,6 +258,8 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
.battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
.battery_scale_avail = jz4725b_adc_battery_scale_avail,
.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
+ .battery_vref_mode = true,
+ .has_aux2 = false,
.init_clk_div = jz4725b_adc_init_clk_div,
};
@@ -211,9 +270,23 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
.battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
.battery_scale_avail = jz4740_adc_battery_scale_avail,
.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
+ .battery_vref_mode = true,
+ .has_aux2 = false,
.init_clk_div = NULL, /* no ADCLK register on JZ4740 */
};
+static const struct ingenic_adc_soc_data jz4770_adc_soc_data = {
+ .battery_high_vref = JZ4770_ADC_BATTERY_VREF,
+ .battery_high_vref_bits = JZ4770_ADC_BATTERY_VREF_BITS,
+ .battery_raw_avail = jz4770_adc_battery_raw_avail,
+ .battery_raw_avail_size = ARRAY_SIZE(jz4770_adc_battery_raw_avail),
+ .battery_scale_avail = jz4770_adc_battery_scale_avail,
+ .battery_scale_avail_size = ARRAY_SIZE(jz4770_adc_battery_scale_avail),
+ .battery_vref_mode = false,
+ .has_aux2 = true,
+ .init_clk_div = jz4770_adc_init_clk_div,
+};
+
static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
struct iio_chan_spec const *chan,
const int **vals,
@@ -239,6 +312,42 @@ static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
};
}
+static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc,
+ struct iio_chan_spec const *chan,
+ int *val)
+{
+ int bit, ret, engine = (chan->channel == INGENIC_ADC_BATTERY);
+
+ /* We cannot sample AUX/AUX2 in parallel. */
+ mutex_lock(&adc->aux_lock);
+ if (adc->soc_data->has_aux2 && engine == 0) {
+ bit = BIT(chan->channel == INGENIC_ADC_AUX2);
+ ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit);
+ }
+
+ clk_enable(adc->clk);
+ ret = ingenic_adc_capture(adc, engine);
+ if (ret)
+ goto out;
+
+ switch (chan->channel) {
+ case INGENIC_ADC_AUX:
+ case INGENIC_ADC_AUX2:
+ *val = readw(adc->base + JZ_ADC_REG_ADSDAT);
+ break;
+ case INGENIC_ADC_BATTERY:
+ *val = readw(adc->base + JZ_ADC_REG_ADBDAT);
+ break;
+ }
+
+ ret = IIO_VAL_INT;
+out:
+ clk_disable(adc->clk);
+ mutex_unlock(&adc->aux_lock);
+
+ return ret;
+}
+
static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
struct iio_chan_spec const *chan,
int *val,
@@ -246,32 +355,14 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
long m)
{
struct ingenic_adc *adc = iio_priv(iio_dev);
- int ret;
switch (m) {
case IIO_CHAN_INFO_RAW:
- clk_enable(adc->clk);
- ret = ingenic_adc_capture(adc, chan->channel);
- if (ret) {
- clk_disable(adc->clk);
- return ret;
- }
-
- switch (chan->channel) {
- case INGENIC_ADC_AUX:
- *val = readw(adc->base + JZ_ADC_REG_ADSDAT);
- break;
- case INGENIC_ADC_BATTERY:
- *val = readw(adc->base + JZ_ADC_REG_ADBDAT);
- break;
- }
-
- clk_disable(adc->clk);
-
- return IIO_VAL_INT;
+ return ingenic_adc_read_chan_info_raw(adc, chan, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->channel) {
case INGENIC_ADC_AUX:
+ case INGENIC_ADC_AUX2:
*val = JZ_ADC_AUX_VREF;
*val2 = JZ_ADC_AUX_VREF_BITS;
break;
@@ -322,6 +413,14 @@ static const struct iio_chan_spec ingenic_channels[] = {
.indexed = 1,
.channel = INGENIC_ADC_BATTERY,
},
+ { /* Must always be last in the array. */
+ .extend_name = "aux2",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_AUX2,
+ },
};
static int ingenic_adc_probe(struct platform_device *pdev)
@@ -343,6 +442,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
adc = iio_priv(iio_dev);
mutex_init(&adc->lock);
+ mutex_init(&adc->aux_lock);
adc->soc_data = soc_data;
mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -374,6 +474,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
/* Put hardware in a known passive state. */
writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
+ usleep_range(2000, 3000); /* Must wait at least 2ms. */
clk_disable(adc->clk);
ret = devm_add_action_or_reset(dev, ingenic_adc_clk_cleanup, adc->clk);
@@ -387,6 +488,9 @@ static int ingenic_adc_probe(struct platform_device *pdev)
iio_dev->modes = INDIO_DIRECT_MODE;
iio_dev->channels = ingenic_channels;
iio_dev->num_channels = ARRAY_SIZE(ingenic_channels);
+ /* Remove AUX2 from the list of supported channels. */
+ if (!adc->soc_data->has_aux2)
+ iio_dev->num_channels -= 1;
iio_dev->info = &ingenic_adc_info;
ret = devm_iio_device_register(dev, iio_dev);
@@ -400,6 +504,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
static const struct of_device_id ingenic_adc_of_match[] = {
{ .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
{ .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
+ { .compatible = "ingenic,jz4770-adc", .data = &jz4770_adc_soc_data, },
{ },
};
MODULE_DEVICE_TABLE(of, ingenic_adc_of_match);
diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c
new file mode 100644
index 000000000000..67d096f8180d
--- /dev/null
+++ b/drivers/iio/adc/intel_mrfld_adc.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ADC driver for Basin Cove PMIC
+ *
+ * Copyright (C) 2012 Intel Corporation
+ * Author: Bin Yang <bin.yang@intel.com>
+ *
+ * Rewritten for upstream by:
+ * Vincent Pelletier <plr.vincent@gmail.com>
+ * Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/mfd/intel_soc_pmic_mrfld.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/driver.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+
+#include <asm/unaligned.h>
+
+#define BCOVE_GPADCREQ 0xDC
+#define BCOVE_GPADCREQ_BUSY BIT(0)
+#define BCOVE_GPADCREQ_IRQEN BIT(1)
+
+#define BCOVE_ADCIRQ_ALL ( \
+ BCOVE_ADCIRQ_BATTEMP | \
+ BCOVE_ADCIRQ_SYSTEMP | \
+ BCOVE_ADCIRQ_BATTID | \
+ BCOVE_ADCIRQ_VIBATT | \
+ BCOVE_ADCIRQ_CCTICK)
+
+#define BCOVE_ADC_TIMEOUT msecs_to_jiffies(1000)
+
+static const u8 mrfld_adc_requests[] = {
+ BCOVE_ADCIRQ_VIBATT,
+ BCOVE_ADCIRQ_BATTID,
+ BCOVE_ADCIRQ_VIBATT,
+ BCOVE_ADCIRQ_SYSTEMP,
+ BCOVE_ADCIRQ_BATTEMP,
+ BCOVE_ADCIRQ_BATTEMP,
+ BCOVE_ADCIRQ_SYSTEMP,
+ BCOVE_ADCIRQ_SYSTEMP,
+ BCOVE_ADCIRQ_SYSTEMP,
+};
+
+struct mrfld_adc {
+ struct regmap *regmap;
+ struct completion completion;
+ /* Lock to protect the IPC transfers */
+ struct mutex lock;
+};
+
+static irqreturn_t mrfld_adc_thread_isr(int irq, void *data)
+{
+ struct iio_dev *indio_dev = data;
+ struct mrfld_adc *adc = iio_priv(indio_dev);
+
+ complete(&adc->completion);
+ return IRQ_HANDLED;
+}
+
+static int mrfld_adc_single_conv(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *result)
+{
+ struct mrfld_adc *adc = iio_priv(indio_dev);
+ struct regmap *regmap = adc->regmap;
+ unsigned int req;
+ long timeout;
+ u8 buf[2];
+ int ret;
+
+ reinit_completion(&adc->completion);
+
+ regmap_update_bits(regmap, BCOVE_MADCIRQ, BCOVE_ADCIRQ_ALL, 0);
+ regmap_update_bits(regmap, BCOVE_MIRQLVL1, BCOVE_LVL1_ADC, 0);
+
+ ret = regmap_read_poll_timeout(regmap, BCOVE_GPADCREQ, req,
+ !(req & BCOVE_GPADCREQ_BUSY),
+ 2000, 1000000);
+ if (ret)
+ goto done;
+
+ req = mrfld_adc_requests[chan->channel];
+ ret = regmap_write(regmap, BCOVE_GPADCREQ, BCOVE_GPADCREQ_IRQEN | req);
+ if (ret)
+ goto done;
+
+ timeout = wait_for_completion_interruptible_timeout(&adc->completion,
+ BCOVE_ADC_TIMEOUT);
+ if (timeout < 0) {
+ ret = timeout;
+ goto done;
+ }
+ if (timeout == 0) {
+ ret = -ETIMEDOUT;
+ goto done;
+ }
+
+ ret = regmap_bulk_read(regmap, chan->address, buf, 2);
+ if (ret)
+ goto done;
+
+ *result = get_unaligned_be16(buf);
+ ret = IIO_VAL_INT;
+
+done:
+ regmap_update_bits(regmap, BCOVE_MIRQLVL1, BCOVE_LVL1_ADC, 0xff);
+ regmap_update_bits(regmap, BCOVE_MADCIRQ, BCOVE_ADCIRQ_ALL, 0xff);
+
+ return ret;
+}
+
+static int mrfld_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct mrfld_adc *adc = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&adc->lock);
+ ret = mrfld_adc_single_conv(indio_dev, chan, val);
+ mutex_unlock(&adc->lock);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info mrfld_adc_iio_info = {
+ .read_raw = &mrfld_adc_read_raw,
+};
+
+#define BCOVE_ADC_CHANNEL(_type, _channel, _datasheet_name, _address) \
+ { \
+ .indexed = 1, \
+ .type = _type, \
+ .channel = _channel, \
+ .address = _address, \
+ .datasheet_name = _datasheet_name, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ }
+
+static const struct iio_chan_spec mrfld_adc_channels[] = {
+ BCOVE_ADC_CHANNEL(IIO_VOLTAGE, 0, "CH0", 0xE9),
+ BCOVE_ADC_CHANNEL(IIO_RESISTANCE, 1, "CH1", 0xEB),
+ BCOVE_ADC_CHANNEL(IIO_CURRENT, 2, "CH2", 0xED),
+ BCOVE_ADC_CHANNEL(IIO_TEMP, 3, "CH3", 0xCC),
+ BCOVE_ADC_CHANNEL(IIO_TEMP, 4, "CH4", 0xC8),
+ BCOVE_ADC_CHANNEL(IIO_TEMP, 5, "CH5", 0xCA),
+ BCOVE_ADC_CHANNEL(IIO_TEMP, 6, "CH6", 0xC2),
+ BCOVE_ADC_CHANNEL(IIO_TEMP, 7, "CH7", 0xC4),
+ BCOVE_ADC_CHANNEL(IIO_TEMP, 8, "CH8", 0xC6),
+};
+
+static struct iio_map iio_maps[] = {
+ IIO_MAP("CH0", "bcove-battery", "VBATRSLT"),
+ IIO_MAP("CH1", "bcove-battery", "BATTID"),
+ IIO_MAP("CH2", "bcove-battery", "IBATRSLT"),
+ IIO_MAP("CH3", "bcove-temp", "PMICTEMP"),
+ IIO_MAP("CH4", "bcove-temp", "BATTEMP0"),
+ IIO_MAP("CH5", "bcove-temp", "BATTEMP1"),
+ IIO_MAP("CH6", "bcove-temp", "SYSTEMP0"),
+ IIO_MAP("CH7", "bcove-temp", "SYSTEMP1"),
+ IIO_MAP("CH8", "bcove-temp", "SYSTEMP2"),
+ {}
+};
+
+static int mrfld_adc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent);
+ struct iio_dev *indio_dev;
+ struct mrfld_adc *adc;
+ int irq;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*indio_dev));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ adc = iio_priv(indio_dev);
+
+ mutex_init(&adc->lock);
+ init_completion(&adc->completion);
+ adc->regmap = pmic->regmap;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, mrfld_adc_thread_isr,
+ IRQF_ONESHOT | IRQF_SHARED, pdev->name,
+ indio_dev);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, indio_dev);
+
+ indio_dev->dev.parent = dev;
+ indio_dev->name = pdev->name;
+
+ indio_dev->channels = mrfld_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(mrfld_adc_channels);
+ indio_dev->info = &mrfld_adc_iio_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = iio_map_array_register(indio_dev, iio_maps);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret < 0)
+ goto err_array_unregister;
+
+ return 0;
+
+err_array_unregister:
+ iio_map_array_unregister(indio_dev);
+ return ret;
+}
+
+static int mrfld_adc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+ iio_map_array_unregister(indio_dev);
+
+ return 0;
+}
+
+static const struct platform_device_id mrfld_adc_id_table[] = {
+ { .name = "mrfld_bcove_adc" },
+ {}
+};
+MODULE_DEVICE_TABLE(platform, mrfld_adc_id_table);
+
+static struct platform_driver mrfld_adc_driver = {
+ .driver = {
+ .name = "mrfld_bcove_adc",
+ },
+ .probe = mrfld_adc_probe,
+ .remove = mrfld_adc_remove,
+ .id_table = mrfld_adc_id_table,
+};
+module_platform_driver(mrfld_adc_driver);
+
+MODULE_AUTHOR("Bin Yang <bin.yang@intel.com>");
+MODULE_AUTHOR("Vincent Pelletier <plr.vincent@gmail.com>");
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
+MODULE_DESCRIPTION("ADC driver for Basin Cove PMIC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
index 214883458582..e171db20c04a 100644
--- a/drivers/iio/adc/max1027.c
+++ b/drivers/iio/adc/max1027.c
@@ -63,12 +63,18 @@ enum max1027_id {
max1027,
max1029,
max1031,
+ max1227,
+ max1229,
+ max1231,
};
static const struct spi_device_id max1027_id[] = {
{"max1027", max1027},
{"max1029", max1029},
{"max1031", max1031},
+ {"max1227", max1227},
+ {"max1229", max1229},
+ {"max1231", max1231},
{}
};
MODULE_DEVICE_TABLE(spi, max1027_id);
@@ -78,12 +84,15 @@ static const struct of_device_id max1027_adc_dt_ids[] = {
{ .compatible = "maxim,max1027" },
{ .compatible = "maxim,max1029" },
{ .compatible = "maxim,max1031" },
+ { .compatible = "maxim,max1227" },
+ { .compatible = "maxim,max1229" },
+ { .compatible = "maxim,max1231" },
{},
};
MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids);
#endif
-#define MAX1027_V_CHAN(index) \
+#define MAX1027_V_CHAN(index, depth) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
@@ -93,7 +102,7 @@ MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids);
.scan_index = index + 1, \
.scan_type = { \
.sign = 'u', \
- .realbits = 10, \
+ .realbits = depth, \
.storagebits = 16, \
.shift = 2, \
.endianness = IIO_BE, \
@@ -115,52 +124,54 @@ MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids);
}, \
}
+#define MAX1X27_CHANNELS(depth) \
+ MAX1027_T_CHAN, \
+ MAX1027_V_CHAN(0, depth), \
+ MAX1027_V_CHAN(1, depth), \
+ MAX1027_V_CHAN(2, depth), \
+ MAX1027_V_CHAN(3, depth), \
+ MAX1027_V_CHAN(4, depth), \
+ MAX1027_V_CHAN(5, depth), \
+ MAX1027_V_CHAN(6, depth), \
+ MAX1027_V_CHAN(7, depth)
+
+#define MAX1X29_CHANNELS(depth) \
+ MAX1X27_CHANNELS(depth), \
+ MAX1027_V_CHAN(8, depth), \
+ MAX1027_V_CHAN(9, depth), \
+ MAX1027_V_CHAN(10, depth), \
+ MAX1027_V_CHAN(11, depth)
+
+#define MAX1X31_CHANNELS(depth) \
+ MAX1X27_CHANNELS(depth), \
+ MAX1X29_CHANNELS(depth), \
+ MAX1027_V_CHAN(12, depth), \
+ MAX1027_V_CHAN(13, depth), \
+ MAX1027_V_CHAN(14, depth), \
+ MAX1027_V_CHAN(15, depth)
+
static const struct iio_chan_spec max1027_channels[] = {
- MAX1027_T_CHAN,
- MAX1027_V_CHAN(0),
- MAX1027_V_CHAN(1),
- MAX1027_V_CHAN(2),
- MAX1027_V_CHAN(3),
- MAX1027_V_CHAN(4),
- MAX1027_V_CHAN(5),
- MAX1027_V_CHAN(6),
- MAX1027_V_CHAN(7)
+ MAX1X27_CHANNELS(10),
};
static const struct iio_chan_spec max1029_channels[] = {
- MAX1027_T_CHAN,
- MAX1027_V_CHAN(0),
- MAX1027_V_CHAN(1),
- MAX1027_V_CHAN(2),
- MAX1027_V_CHAN(3),
- MAX1027_V_CHAN(4),
- MAX1027_V_CHAN(5),
- MAX1027_V_CHAN(6),
- MAX1027_V_CHAN(7),
- MAX1027_V_CHAN(8),
- MAX1027_V_CHAN(9),
- MAX1027_V_CHAN(10),
- MAX1027_V_CHAN(11)
+ MAX1X29_CHANNELS(10),
};
static const struct iio_chan_spec max1031_channels[] = {
- MAX1027_T_CHAN,
- MAX1027_V_CHAN(0),
- MAX1027_V_CHAN(1),
- MAX1027_V_CHAN(2),
- MAX1027_V_CHAN(3),
- MAX1027_V_CHAN(4),
- MAX1027_V_CHAN(5),
- MAX1027_V_CHAN(6),
- MAX1027_V_CHAN(7),
- MAX1027_V_CHAN(8),
- MAX1027_V_CHAN(9),
- MAX1027_V_CHAN(10),
- MAX1027_V_CHAN(11),
- MAX1027_V_CHAN(12),
- MAX1027_V_CHAN(13),
- MAX1027_V_CHAN(14),
- MAX1027_V_CHAN(15)
+ MAX1X31_CHANNELS(10),
+};
+
+static const struct iio_chan_spec max1227_channels[] = {
+ MAX1X27_CHANNELS(12),
+};
+
+static const struct iio_chan_spec max1229_channels[] = {
+ MAX1X29_CHANNELS(12),
+};
+
+static const struct iio_chan_spec max1231_channels[] = {
+ MAX1X31_CHANNELS(12),
};
static const unsigned long max1027_available_scan_masks[] = {
@@ -200,6 +211,21 @@ static const struct max1027_chip_info max1027_chip_info_tbl[] = {
.num_channels = ARRAY_SIZE(max1031_channels),
.available_scan_masks = max1031_available_scan_masks,
},
+ [max1227] = {
+ .channels = max1227_channels,
+ .num_channels = ARRAY_SIZE(max1227_channels),
+ .available_scan_masks = max1027_available_scan_masks,
+ },
+ [max1229] = {
+ .channels = max1229_channels,
+ .num_channels = ARRAY_SIZE(max1229_channels),
+ .available_scan_masks = max1029_available_scan_masks,
+ },
+ [max1231] = {
+ .channels = max1231_channels,
+ .num_channels = ARRAY_SIZE(max1231_channels),
+ .available_scan_masks = max1031_available_scan_masks,
+ },
};
struct max1027_state {
@@ -284,7 +310,7 @@ static int max1027_read_raw(struct iio_dev *indio_dev,
break;
case IIO_VOLTAGE:
*val = 2500;
- *val2 = 10;
+ *val2 = chan->scan_type.realbits;
ret = IIO_VAL_FRACTIONAL_LOG2;
break;
default:
@@ -309,8 +335,11 @@ static int max1027_debugfs_reg_access(struct iio_dev *indio_dev,
struct max1027_state *st = iio_priv(indio_dev);
u8 *val = (u8 *)st->buffer;
- if (readval != NULL)
- return -EINVAL;
+ if (readval) {
+ int ret = spi_read(st->spi, val, 2);
+ *readval = be16_to_cpu(st->buffer[0]);
+ return ret;
+ }
*val = (u8)writeval;
return spi_write(st->spi, val, 1);
@@ -427,34 +456,47 @@ static int max1027_probe(struct spi_device *spi)
return -ENOMEM;
}
- ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
- &iio_pollfunc_store_time,
- &max1027_trigger_handler, NULL);
- if (ret < 0) {
- dev_err(&indio_dev->dev, "Failed to setup buffer\n");
- return ret;
- }
+ if (spi->irq) {
+ ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &max1027_trigger_handler,
+ NULL);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Failed to setup buffer\n");
+ return ret;
+ }
- st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-trigger",
- indio_dev->name);
- if (st->trig == NULL) {
- ret = -ENOMEM;
- dev_err(&indio_dev->dev, "Failed to allocate iio trigger\n");
- return ret;
- }
+ st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-trigger",
+ indio_dev->name);
+ if (st->trig == NULL) {
+ ret = -ENOMEM;
+ dev_err(&indio_dev->dev,
+ "Failed to allocate iio trigger\n");
+ return ret;
+ }
- st->trig->ops = &max1027_trigger_ops;
- st->trig->dev.parent = &spi->dev;
- iio_trigger_set_drvdata(st->trig, indio_dev);
- iio_trigger_register(st->trig);
+ st->trig->ops = &max1027_trigger_ops;
+ st->trig->dev.parent = &spi->dev;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
+ iio_trigger_register(st->trig);
+
+ ret = devm_request_threaded_irq(&spi->dev, spi->irq,
+ iio_trigger_generic_data_rdy_poll,
+ NULL,
+ IRQF_TRIGGER_FALLING,
+ spi->dev.driver->name,
+ st->trig);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n");
+ return ret;
+ }
+ }
- ret = devm_request_threaded_irq(&spi->dev, spi->irq,
- iio_trigger_generic_data_rdy_poll,
- NULL,
- IRQF_TRIGGER_FALLING,
- spi->dev.driver->name, st->trig);
+ /* Internal reset */
+ st->reg = MAX1027_RST_REG;
+ ret = spi_write(st->spi, &st->reg, 1);
if (ret < 0) {
- dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n");
+ dev_err(&indio_dev->dev, "Failed to reset the ADC\n");
return ret;
}
@@ -480,5 +522,5 @@ static struct spi_driver max1027_driver = {
module_spi_driver(max1027_driver);
MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>");
-MODULE_DESCRIPTION("MAX1027/MAX1029/MAX1031 ADC");
+MODULE_DESCRIPTION("MAX1X27/MAX1X29/MAX1X31 ADC");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 38bf10085696..465c7625a55a 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -164,7 +164,7 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
case mcp3550_60:
case mcp3551:
case mcp3553: {
- u32 raw = be32_to_cpup((u32 *)adc->rx_buf);
+ u32 raw = be32_to_cpup((__be32 *)adc->rx_buf);
if (!(adc->spi->mode & SPI_CPOL))
raw <<= 1; /* strip Data Ready bit in SPI mode 0,0 */
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 7b27306330a3..22a470db9ef8 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -1187,7 +1187,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
const struct meson_sar_adc_data *match_data;
struct meson_sar_adc_priv *priv;
struct iio_dev *indio_dev;
- struct resource *res;
void __iomem *base;
int irq, ret;
@@ -1214,8 +1213,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &meson_sar_adc_iio_info;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c
index a6c046575ec3..66b387f9b36d 100644
--- a/drivers/iio/adc/sc27xx_adc.c
+++ b/drivers/iio/adc/sc27xx_adc.c
@@ -477,13 +477,6 @@ static void sc27xx_adc_disable(void *_data)
SC27XX_MODULE_ADC_EN, 0);
}
-static void sc27xx_adc_free_hwlock(void *_data)
-{
- struct hwspinlock *hwlock = _data;
-
- hwspin_lock_free(hwlock);
-}
-
static int sc27xx_adc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -520,19 +513,12 @@ static int sc27xx_adc_probe(struct platform_device *pdev)
return ret;
}
- sc27xx_data->hwlock = hwspin_lock_request_specific(ret);
+ sc27xx_data->hwlock = devm_hwspin_lock_request_specific(dev, ret);
if (!sc27xx_data->hwlock) {
dev_err(dev, "failed to request hwspinlock\n");
return -ENXIO;
}
- ret = devm_add_action_or_reset(dev, sc27xx_adc_free_hwlock,
- sc27xx_data->hwlock);
- if (ret) {
- dev_err(dev, "failed to add hwspinlock action\n");
- return ret;
- }
-
sc27xx_data->dev = dev;
ret = sc27xx_adc_enable(sc27xx_data);
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 93a096a91f8c..20c626c289ed 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -38,12 +38,12 @@
#define HAS_ANASWVDD BIT(1)
/**
- * stm32_adc_common_regs - stm32 common registers, compatible dependent data
+ * struct stm32_adc_common_regs - stm32 common registers
* @csr: common status register offset
* @ccr: common control register offset
- * @eoc1: adc1 end of conversion flag in @csr
- * @eoc2: adc2 end of conversion flag in @csr
- * @eoc3: adc3 end of conversion flag in @csr
+ * @eoc1_msk: adc1 end of conversion flag in @csr
+ * @eoc2_msk: adc2 end of conversion flag in @csr
+ * @eoc3_msk: adc3 end of conversion flag in @csr
* @ier: interrupt enable register offset for each adc
* @eocie_msk: end of conversion interrupt enable mask in @ier
*/
@@ -60,7 +60,7 @@ struct stm32_adc_common_regs {
struct stm32_adc_priv;
/**
- * stm32_adc_priv_cfg - stm32 core compatible configuration data
+ * struct stm32_adc_priv_cfg - stm32 core compatible configuration data
* @regs: common registers for all instances
* @clk_sel: clock selection routine
* @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
@@ -117,6 +117,7 @@ static int stm32f4_pclk_div[] = {2, 4, 6, 8};
/**
* stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler
+ * @pdev: platform device
* @priv: stm32 ADC core private data
* Select clock prescaler used for analog conversions, before using ADC.
*/
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 73aee5949b6b..3b291d72701c 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -102,7 +102,7 @@ struct stm32_adc_calib {
};
/**
- * stm32_adc_regs - stm32 ADC misc registers & bitfield desc
+ * struct stm32_adc_regs - stm32 ADC misc registers & bitfield desc
* @reg: register offset
* @mask: bitfield mask
* @shift: left shift
@@ -114,7 +114,7 @@ struct stm32_adc_regs {
};
/**
- * stm32_adc_regspec - stm32 registers definition, compatible dependent data
+ * struct stm32_adc_regspec - stm32 registers definition
* @dr: data register offset
* @ier_eoc: interrupt enable register & eocie bitfield
* @isr_eoc: interrupt status register & eoc bitfield
@@ -140,7 +140,7 @@ struct stm32_adc_regspec {
struct stm32_adc;
/**
- * stm32_adc_cfg - stm32 compatible configuration data
+ * struct stm32_adc_cfg - stm32 compatible configuration data
* @regs: registers descriptions
* @adc_info: per instance input channels definitions
* @trigs: external trigger sources
@@ -183,8 +183,8 @@ struct stm32_adc_cfg {
* @rx_buf: dma rx buffer cpu address
* @rx_dma_buf: dma rx buffer bus address
* @rx_buf_sz: dma rx buffer size
- * @difsel bitmask to set single-ended/differential channel
- * @pcsel bitmask to preselect channels on some devices
+ * @difsel: bitmask to set single-ended/differential channel
+ * @pcsel: bitmask to preselect channels on some devices
* @smpr_val: sampling time settings (e.g. smpr1 / smpr2)
* @cal: optional calibration data on some devices
* @chan_name: channel name array
@@ -254,7 +254,7 @@ static const struct stm32_adc_info stm32h7_adc_info = {
.num_res = ARRAY_SIZE(stm32h7_adc_resolutions),
};
-/**
+/*
* stm32f4_sq - describe regular sequence registers
* - L: sequence len (register & bit field)
* - SQ1..SQ16: sequence entries (register & bit field)
@@ -301,7 +301,7 @@ static struct stm32_adc_trig_info stm32f4_adc_trigs[] = {
{}, /* sentinel */
};
-/**
+/*
* stm32f4_smp_bits[] - describe sampling time register index & bit fields
* Sorted so it can be indexed by channel number.
*/
@@ -392,7 +392,7 @@ static struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
{},
};
-/**
+/*
* stm32h7_smp_bits - describe sampling time register index & bit fields
* Sorted so it can be indexed by channel number.
*/
@@ -994,6 +994,7 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
/**
* stm32_adc_get_trig_extsel() - Get external trigger selection
+ * @indio_dev: IIO device structure
* @trig: trigger
*
* Returns trigger extsel value, if trig matches, -EINVAL otherwise.
@@ -1297,6 +1298,10 @@ static int stm32_adc_of_xlate(struct iio_dev *indio_dev,
/**
* stm32_adc_debugfs_reg_access - read or write register value
+ * @indio_dev: IIO device structure
+ * @reg: register offset
+ * @writeval: value to write
+ * @readval: value to read
*
* To read a value from an ADC register:
* echo [ADC reg offset] > direct_reg_access
diff --git a/drivers/iio/adc/stmpe-adc.c b/drivers/iio/adc/stmpe-adc.c
index bd72727fc417..0f88048ea48f 100644
--- a/drivers/iio/adc/stmpe-adc.c
+++ b/drivers/iio/adc/stmpe-adc.c
@@ -175,7 +175,7 @@ static int stmpe_read_raw(struct iio_dev *indio_dev,
static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
{
struct stmpe_adc *info = (struct stmpe_adc *)dev_id;
- u16 data;
+ __be16 data;
if (info->channel <= STMPE_ADC_LAST_NR) {
int int_sta;
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 55c5119fe575..472b08f37fea 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -495,7 +495,7 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
ret = twl4030_madc_disable_irq(madc, i);
if (ret < 0)
dev_dbg(madc->dev, "Disable interrupt failed %d\n", i);
- madc->requests[i].result_pending = 1;
+ madc->requests[i].result_pending = true;
}
for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
r = &madc->requests[i];
@@ -507,8 +507,8 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf, r->raw);
/* Free request */
- r->result_pending = 0;
- r->active = 0;
+ r->result_pending = false;
+ r->active = false;
}
mutex_unlock(&madc->lock);
@@ -521,15 +521,15 @@ err_i2c:
*/
for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
r = &madc->requests[i];
- if (r->active == 0)
+ if (!r->active)
continue;
method = &twl4030_conversion_methods[r->method];
/* Read results */
len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf, r->raw);
/* Free request */
- r->result_pending = 0;
- r->active = 0;
+ r->result_pending = false;
+ r->active = false;
}
mutex_unlock(&madc->lock);
@@ -652,16 +652,16 @@ static int twl4030_madc_conversion(struct twl4030_madc_request *req)
ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
if (ret < 0)
goto out;
- twl4030_madc->requests[req->method].active = 1;
+ twl4030_madc->requests[req->method].active = true;
/* Wait until conversion is ready (ctrl register returns EOC) */
ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
if (ret) {
- twl4030_madc->requests[req->method].active = 0;
+ twl4030_madc->requests[req->method].active = false;
goto out;
}
ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
req->channels, req->rbuf, req->raw);
- twl4030_madc->requests[req->method].active = 0;
+ twl4030_madc->requests[req->method].active = false;
out:
mutex_unlock(&twl4030_madc->lock);
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 4fd389678dba..ec227b358cd6 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1150,7 +1150,6 @@ static int xadc_probe(struct platform_device *pdev)
const struct of_device_id *id;
struct iio_dev *indio_dev;
unsigned int bipolar_mask;
- struct resource *mem;
unsigned int conf0;
struct xadc *xadc;
int ret;
@@ -1180,8 +1179,7 @@ static int xadc_probe(struct platform_device *pdev)
spin_lock_init(&xadc->lock);
INIT_DELAYED_WORK(&xadc->zynq_unmask_work, xadc_zynq_unmask_worker);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- xadc->base = devm_ioremap_resource(&pdev->dev, mem);
+ xadc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xadc->base))
return PTR_ERR(xadc->base);
diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c
index 3a20cb5d9bff..6c175eb1c7a7 100644
--- a/drivers/iio/chemical/atlas-ph-sensor.c
+++ b/drivers/iio/chemical/atlas-ph-sensor.c
@@ -323,16 +323,16 @@ static int atlas_buffer_predisable(struct iio_dev *indio_dev)
struct atlas_data *data = iio_priv(indio_dev);
int ret;
- ret = iio_triggered_buffer_predisable(indio_dev);
+ ret = atlas_set_interrupt(data, false);
if (ret)
return ret;
- ret = atlas_set_interrupt(data, false);
+ pm_runtime_mark_last_busy(&data->client->dev);
+ ret = pm_runtime_put_autosuspend(&data->client->dev);
if (ret)
return ret;
- pm_runtime_mark_last_busy(&data->client->dev);
- return pm_runtime_put_autosuspend(&data->client->dev);
+ return iio_triggered_buffer_predisable(indio_dev);
}
static const struct iio_trigger_ops atlas_interrupt_trigger_ops = {
diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c
index 8cc8fe5e356d..403e8803471a 100644
--- a/drivers/iio/chemical/sgp30.c
+++ b/drivers/iio/chemical/sgp30.c
@@ -483,7 +483,7 @@ static void sgp_init(struct sgp_data *data)
data->iaq_defval_skip_jiffies =
43 * data->measure_interval_jiffies;
break;
- };
+ }
}
static const struct iio_info sgp_info = {
diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c
index edbb956e81e8..acb9f8ecbb3d 100644
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -117,7 +117,7 @@ static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size)
break;
case SPS30_READ_AUTO_CLEANING_PERIOD:
buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8;
- buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD;
+ buf[1] = (u8)(SPS30_AUTO_CLEANING_PERIOD & 0xff);
/* fall through */
case SPS30_READ_DATA_READY_FLAG:
case SPS30_READ_DATA:
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c
index 8de9f40226e6..14bbac6bee98 100644
--- a/drivers/iio/dac/ad7303.c
+++ b/drivers/iio/dac/ad7303.c
@@ -41,6 +41,7 @@ struct ad7303_state {
struct regulator *vdd_reg;
struct regulator *vref_reg;
+ struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
@@ -79,7 +80,7 @@ static ssize_t ad7303_write_dac_powerdown(struct iio_dev *indio_dev,
if (ret)
return ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if (pwr_down)
st->config |= AD7303_CFG_POWER_DOWN(chan->channel);
@@ -90,7 +91,7 @@ static ssize_t ad7303_write_dac_powerdown(struct iio_dev *indio_dev,
* mode, so just write one of the DAC channels again */
ad7303_write(st, chan->channel, st->dac_cache[chan->channel]);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return len;
}
@@ -116,7 +117,9 @@ static int ad7303_read_raw(struct iio_dev *indio_dev,
switch (info) {
case IIO_CHAN_INFO_RAW:
+ mutex_lock(&st->lock);
*val = st->dac_cache[chan->channel];
+ mutex_unlock(&st->lock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
vref_uv = ad7303_get_vref(st, chan);
@@ -144,11 +147,11 @@ static int ad7303_write_raw(struct iio_dev *indio_dev,
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = ad7303_write(st, chan->address, val);
if (ret == 0)
st->dac_cache[chan->channel] = val;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
break;
default:
ret = -EINVAL;
@@ -211,6 +214,8 @@ static int ad7303_probe(struct spi_device *spi)
st->spi = spi;
+ mutex_init(&st->lock);
+
st->vdd_reg = devm_regulator_get(&spi->dev, "Vdd");
if (IS_ERR(st->vdd_reg))
return PTR_ERR(st->vdd_reg);
diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c
index d0fb3124de07..9e6b4cd0a5cc 100644
--- a/drivers/iio/dac/stm32-dac-core.c
+++ b/drivers/iio/dac/stm32-dac-core.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
@@ -50,6 +51,41 @@ static const struct regmap_config stm32_dac_regmap_cfg = {
.max_register = 0x3fc,
};
+static int stm32_dac_core_hw_start(struct device *dev)
+{
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
+ struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
+ int ret;
+
+ ret = regulator_enable(priv->vref);
+ if (ret < 0) {
+ dev_err(dev, "vref enable failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(priv->pclk);
+ if (ret < 0) {
+ dev_err(dev, "pclk enable failed: %d\n", ret);
+ goto err_regulator_disable;
+ }
+
+ return 0;
+
+err_regulator_disable:
+ regulator_disable(priv->vref);
+
+ return ret;
+}
+
+static void stm32_dac_core_hw_stop(struct device *dev)
+{
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
+ struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
+
+ clk_disable_unprepare(priv->pclk);
+ regulator_disable(priv->vref);
+}
+
static int stm32_dac_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -66,6 +102,8 @@ static int stm32_dac_probe(struct platform_device *pdev)
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ platform_set_drvdata(pdev, &priv->common);
+
cfg = (const struct stm32_dac_cfg *)
of_match_device(dev->driver->of_match_table, dev)->data;
@@ -74,11 +112,19 @@ static int stm32_dac_probe(struct platform_device *pdev)
if (IS_ERR(mmio))
return PTR_ERR(mmio);
- regmap = devm_regmap_init_mmio(dev, mmio, &stm32_dac_regmap_cfg);
+ regmap = devm_regmap_init_mmio_clk(dev, "pclk", mmio,
+ &stm32_dac_regmap_cfg);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
priv->common.regmap = regmap;
+ priv->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(priv->pclk)) {
+ ret = PTR_ERR(priv->pclk);
+ dev_err(dev, "pclk get failed\n");
+ return ret;
+ }
+
priv->vref = devm_regulator_get(dev, "vref");
if (IS_ERR(priv->vref)) {
ret = PTR_ERR(priv->vref);
@@ -86,33 +132,22 @@ static int stm32_dac_probe(struct platform_device *pdev)
return ret;
}
- ret = regulator_enable(priv->vref);
- if (ret < 0) {
- dev_err(dev, "vref enable failed\n");
- return ret;
- }
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ ret = stm32_dac_core_hw_start(dev);
+ if (ret)
+ goto err_pm_stop;
ret = regulator_get_voltage(priv->vref);
if (ret < 0) {
dev_err(dev, "vref get voltage failed, %d\n", ret);
- goto err_vref;
+ goto err_hw_stop;
}
priv->common.vref_mv = ret / 1000;
dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv);
- priv->pclk = devm_clk_get(dev, "pclk");
- if (IS_ERR(priv->pclk)) {
- ret = PTR_ERR(priv->pclk);
- dev_err(dev, "pclk get failed\n");
- goto err_vref;
- }
-
- ret = clk_prepare_enable(priv->pclk);
- if (ret < 0) {
- dev_err(dev, "pclk enable failed\n");
- goto err_vref;
- }
-
priv->rst = devm_reset_control_get_exclusive(dev, NULL);
if (!IS_ERR(priv->rst)) {
reset_control_assert(priv->rst);
@@ -128,39 +163,79 @@ static int stm32_dac_probe(struct platform_device *pdev)
priv->common.hfsel ?
STM32H7_DAC_CR_HFSEL : 0);
if (ret)
- goto err_pclk;
+ goto err_hw_stop;
}
- platform_set_drvdata(pdev, &priv->common);
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, dev);
if (ret < 0) {
dev_err(dev, "failed to populate DT children\n");
- goto err_pclk;
+ goto err_hw_stop;
}
+ pm_runtime_put(dev);
+
return 0;
-err_pclk:
- clk_disable_unprepare(priv->pclk);
-err_vref:
- regulator_disable(priv->vref);
+err_hw_stop:
+ stm32_dac_core_hw_stop(dev);
+err_pm_stop:
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ pm_runtime_put_noidle(dev);
return ret;
}
static int stm32_dac_remove(struct platform_device *pdev)
{
- struct stm32_dac_common *common = platform_get_drvdata(pdev);
+ pm_runtime_get_sync(&pdev->dev);
+ of_platform_depopulate(&pdev->dev);
+ stm32_dac_core_hw_stop(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_dac_core_resume(struct device *dev)
+{
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
+ int ret;
- of_platform_depopulate(&pdev->dev);
- clk_disable_unprepare(priv->pclk);
- regulator_disable(priv->vref);
+ if (priv->common.hfsel) {
+ /* restore hfsel (maybe lost under low power state) */
+ ret = regmap_update_bits(priv->common.regmap, STM32_DAC_CR,
+ STM32H7_DAC_CR_HFSEL,
+ STM32H7_DAC_CR_HFSEL);
+ if (ret)
+ return ret;
+ }
+
+ return pm_runtime_force_resume(dev);
+}
+
+static int __maybe_unused stm32_dac_core_runtime_suspend(struct device *dev)
+{
+ stm32_dac_core_hw_stop(dev);
return 0;
}
+static int __maybe_unused stm32_dac_core_runtime_resume(struct device *dev)
+{
+ return stm32_dac_core_hw_start(dev);
+}
+
+static const struct dev_pm_ops stm32_dac_core_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, stm32_dac_core_resume)
+ SET_RUNTIME_PM_OPS(stm32_dac_core_runtime_suspend,
+ stm32_dac_core_runtime_resume,
+ NULL)
+};
+
static const struct stm32_dac_cfg stm32h7_dac_cfg = {
.has_hfsel = true,
};
@@ -182,6 +257,7 @@ static struct platform_driver stm32_dac_driver = {
.driver = {
.name = "stm32-dac-core",
.of_match_table = stm32_dac_of_match,
+ .pm = &stm32_dac_core_pm_ops,
},
};
module_platform_driver(stm32_dac_driver);
diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
index cce26a3a6627..f22c1d9129b2 100644
--- a/drivers/iio/dac/stm32-dac.c
+++ b/drivers/iio/dac/stm32-dac.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include "stm32-dac-core.h"
@@ -20,6 +21,8 @@
#define STM32_DAC_CHANNEL_2 2
#define STM32_DAC_IS_CHAN_1(ch) ((ch) & STM32_DAC_CHANNEL_1)
+#define STM32_DAC_AUTO_SUSPEND_DELAY_MS 2000
+
/**
* struct stm32_dac - private data of DAC driver
* @common: reference to DAC common data
@@ -49,15 +52,34 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch,
bool enable)
{
struct stm32_dac *dac = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
u32 msk = STM32_DAC_IS_CHAN_1(ch) ? STM32_DAC_CR_EN1 : STM32_DAC_CR_EN2;
u32 en = enable ? msk : 0;
int ret;
+ /* already enabled / disabled ? */
+ mutex_lock(&indio_dev->mlock);
+ ret = stm32_dac_is_enabled(indio_dev, ch);
+ if (ret < 0 || enable == !!ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret < 0 ? ret : 0;
+ }
+
+ if (enable) {
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(dev);
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ }
+
ret = regmap_update_bits(dac->common->regmap, STM32_DAC_CR, msk, en);
+ mutex_unlock(&indio_dev->mlock);
if (ret < 0) {
dev_err(&indio_dev->dev, "%s failed\n", en ?
"Enable" : "Disable");
- return ret;
+ goto err_put_pm;
}
/*
@@ -68,7 +90,20 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch,
if (en && dac->common->hfsel)
udelay(1);
+ if (!enable) {
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ }
+
return 0;
+
+err_put_pm:
+ if (enable) {
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ }
+
+ return ret;
}
static int stm32_dac_get_value(struct stm32_dac *dac, int channel, int *val)
@@ -272,6 +307,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev)
static int stm32_dac_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
struct iio_dev *indio_dev;
struct stm32_dac *dac;
int ret;
@@ -296,9 +332,61 @@ static int stm32_dac_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- return devm_iio_device_register(&pdev->dev, indio_dev);
+ /* Get stm32-dac-core PM online */
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_set_autosuspend_delay(dev, STM32_DAC_AUTO_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_enable(dev);
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto err_pm_put;
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return 0;
+
+err_pm_put:
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ pm_runtime_put_noidle(dev);
+
+ return ret;
}
+static int stm32_dac_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+ pm_runtime_get_sync(&pdev->dev);
+ iio_device_unregister(indio_dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_dac_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ int channel = indio_dev->channels[0].channel;
+ int ret;
+
+ /* Ensure DAC is disabled before suspend */
+ ret = stm32_dac_is_enabled(indio_dev, channel);
+ if (ret)
+ return ret < 0 ? ret : -EBUSY;
+
+ return pm_runtime_force_suspend(dev);
+}
+
+static const struct dev_pm_ops stm32_dac_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(stm32_dac_suspend, pm_runtime_force_resume)
+};
+
static const struct of_device_id stm32_dac_of_match[] = {
{ .compatible = "st,stm32-dac", },
{},
@@ -307,9 +395,11 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
+ .remove = stm32_dac_remove,
.driver = {
.name = "stm32-dac",
.of_match_table = stm32_dac_of_match,
+ .pm = &stm32_dac_pm_ops,
},
};
module_platform_driver(stm32_dac_driver);
diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c
index 236220d6de02..1b84b8e112fe 100644
--- a/drivers/iio/gyro/adis16080.c
+++ b/drivers/iio/gyro/adis16080.c
@@ -38,10 +38,12 @@ struct adis16080_chip_info {
* @us: actual spi_device to write data
* @info: chip specific parameters
* @buf: transmit or receive buffer
+ * @lock lock to protect buffer during reads
**/
struct adis16080_state {
struct spi_device *us;
const struct adis16080_chip_info *info;
+ struct mutex lock;
__be16 buf ____cacheline_aligned;
};
@@ -82,9 +84,9 @@ static int adis16080_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = adis16080_read_sample(indio_dev, chan->address, val);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret ? ret : IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
@@ -196,6 +198,8 @@ static int adis16080_probe(struct spi_device *spi)
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
+ mutex_init(&st->lock);
+
/* Allocate the comms buffers */
st->us = spi;
st->info = &adis16080_chip_info[id->driver_data];
diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c
index de3f66f89496..79e63c8a2ea8 100644
--- a/drivers/iio/gyro/adis16130.c
+++ b/drivers/iio/gyro/adis16130.c
@@ -76,9 +76,7 @@ static int adis16130_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
/* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
ret = adis16130_spi_read(indio_dev, chan->address, &temp);
- mutex_unlock(&indio_dev->mlock);
if (ret)
return ret;
*val = temp;
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c
index 998fb8d66fe3..981ae2291505 100644
--- a/drivers/iio/gyro/itg3200_core.c
+++ b/drivers/iio/gyro/itg3200_core.c
@@ -154,7 +154,7 @@ static int itg3200_write_raw(struct iio_dev *indio_dev,
t);
mutex_unlock(&indio_dev->mlock);
- return ret;
+ return ret;
default:
return -EINVAL;
diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
index 80154bca18b6..8e908a749f95 100644
--- a/drivers/iio/gyro/mpu3050-core.c
+++ b/drivers/iio/gyro/mpu3050-core.c
@@ -543,7 +543,7 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p)
toread = bytes_per_datum;
offset = 1;
/* Put in some dummy value */
- fifo_values[0] = 0xAAAA;
+ fifo_values[0] = cpu_to_be16(0xAAAA);
}
ret = regmap_bulk_read(mpu3050->map,
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index c0acbb5d2ffb..57be68b291fa 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -14,7 +14,6 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index f3c7282321a8..60bb1029e759 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -40,6 +40,33 @@ config ADIS16480
source "drivers/iio/imu/bmi160/Kconfig"
+config FXOS8700
+ tristate
+
+config FXOS8700_I2C
+ tristate "NXP FXOS8700 I2C driver"
+ depends on I2C
+ select FXOS8700
+ select REGMAP_I2C
+ help
+ Say yes here to build support for the NXP FXOS8700 m+g combo
+ sensor on I2C.
+
+ This driver can also be built as a module. If so, the module will be
+ called fxos8700_i2c.
+
+config FXOS8700_SPI
+ tristate "NXP FXOS8700 SPI driver"
+ depends on SPI
+ select FXOS8700
+ select REGMAP_SPI
+ help
+ Say yes here to build support for the NXP FXOS8700 m+g combo
+ sensor on SPI.
+
+ This driver can also be built as a module. If so, the module will be
+ called fxos8700_spi.
+
config KMX61
tristate "Kionix KMX61 6-axis accelerometer and magnetometer"
depends on I2C
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 4a6958865504..5237fd4bc384 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -14,6 +14,11 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += bmi160/
+
+obj-$(CONFIG_FXOS8700) += fxos8700_core.o
+obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o
+obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o
+
obj-y += inv_mpu6050/
obj-$(CONFIG_KMX61) += kmx61.o
diff --git a/drivers/iio/imu/fxos8700.h b/drivers/iio/imu/fxos8700.h
new file mode 100644
index 000000000000..6dfb8d7099e4
--- /dev/null
+++ b/drivers/iio/imu/fxos8700.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef FXOS8700_H_
+#define FXOS8700_H_
+
+extern const struct regmap_config fxos8700_regmap_config;
+
+int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
+ const char *name, bool use_spi);
+
+#endif /* FXOS8700_H_ */
diff --git a/drivers/iio/imu/fxos8700_core.c b/drivers/iio/imu/fxos8700_core.c
new file mode 100644
index 000000000000..7b47be44ea59
--- /dev/null
+++ b/drivers/iio/imu/fxos8700_core.c
@@ -0,0 +1,649 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FXOS8700 - NXP IMU (accelerometer plus magnetometer)
+ *
+ * IIO core driver for FXOS8700, with support for I2C/SPI busses
+ *
+ * TODO: Buffer, trigger, and IRQ support
+ */
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/acpi.h>
+#include <linux/bitops.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#include "fxos8700.h"
+
+/* Register Definitions */
+#define FXOS8700_STATUS 0x00
+#define FXOS8700_OUT_X_MSB 0x01
+#define FXOS8700_OUT_X_LSB 0x02
+#define FXOS8700_OUT_Y_MSB 0x03
+#define FXOS8700_OUT_Y_LSB 0x04
+#define FXOS8700_OUT_Z_MSB 0x05
+#define FXOS8700_OUT_Z_LSB 0x06
+#define FXOS8700_F_SETUP 0x09
+#define FXOS8700_TRIG_CFG 0x0a
+#define FXOS8700_SYSMOD 0x0b
+#define FXOS8700_INT_SOURCE 0x0c
+#define FXOS8700_WHO_AM_I 0x0d
+#define FXOS8700_XYZ_DATA_CFG 0x0e
+#define FXOS8700_HP_FILTER_CUTOFF 0x0f
+#define FXOS8700_PL_STATUS 0x10
+#define FXOS8700_PL_CFG 0x11
+#define FXOS8700_PL_COUNT 0x12
+#define FXOS8700_PL_BF_ZCOMP 0x13
+#define FXOS8700_PL_THS_REG 0x14
+#define FXOS8700_A_FFMT_CFG 0x15
+#define FXOS8700_A_FFMT_SRC 0x16
+#define FXOS8700_A_FFMT_THS 0x17
+#define FXOS8700_A_FFMT_COUNT 0x18
+#define FXOS8700_TRANSIENT_CFG 0x1d
+#define FXOS8700_TRANSIENT_SRC 0x1e
+#define FXOS8700_TRANSIENT_THS 0x1f
+#define FXOS8700_TRANSIENT_COUNT 0x20
+#define FXOS8700_PULSE_CFG 0x21
+#define FXOS8700_PULSE_SRC 0x22
+#define FXOS8700_PULSE_THSX 0x23
+#define FXOS8700_PULSE_THSY 0x24
+#define FXOS8700_PULSE_THSZ 0x25
+#define FXOS8700_PULSE_TMLT 0x26
+#define FXOS8700_PULSE_LTCY 0x27
+#define FXOS8700_PULSE_WIND 0x28
+#define FXOS8700_ASLP_COUNT 0x29
+#define FXOS8700_CTRL_REG1 0x2a
+#define FXOS8700_CTRL_REG2 0x2b
+#define FXOS8700_CTRL_REG3 0x2c
+#define FXOS8700_CTRL_REG4 0x2d
+#define FXOS8700_CTRL_REG5 0x2e
+#define FXOS8700_OFF_X 0x2f
+#define FXOS8700_OFF_Y 0x30
+#define FXOS8700_OFF_Z 0x31
+#define FXOS8700_M_DR_STATUS 0x32
+#define FXOS8700_M_OUT_X_MSB 0x33
+#define FXOS8700_M_OUT_X_LSB 0x34
+#define FXOS8700_M_OUT_Y_MSB 0x35
+#define FXOS8700_M_OUT_Y_LSB 0x36
+#define FXOS8700_M_OUT_Z_MSB 0x37
+#define FXOS8700_M_OUT_Z_LSB 0x38
+#define FXOS8700_CMP_X_MSB 0x39
+#define FXOS8700_CMP_X_LSB 0x3a
+#define FXOS8700_CMP_Y_MSB 0x3b
+#define FXOS8700_CMP_Y_LSB 0x3c
+#define FXOS8700_CMP_Z_MSB 0x3d
+#define FXOS8700_CMP_Z_LSB 0x3e
+#define FXOS8700_M_OFF_X_MSB 0x3f
+#define FXOS8700_M_OFF_X_LSB 0x40
+#define FXOS8700_M_OFF_Y_MSB 0x41
+#define FXOS8700_M_OFF_Y_LSB 0x42
+#define FXOS8700_M_OFF_Z_MSB 0x43
+#define FXOS8700_M_OFF_Z_LSB 0x44
+#define FXOS8700_MAX_X_MSB 0x45
+#define FXOS8700_MAX_X_LSB 0x46
+#define FXOS8700_MAX_Y_MSB 0x47
+#define FXOS8700_MAX_Y_LSB 0x48
+#define FXOS8700_MAX_Z_MSB 0x49
+#define FXOS8700_MAX_Z_LSB 0x4a
+#define FXOS8700_MIN_X_MSB 0x4b
+#define FXOS8700_MIN_X_LSB 0x4c
+#define FXOS8700_MIN_Y_MSB 0x4d
+#define FXOS8700_MIN_Y_LSB 0x4e
+#define FXOS8700_MIN_Z_MSB 0x4f
+#define FXOS8700_MIN_Z_LSB 0x50
+#define FXOS8700_TEMP 0x51
+#define FXOS8700_M_THS_CFG 0x52
+#define FXOS8700_M_THS_SRC 0x53
+#define FXOS8700_M_THS_X_MSB 0x54
+#define FXOS8700_M_THS_X_LSB 0x55
+#define FXOS8700_M_THS_Y_MSB 0x56
+#define FXOS8700_M_THS_Y_LSB 0x57
+#define FXOS8700_M_THS_Z_MSB 0x58
+#define FXOS8700_M_THS_Z_LSB 0x59
+#define FXOS8700_M_THS_COUNT 0x5a
+#define FXOS8700_M_CTRL_REG1 0x5b
+#define FXOS8700_M_CTRL_REG2 0x5c
+#define FXOS8700_M_CTRL_REG3 0x5d
+#define FXOS8700_M_INT_SRC 0x5e
+#define FXOS8700_A_VECM_CFG 0x5f
+#define FXOS8700_A_VECM_THS_MSB 0x60
+#define FXOS8700_A_VECM_THS_LSB 0x61
+#define FXOS8700_A_VECM_CNT 0x62
+#define FXOS8700_A_VECM_INITX_MSB 0x63
+#define FXOS8700_A_VECM_INITX_LSB 0x64
+#define FXOS8700_A_VECM_INITY_MSB 0x65
+#define FXOS8700_A_VECM_INITY_LSB 0x66
+#define FXOS8700_A_VECM_INITZ_MSB 0x67
+#define FXOS8700_A_VECM_INITZ_LSB 0x68
+#define FXOS8700_M_VECM_CFG 0x69
+#define FXOS8700_M_VECM_THS_MSB 0x6a
+#define FXOS8700_M_VECM_THS_LSB 0x6b
+#define FXOS8700_M_VECM_CNT 0x6c
+#define FXOS8700_M_VECM_INITX_MSB 0x6d
+#define FXOS8700_M_VECM_INITX_LSB 0x6e
+#define FXOS8700_M_VECM_INITY_MSB 0x6f
+#define FXOS8700_M_VECM_INITY_LSB 0x70
+#define FXOS8700_M_VECM_INITZ_MSB 0x71
+#define FXOS8700_M_VECM_INITZ_LSB 0x72
+#define FXOS8700_A_FFMT_THS_X_MSB 0x73
+#define FXOS8700_A_FFMT_THS_X_LSB 0x74
+#define FXOS8700_A_FFMT_THS_Y_MSB 0x75
+#define FXOS8700_A_FFMT_THS_Y_LSB 0x76
+#define FXOS8700_A_FFMT_THS_Z_MSB 0x77
+#define FXOS8700_A_FFMT_THS_Z_LSB 0x78
+#define FXOS8700_A_TRAN_INIT_MSB 0x79
+#define FXOS8700_A_TRAN_INIT_LSB_X 0x7a
+#define FXOS8700_A_TRAN_INIT_LSB_Y 0x7b
+#define FXOS8700_A_TRAN_INIT_LSB_Z 0x7d
+#define FXOS8700_TM_NVM_LOCK 0x7e
+#define FXOS8700_NVM_DATA0_35 0x80
+#define FXOS8700_NVM_DATA_BNK3 0xa4
+#define FXOS8700_NVM_DATA_BNK2 0xa5
+#define FXOS8700_NVM_DATA_BNK1 0xa6
+#define FXOS8700_NVM_DATA_BNK0 0xa7
+
+/* Bit definitions for FXOS8700_CTRL_REG1 */
+#define FXOS8700_CTRL_ODR_MSK 0x38
+#define FXOS8700_CTRL_ODR_MAX 0x00
+#define FXOS8700_CTRL_ODR_MIN GENMASK(4, 3)
+
+/* Bit definitions for FXOS8700_M_CTRL_REG1 */
+#define FXOS8700_HMS_MASK GENMASK(1, 0)
+#define FXOS8700_OS_MASK GENMASK(4, 2)
+
+/* Bit definitions for FXOS8700_M_CTRL_REG2 */
+#define FXOS8700_MAXMIN_RST BIT(2)
+#define FXOS8700_MAXMIN_DIS_THS BIT(3)
+#define FXOS8700_MAXMIN_DIS BIT(4)
+
+#define FXOS8700_ACTIVE 0x01
+#define FXOS8700_ACTIVE_MIN_USLEEP 4000 /* from table 6 in datasheet */
+
+#define FXOS8700_DEVICE_ID 0xC7
+#define FXOS8700_PRE_DEVICE_ID 0xC4
+#define FXOS8700_DATA_BUF_SIZE 3
+
+struct fxos8700_data {
+ struct regmap *regmap;
+ struct iio_trigger *trig;
+ __be16 buf[FXOS8700_DATA_BUF_SIZE] ____cacheline_aligned;
+};
+
+/* Regmap info */
+static const struct regmap_range read_range[] = {
+ {
+ .range_min = FXOS8700_STATUS,
+ .range_max = FXOS8700_A_FFMT_COUNT,
+ }, {
+ .range_min = FXOS8700_TRANSIENT_CFG,
+ .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
+ },
+};
+
+static const struct regmap_range write_range[] = {
+ {
+ .range_min = FXOS8700_F_SETUP,
+ .range_max = FXOS8700_TRIG_CFG,
+ }, {
+ .range_min = FXOS8700_XYZ_DATA_CFG,
+ .range_max = FXOS8700_HP_FILTER_CUTOFF,
+ }, {
+ .range_min = FXOS8700_PL_CFG,
+ .range_max = FXOS8700_A_FFMT_CFG,
+ }, {
+ .range_min = FXOS8700_A_FFMT_THS,
+ .range_max = FXOS8700_TRANSIENT_CFG,
+ }, {
+ .range_min = FXOS8700_TRANSIENT_THS,
+ .range_max = FXOS8700_PULSE_CFG,
+ }, {
+ .range_min = FXOS8700_PULSE_THSX,
+ .range_max = FXOS8700_OFF_Z,
+ }, {
+ .range_min = FXOS8700_M_OFF_X_MSB,
+ .range_max = FXOS8700_M_OFF_Z_LSB,
+ }, {
+ .range_min = FXOS8700_M_THS_CFG,
+ .range_max = FXOS8700_M_THS_CFG,
+ }, {
+ .range_min = FXOS8700_M_THS_X_MSB,
+ .range_max = FXOS8700_M_CTRL_REG3,
+ }, {
+ .range_min = FXOS8700_A_VECM_CFG,
+ .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
+ },
+};
+
+static const struct regmap_access_table driver_read_table = {
+ .yes_ranges = read_range,
+ .n_yes_ranges = ARRAY_SIZE(read_range),
+};
+
+static const struct regmap_access_table driver_write_table = {
+ .yes_ranges = write_range,
+ .n_yes_ranges = ARRAY_SIZE(write_range),
+};
+
+const struct regmap_config fxos8700_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = FXOS8700_NVM_DATA_BNK0,
+ .rd_table = &driver_read_table,
+ .wr_table = &driver_write_table,
+};
+EXPORT_SYMBOL(fxos8700_regmap_config);
+
+#define FXOS8700_CHANNEL(_type, _axis) { \
+ .type = _type, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+}
+
+enum fxos8700_accel_scale_bits {
+ MODE_2G = 0,
+ MODE_4G,
+ MODE_8G,
+};
+
+/* scan indexes follow DATA register order */
+enum fxos8700_scan_axis {
+ FXOS8700_SCAN_ACCEL_X = 0,
+ FXOS8700_SCAN_ACCEL_Y,
+ FXOS8700_SCAN_ACCEL_Z,
+ FXOS8700_SCAN_MAGN_X,
+ FXOS8700_SCAN_MAGN_Y,
+ FXOS8700_SCAN_MAGN_Z,
+ FXOS8700_SCAN_RHALL,
+ FXOS8700_SCAN_TIMESTAMP,
+};
+
+enum fxos8700_sensor {
+ FXOS8700_ACCEL = 0,
+ FXOS8700_MAGN,
+ FXOS8700_NUM_SENSORS /* must be last */
+};
+
+enum fxos8700_int_pin {
+ FXOS8700_PIN_INT1,
+ FXOS8700_PIN_INT2
+};
+
+struct fxos8700_scale {
+ u8 bits;
+ int uscale;
+};
+
+struct fxos8700_odr {
+ u8 bits;
+ int odr;
+ int uodr;
+};
+
+static const struct fxos8700_scale fxos8700_accel_scale[] = {
+ { MODE_2G, 244},
+ { MODE_4G, 488},
+ { MODE_8G, 976},
+};
+
+/*
+ * Accellerometer and magnetometer have the same ODR options, set in the
+ * CTRL_REG1 register. ODR is halved when using both sensors at once in
+ * hybrid mode.
+ */
+static const struct fxos8700_odr fxos8700_odr[] = {
+ {0x00, 800, 0},
+ {0x01, 400, 0},
+ {0x02, 200, 0},
+ {0x03, 100, 0},
+ {0x04, 50, 0},
+ {0x05, 12, 500000},
+ {0x06, 6, 250000},
+ {0x07, 1, 562500},
+};
+
+static const struct iio_chan_spec fxos8700_channels[] = {
+ FXOS8700_CHANNEL(IIO_ACCEL, X),
+ FXOS8700_CHANNEL(IIO_ACCEL, Y),
+ FXOS8700_CHANNEL(IIO_ACCEL, Z),
+ FXOS8700_CHANNEL(IIO_MAGN, X),
+ FXOS8700_CHANNEL(IIO_MAGN, Y),
+ FXOS8700_CHANNEL(IIO_MAGN, Z),
+ IIO_CHAN_SOFT_TIMESTAMP(FXOS8700_SCAN_TIMESTAMP),
+};
+
+static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
+{
+ switch (iio_type) {
+ case IIO_ACCEL:
+ return FXOS8700_ACCEL;
+ case IIO_ANGL_VEL:
+ return FXOS8700_MAGN;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int fxos8700_set_active_mode(struct fxos8700_data *data,
+ enum fxos8700_sensor t, bool mode)
+{
+ int ret;
+
+ ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, mode);
+ if (ret)
+ return ret;
+
+ usleep_range(FXOS8700_ACTIVE_MIN_USLEEP,
+ FXOS8700_ACTIVE_MIN_USLEEP + 1000);
+
+ return 0;
+}
+
+static int fxos8700_set_scale(struct fxos8700_data *data,
+ enum fxos8700_sensor t, int uscale)
+{
+ int i;
+ static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
+ struct device *dev = regmap_get_device(data->regmap);
+
+ if (t == FXOS8700_MAGN) {
+ dev_err(dev, "Magnetometer scale is locked at 1200uT\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < scale_num; i++)
+ if (fxos8700_accel_scale[i].uscale == uscale)
+ break;
+
+ if (i == scale_num)
+ return -EINVAL;
+
+ return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
+ fxos8700_accel_scale[i].bits);
+}
+
+static int fxos8700_get_scale(struct fxos8700_data *data,
+ enum fxos8700_sensor t, int *uscale)
+{
+ int i, ret, val;
+ static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
+
+ if (t == FXOS8700_MAGN) {
+ *uscale = 1200; /* Magnetometer is locked at 1200uT */
+ return 0;
+ }
+
+ ret = regmap_read(data->regmap, FXOS8700_XYZ_DATA_CFG, &val);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < scale_num; i++) {
+ if (fxos8700_accel_scale[i].bits == (val & 0x3)) {
+ *uscale = fxos8700_accel_scale[i].uscale;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
+ int axis, int *val)
+{
+ u8 base, reg;
+ int ret;
+ enum fxos8700_sensor type = fxos8700_to_sensor(chan_type);
+
+ base = type ? FXOS8700_OUT_X_MSB : FXOS8700_M_OUT_X_MSB;
+
+ /* Block read 6 bytes of device output registers to avoid data loss */
+ ret = regmap_bulk_read(data->regmap, base, data->buf,
+ FXOS8700_DATA_BUF_SIZE);
+ if (ret)
+ return ret;
+
+ /* Convert axis to buffer index */
+ reg = axis - IIO_MOD_X;
+
+ /* Convert to native endianness */
+ *val = sign_extend32(be16_to_cpu(data->buf[reg]), 15);
+
+ return 0;
+}
+
+static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
+ int odr, int uodr)
+{
+ int i, ret, val;
+ bool active_mode;
+ static const int odr_num = ARRAY_SIZE(fxos8700_odr);
+
+ ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
+ if (ret)
+ return ret;
+
+ active_mode = val & FXOS8700_ACTIVE;
+
+ if (active_mode) {
+ /*
+ * The device must be in standby mode to change any of the
+ * other fields within CTRL_REG1
+ */
+ ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
+ val & ~FXOS8700_ACTIVE);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < odr_num; i++)
+ if (fxos8700_odr[i].odr == odr && fxos8700_odr[i].uodr == uodr)
+ break;
+
+ if (i >= odr_num)
+ return -EINVAL;
+
+ return regmap_update_bits(data->regmap,
+ FXOS8700_CTRL_REG1,
+ FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE,
+ fxos8700_odr[i].bits << 3 | active_mode);
+}
+
+static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
+ int *odr, int *uodr)
+{
+ int i, val, ret;
+ static const int odr_num = ARRAY_SIZE(fxos8700_odr);
+
+ ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
+ if (ret)
+ return ret;
+
+ val &= FXOS8700_CTRL_ODR_MSK;
+
+ for (i = 0; i < odr_num; i++)
+ if (val == fxos8700_odr[i].bits)
+ break;
+
+ if (i >= odr_num)
+ return -EINVAL;
+
+ *odr = fxos8700_odr[i].odr;
+ *uodr = fxos8700_odr[i].uodr;
+
+ return 0;
+}
+
+static int fxos8700_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret;
+ struct fxos8700_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = fxos8700_get_data(data, chan->type, chan->channel2, val);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ ret = fxos8700_get_scale(data, fxos8700_to_sensor(chan->type),
+ val2);
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = fxos8700_get_odr(data, fxos8700_to_sensor(chan->type),
+ val, val2);
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int fxos8700_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct fxos8700_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return fxos8700_set_scale(data, fxos8700_to_sensor(chan->type),
+ val2);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return fxos8700_set_odr(data, fxos8700_to_sensor(chan->type),
+ val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
+ "1.5625 6.25 12.5 50 100 200 400 800");
+static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
+ "1.5625 6.25 12.5 50 100 200 400 800");
+static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
+static IIO_CONST_ATTR(in_magn_scale_available, "0.000001200");
+
+static struct attribute *fxos8700_attrs[] = {
+ &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
+ &iio_const_attr_in_magn_sampling_frequency_available.dev_attr.attr,
+ &iio_const_attr_in_accel_scale_available.dev_attr.attr,
+ &iio_const_attr_in_magn_scale_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group fxos8700_attrs_group = {
+ .attrs = fxos8700_attrs,
+};
+
+static const struct iio_info fxos8700_info = {
+ .read_raw = fxos8700_read_raw,
+ .write_raw = fxos8700_write_raw,
+ .attrs = &fxos8700_attrs_group,
+};
+
+static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
+{
+ int ret;
+ unsigned int val;
+ struct device *dev = regmap_get_device(data->regmap);
+
+ ret = regmap_read(data->regmap, FXOS8700_WHO_AM_I, &val);
+ if (ret) {
+ dev_err(dev, "Error reading chip id\n");
+ return ret;
+ }
+ if (val != FXOS8700_DEVICE_ID && val != FXOS8700_PRE_DEVICE_ID) {
+ dev_err(dev, "Wrong chip id, got %x expected %x or %x\n",
+ val, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);
+ return -ENODEV;
+ }
+
+ ret = fxos8700_set_active_mode(data, FXOS8700_ACCEL, true);
+ if (ret)
+ return ret;
+
+ ret = fxos8700_set_active_mode(data, FXOS8700_MAGN, true);
+ if (ret)
+ return ret;
+
+ /*
+ * The device must be in standby mode to change any of the other fields
+ * within CTRL_REG1
+ */
+ ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, 0x00);
+ if (ret)
+ return ret;
+
+ /* Set max oversample ratio (OSR) and both devices active */
+ ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG1,
+ FXOS8700_HMS_MASK | FXOS8700_OS_MASK);
+ if (ret)
+ return ret;
+
+ /* Disable and rst min/max measurements & threshold */
+ ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG2,
+ FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |
+ FXOS8700_MAXMIN_DIS);
+ if (ret)
+ return ret;
+
+ /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
+ ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
+ FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE);
+ if (ret)
+ return ret;
+
+ /* Set for max full-scale range (+/-8G) */
+ return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
+}
+
+static void fxos8700_chip_uninit(void *data)
+{
+ struct fxos8700_data *fxos8700_data = data;
+
+ fxos8700_set_active_mode(fxos8700_data, FXOS8700_ACCEL, false);
+ fxos8700_set_active_mode(fxos8700_data, FXOS8700_MAGN, false);
+}
+
+int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
+ const char *name, bool use_spi)
+{
+ struct iio_dev *indio_dev;
+ struct fxos8700_data *data;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ dev_set_drvdata(dev, indio_dev);
+ data->regmap = regmap;
+
+ ret = fxos8700_chip_init(data, use_spi);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, fxos8700_chip_uninit, data);
+ if (ret)
+ return ret;
+
+ indio_dev->dev.parent = dev;
+ indio_dev->channels = fxos8700_channels;
+ indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);
+ indio_dev->name = name ? name : "fxos8700";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &fxos8700_info;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+EXPORT_SYMBOL_GPL(fxos8700_core_probe);
+
+MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
+MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/fxos8700_i2c.c b/drivers/iio/imu/fxos8700_i2c.c
new file mode 100644
index 000000000000..3ceb76366313
--- /dev/null
+++ b/drivers/iio/imu/fxos8700_i2c.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FXOS8700 - NXP IMU, I2C bits
+ *
+ * 7-bit I2C slave address determined by SA1 and SA0 logic level
+ * inputs represented in the following table:
+ * SA1 | SA0 | Slave Address
+ * 0 | 0 | 0x1E
+ * 0 | 1 | 0x1D
+ * 1 | 0 | 0x1C
+ * 1 | 1 | 0x1F
+ */
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+
+#include "fxos8700.h"
+
+static int fxos8700_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap *regmap;
+ const char *name = NULL;
+
+ regmap = devm_regmap_init_i2c(client, &fxos8700_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+ (int)PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ if (id)
+ name = id->name;
+
+ return fxos8700_core_probe(&client->dev, regmap, name, false);
+}
+
+static const struct i2c_device_id fxos8700_i2c_id[] = {
+ {"fxos8700", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, fxos8700_i2c_id);
+
+static const struct acpi_device_id fxos8700_acpi_match[] = {
+ {"FXOS8700", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, fxos8700_acpi_match);
+
+static const struct of_device_id fxos8700_of_match[] = {
+ { .compatible = "nxp,fxos8700" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, fxos8700_of_match);
+
+static struct i2c_driver fxos8700_i2c_driver = {
+ .driver = {
+ .name = "fxos8700_i2c",
+ .acpi_match_table = ACPI_PTR(fxos8700_acpi_match),
+ .of_match_table = fxos8700_of_match,
+ },
+ .probe = fxos8700_i2c_probe,
+ .id_table = fxos8700_i2c_id,
+};
+module_i2c_driver(fxos8700_i2c_driver);
+
+MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
+MODULE_DESCRIPTION("FXOS8700 I2C driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/fxos8700_spi.c b/drivers/iio/imu/fxos8700_spi.c
new file mode 100644
index 000000000000..57e7bb6444e7
--- /dev/null
+++ b/drivers/iio/imu/fxos8700_spi.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FXOS8700 - NXP IMU, SPI bits
+ */
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "fxos8700.h"
+
+static int fxos8700_spi_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+ const struct spi_device_id *id = spi_get_device_id(spi);
+
+ regmap = devm_regmap_init_spi(spi, &fxos8700_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&spi->dev, "Failed to register spi regmap %d\n",
+ (int)PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ return fxos8700_core_probe(&spi->dev, regmap, id->name, true);
+}
+
+static const struct spi_device_id fxos8700_spi_id[] = {
+ {"fxos8700", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(spi, fxos8700_spi_id);
+
+static const struct acpi_device_id fxos8700_acpi_match[] = {
+ {"FXOS8700", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, fxos8700_acpi_match);
+
+static const struct of_device_id fxos8700_of_match[] = {
+ { .compatible = "nxp,fxos8700" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, fxos8700_of_match);
+
+static struct spi_driver fxos8700_spi_driver = {
+ .probe = fxos8700_spi_probe,
+ .id_table = fxos8700_spi_id,
+ .driver = {
+ .acpi_match_table = ACPI_PTR(fxos8700_acpi_match),
+ .of_match_table = fxos8700_of_match,
+ .name = "fxos8700_spi",
+ },
+};
+module_spi_driver(fxos8700_spi_driver);
+
+MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
+MODULE_DESCRIPTION("FXOS8700 SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile
index 70ffe0d13d8c..c103441a906b 100644
--- a/drivers/iio/imu/inv_mpu6050/Makefile
+++ b/drivers/iio/imu/inv_mpu6050/Makefile
@@ -4,10 +4,11 @@
#
obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o
-inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o
+inv-mpu6050-y := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o \
+ inv_mpu_aux.o inv_mpu_magn.o
obj-$(CONFIG_INV_MPU6050_I2C) += inv-mpu6050-i2c.o
-inv-mpu6050-i2c-objs := inv_mpu_i2c.o inv_mpu_acpi.o
+inv-mpu6050-i2c-y := inv_mpu_i2c.o inv_mpu_acpi.o
obj-$(CONFIG_INV_MPU6050_SPI) += inv-mpu6050-spi.o
-inv-mpu6050-spi-objs := inv_mpu_spi.o
+inv-mpu6050-spi-y := inv_mpu_spi.o
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_aux.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_aux.c
new file mode 100644
index 000000000000..7327e5723f96
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_aux.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 TDK-InvenSense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+
+#include "inv_mpu_aux.h"
+#include "inv_mpu_iio.h"
+
+/*
+ * i2c master auxiliary bus transfer function.
+ * Requires the i2c operations to be correctly setup before.
+ */
+static int inv_mpu_i2c_master_xfer(const struct inv_mpu6050_state *st)
+{
+ /* use 50hz frequency for xfer */
+ const unsigned int freq = 50;
+ const unsigned int period_ms = 1000 / freq;
+ uint8_t d;
+ unsigned int user_ctrl;
+ int ret;
+
+ /* set sample rate */
+ d = INV_MPU6050_FIFO_RATE_TO_DIVIDER(freq);
+ ret = regmap_write(st->map, st->reg->sample_rate_div, d);
+ if (ret)
+ return ret;
+
+ /* start i2c master */
+ user_ctrl = st->chip_config.user_ctrl | INV_MPU6050_BIT_I2C_MST_EN;
+ ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
+ if (ret)
+ goto error_restore_rate;
+
+ /* wait for xfer: 1 period + half-period margin */
+ msleep(period_ms + period_ms / 2);
+
+ /* stop i2c master */
+ user_ctrl = st->chip_config.user_ctrl;
+ ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
+ if (ret)
+ goto error_stop_i2c;
+
+ /* restore sample rate */
+ d = st->chip_config.divider;
+ ret = regmap_write(st->map, st->reg->sample_rate_div, d);
+ if (ret)
+ goto error_restore_rate;
+
+ return 0;
+
+error_stop_i2c:
+ regmap_write(st->map, st->reg->user_ctrl, st->chip_config.user_ctrl);
+error_restore_rate:
+ regmap_write(st->map, st->reg->sample_rate_div, st->chip_config.divider);
+ return ret;
+}
+
+/**
+ * inv_mpu_aux_init() - init i2c auxiliary bus
+ * @st: driver internal state
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+int inv_mpu_aux_init(const struct inv_mpu6050_state *st)
+{
+ unsigned int val;
+ int ret;
+
+ /* configure i2c master */
+ val = INV_MPU6050_BITS_I2C_MST_CLK_400KHZ |
+ INV_MPU6050_BIT_WAIT_FOR_ES;
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_MST_CTRL, val);
+ if (ret)
+ return ret;
+
+ /* configure i2c master delay */
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV4_CTRL, 0);
+ if (ret)
+ return ret;
+
+ val = INV_MPU6050_BIT_I2C_SLV0_DLY_EN |
+ INV_MPU6050_BIT_I2C_SLV1_DLY_EN |
+ INV_MPU6050_BIT_I2C_SLV2_DLY_EN |
+ INV_MPU6050_BIT_I2C_SLV3_DLY_EN |
+ INV_MPU6050_BIT_DELAY_ES_SHADOW;
+ return regmap_write(st->map, INV_MPU6050_REG_I2C_MST_DELAY_CTRL, val);
+}
+
+/**
+ * inv_mpu_aux_read() - read register function for i2c auxiliary bus
+ * @st: driver internal state.
+ * @addr: chip i2c Address
+ * @reg: chip register address
+ * @val: buffer for storing read bytes
+ * @size: number of bytes to read
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+int inv_mpu_aux_read(const struct inv_mpu6050_state *st, uint8_t addr,
+ uint8_t reg, uint8_t *val, size_t size)
+{
+ unsigned int status;
+ int ret;
+
+ if (size > 0x0F)
+ return -EINVAL;
+
+ /* setup i2c SLV0 control: i2c addr, register, enable + size */
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_ADDR(0),
+ INV_MPU6050_BIT_I2C_SLV_RNW | addr);
+ if (ret)
+ return ret;
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_REG(0), reg);
+ if (ret)
+ return ret;
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0),
+ INV_MPU6050_BIT_SLV_EN | size);
+ if (ret)
+ return ret;
+
+ /* do i2c xfer */
+ ret = inv_mpu_i2c_master_xfer(st);
+ if (ret)
+ goto error_disable_i2c;
+
+ /* disable i2c slave */
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0), 0);
+ if (ret)
+ goto error_disable_i2c;
+
+ /* check i2c status */
+ ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);
+ if (ret)
+ return ret;
+ if (status & INV_MPU6050_BIT_I2C_SLV0_NACK)
+ return -EIO;
+
+ /* read data in registers */
+ return regmap_bulk_read(st->map, INV_MPU6050_REG_EXT_SENS_DATA,
+ val, size);
+
+error_disable_i2c:
+ regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0), 0);
+ return ret;
+}
+
+/**
+ * inv_mpu_aux_write() - write register function for i2c auxiliary bus
+ * @st: driver internal state.
+ * @addr: chip i2c Address
+ * @reg: chip register address
+ * @val: 1 byte value to write
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+int inv_mpu_aux_write(const struct inv_mpu6050_state *st, uint8_t addr,
+ uint8_t reg, uint8_t val)
+{
+ unsigned int status;
+ int ret;
+
+ /* setup i2c SLV0 control: i2c addr, register, value, enable + size */
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_ADDR(0), addr);
+ if (ret)
+ return ret;
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_REG(0), reg);
+ if (ret)
+ return ret;
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(0), val);
+ if (ret)
+ return ret;
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0),
+ INV_MPU6050_BIT_SLV_EN | 1);
+ if (ret)
+ return ret;
+
+ /* do i2c xfer */
+ ret = inv_mpu_i2c_master_xfer(st);
+ if (ret)
+ goto error_disable_i2c;
+
+ /* disable i2c slave */
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0), 0);
+ if (ret)
+ goto error_disable_i2c;
+
+ /* check i2c status */
+ ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);
+ if (ret)
+ return ret;
+ if (status & INV_MPU6050_BIT_I2C_SLV0_NACK)
+ return -EIO;
+
+ return 0;
+
+error_disable_i2c:
+ regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0), 0);
+ return ret;
+}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_aux.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_aux.h
new file mode 100644
index 000000000000..b66997545762
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_aux.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 TDK-InvenSense, Inc.
+ */
+
+#ifndef INV_MPU_AUX_H_
+#define INV_MPU_AUX_H_
+
+#include "inv_mpu_iio.h"
+
+int inv_mpu_aux_init(const struct inv_mpu6050_state *st);
+
+int inv_mpu_aux_read(const struct inv_mpu6050_state *st, uint8_t addr,
+ uint8_t reg, uint8_t *val, size_t size);
+
+int inv_mpu_aux_write(const struct inv_mpu6050_state *st, uint8_t addr,
+ uint8_t reg, uint8_t val);
+
+#endif /* INV_MPU_AUX_H_ */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 868281b8adb0..9f9acde229c8 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include "inv_mpu_iio.h"
+#include "inv_mpu_magn.h"
/*
* this is the gyro scale translated from dynamic range plus/minus
@@ -103,6 +104,7 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = {
.divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU6050_INIT_FIFO_RATE),
.gyro_fifo_enable = false,
.accl_fifo_enable = false,
+ .magn_fifo_enable = false,
.accl_fs = INV_MPU6050_FS_02G,
.user_ctrl = 0,
};
@@ -341,6 +343,11 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
*/
st->chip_period = NSEC_PER_MSEC;
+ /* magn chip init, noop if not present in the chip */
+ result = inv_mpu_magn_probe(st);
+ if (result)
+ goto error_power_off;
+
return inv_mpu6050_set_power_itg(st, false);
error_power_off:
@@ -420,6 +427,9 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
ret = inv_mpu6050_sensor_show(st, st->reg->temperature,
IIO_MOD_X, val);
break;
+ case IIO_MAGN:
+ ret = inv_mpu_magn_read(st, chan->channel2, val);
+ break;
default:
ret = -EINVAL;
break;
@@ -478,6 +488,8 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
*val2 = INV_MPU6050_TEMP_SCALE;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_MAGN:
+ return inv_mpu_magn_get_scale(st, chan, val, val2);
default:
return -EINVAL;
}
@@ -719,6 +731,11 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
if (result)
goto fifo_rate_fail_power_off;
+ /* update rate for magn, noop if not present in chip */
+ result = inv_mpu_magn_set_rate(st, fifo_rate);
+ if (result)
+ goto fifo_rate_fail_power_off;
+
fifo_rate_fail_power_off:
result |= inv_mpu6050_set_power_itg(st, false);
fifo_rate_fail_unlock:
@@ -804,8 +821,14 @@ inv_get_mount_matrix(const struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct inv_mpu6050_state *data = iio_priv(indio_dev);
+ const struct iio_mount_matrix *matrix;
- return &data->orientation;
+ if (chan->type == IIO_MAGN)
+ matrix = &data->magn_orient;
+ else
+ matrix = &data->orientation;
+
+ return matrix;
}
static const struct iio_chan_spec_ext_info inv_ext_info[] = {
@@ -873,6 +896,98 @@ static const unsigned long inv_mpu_scan_masks[] = {
0,
};
+#define INV_MPU9X50_MAGN_CHAN(_chan2, _bits, _index) \
+ { \
+ .type = IIO_MAGN, \
+ .modified = 1, \
+ .channel2 = _chan2, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_RAW), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = _bits, \
+ .storagebits = 16, \
+ .shift = 0, \
+ .endianness = IIO_BE, \
+ }, \
+ .ext_info = inv_ext_info, \
+ }
+
+static const struct iio_chan_spec inv_mpu9250_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP),
+ /*
+ * Note that temperature should only be via polled reading only,
+ * not the final scan elements output.
+ */
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
+ | BIT(IIO_CHAN_INFO_OFFSET)
+ | BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = -1,
+ },
+ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
+ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y),
+ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z),
+
+ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X),
+ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y),
+ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
+
+ /* Magnetometer resolution is 16 bits */
+ INV_MPU9X50_MAGN_CHAN(IIO_MOD_X, 16, INV_MPU9X50_SCAN_MAGN_X),
+ INV_MPU9X50_MAGN_CHAN(IIO_MOD_Y, 16, INV_MPU9X50_SCAN_MAGN_Y),
+ INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 16, INV_MPU9X50_SCAN_MAGN_Z),
+};
+
+static const unsigned long inv_mpu9x50_scan_masks[] = {
+ /* 3-axis accel */
+ BIT(INV_MPU6050_SCAN_ACCL_X)
+ | BIT(INV_MPU6050_SCAN_ACCL_Y)
+ | BIT(INV_MPU6050_SCAN_ACCL_Z),
+ /* 3-axis gyro */
+ BIT(INV_MPU6050_SCAN_GYRO_X)
+ | BIT(INV_MPU6050_SCAN_GYRO_Y)
+ | BIT(INV_MPU6050_SCAN_GYRO_Z),
+ /* 3-axis magn */
+ BIT(INV_MPU9X50_SCAN_MAGN_X)
+ | BIT(INV_MPU9X50_SCAN_MAGN_Y)
+ | BIT(INV_MPU9X50_SCAN_MAGN_Z),
+ /* 6-axis accel + gyro */
+ BIT(INV_MPU6050_SCAN_ACCL_X)
+ | BIT(INV_MPU6050_SCAN_ACCL_Y)
+ | BIT(INV_MPU6050_SCAN_ACCL_Z)
+ | BIT(INV_MPU6050_SCAN_GYRO_X)
+ | BIT(INV_MPU6050_SCAN_GYRO_Y)
+ | BIT(INV_MPU6050_SCAN_GYRO_Z),
+ /* 6-axis accel + magn */
+ BIT(INV_MPU6050_SCAN_ACCL_X)
+ | BIT(INV_MPU6050_SCAN_ACCL_Y)
+ | BIT(INV_MPU6050_SCAN_ACCL_Z)
+ | BIT(INV_MPU9X50_SCAN_MAGN_X)
+ | BIT(INV_MPU9X50_SCAN_MAGN_Y)
+ | BIT(INV_MPU9X50_SCAN_MAGN_Z),
+ /* 6-axis gyro + magn */
+ BIT(INV_MPU6050_SCAN_GYRO_X)
+ | BIT(INV_MPU6050_SCAN_GYRO_Y)
+ | BIT(INV_MPU6050_SCAN_GYRO_Z)
+ | BIT(INV_MPU9X50_SCAN_MAGN_X)
+ | BIT(INV_MPU9X50_SCAN_MAGN_Y)
+ | BIT(INV_MPU9X50_SCAN_MAGN_Z),
+ /* 9-axis accel + gyro + magn */
+ BIT(INV_MPU6050_SCAN_ACCL_X)
+ | BIT(INV_MPU6050_SCAN_ACCL_Y)
+ | BIT(INV_MPU6050_SCAN_ACCL_Z)
+ | BIT(INV_MPU6050_SCAN_GYRO_X)
+ | BIT(INV_MPU6050_SCAN_GYRO_Y)
+ | BIT(INV_MPU6050_SCAN_GYRO_Z)
+ | BIT(INV_MPU9X50_SCAN_MAGN_X)
+ | BIT(INV_MPU9X50_SCAN_MAGN_Y)
+ | BIT(INV_MPU9X50_SCAN_MAGN_Z),
+ 0,
+};
+
static const struct iio_chan_spec inv_icm20602_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP),
{
@@ -1154,6 +1269,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
return result;
}
+ /* fill magnetometer orientation */
+ result = inv_mpu_magn_set_orient(st);
+ if (result)
+ return result;
+
/* power is turned on inside check chip type*/
result = inv_check_and_setup_chip(st);
if (result)
@@ -1165,9 +1285,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
return result;
}
- if (inv_mpu_bus_setup)
- inv_mpu_bus_setup(indio_dev);
-
dev_set_drvdata(dev, indio_dev);
indio_dev->dev.parent = dev;
/* name will be NULL when enumerated via ACPI */
@@ -1176,14 +1293,37 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
else
indio_dev->name = dev_name(dev);
- if (chip_type == INV_ICM20602) {
+ /* requires parent device set in indio_dev */
+ if (inv_mpu_bus_setup)
+ inv_mpu_bus_setup(indio_dev);
+
+ switch (chip_type) {
+ case INV_MPU9250:
+ case INV_MPU9255:
+ /*
+ * Use magnetometer inside the chip only if there is no i2c
+ * auxiliary device in use.
+ */
+ if (!st->magn_disabled) {
+ indio_dev->channels = inv_mpu9250_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels);
+ indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
+ } else {
+ indio_dev->channels = inv_mpu_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
+ indio_dev->available_scan_masks = inv_mpu_scan_masks;
+ }
+ break;
+ case INV_ICM20602:
indio_dev->channels = inv_icm20602_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels);
indio_dev->available_scan_masks = inv_icm20602_scan_masks;
- } else {
+ break;
+ default:
indio_dev->channels = inv_mpu_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
indio_dev->available_scan_masks = inv_mpu_scan_masks;
+ break;
}
indio_dev->info = &mpu_info;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 4b8b5a87398c..389cc8505e0e 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -68,6 +68,56 @@ static const char *inv_mpu_match_acpi_device(struct device *dev,
return dev_name(dev);
}
+static bool inv_mpu_i2c_aux_bus(struct device *dev)
+{
+ struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
+
+ switch (st->chip_type) {
+ case INV_ICM20608:
+ case INV_ICM20602:
+ /* no i2c auxiliary bus on the chip */
+ return false;
+ case INV_MPU9250:
+ case INV_MPU9255:
+ if (st->magn_disabled)
+ return true;
+ else
+ return false;
+ default:
+ return true;
+ }
+}
+
+/*
+ * MPU9xxx magnetometer support requires to disable i2c auxiliary bus support.
+ * To ensure backward compatibility with existing setups, do not disable
+ * i2c auxiliary bus if it used.
+ * Check for i2c-gate node in devicetree and set magnetometer disabled.
+ * Only MPU6500 is supported by ACPI, no need to check.
+ */
+static int inv_mpu_magn_disable(struct iio_dev *indio_dev)
+{
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
+ struct device_node *mux_node;
+
+ switch (st->chip_type) {
+ case INV_MPU9250:
+ case INV_MPU9255:
+ mux_node = of_get_child_by_name(dev->of_node, "i2c-gate");
+ if (mux_node != NULL) {
+ st->magn_disabled = true;
+ dev_warn(dev, "disable internal use of magnetometer\n");
+ }
+ of_node_put(mux_node);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
/**
* inv_mpu_probe() - probe function.
* @client: i2c client.
@@ -112,17 +162,12 @@ static int inv_mpu_probe(struct i2c_client *client,
}
result = inv_mpu_core_probe(regmap, client->irq, name,
- NULL, chip_type);
+ inv_mpu_magn_disable, chip_type);
if (result < 0)
return result;
st = iio_priv(dev_get_drvdata(&client->dev));
- switch (st->chip_type) {
- case INV_ICM20608:
- case INV_ICM20602:
- /* no i2c auxiliary bus on the chip */
- break;
- default:
+ if (inv_mpu_i2c_aux_bus(&client->dev)) {
/* declare i2c auxiliary bus */
st->muxc = i2c_mux_alloc(client->adapter, &client->dev,
1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
@@ -137,7 +182,6 @@ static int inv_mpu_probe(struct i2c_client *client,
result = inv_mpu_acpi_create_mux_client(client);
if (result)
goto out_del_mux;
- break;
}
return 0;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 51235677c534..5f6bbe880d78 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -2,6 +2,10 @@
/*
* Copyright (C) 2012 Invensense, Inc.
*/
+
+#ifndef INV_MPU_IIO_H_
+#define INV_MPU_IIO_H_
+
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/mutex.h>
@@ -82,6 +86,7 @@ enum inv_devices {
* @accl_fs: accel full scale range.
* @accl_fifo_enable: enable accel data output
* @gyro_fifo_enable: enable gyro data output
+ * @magn_fifo_enable: enable magn data output
* @divider: chip sample rate divider (sample rate divider - 1)
*/
struct inv_mpu6050_chip_config {
@@ -90,6 +95,7 @@ struct inv_mpu6050_chip_config {
unsigned int accl_fs:2;
unsigned int accl_fifo_enable:1;
unsigned int gyro_fifo_enable:1;
+ unsigned int magn_fifo_enable:1;
u8 divider;
u8 user_ctrl;
};
@@ -127,6 +133,9 @@ struct inv_mpu6050_hw {
* @it_timestamp: timestamp from previous interrupt.
* @data_timestamp: timestamp for next data sample.
* @vddio_supply voltage regulator for the chip.
+ * @magn_disabled: magnetometer disabled for backward compatibility reason.
+ * @magn_raw_to_gauss: coefficient to convert mag raw value to Gauss.
+ * @magn_orient: magnetometer sensor chip orientation if available.
*/
struct inv_mpu6050_state {
struct mutex lock;
@@ -148,6 +157,9 @@ struct inv_mpu6050_state {
s64 it_timestamp;
s64 data_timestamp;
struct regulator *vddio_supply;
+ bool magn_disabled;
+ s32 magn_raw_to_gauss[3];
+ struct iio_mount_matrix magn_orient;
};
/*register and associated bit definition*/
@@ -160,9 +172,41 @@ struct inv_mpu6050_state {
#define INV_MPU6050_REG_ACCEL_CONFIG 0x1C
#define INV_MPU6050_REG_FIFO_EN 0x23
+#define INV_MPU6050_BIT_SLAVE_0 0x01
+#define INV_MPU6050_BIT_SLAVE_1 0x02
+#define INV_MPU6050_BIT_SLAVE_2 0x04
#define INV_MPU6050_BIT_ACCEL_OUT 0x08
#define INV_MPU6050_BITS_GYRO_OUT 0x70
+#define INV_MPU6050_REG_I2C_MST_CTRL 0x24
+#define INV_MPU6050_BITS_I2C_MST_CLK_400KHZ 0x0D
+#define INV_MPU6050_BIT_I2C_MST_P_NSR 0x10
+#define INV_MPU6050_BIT_SLV3_FIFO_EN 0x20
+#define INV_MPU6050_BIT_WAIT_FOR_ES 0x40
+#define INV_MPU6050_BIT_MULT_MST_EN 0x80
+
+/* control I2C slaves from 0 to 3 */
+#define INV_MPU6050_REG_I2C_SLV_ADDR(_x) (0x25 + 3 * (_x))
+#define INV_MPU6050_BIT_I2C_SLV_RNW 0x80
+
+#define INV_MPU6050_REG_I2C_SLV_REG(_x) (0x26 + 3 * (_x))
+
+#define INV_MPU6050_REG_I2C_SLV_CTRL(_x) (0x27 + 3 * (_x))
+#define INV_MPU6050_BIT_SLV_GRP 0x10
+#define INV_MPU6050_BIT_SLV_REG_DIS 0x20
+#define INV_MPU6050_BIT_SLV_BYTE_SW 0x40
+#define INV_MPU6050_BIT_SLV_EN 0x80
+
+/* I2C master delay register */
+#define INV_MPU6050_REG_I2C_SLV4_CTRL 0x34
+#define INV_MPU6050_BITS_I2C_MST_DLY(_x) ((_x) & 0x1F)
+
+#define INV_MPU6050_REG_I2C_MST_STATUS 0x36
+#define INV_MPU6050_BIT_I2C_SLV0_NACK 0x01
+#define INV_MPU6050_BIT_I2C_SLV1_NACK 0x02
+#define INV_MPU6050_BIT_I2C_SLV2_NACK 0x04
+#define INV_MPU6050_BIT_I2C_SLV3_NACK 0x08
+
#define INV_MPU6050_REG_INT_ENABLE 0x38
#define INV_MPU6050_BIT_DATA_RDY_EN 0x01
#define INV_MPU6050_BIT_DMP_INT_EN 0x02
@@ -175,6 +219,18 @@ struct inv_mpu6050_state {
#define INV_MPU6050_BIT_FIFO_OVERFLOW_INT 0x10
#define INV_MPU6050_BIT_RAW_DATA_RDY_INT 0x01
+#define INV_MPU6050_REG_EXT_SENS_DATA 0x49
+
+/* I2C slaves data output from 0 to 3 */
+#define INV_MPU6050_REG_I2C_SLV_DO(_x) (0x63 + (_x))
+
+#define INV_MPU6050_REG_I2C_MST_DELAY_CTRL 0x67
+#define INV_MPU6050_BIT_I2C_SLV0_DLY_EN 0x01
+#define INV_MPU6050_BIT_I2C_SLV1_DLY_EN 0x02
+#define INV_MPU6050_BIT_I2C_SLV2_DLY_EN 0x04
+#define INV_MPU6050_BIT_I2C_SLV3_DLY_EN 0x08
+#define INV_MPU6050_BIT_DELAY_ES_SHADOW 0x80
+
#define INV_MPU6050_REG_USER_CTRL 0x6A
#define INV_MPU6050_BIT_FIFO_RST 0x04
#define INV_MPU6050_BIT_DMP_RST 0x08
@@ -202,6 +258,9 @@ struct inv_mpu6050_state {
#define INV_MPU6050_BYTES_PER_3AXIS_SENSOR 6
#define INV_MPU6050_FIFO_COUNT_BYTE 2
+/* MPU9X50 9-axis magnetometer */
+#define INV_MPU9X50_BYTES_MAGN 7
+
/* ICM20602 FIFO samples include temperature readings */
#define INV_ICM20602_BYTES_PER_TEMP_SENSOR 2
@@ -229,8 +288,8 @@ struct inv_mpu6050_state {
#define INV_ICM20602_TEMP_OFFSET 8170
#define INV_ICM20602_TEMP_SCALE 3060
-/* 6 + 6 round up and plus 8 */
-#define INV_MPU6050_OUTPUT_DATA_SIZE 24
+/* 6 + 6 + 7 (for MPU9x50) = 19 round up to 24 and plus 8 */
+#define INV_MPU6050_OUTPUT_DATA_SIZE 32
#define INV_MPU6050_REG_INT_PIN_CFG 0x37
#define INV_MPU6050_ACTIVE_HIGH 0x00
@@ -279,6 +338,11 @@ enum inv_mpu6050_scan {
INV_MPU6050_SCAN_GYRO_Y,
INV_MPU6050_SCAN_GYRO_Z,
INV_MPU6050_SCAN_TIMESTAMP,
+
+ INV_MPU9X50_SCAN_MAGN_X = INV_MPU6050_SCAN_GYRO_Z + 1,
+ INV_MPU9X50_SCAN_MAGN_Y,
+ INV_MPU9X50_SCAN_MAGN_Z,
+ INV_MPU9X50_SCAN_TIMESTAMP,
};
/* scan element definition for ICM20602, which includes temperature */
@@ -344,3 +408,5 @@ void inv_mpu_acpi_delete_mux_client(struct i2c_client *client);
int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type);
extern const struct dev_pm_ops inv_mpu_pmops;
+
+#endif
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
new file mode 100644
index 000000000000..02735af152c8
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 TDK-InvenSense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/string.h>
+
+#include "inv_mpu_aux.h"
+#include "inv_mpu_iio.h"
+#include "inv_mpu_magn.h"
+
+/*
+ * MPU9250 magnetometer is an AKM AK8963 chip on I2C aux bus
+ */
+#define INV_MPU_MAGN_I2C_ADDR 0x0C
+
+#define INV_MPU_MAGN_REG_WIA 0x00
+#define INV_MPU_MAGN_BITS_WIA 0x48
+
+#define INV_MPU_MAGN_REG_ST1 0x02
+#define INV_MPU_MAGN_BIT_DRDY 0x01
+#define INV_MPU_MAGN_BIT_DOR 0x02
+
+#define INV_MPU_MAGN_REG_DATA 0x03
+
+#define INV_MPU_MAGN_REG_ST2 0x09
+#define INV_MPU_MAGN_BIT_HOFL 0x08
+#define INV_MPU_MAGN_BIT_BITM 0x10
+
+#define INV_MPU_MAGN_REG_CNTL1 0x0A
+#define INV_MPU_MAGN_BITS_MODE_PWDN 0x00
+#define INV_MPU_MAGN_BITS_MODE_SINGLE 0x01
+#define INV_MPU_MAGN_BITS_MODE_FUSE 0x0F
+#define INV_MPU_MAGN_BIT_OUTPUT_BIT 0x10
+
+#define INV_MPU_MAGN_REG_CNTL2 0x0B
+#define INV_MPU_MAGN_BIT_SRST 0x01
+
+#define INV_MPU_MAGN_REG_ASAX 0x10
+#define INV_MPU_MAGN_REG_ASAY 0x11
+#define INV_MPU_MAGN_REG_ASAZ 0x12
+
+/* Magnetometer maximum frequency */
+#define INV_MPU_MAGN_FREQ_HZ_MAX 50
+
+static bool inv_magn_supported(const struct inv_mpu6050_state *st)
+{
+ switch (st->chip_type) {
+ case INV_MPU9250:
+ case INV_MPU9255:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* init magnetometer chip */
+static int inv_magn_init(struct inv_mpu6050_state *st)
+{
+ uint8_t val;
+ uint8_t asa[3];
+ int ret;
+
+ /* check whoami */
+ ret = inv_mpu_aux_read(st, INV_MPU_MAGN_I2C_ADDR, INV_MPU_MAGN_REG_WIA,
+ &val, sizeof(val));
+ if (ret)
+ return ret;
+ if (val != INV_MPU_MAGN_BITS_WIA)
+ return -ENODEV;
+
+ /* reset chip */
+ ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
+ INV_MPU_MAGN_REG_CNTL2,
+ INV_MPU_MAGN_BIT_SRST);
+ if (ret)
+ return ret;
+
+ /* read fuse ROM data */
+ ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
+ INV_MPU_MAGN_REG_CNTL1,
+ INV_MPU_MAGN_BITS_MODE_FUSE);
+ if (ret)
+ return ret;
+
+ ret = inv_mpu_aux_read(st, INV_MPU_MAGN_I2C_ADDR, INV_MPU_MAGN_REG_ASAX,
+ asa, sizeof(asa));
+ if (ret)
+ return ret;
+
+ /* switch back to power-down */
+ ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
+ INV_MPU_MAGN_REG_CNTL1,
+ INV_MPU_MAGN_BITS_MODE_PWDN);
+ if (ret)
+ return ret;
+
+ /*
+ * Sensitivity adjustement and scale to Gauss
+ *
+ * Hadj = H * (((ASA - 128) * 0.5 / 128) + 1)
+ * Factor simplification:
+ * Hadj = H * ((ASA + 128) / 256)
+ *
+ * Sensor sentivity
+ * 0.15 uT in 16 bits mode
+ * 1 uT = 0.01 G and value is in micron (1e6)
+ * sensitvity = 0.15 uT * 0.01 * 1e6
+ *
+ * raw_to_gauss = Hadj * 1500
+ */
+ st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 128) * 1500) / 256;
+ st->magn_raw_to_gauss[1] = (((int32_t)asa[1] + 128) * 1500) / 256;
+ st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * 1500) / 256;
+
+ return 0;
+}
+
+/**
+ * inv_mpu_magn_probe() - probe and setup magnetometer chip
+ * @st: driver internal state
+ *
+ * Returns 0 on success, a negative error code otherwise
+ *
+ * It is probing the chip and setting up all needed i2c transfers.
+ * Noop if there is no magnetometer in the chip.
+ */
+int inv_mpu_magn_probe(struct inv_mpu6050_state *st)
+{
+ int ret;
+
+ /* quit if chip is not supported */
+ if (!inv_magn_supported(st))
+ return 0;
+
+ /* configure i2c master aux port */
+ ret = inv_mpu_aux_init(st);
+ if (ret)
+ return ret;
+
+ /* check and init mag chip */
+ ret = inv_magn_init(st);
+ if (ret)
+ return ret;
+
+ /*
+ * configure mpu i2c master accesses
+ * i2c SLV0: read sensor data, 7 bytes data(6)-ST2
+ * Byte swap data to store them in big-endian in impair address groups
+ */
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_ADDR(0),
+ INV_MPU6050_BIT_I2C_SLV_RNW | INV_MPU_MAGN_I2C_ADDR);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_REG(0),
+ INV_MPU_MAGN_REG_DATA);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0),
+ INV_MPU6050_BIT_SLV_EN |
+ INV_MPU6050_BIT_SLV_BYTE_SW |
+ INV_MPU6050_BIT_SLV_GRP |
+ INV_MPU9X50_BYTES_MAGN);
+ if (ret)
+ return ret;
+
+ /* i2c SLV1: launch single measurement */
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_ADDR(1),
+ INV_MPU_MAGN_I2C_ADDR);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_REG(1),
+ INV_MPU_MAGN_REG_CNTL1);
+ if (ret)
+ return ret;
+
+ /* add 16 bits mode */
+ ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1),
+ INV_MPU_MAGN_BITS_MODE_SINGLE |
+ INV_MPU_MAGN_BIT_OUTPUT_BIT);
+ if (ret)
+ return ret;
+
+ return regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(1),
+ INV_MPU6050_BIT_SLV_EN | 1);
+}
+
+/**
+ * inv_mpu_magn_set_rate() - set magnetometer sampling rate
+ * @st: driver internal state
+ * @fifo_rate: mpu set fifo rate
+ *
+ * Returns 0 on success, a negative error code otherwise
+ *
+ * Limit sampling frequency to the maximum value supported by the
+ * magnetometer chip. Resulting in duplicated data for higher frequencies.
+ * Noop if there is no magnetometer in the chip.
+ */
+int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate)
+{
+ uint8_t d;
+
+ /* quit if chip is not supported */
+ if (!inv_magn_supported(st))
+ return 0;
+
+ /*
+ * update i2c master delay to limit mag sampling to max frequency
+ * compute fifo_rate divider d: rate = fifo_rate / (d + 1)
+ */
+ if (fifo_rate > INV_MPU_MAGN_FREQ_HZ_MAX)
+ d = fifo_rate / INV_MPU_MAGN_FREQ_HZ_MAX - 1;
+ else
+ d = 0;
+
+ return regmap_write(st->map, INV_MPU6050_REG_I2C_SLV4_CTRL, d);
+}
+
+/**
+ * inv_mpu_magn_set_orient() - fill magnetometer mounting matrix
+ * @st: driver internal state
+ *
+ * Returns 0 on success, a negative error code otherwise
+ *
+ * Fill magnetometer mounting matrix using the provided chip matrix.
+ */
+int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st)
+{
+ const char *orient;
+ char *str;
+ int i;
+
+ /* fill magnetometer orientation */
+ switch (st->chip_type) {
+ case INV_MPU9250:
+ case INV_MPU9255:
+ /* x <- y */
+ st->magn_orient.rotation[0] = st->orientation.rotation[3];
+ st->magn_orient.rotation[1] = st->orientation.rotation[4];
+ st->magn_orient.rotation[2] = st->orientation.rotation[5];
+ /* y <- x */
+ st->magn_orient.rotation[3] = st->orientation.rotation[0];
+ st->magn_orient.rotation[4] = st->orientation.rotation[1];
+ st->magn_orient.rotation[5] = st->orientation.rotation[2];
+ /* z <- -z */
+ for (i = 0; i < 3; ++i) {
+ orient = st->orientation.rotation[6 + i];
+ /* use length + 2 for adding minus sign if needed */
+ str = devm_kzalloc(regmap_get_device(st->map),
+ strlen(orient) + 2, GFP_KERNEL);
+ if (str == NULL)
+ return -ENOMEM;
+ if (strcmp(orient, "0") == 0) {
+ strcpy(str, orient);
+ } else if (orient[0] == '-') {
+ strcpy(str, &orient[1]);
+ } else {
+ str[0] = '-';
+ strcpy(&str[1], orient);
+ }
+ st->magn_orient.rotation[6 + i] = str;
+ }
+ break;
+ default:
+ st->magn_orient = st->orientation;
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * inv_mpu_magn_read() - read magnetometer data
+ * @st: driver internal state
+ * @axis: IIO modifier axis value
+ * @val: store corresponding axis value
+ *
+ * Returns 0 on success, a negative error code otherwise
+ */
+int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val)
+{
+ unsigned int user_ctrl, status;
+ __be16 data[3];
+ uint8_t addr;
+ uint8_t d;
+ unsigned int period_ms;
+ int ret;
+
+ /* quit if chip is not supported */
+ if (!inv_magn_supported(st))
+ return -ENODEV;
+
+ /* Mag data: X - Y - Z */
+ switch (axis) {
+ case IIO_MOD_X:
+ addr = 0;
+ break;
+ case IIO_MOD_Y:
+ addr = 1;
+ break;
+ case IIO_MOD_Z:
+ addr = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* set sample rate to max mag freq */
+ d = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU_MAGN_FREQ_HZ_MAX);
+ ret = regmap_write(st->map, st->reg->sample_rate_div, d);
+ if (ret)
+ return ret;
+
+ /* start i2c master, wait for xfer, stop */
+ user_ctrl = st->chip_config.user_ctrl | INV_MPU6050_BIT_I2C_MST_EN;
+ ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
+ if (ret)
+ return ret;
+
+ /* need to wait 2 periods + half-period margin */
+ period_ms = 1000 / INV_MPU_MAGN_FREQ_HZ_MAX;
+ msleep(period_ms * 2 + period_ms / 2);
+ user_ctrl = st->chip_config.user_ctrl;
+ ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
+ if (ret)
+ return ret;
+
+ /* restore sample rate */
+ d = st->chip_config.divider;
+ ret = regmap_write(st->map, st->reg->sample_rate_div, d);
+ if (ret)
+ return ret;
+
+ /* check i2c status and read raw data */
+ ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);
+ if (ret)
+ return ret;
+
+ if (status & INV_MPU6050_BIT_I2C_SLV0_NACK ||
+ status & INV_MPU6050_BIT_I2C_SLV1_NACK)
+ return -EIO;
+
+ ret = regmap_bulk_read(st->map, INV_MPU6050_REG_EXT_SENS_DATA,
+ data, sizeof(data));
+ if (ret)
+ return ret;
+
+ *val = (int16_t)be16_to_cpu(data[addr]);
+
+ return IIO_VAL_INT;
+}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
new file mode 100644
index 000000000000..b41bd0578478
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 TDK-InvenSense, Inc.
+ */
+
+#ifndef INV_MPU_MAGN_H_
+#define INV_MPU_MAGN_H_
+
+#include <linux/kernel.h>
+
+#include "inv_mpu_iio.h"
+
+int inv_mpu_magn_probe(struct inv_mpu6050_state *st);
+
+/**
+ * inv_mpu_magn_get_scale() - get magnetometer scale value
+ * @st: driver internal state
+ *
+ * Returns IIO data format.
+ */
+static inline int inv_mpu_magn_get_scale(const struct inv_mpu6050_state *st,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2)
+{
+ *val = 0;
+ *val2 = st->magn_raw_to_gauss[chan->address];
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate);
+
+int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st);
+
+int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val);
+
+#endif /* INV_MPU_MAGN_H_ */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 72d8c5790076..10d16ec5104b 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -124,7 +124,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
/* enable interrupt */
if (st->chip_config.accl_fifo_enable ||
- st->chip_config.gyro_fifo_enable) {
+ st->chip_config.gyro_fifo_enable ||
+ st->chip_config.magn_fifo_enable) {
result = regmap_write(st->map, st->reg->int_enable,
INV_MPU6050_BIT_DATA_RDY_EN);
if (result)
@@ -141,6 +142,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
d |= INV_MPU6050_BITS_GYRO_OUT;
if (st->chip_config.accl_fifo_enable)
d |= INV_MPU6050_BIT_ACCEL_OUT;
+ if (st->chip_config.magn_fifo_enable)
+ d |= INV_MPU6050_BIT_SLAVE_0;
result = regmap_write(st->map, st->reg->fifo_en, d);
if (result)
goto reset_fifo_fail;
@@ -187,7 +190,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
}
if (!(st->chip_config.accl_fifo_enable |
- st->chip_config.gyro_fifo_enable))
+ st->chip_config.gyro_fifo_enable |
+ st->chip_config.magn_fifo_enable))
goto end_session;
bytes_per_datum = 0;
if (st->chip_config.accl_fifo_enable)
@@ -199,6 +203,9 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
if (st->chip_type == INV_ICM20602)
bytes_per_datum += INV_ICM20602_BYTES_PER_TEMP_SENSOR;
+ if (st->chip_config.magn_fifo_enable)
+ bytes_per_datum += INV_MPU9X50_BYTES_MAGN;
+
/*
* read fifo_count register to know how many bytes are inside the FIFO
* right now
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index dd55e70b6f77..d7d951927a44 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -5,7 +5,7 @@
#include "inv_mpu_iio.h"
-static void inv_scan_query(struct iio_dev *indio_dev)
+static void inv_scan_query_mpu6050(struct iio_dev *indio_dev)
{
struct inv_mpu6050_state *st = iio_priv(indio_dev);
@@ -26,6 +26,60 @@ static void inv_scan_query(struct iio_dev *indio_dev)
indio_dev->active_scan_mask);
}
+static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev)
+{
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+ inv_scan_query_mpu6050(indio_dev);
+
+ /* no magnetometer if i2c auxiliary bus is used */
+ if (st->magn_disabled)
+ return;
+
+ st->chip_config.magn_fifo_enable =
+ test_bit(INV_MPU9X50_SCAN_MAGN_X,
+ indio_dev->active_scan_mask) ||
+ test_bit(INV_MPU9X50_SCAN_MAGN_Y,
+ indio_dev->active_scan_mask) ||
+ test_bit(INV_MPU9X50_SCAN_MAGN_Z,
+ indio_dev->active_scan_mask);
+}
+
+static void inv_scan_query(struct iio_dev *indio_dev)
+{
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+ switch (st->chip_type) {
+ case INV_MPU9250:
+ case INV_MPU9255:
+ return inv_scan_query_mpu9x50(indio_dev);
+ default:
+ return inv_scan_query_mpu6050(indio_dev);
+ }
+}
+
+static unsigned int inv_compute_skip_samples(const struct inv_mpu6050_state *st)
+{
+ unsigned int gyro_skip = 0;
+ unsigned int magn_skip = 0;
+ unsigned int skip_samples;
+
+ /* gyro first sample is out of specs, skip it */
+ if (st->chip_config.gyro_fifo_enable)
+ gyro_skip = 1;
+
+ /* mag first sample is always not ready, skip it */
+ if (st->chip_config.magn_fifo_enable)
+ magn_skip = 1;
+
+ /* compute first samples to skip */
+ skip_samples = gyro_skip;
+ if (magn_skip > skip_samples)
+ skip_samples = magn_skip;
+
+ return skip_samples;
+}
+
/**
* inv_mpu6050_set_enable() - enable chip functions.
* @indio_dev: Device driver instance.
@@ -34,6 +88,7 @@ static void inv_scan_query(struct iio_dev *indio_dev)
static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
{
struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ uint8_t d;
int result;
if (enable) {
@@ -41,14 +96,11 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
if (result)
return result;
inv_scan_query(indio_dev);
- st->skip_samples = 0;
if (st->chip_config.gyro_fifo_enable) {
result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result)
goto error_power_off;
- /* gyro first sample is out of specs, skip it */
- st->skip_samples = 1;
}
if (st->chip_config.accl_fifo_enable) {
result = inv_mpu6050_switch_engine(st, true,
@@ -56,22 +108,32 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
if (result)
goto error_gyro_off;
}
+ if (st->chip_config.magn_fifo_enable) {
+ d = st->chip_config.user_ctrl |
+ INV_MPU6050_BIT_I2C_MST_EN;
+ result = regmap_write(st->map, st->reg->user_ctrl, d);
+ if (result)
+ goto error_accl_off;
+ st->chip_config.user_ctrl = d;
+ }
+ st->skip_samples = inv_compute_skip_samples(st);
result = inv_reset_fifo(indio_dev);
if (result)
- goto error_accl_off;
+ goto error_magn_off;
} else {
result = regmap_write(st->map, st->reg->fifo_en, 0);
if (result)
- goto error_accl_off;
+ goto error_magn_off;
result = regmap_write(st->map, st->reg->int_enable, 0);
if (result)
- goto error_accl_off;
+ goto error_magn_off;
- result = regmap_write(st->map, st->reg->user_ctrl,
- st->chip_config.user_ctrl);
+ d = st->chip_config.user_ctrl & ~INV_MPU6050_BIT_I2C_MST_EN;
+ result = regmap_write(st->map, st->reg->user_ctrl, d);
if (result)
- goto error_accl_off;
+ goto error_magn_off;
+ st->chip_config.user_ctrl = d;
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_ACCL_STBY);
@@ -90,6 +152,10 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
return 0;
+error_magn_off:
+ /* always restore user_ctrl to disable fifo properly */
+ st->chip_config.user_ctrl &= ~INV_MPU6050_BIT_I2C_MST_EN;
+ regmap_write(st->map, st->reg->user_ctrl, st->chip_config.user_ctrl);
error_accl_off:
if (st->chip_config.accl_fifo_enable)
inv_mpu6050_switch_engine(st, false,
diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig
index 77aa0e77212d..28f59d09208a 100644
--- a/drivers/iio/imu/st_lsm6dsx/Kconfig
+++ b/drivers/iio/imu/st_lsm6dsx/Kconfig
@@ -12,7 +12,8 @@ config IIO_ST_LSM6DSX
Say yes here to build support for STMicroelectronics LSM6DSx imu
sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm,
ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c,
- ism330dhcx and the accelerometer/gyroscope of lsm9ds1.
+ ism330dhcx, lsm6dsrx, lsm6ds0 and the accelerometer/gyroscope
+ of lsm9ds1.
To compile this driver as a module, choose M here: the module
will be called st_lsm6dsx.
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index 0fe6999b8257..37e499fe6bcf 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -12,6 +12,7 @@
#define ST_LSM6DSX_H
#include <linux/device.h>
+#include <linux/iio/iio.h>
#define ST_LSM6DS3_DEV_NAME "lsm6ds3"
#define ST_LSM6DS3H_DEV_NAME "lsm6ds3h"
@@ -25,6 +26,8 @@
#define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c"
#define ST_ISM330DHCX_DEV_NAME "ism330dhcx"
#define ST_LSM9DS1_DEV_NAME "lsm9ds1-imu"
+#define ST_LSM6DS0_DEV_NAME "lsm6ds0"
+#define ST_LSM6DSRX_DEV_NAME "lsm6dsrx"
enum st_lsm6dsx_hw_id {
ST_LSM6DS3_ID,
@@ -39,6 +42,8 @@ enum st_lsm6dsx_hw_id {
ST_LSM6DS3TRC_ID,
ST_ISM330DHCX_ID,
ST_LSM9DS1_ID,
+ ST_LSM6DS0_ID,
+ ST_LSM6DSRX_ID,
ST_LSM6DSX_MAX_ID,
};
@@ -54,6 +59,26 @@ enum st_lsm6dsx_hw_id {
* ST_LSM6DSX_TAGGED_SAMPLE_SIZE)
#define ST_LSM6DSX_SHIFT_VAL(val, mask) (((val) << __ffs(mask)) & (mask))
+#define ST_LSM6DSX_CHANNEL_ACC(chan_type, addr, mod, scan_idx) \
+{ \
+ .type = chan_type, \
+ .address = addr, \
+ .modified = 1, \
+ .channel2 = mod, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = scan_idx, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+ .event_spec = &st_lsm6dsx_event, \
+ .num_event_specs = 1, \
+}
+
#define ST_LSM6DSX_CHANNEL(chan_type, addr, mod, scan_idx) \
{ \
.type = chan_type, \
@@ -132,12 +157,14 @@ struct st_lsm6dsx_fifo_ops {
* @hr_timer: Hw timer resolution register info (addr + mask).
* @fifo_en: Hw timer FIFO enable register info (addr + mask).
* @decimator: Hw timer FIFO decimator register info (addr + mask).
+ * @freq_fine: Difference in % of ODR with respect to the typical.
*/
struct st_lsm6dsx_hw_ts_settings {
struct st_lsm6dsx_reg timer_en;
struct st_lsm6dsx_reg hr_timer;
struct st_lsm6dsx_reg fifo_en;
struct st_lsm6dsx_reg decimator;
+ u8 freq_fine;
};
/**
@@ -164,6 +191,16 @@ struct st_lsm6dsx_shub_settings {
u8 batch_en;
};
+struct st_lsm6dsx_event_settings {
+ struct st_lsm6dsx_reg enable_reg;
+ struct st_lsm6dsx_reg wakeup_reg;
+ u8 wakeup_src_reg;
+ u8 wakeup_src_status_mask;
+ u8 wakeup_src_z_mask;
+ u8 wakeup_src_y_mask;
+ u8 wakeup_src_x_mask;
+};
+
enum st_lsm6dsx_ext_sensor_id {
ST_LSM6DSX_ID_MAGN,
};
@@ -207,12 +244,14 @@ struct st_lsm6dsx_ext_dev_settings {
/**
* struct st_lsm6dsx_settings - ST IMU sensor settings
* @wai: Sensor WhoAmI default value.
- * @int1_addr: Control Register address for INT1
- * @int2_addr: Control Register address for INT2
- * @reset_addr: register address for reset/reboot
+ * @reset: register address for reset.
+ * @boot: register address for boot.
+ * @bdu: register address for Block Data Update.
* @max_fifo_size: Sensor max fifo length in FIFO words.
* @id: List of hw id/device name supported by the driver configuration.
* @channels: IIO channels supported by the device.
+ * @irq_config: interrupts related registers.
+ * @drdy_mask: register info for data-ready mask (addr + mask).
* @odr_table: Hw sensors odr table (Hz + val).
* @fs_table: Hw sensors gain table (gain + val).
* @decimator: List of decimator register info (addr + mask).
@@ -223,9 +262,9 @@ struct st_lsm6dsx_ext_dev_settings {
*/
struct st_lsm6dsx_settings {
u8 wai;
- u8 int1_addr;
- u8 int2_addr;
- u8 reset_addr;
+ struct st_lsm6dsx_reg reset;
+ struct st_lsm6dsx_reg boot;
+ struct st_lsm6dsx_reg bdu;
u16 max_fifo_size;
struct {
enum st_lsm6dsx_hw_id hw_id;
@@ -235,6 +274,17 @@ struct st_lsm6dsx_settings {
const struct iio_chan_spec *chan;
int len;
} channels[2];
+ struct {
+ struct st_lsm6dsx_reg irq1;
+ struct st_lsm6dsx_reg irq2;
+ struct st_lsm6dsx_reg irq1_func;
+ struct st_lsm6dsx_reg irq2_func;
+ struct st_lsm6dsx_reg lir;
+ struct st_lsm6dsx_reg clear_on_read;
+ struct st_lsm6dsx_reg hla;
+ struct st_lsm6dsx_reg od;
+ } irq_config;
+ struct st_lsm6dsx_reg drdy_mask;
struct st_lsm6dsx_odr_table_entry odr_table[2];
struct st_lsm6dsx_fs_table_entry fs_table[2];
struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID];
@@ -242,6 +292,7 @@ struct st_lsm6dsx_settings {
struct st_lsm6dsx_fifo_ops fifo_ops;
struct st_lsm6dsx_hw_ts_settings ts_settings;
struct st_lsm6dsx_shub_settings shub_settings;
+ struct st_lsm6dsx_event_settings event_settings;
};
enum st_lsm6dsx_sensor_id {
@@ -301,9 +352,13 @@ struct st_lsm6dsx_sensor {
* @fifo_mode: FIFO operating mode supported by the device.
* @suspend_mask: Suspended sensor bitmask.
* @enable_mask: Enabled sensor bitmask.
+ * @ts_gain: Hw timestamp rate after internal calibration.
* @ts_sip: Total number of timestamp samples in a given pattern.
* @sip: Total number of samples (acc/gyro/ts) in a given pattern.
* @buff: Device read buffer.
+ * @irq_routing: pointer to interrupt routing configuration.
+ * @event_threshold: wakeup event threshold.
+ * @enable_event: enabled event bitmask.
* @iio_devs: Pointers to acc/gyro iio_dev instances.
* @settings: Pointer to the specific sensor settings in use.
*/
@@ -319,9 +374,14 @@ struct st_lsm6dsx_hw {
enum st_lsm6dsx_fifo_mode fifo_mode;
u8 suspend_mask;
u8 enable_mask;
+ s64 ts_gain;
u8 ts_sip;
u8 sip;
+ const struct st_lsm6dsx_reg *irq_routing;
+ u8 event_threshold;
+ u8 enable_event;
+
u8 *buff;
struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX];
@@ -329,6 +389,13 @@ struct st_lsm6dsx_hw {
const struct st_lsm6dsx_settings *settings;
};
+static const struct iio_event_spec st_lsm6dsx_event = {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE)
+};
+
static const unsigned long st_lsm6dsx_available_scan_masks[] = {0x7, 0x0};
extern const struct dev_pm_ops st_lsm6dsx_pm_ops;
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index b0f3da1976e4..31cd90d2c60e 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -14,10 +14,10 @@
* (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the
* value of the decimation factor and ODR set for each FIFO data set.
*
- * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: The FIFO buffer can be
- * configured to store data from gyroscope and accelerometer. Each sample
- * is queued with a tag (1B) indicating data source (gyroscope, accelerometer,
- * hw timer).
+ * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/LSM6DSRX/ISM330DHCX:
+ * The FIFO buffer can be configured to store data from gyroscope and
+ * accelerometer. Each sample is queued with a tag (1B) indicating data
+ * source (gyroscope, accelerometer, hw timer).
*
* FIFO supported modes:
* - BYPASS: FIFO disabled
@@ -30,8 +30,6 @@
* Denis Ciocca <denis.ciocca@st.com>
*/
#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
@@ -42,10 +40,6 @@
#include "st_lsm6dsx.h"
-#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12
-#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5)
-#define ST_LSM6DSX_REG_PP_OD_ADDR 0x12
-#define ST_LSM6DSX_REG_PP_OD_MASK BIT(4)
#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a
#define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0)
#define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3)
@@ -56,7 +50,6 @@
#define ST_LSM6DSX_MAX_FIFO_ODR_VAL 0x08
-#define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */
#define ST_LSM6DSX_TS_RESET_VAL 0xaa
struct st_lsm6dsx_decimator_entry {
@@ -429,7 +422,7 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
*/
if (!reset_ts && ts >= 0xff0000)
reset_ts = true;
- ts *= ST_LSM6DSX_TS_SENSITIVITY;
+ ts *= hw->ts_gain;
offset += ST_LSM6DSX_SAMPLE_SIZE;
}
@@ -456,13 +449,19 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
return read_len;
}
+#define ST_LSM6DSX_INVALID_SAMPLE 0x7ffd
static int
st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag,
u8 *data, s64 ts)
{
+ s16 val = le16_to_cpu(*(__le16 *)data);
struct st_lsm6dsx_sensor *sensor;
struct iio_dev *iio_dev;
+ /* invalid sample during bootstrap phase */
+ if (val >= ST_LSM6DSX_INVALID_SAMPLE)
+ return -EINVAL;
+
/*
* EXT_TAG are managed in FIFO fashion so ST_LSM6DSX_EXT0_TAG
* corresponds to the first enabled channel, ST_LSM6DSX_EXT1_TAG
@@ -572,7 +571,7 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw)
*/
if (!reset_ts && ts >= 0xffff0000)
reset_ts = true;
- ts *= ST_LSM6DSX_TS_SENSITIVITY;
+ ts *= hw->ts_gain;
} else {
st_lsm6dsx_push_tagged_data(hw, tag, iio_buff,
ts);
@@ -592,6 +591,9 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
{
int err;
+ if (!hw->settings->fifo_ops.read_fifo)
+ return -ENOTSUPP;
+
mutex_lock(&hw->fifo_lock);
hw->settings->fifo_ops.read_fifo(hw);
@@ -654,25 +656,6 @@ out:
return err;
}
-static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
-{
- struct st_lsm6dsx_hw *hw = private;
-
- return hw->sip > 0 ? IRQ_WAKE_THREAD : IRQ_NONE;
-}
-
-static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
-{
- struct st_lsm6dsx_hw *hw = private;
- int count;
-
- mutex_lock(&hw->fifo_lock);
- count = hw->settings->fifo_ops.read_fifo(hw);
- mutex_unlock(&hw->fifo_lock);
-
- return count ? IRQ_HANDLED : IRQ_NONE;
-}
-
static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
@@ -702,59 +685,8 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = {
int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{
- struct device_node *np = hw->dev->of_node;
- struct st_sensors_platform_data *pdata;
struct iio_buffer *buffer;
- unsigned long irq_type;
- bool irq_active_low;
- int i, err;
-
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
- switch (irq_type) {
- case IRQF_TRIGGER_HIGH:
- case IRQF_TRIGGER_RISING:
- irq_active_low = false;
- break;
- case IRQF_TRIGGER_LOW:
- case IRQF_TRIGGER_FALLING:
- irq_active_low = true;
- break;
- default:
- dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
- return -EINVAL;
- }
-
- err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_HLACTIVE_ADDR,
- ST_LSM6DSX_REG_HLACTIVE_MASK,
- FIELD_PREP(ST_LSM6DSX_REG_HLACTIVE_MASK,
- irq_active_low));
- if (err < 0)
- return err;
-
- pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
- if ((np && of_property_read_bool(np, "drive-open-drain")) ||
- (pdata && pdata->open_drain)) {
- err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_PP_OD_ADDR,
- ST_LSM6DSX_REG_PP_OD_MASK,
- FIELD_PREP(ST_LSM6DSX_REG_PP_OD_MASK,
- 1));
- if (err < 0)
- return err;
-
- irq_type |= IRQF_SHARED;
- }
-
- err = devm_request_threaded_irq(hw->dev, hw->irq,
- st_lsm6dsx_handler_irq,
- st_lsm6dsx_handler_thread,
- irq_type | IRQF_ONESHOT,
- "lsm6dsx", hw);
- if (err) {
- dev_err(hw->dev, "failed to request trigger irq %d\n",
- hw->irq);
- return err;
- }
+ int i;
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
if (!hw->iio_devs[i])
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index fd5ebe1e1594..1f28a7733fc0 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -32,7 +32,7 @@
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
* - FIFO size: 3KB
*
- * - LSM9DS1:
+ * - LSM9DS1/LSM6DS0:
* - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952
* - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
* - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952
@@ -48,8 +48,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/bitfield.h>
@@ -58,17 +61,14 @@
#include "st_lsm6dsx.h"
-#define ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK BIT(3)
#define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f
-#define ST_LSM6DSX_REG_RESET_MASK BIT(0)
-#define ST_LSM6DSX_REG_BOOT_MASK BIT(7)
-#define ST_LSM6DSX_REG_BDU_ADDR 0x12
-#define ST_LSM6DSX_REG_BDU_MASK BIT(6)
+
+#define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */
static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = {
- ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0),
- ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1),
- ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2),
+ ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0),
+ ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1),
+ ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
@@ -89,14 +89,26 @@ static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = {
static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
{
.wai = 0x68,
- .int1_addr = 0x0c,
- .int2_addr = 0x0d,
- .reset_addr = 0x22,
+ .reset = {
+ .addr = 0x22,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x22,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x22,
+ .mask = BIT(6),
+ },
.max_fifo_size = 32,
.id = {
{
.hw_id = ST_LSM9DS1_ID,
.name = ST_LSM9DS1_DEV_NAME,
+ }, {
+ .hw_id = ST_LSM6DS0_ID,
+ .name = ST_LSM6DS0_DEV_NAME,
},
},
.channels = {
@@ -152,18 +164,46 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x10,
.mask = GENMASK(4, 3),
},
- .fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 },
- .fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 },
- .fs_avl[2] = { IIO_DEGREE_TO_RAD(2000), 0x3 },
+
+ .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 },
+ .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
+ .fs_avl[2] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
.fs_len = 3,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0c,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .hla = {
+ .addr = 0x22,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x22,
+ .mask = BIT(4),
+ },
+ },
},
{
.wai = 0x69,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 1365,
.id = {
{
@@ -231,6 +271,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x58,
+ .mask = BIT(0),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.decimator = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x08,
@@ -272,12 +342,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.mask = GENMASK(5, 3),
},
},
+ .event_settings = {
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
+ },
},
{
.wai = 0x69,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 682,
.id = {
{
@@ -345,6 +435,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x58,
+ .mask = BIT(0),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.decimator = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x08,
@@ -386,12 +506,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.mask = GENMASK(5, 3),
},
},
+ .event_settings = {
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
+ },
},
{
.wai = 0x6a,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 682,
.id = {
{
@@ -468,6 +608,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x58,
+ .mask = BIT(0),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.decimator = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x08,
@@ -509,12 +679,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.mask = GENMASK(5, 3),
},
},
+ .event_settings = {
+ .enable_reg = {
+ .addr = 0x58,
+ .mask = BIT(7),
+ },
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
+ },
},
{
.wai = 0x6c,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 512,
.id = {
{
@@ -535,6 +729,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
},
},
+ .drdy_mask = {
+ .addr = 0x13,
+ .mask = BIT(3),
+ },
.odr_table = {
[ST_LSM6DSX_ID_ACC] = {
.reg = {
@@ -585,6 +783,40 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x56,
+ .mask = BIT(0),
+ },
+ .clear_on_read = {
+ .addr = 0x56,
+ .mask = BIT(6),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.batch = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x09,
@@ -617,6 +849,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x0a,
.mask = GENMASK(7, 6),
},
+ .freq_fine = 0x63,
},
.shub_settings = {
.page_mux = {
@@ -643,13 +876,37 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.slv0_addr = 0x15,
.dw_slv0_addr = 0x21,
.batch_en = BIT(3),
- }
+ },
+ .event_settings = {
+ .enable_reg = {
+ .addr = 0x58,
+ .mask = BIT(7),
+ },
+ .wakeup_reg = {
+ .addr = 0x5b,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
+ },
},
{
.wai = 0x6b,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 512,
.id = {
{
@@ -667,6 +924,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
},
},
+ .drdy_mask = {
+ .addr = 0x13,
+ .mask = BIT(3),
+ },
.odr_table = {
[ST_LSM6DSX_ID_ACC] = {
.reg = {
@@ -717,6 +978,40 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x56,
+ .mask = BIT(0),
+ },
+ .clear_on_read = {
+ .addr = 0x56,
+ .mask = BIT(6),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.batch = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x09,
@@ -749,13 +1044,38 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x0a,
.mask = GENMASK(7, 6),
},
+ .freq_fine = 0x63,
+ },
+ .event_settings = {
+ .enable_reg = {
+ .addr = 0x58,
+ .mask = BIT(7),
+ },
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
},
},
{
.wai = 0x6b,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 512,
.id = {
{
@@ -764,6 +1084,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
}, {
.hw_id = ST_ISM330DHCX_ID,
.name = ST_ISM330DHCX_DEV_NAME,
+ }, {
+ .hw_id = ST_LSM6DSRX_ID,
+ .name = ST_LSM6DSRX_DEV_NAME,
},
},
.channels = {
@@ -776,6 +1099,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
},
},
+ .drdy_mask = {
+ .addr = 0x13,
+ .mask = BIT(3),
+ },
.odr_table = {
[ST_LSM6DSX_ID_ACC] = {
.reg = {
@@ -826,6 +1153,40 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x56,
+ .mask = BIT(0),
+ },
+ .clear_on_read = {
+ .addr = 0x56,
+ .mask = BIT(6),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.batch = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x09,
@@ -858,6 +1219,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x0a,
.mask = GENMASK(7, 6),
},
+ .freq_fine = 0x63,
},
.shub_settings = {
.page_mux = {
@@ -884,6 +1246,21 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.slv0_addr = 0x15,
.dw_slv0_addr = 0x21,
.batch_en = BIT(3),
+ },
+ .event_settings = {
+ .enable_reg = {
+ .addr = 0x58,
+ .mask = BIT(7),
+ },
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
}
},
};
@@ -1091,7 +1468,8 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
if (err < 0)
return err;
- st_lsm6dsx_sensor_set_enable(sensor, false);
+ if (!hw->enable_event)
+ st_lsm6dsx_sensor_set_enable(sensor, false);
*val = (s16)le16_to_cpu(data);
@@ -1164,6 +1542,144 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
return err;
}
+static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state)
+{
+ const struct st_lsm6dsx_reg *reg;
+ unsigned int data;
+ int err;
+
+ if (!hw->settings->irq_config.irq1_func.addr)
+ return -ENOTSUPP;
+
+ reg = &hw->settings->event_settings.enable_reg;
+ if (reg->addr) {
+ data = ST_LSM6DSX_SHIFT_VAL(state, reg->mask);
+ err = st_lsm6dsx_update_bits_locked(hw, reg->addr,
+ reg->mask, data);
+ if (err < 0)
+ return err;
+ }
+
+ /* Enable wakeup interrupt */
+ data = ST_LSM6DSX_SHIFT_VAL(state, hw->irq_routing->mask);
+ return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing->addr,
+ hw->irq_routing->mask, data);
+}
+
+static int st_lsm6dsx_read_event(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ *val2 = 0;
+ *val = hw->event_threshold;
+
+ return IIO_VAL_INT;
+}
+
+static int
+st_lsm6dsx_write_event(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ const struct st_lsm6dsx_reg *reg;
+ unsigned int data;
+ int err;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (val < 0 || val > 31)
+ return -EINVAL;
+
+ reg = &hw->settings->event_settings.wakeup_reg;
+ data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask);
+ err = st_lsm6dsx_update_bits_locked(hw, reg->addr,
+ reg->mask, data);
+ if (err < 0)
+ return -EINVAL;
+
+ hw->event_threshold = val;
+
+ return 0;
+}
+
+static int
+st_lsm6dsx_read_event_config(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ return !!(hw->enable_event & BIT(chan->channel2));
+}
+
+static int
+st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, int state)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ u8 enable_event;
+ int err = 0;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (state) {
+ enable_event = hw->enable_event | BIT(chan->channel2);
+
+ /* do not enable events if they are already enabled */
+ if (hw->enable_event)
+ goto out;
+ } else {
+ enable_event = hw->enable_event & ~BIT(chan->channel2);
+
+ /* only turn off sensor if no events is enabled */
+ if (enable_event)
+ goto out;
+ }
+
+ /* stop here if no changes have been made */
+ if (hw->enable_event == enable_event)
+ return 0;
+
+ err = st_lsm6dsx_event_setup(hw, state);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&hw->conf_lock);
+ err = st_lsm6dsx_sensor_set_enable(sensor, state);
+ mutex_unlock(&hw->conf_lock);
+ if (err < 0)
+ return err;
+
+out:
+ hw->enable_event = enable_event;
+
+ return 0;
+}
+
int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
@@ -1243,6 +1759,10 @@ static const struct iio_info st_lsm6dsx_acc_info = {
.attrs = &st_lsm6dsx_acc_attribute_group,
.read_raw = st_lsm6dsx_read_raw,
.write_raw = st_lsm6dsx_write_raw,
+ .read_event_value = st_lsm6dsx_read_event,
+ .write_event_value = st_lsm6dsx_write_event,
+ .read_event_config = st_lsm6dsx_read_event_config,
+ .write_event_config = st_lsm6dsx_write_event_config,
.hwfifo_set_watermark = st_lsm6dsx_set_watermark,
};
@@ -1273,7 +1793,9 @@ static int st_lsm6dsx_of_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin)
return of_property_read_u32(np, "st,drdy-int-pin", drdy_pin);
}
-static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg)
+static int
+st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
+ const struct st_lsm6dsx_reg **drdy_reg)
{
int err = 0, drdy_pin;
@@ -1287,10 +1809,12 @@ static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg)
switch (drdy_pin) {
case 1:
- *drdy_reg = hw->settings->int1_addr;
+ hw->irq_routing = &hw->settings->irq_config.irq1_func;
+ *drdy_reg = &hw->settings->irq_config.irq1;
break;
case 2:
- *drdy_reg = hw->settings->int2_addr;
+ hw->irq_routing = &hw->settings->irq_config.irq2_func;
+ *drdy_reg = &hw->settings->irq_config.irq2;
break;
default:
dev_err(hw->dev, "unsupported data ready pin\n");
@@ -1381,51 +1905,95 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw)
if (err < 0)
return err;
}
+
+ /* calibrate timestamp sensitivity */
+ hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY;
+ if (ts_settings->freq_fine) {
+ err = regmap_read(hw->regmap, ts_settings->freq_fine, &val);
+ if (err < 0)
+ return err;
+
+ /*
+ * linearize the AN5192 formula:
+ * 1 / (1 + x) ~= 1 - x (Taylor’s Series)
+ * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val))
+ * ttrim[ns] ~= 25000 - 37.5 * val
+ * ttrim[ns] ~= 25000 - (37500 * val) / 1000
+ */
+ hw->ts_gain -= ((s8)val * 37500) / 1000;
+ }
+
return 0;
}
static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
{
- u8 drdy_int_reg;
+ const struct st_lsm6dsx_reg *reg;
int err;
/* device sw reset */
- err = regmap_update_bits(hw->regmap, hw->settings->reset_addr,
- ST_LSM6DSX_REG_RESET_MASK,
- FIELD_PREP(ST_LSM6DSX_REG_RESET_MASK, 1));
+ reg = &hw->settings->reset;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
if (err < 0)
return err;
msleep(50);
/* reload trimming parameter */
- err = regmap_update_bits(hw->regmap, hw->settings->reset_addr,
- ST_LSM6DSX_REG_BOOT_MASK,
- FIELD_PREP(ST_LSM6DSX_REG_BOOT_MASK, 1));
+ reg = &hw->settings->boot;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
if (err < 0)
return err;
msleep(50);
/* enable Block Data Update */
- err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_BDU_ADDR,
- ST_LSM6DSX_REG_BDU_MASK,
- FIELD_PREP(ST_LSM6DSX_REG_BDU_MASK, 1));
+ reg = &hw->settings->bdu;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
if (err < 0)
return err;
/* enable FIFO watermak interrupt */
- err = st_lsm6dsx_get_drdy_reg(hw, &drdy_int_reg);
+ err = st_lsm6dsx_get_drdy_reg(hw, &reg);
if (err < 0)
return err;
- err = regmap_update_bits(hw->regmap, drdy_int_reg,
- ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK,
- FIELD_PREP(ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK,
- 1));
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
if (err < 0)
return err;
+ /* enable Latched interrupts for device events */
+ if (hw->settings->irq_config.lir.addr) {
+ reg = &hw->settings->irq_config.lir;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
+ if (err < 0)
+ return err;
+
+ /* enable clear on read for latched interrupts */
+ if (hw->settings->irq_config.clear_on_read.addr) {
+ reg = &hw->settings->irq_config.clear_on_read;
+ err = regmap_update_bits(hw->regmap,
+ reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
+ if (err < 0)
+ return err;
+ }
+ }
+
+ /* enable drdy-mas if available */
+ if (hw->settings->drdy_mask.addr) {
+ reg = &hw->settings->drdy_mask;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
+ if (err < 0)
+ return err;
+ }
+
err = st_lsm6dsx_init_shub(hw);
if (err < 0)
return err;
@@ -1476,10 +2044,138 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
return iio_dev;
}
+static bool
+st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw)
+{
+ const struct st_lsm6dsx_event_settings *event_settings;
+ int err, data;
+ s64 timestamp;
+
+ if (!hw->enable_event)
+ return false;
+
+ event_settings = &hw->settings->event_settings;
+ err = st_lsm6dsx_read_locked(hw, event_settings->wakeup_src_reg,
+ &data, sizeof(data));
+ if (err < 0)
+ return false;
+
+ timestamp = iio_get_time_ns(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
+ if ((data & hw->settings->event_settings.wakeup_src_z_mask) &&
+ (hw->enable_event & BIT(IIO_MOD_Z)))
+ iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
+ 0,
+ IIO_MOD_Z,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ timestamp);
+
+ if ((data & hw->settings->event_settings.wakeup_src_y_mask) &&
+ (hw->enable_event & BIT(IIO_MOD_Y)))
+ iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
+ 0,
+ IIO_MOD_Y,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ timestamp);
+
+ if ((data & hw->settings->event_settings.wakeup_src_x_mask) &&
+ (hw->enable_event & BIT(IIO_MOD_X)))
+ iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
+ 0,
+ IIO_MOD_X,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ timestamp);
+
+ return data & event_settings->wakeup_src_status_mask;
+}
+
+static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
+{
+ struct st_lsm6dsx_hw *hw = private;
+ bool event;
+ int count;
+
+ event = st_lsm6dsx_report_motion_event(hw);
+
+ if (!hw->settings->fifo_ops.read_fifo)
+ return event ? IRQ_HANDLED : IRQ_NONE;
+
+ mutex_lock(&hw->fifo_lock);
+ count = hw->settings->fifo_ops.read_fifo(hw);
+ mutex_unlock(&hw->fifo_lock);
+
+ return count || event ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
+{
+ struct device_node *np = hw->dev->of_node;
+ struct st_sensors_platform_data *pdata;
+ const struct st_lsm6dsx_reg *reg;
+ unsigned long irq_type;
+ bool irq_active_low;
+ int err;
+
+ irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
+
+ switch (irq_type) {
+ case IRQF_TRIGGER_HIGH:
+ case IRQF_TRIGGER_RISING:
+ irq_active_low = false;
+ break;
+ case IRQF_TRIGGER_LOW:
+ case IRQF_TRIGGER_FALLING:
+ irq_active_low = true;
+ break;
+ default:
+ dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
+ return -EINVAL;
+ }
+
+ reg = &hw->settings->irq_config.hla;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(irq_active_low,
+ reg->mask));
+ if (err < 0)
+ return err;
+
+ pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
+ if ((np && of_property_read_bool(np, "drive-open-drain")) ||
+ (pdata && pdata->open_drain)) {
+ reg = &hw->settings->irq_config.od;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
+ if (err < 0)
+ return err;
+
+ irq_type |= IRQF_SHARED;
+ }
+
+ err = devm_request_threaded_irq(hw->dev, hw->irq,
+ NULL,
+ st_lsm6dsx_handler_thread,
+ irq_type | IRQF_ONESHOT,
+ "lsm6dsx", hw);
+ if (err) {
+ dev_err(hw->dev, "failed to request trigger irq %d\n",
+ hw->irq);
+ return err;
+ }
+
+ return 0;
+}
+
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
struct regmap *regmap)
{
+ struct st_sensors_platform_data *pdata = dev->platform_data;
const struct st_lsm6dsx_shub_settings *hub_settings;
+ struct device_node *np = dev->of_node;
struct st_lsm6dsx_hw *hw;
const char *name = NULL;
int i, err;
@@ -1524,6 +2220,10 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
}
if (hw->irq > 0) {
+ err = st_lsm6dsx_irq_setup(hw);
+ if (err < 0)
+ return err;
+
err = st_lsm6dsx_fifo_setup(hw);
if (err < 0)
return err;
@@ -1538,6 +2238,10 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
return err;
}
+ if ((np && of_property_read_bool(np, "wakeup-source")) ||
+ (pdata && pdata->wakeup_source))
+ device_init_wakeup(dev, true);
+
return 0;
}
EXPORT_SYMBOL(st_lsm6dsx_probe);
@@ -1556,6 +2260,13 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
if (!(hw->enable_mask & BIT(sensor->id)))
continue;
+ if (device_may_wakeup(dev) &&
+ sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event) {
+ /* Enable wake from IRQ */
+ enable_irq_wake(hw->irq);
+ continue;
+ }
+
if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
sensor->id == ST_LSM6DSX_ID_EXT1 ||
sensor->id == ST_LSM6DSX_ID_EXT2)
@@ -1585,6 +2296,10 @@ static int __maybe_unused st_lsm6dsx_resume(struct device *dev)
continue;
sensor = iio_priv(hw->iio_devs[i]);
+ if (device_may_wakeup(dev) &&
+ sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event)
+ disable_irq_wake(hw->irq);
+
if (!(hw->suspend_mask & BIT(sensor->id)))
continue;
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
index f52511059545..cd47ec1fedcb 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -87,6 +87,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
.compatible = "st,lsm9ds1-imu",
.data = (void *)ST_LSM9DS1_ID,
},
+ {
+ .compatible = "st,lsm6ds0",
+ .data = (void *)ST_LSM6DS0_ID,
+ },
+ {
+ .compatible = "st,lsm6dsrx",
+ .data = (void *)ST_LSM6DSRX_ID,
+ },
{},
};
MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
@@ -104,6 +112,8 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
{ ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID },
{ ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID },
{ ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID },
+ { ST_LSM6DS0_DEV_NAME, ST_LSM6DS0_ID },
+ { ST_LSM6DSRX_DEV_NAME, ST_LSM6DSRX_ID },
{},
};
MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
index 344b28dddebb..67ff36eac247 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
@@ -87,6 +87,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
.compatible = "st,lsm9ds1-imu",
.data = (void *)ST_LSM9DS1_ID,
},
+ {
+ .compatible = "st,lsm6ds0",
+ .data = (void *)ST_LSM6DS0_ID,
+ },
+ {
+ .compatible = "st,lsm6dsrx",
+ .data = (void *)ST_LSM6DSRX_ID,
+ },
{},
};
MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
@@ -104,6 +112,8 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
{ ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID },
{ ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID },
{ ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID },
+ { ST_LSM6DS0_DEV_NAME, ST_LSM6DS0_ID },
+ { ST_LSM6DSRX_DEV_NAME, ST_LSM6DSRX_ID },
{},
};
MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 524a686077ca..f72c2dc5f703 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1238,6 +1238,16 @@ static ssize_t iio_show_dev_name(struct device *dev,
static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
+static ssize_t iio_show_dev_label(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->label);
+}
+
+static DEVICE_ATTR(label, S_IRUGO, iio_show_dev_label, NULL);
+
static ssize_t iio_show_timestamp_clock(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1354,6 +1364,8 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
if (indio_dev->name)
attrcount++;
+ if (indio_dev->label)
+ attrcount++;
if (clk)
attrcount++;
@@ -1376,6 +1388,8 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
if (indio_dev->name)
indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
+ if (indio_dev->label)
+ indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_label.attr;
if (clk)
indio_dev->chan_attr_group.attrs[attrn++] = clk;
@@ -1647,6 +1661,9 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
if (!indio_dev->dev.of_node && indio_dev->dev.parent)
indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
+ indio_dev->label = of_get_property(indio_dev->dev.of_node, "label",
+ NULL);
+
ret = iio_check_unique_scan_index(indio_dev);
if (ret < 0)
return ret;
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 4a1a883dc061..d793c1541705 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -32,6 +32,17 @@ config ADJD_S311
This driver can also be built as a module. If so, the module
will be called adjd_s311.
+config ADUX1020
+ tristate "ADUX1020 photometric sensor"
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Say Y here if you want to build a driver for the Analog Devices
+ ADUX1020 photometric sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called adux1020.
+
config AL3320A
tristate "AL3320A ambient light sensor"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 00d1f9b98f39..5d650ce46a40 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -6,6 +6,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ACPI_ALS) += acpi-als.o
obj-$(CONFIG_ADJD_S311) += adjd_s311.o
+obj-$(CONFIG_ADUX1020) += adux1020.o
obj-$(CONFIG_AL3320A) += al3320a.o
obj-$(CONFIG_APDS9300) += apds9300.o
obj-$(CONFIG_APDS9960) += apds9960.o
diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c
new file mode 100644
index 000000000000..b07797ac10d7
--- /dev/null
+++ b/drivers/iio/light/adux1020.c
@@ -0,0 +1,849 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * adux1020.c - Support for Analog Devices ADUX1020 photometric sensor
+ *
+ * Copyright (C) 2019 Linaro Ltd.
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ *
+ * TODO: Triggered buffer support
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+
+#define ADUX1020_REGMAP_NAME "adux1020_regmap"
+#define ADUX1020_DRV_NAME "adux1020"
+
+/* System registers */
+#define ADUX1020_REG_CHIP_ID 0x08
+#define ADUX1020_REG_SLAVE_ADDRESS 0x09
+
+#define ADUX1020_REG_SW_RESET 0x0f
+#define ADUX1020_REG_INT_ENABLE 0x1c
+#define ADUX1020_REG_INT_POLARITY 0x1d
+#define ADUX1020_REG_PROX_TH_ON1 0x2a
+#define ADUX1020_REG_PROX_TH_OFF1 0x2b
+#define ADUX1020_REG_PROX_TYPE 0x2f
+#define ADUX1020_REG_TEST_MODES_3 0x32
+#define ADUX1020_REG_FORCE_MODE 0x33
+#define ADUX1020_REG_FREQUENCY 0x40
+#define ADUX1020_REG_LED_CURRENT 0x41
+#define ADUX1020_REG_OP_MODE 0x45
+#define ADUX1020_REG_INT_MASK 0x48
+#define ADUX1020_REG_INT_STATUS 0x49
+#define ADUX1020_REG_DATA_BUFFER 0x60
+
+/* Chip ID bits */
+#define ADUX1020_CHIP_ID_MASK GENMASK(11, 0)
+#define ADUX1020_CHIP_ID 0x03fc
+
+#define ADUX1020_SW_RESET BIT(1)
+#define ADUX1020_FIFO_FLUSH BIT(15)
+#define ADUX1020_OP_MODE_MASK GENMASK(3, 0)
+#define ADUX1020_DATA_OUT_MODE_MASK GENMASK(7, 4)
+#define ADUX1020_DATA_OUT_PROX_I FIELD_PREP(ADUX1020_DATA_OUT_MODE_MASK, 1)
+
+#define ADUX1020_MODE_INT_MASK GENMASK(7, 0)
+#define ADUX1020_INT_ENABLE 0x2094
+#define ADUX1020_INT_DISABLE 0x2090
+#define ADUX1020_PROX_INT_ENABLE 0x00f0
+#define ADUX1020_PROX_ON1_INT BIT(0)
+#define ADUX1020_PROX_OFF1_INT BIT(1)
+#define ADUX1020_FIFO_INT_ENABLE 0x7f
+#define ADUX1020_MODE_INT_DISABLE 0xff
+#define ADUX1020_MODE_INT_STATUS_MASK GENMASK(7, 0)
+#define ADUX1020_FIFO_STATUS_MASK GENMASK(15, 8)
+#define ADUX1020_INT_CLEAR 0xff
+#define ADUX1020_PROX_TYPE BIT(15)
+
+#define ADUX1020_INT_PROX_ON1 BIT(0)
+#define ADUX1020_INT_PROX_OFF1 BIT(1)
+
+#define ADUX1020_FORCE_CLOCK_ON 0x0f4f
+#define ADUX1020_FORCE_CLOCK_RESET 0x0040
+#define ADUX1020_ACTIVE_4_STATE 0x0008
+
+#define ADUX1020_PROX_FREQ_MASK GENMASK(7, 4)
+#define ADUX1020_PROX_FREQ(x) FIELD_PREP(ADUX1020_PROX_FREQ_MASK, x)
+
+#define ADUX1020_LED_CURRENT_MASK GENMASK(3, 0)
+#define ADUX1020_LED_PIREF_EN BIT(12)
+
+/* Operating modes */
+enum adux1020_op_modes {
+ ADUX1020_MODE_STANDBY,
+ ADUX1020_MODE_PROX_I,
+ ADUX1020_MODE_PROX_XY,
+ ADUX1020_MODE_GEST,
+ ADUX1020_MODE_SAMPLE,
+ ADUX1020_MODE_FORCE = 0x0e,
+ ADUX1020_MODE_IDLE = 0x0f,
+};
+
+struct adux1020_data {
+ struct i2c_client *client;
+ struct iio_dev *indio_dev;
+ struct mutex lock;
+ struct regmap *regmap;
+};
+
+struct adux1020_mode_data {
+ u8 bytes;
+ u8 buf_len;
+ u16 int_en;
+};
+
+static const struct adux1020_mode_data adux1020_modes[] = {
+ [ADUX1020_MODE_PROX_I] = {
+ .bytes = 2,
+ .buf_len = 1,
+ .int_en = ADUX1020_PROX_INT_ENABLE,
+ },
+};
+
+static const struct regmap_config adux1020_regmap_config = {
+ .name = ADUX1020_REGMAP_NAME,
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = 0x6F,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct reg_sequence adux1020_def_conf[] = {
+ { 0x000c, 0x000f },
+ { 0x0010, 0x1010 },
+ { 0x0011, 0x004c },
+ { 0x0012, 0x5f0c },
+ { 0x0013, 0xada5 },
+ { 0x0014, 0x0080 },
+ { 0x0015, 0x0000 },
+ { 0x0016, 0x0600 },
+ { 0x0017, 0x0000 },
+ { 0x0018, 0x2693 },
+ { 0x0019, 0x0004 },
+ { 0x001a, 0x4280 },
+ { 0x001b, 0x0060 },
+ { 0x001c, 0x2094 },
+ { 0x001d, 0x0020 },
+ { 0x001e, 0x0001 },
+ { 0x001f, 0x0100 },
+ { 0x0020, 0x0320 },
+ { 0x0021, 0x0A13 },
+ { 0x0022, 0x0320 },
+ { 0x0023, 0x0113 },
+ { 0x0024, 0x0000 },
+ { 0x0025, 0x2412 },
+ { 0x0026, 0x2412 },
+ { 0x0027, 0x0022 },
+ { 0x0028, 0x0000 },
+ { 0x0029, 0x0300 },
+ { 0x002a, 0x0700 },
+ { 0x002b, 0x0600 },
+ { 0x002c, 0x6000 },
+ { 0x002d, 0x4000 },
+ { 0x002e, 0x0000 },
+ { 0x002f, 0x0000 },
+ { 0x0030, 0x0000 },
+ { 0x0031, 0x0000 },
+ { 0x0032, 0x0040 },
+ { 0x0033, 0x0008 },
+ { 0x0034, 0xE400 },
+ { 0x0038, 0x8080 },
+ { 0x0039, 0x8080 },
+ { 0x003a, 0x2000 },
+ { 0x003b, 0x1f00 },
+ { 0x003c, 0x2000 },
+ { 0x003d, 0x2000 },
+ { 0x003e, 0x0000 },
+ { 0x0040, 0x8069 },
+ { 0x0041, 0x1f2f },
+ { 0x0042, 0x4000 },
+ { 0x0043, 0x0000 },
+ { 0x0044, 0x0008 },
+ { 0x0046, 0x0000 },
+ { 0x0048, 0x00ef },
+ { 0x0049, 0x0000 },
+ { 0x0045, 0x0000 },
+};
+
+static const int adux1020_rates[][2] = {
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 500000 },
+ { 1, 0 },
+ { 2, 0 },
+ { 5, 0 },
+ { 10, 0 },
+ { 20, 0 },
+ { 50, 0 },
+ { 100, 0 },
+ { 190, 0 },
+ { 450, 0 },
+ { 820, 0 },
+ { 1400, 0 },
+};
+
+static const int adux1020_led_currents[][2] = {
+ { 0, 25000 },
+ { 0, 40000 },
+ { 0, 55000 },
+ { 0, 70000 },
+ { 0, 85000 },
+ { 0, 100000 },
+ { 0, 115000 },
+ { 0, 130000 },
+ { 0, 145000 },
+ { 0, 160000 },
+ { 0, 175000 },
+ { 0, 190000 },
+ { 0, 205000 },
+ { 0, 220000 },
+ { 0, 235000 },
+ { 0, 250000 },
+};
+
+static int adux1020_flush_fifo(struct adux1020_data *data)
+{
+ int ret;
+
+ /* Force Idle mode */
+ ret = regmap_write(data->regmap, ADUX1020_REG_FORCE_MODE,
+ ADUX1020_ACTIVE_4_STATE);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_OP_MODE,
+ ADUX1020_OP_MODE_MASK, ADUX1020_MODE_FORCE);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_OP_MODE,
+ ADUX1020_OP_MODE_MASK, ADUX1020_MODE_IDLE);
+ if (ret < 0)
+ return ret;
+
+ /* Flush FIFO */
+ ret = regmap_write(data->regmap, ADUX1020_REG_TEST_MODES_3,
+ ADUX1020_FORCE_CLOCK_ON);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_write(data->regmap, ADUX1020_REG_INT_STATUS,
+ ADUX1020_FIFO_FLUSH);
+ if (ret < 0)
+ return ret;
+
+ return regmap_write(data->regmap, ADUX1020_REG_TEST_MODES_3,
+ ADUX1020_FORCE_CLOCK_RESET);
+}
+
+static int adux1020_read_fifo(struct adux1020_data *data, u16 *buf, u8 buf_len)
+{
+ unsigned int regval;
+ int i, ret;
+
+ /* Enable 32MHz clock */
+ ret = regmap_write(data->regmap, ADUX1020_REG_TEST_MODES_3,
+ ADUX1020_FORCE_CLOCK_ON);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < buf_len; i++) {
+ ret = regmap_read(data->regmap, ADUX1020_REG_DATA_BUFFER,
+ &regval);
+ if (ret < 0)
+ return ret;
+
+ buf[i] = regval;
+ }
+
+ /* Set 32MHz clock to be controlled by internal state machine */
+ return regmap_write(data->regmap, ADUX1020_REG_TEST_MODES_3,
+ ADUX1020_FORCE_CLOCK_RESET);
+}
+
+static int adux1020_set_mode(struct adux1020_data *data,
+ enum adux1020_op_modes mode)
+{
+ int ret;
+
+ /* Switch to standby mode before changing the mode */
+ ret = regmap_write(data->regmap, ADUX1020_REG_OP_MODE,
+ ADUX1020_MODE_STANDBY);
+ if (ret < 0)
+ return ret;
+
+ /* Set data out and switch to the desired mode */
+ switch (mode) {
+ case ADUX1020_MODE_PROX_I:
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_OP_MODE,
+ ADUX1020_DATA_OUT_MODE_MASK,
+ ADUX1020_DATA_OUT_PROX_I);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_OP_MODE,
+ ADUX1020_OP_MODE_MASK,
+ ADUX1020_MODE_PROX_I);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int adux1020_measure(struct adux1020_data *data,
+ enum adux1020_op_modes mode,
+ u16 *val)
+{
+ unsigned int status;
+ int ret, tries = 50;
+
+ /* Disable INT pin as polling is going to be used */
+ ret = regmap_write(data->regmap, ADUX1020_REG_INT_ENABLE,
+ ADUX1020_INT_DISABLE);
+ if (ret < 0)
+ return ret;
+
+ /* Enable mode interrupt */
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK,
+ ADUX1020_MODE_INT_MASK,
+ adux1020_modes[mode].int_en);
+ if (ret < 0)
+ return ret;
+
+ while (tries--) {
+ ret = regmap_read(data->regmap, ADUX1020_REG_INT_STATUS,
+ &status);
+ if (ret < 0)
+ return ret;
+
+ status &= ADUX1020_FIFO_STATUS_MASK;
+ if (status >= adux1020_modes[mode].bytes)
+ break;
+ msleep(20);
+ }
+
+ if (tries < 0)
+ return -EIO;
+
+ ret = adux1020_read_fifo(data, val, adux1020_modes[mode].buf_len);
+ if (ret < 0)
+ return ret;
+
+ /* Clear mode interrupt */
+ ret = regmap_write(data->regmap, ADUX1020_REG_INT_STATUS,
+ (~adux1020_modes[mode].int_en));
+ if (ret < 0)
+ return ret;
+
+ /* Disable mode interrupts */
+ return regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK,
+ ADUX1020_MODE_INT_MASK,
+ ADUX1020_MODE_INT_DISABLE);
+}
+
+static int adux1020_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct adux1020_data *data = iio_priv(indio_dev);
+ u16 buf[3];
+ int ret = -EINVAL;
+ unsigned int regval;
+
+ mutex_lock(&data->lock);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ ret = adux1020_set_mode(data, ADUX1020_MODE_PROX_I);
+ if (ret < 0)
+ goto fail;
+
+ ret = adux1020_measure(data, ADUX1020_MODE_PROX_I, buf);
+ if (ret < 0)
+ goto fail;
+
+ *val = buf[0];
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ break;
+ }
+ break;
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_CURRENT:
+ ret = regmap_read(data->regmap,
+ ADUX1020_REG_LED_CURRENT, &regval);
+ if (ret < 0)
+ goto fail;
+
+ regval = regval & ADUX1020_LED_CURRENT_MASK;
+
+ *val = adux1020_led_currents[regval][0];
+ *val2 = adux1020_led_currents[regval][1];
+
+ ret = IIO_VAL_INT_PLUS_MICRO;
+ break;
+ default:
+ break;
+ }
+ break;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ ret = regmap_read(data->regmap, ADUX1020_REG_FREQUENCY,
+ &regval);
+ if (ret < 0)
+ goto fail;
+
+ regval = FIELD_GET(ADUX1020_PROX_FREQ_MASK, regval);
+
+ *val = adux1020_rates[regval][0];
+ *val2 = adux1020_rates[regval][1];
+
+ ret = IIO_VAL_INT_PLUS_MICRO;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+fail:
+ mutex_unlock(&data->lock);
+
+ return ret;
+};
+
+static inline int adux1020_find_index(const int array[][2], int count, int val,
+ int val2)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ if (val == array[i][0] && val2 == array[i][1])
+ return i;
+
+ return -EINVAL;
+}
+
+static int adux1020_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct adux1020_data *data = iio_priv(indio_dev);
+ int i, ret = -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (chan->type == IIO_PROXIMITY) {
+ i = adux1020_find_index(adux1020_rates,
+ ARRAY_SIZE(adux1020_rates),
+ val, val2);
+ if (i < 0) {
+ ret = i;
+ goto fail;
+ }
+
+ ret = regmap_update_bits(data->regmap,
+ ADUX1020_REG_FREQUENCY,
+ ADUX1020_PROX_FREQ_MASK,
+ ADUX1020_PROX_FREQ(i));
+ }
+ break;
+ case IIO_CHAN_INFO_PROCESSED:
+ if (chan->type == IIO_CURRENT) {
+ i = adux1020_find_index(adux1020_led_currents,
+ ARRAY_SIZE(adux1020_led_currents),
+ val, val2);
+ if (i < 0) {
+ ret = i;
+ goto fail;
+ }
+
+ ret = regmap_update_bits(data->regmap,
+ ADUX1020_REG_LED_CURRENT,
+ ADUX1020_LED_CURRENT_MASK, i);
+ }
+ break;
+ default:
+ break;
+ }
+
+fail:
+ mutex_unlock(&data->lock);
+
+ return ret;
+}
+
+static int adux1020_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, int state)
+{
+ struct adux1020_data *data = iio_priv(indio_dev);
+ int ret, mask;
+
+ mutex_lock(&data->lock);
+
+ ret = regmap_write(data->regmap, ADUX1020_REG_INT_ENABLE,
+ ADUX1020_INT_ENABLE);
+ if (ret < 0)
+ goto fail;
+
+ ret = regmap_write(data->regmap, ADUX1020_REG_INT_POLARITY, 0);
+ if (ret < 0)
+ goto fail;
+
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ if (dir == IIO_EV_DIR_RISING)
+ mask = ADUX1020_PROX_ON1_INT;
+ else
+ mask = ADUX1020_PROX_OFF1_INT;
+
+ if (state)
+ state = 0;
+ else
+ state = mask;
+
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK,
+ mask, state);
+ if (ret < 0)
+ goto fail;
+
+ /*
+ * Trigger proximity interrupt when the intensity is above
+ * or below threshold
+ */
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_PROX_TYPE,
+ ADUX1020_PROX_TYPE,
+ ADUX1020_PROX_TYPE);
+ if (ret < 0)
+ goto fail;
+
+ /* Set proximity mode */
+ ret = adux1020_set_mode(data, ADUX1020_MODE_PROX_I);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+fail:
+ mutex_unlock(&data->lock);
+
+ return ret;
+}
+
+static int adux1020_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct adux1020_data *data = iio_priv(indio_dev);
+ int ret, mask;
+ unsigned int regval;
+
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ if (dir == IIO_EV_DIR_RISING)
+ mask = ADUX1020_PROX_ON1_INT;
+ else
+ mask = ADUX1020_PROX_OFF1_INT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_read(data->regmap, ADUX1020_REG_INT_MASK, &regval);
+ if (ret < 0)
+ return ret;
+
+ return !(regval & mask);
+}
+
+static int adux1020_read_thresh(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info, int *val, int *val2)
+{
+ struct adux1020_data *data = iio_priv(indio_dev);
+ u8 reg;
+ int ret;
+ unsigned int regval;
+
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ if (dir == IIO_EV_DIR_RISING)
+ reg = ADUX1020_REG_PROX_TH_ON1;
+ else
+ reg = ADUX1020_REG_PROX_TH_OFF1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_read(data->regmap, reg, &regval);
+ if (ret < 0)
+ return ret;
+
+ *val = regval;
+
+ return IIO_VAL_INT;
+}
+
+static int adux1020_write_thresh(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info, int val, int val2)
+{
+ struct adux1020_data *data = iio_priv(indio_dev);
+ u8 reg;
+
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ if (dir == IIO_EV_DIR_RISING)
+ reg = ADUX1020_REG_PROX_TH_ON1;
+ else
+ reg = ADUX1020_REG_PROX_TH_OFF1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Full scale threshold value is 0-65535 */
+ if (val < 0 || val > 65535)
+ return -EINVAL;
+
+ return regmap_write(data->regmap, reg, val);
+}
+
+static const struct iio_event_spec adux1020_proximity_event[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
+static const struct iio_chan_spec adux1020_channels[] = {
+ {
+ .type = IIO_PROXIMITY,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = adux1020_proximity_event,
+ .num_event_specs = ARRAY_SIZE(adux1020_proximity_event),
+ },
+ {
+ .type = IIO_CURRENT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .extend_name = "led",
+ .output = 1,
+ },
+};
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
+ "0.1 0.2 0.5 1 2 5 10 20 50 100 190 450 820 1400");
+
+static struct attribute *adux1020_attributes[] = {
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group adux1020_attribute_group = {
+ .attrs = adux1020_attributes,
+};
+
+static const struct iio_info adux1020_info = {
+ .attrs = &adux1020_attribute_group,
+ .read_raw = adux1020_read_raw,
+ .write_raw = adux1020_write_raw,
+ .read_event_config = adux1020_read_event_config,
+ .write_event_config = adux1020_write_event_config,
+ .read_event_value = adux1020_read_thresh,
+ .write_event_value = adux1020_write_thresh,
+};
+
+static irqreturn_t adux1020_interrupt_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct adux1020_data *data = iio_priv(indio_dev);
+ int ret, status;
+
+ ret = regmap_read(data->regmap, ADUX1020_REG_INT_STATUS, &status);
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ status &= ADUX1020_MODE_INT_STATUS_MASK;
+
+ if (status & ADUX1020_INT_PROX_ON1) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns(indio_dev));
+ }
+
+ if (status & ADUX1020_INT_PROX_OFF1) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns(indio_dev));
+ }
+
+ regmap_update_bits(data->regmap, ADUX1020_REG_INT_STATUS,
+ ADUX1020_MODE_INT_MASK, ADUX1020_INT_CLEAR);
+
+ return IRQ_HANDLED;
+}
+
+static int adux1020_chip_init(struct adux1020_data *data)
+{
+ struct i2c_client *client = data->client;
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(data->regmap, ADUX1020_REG_CHIP_ID, &val);
+ if (ret < 0)
+ return ret;
+
+ if ((val & ADUX1020_CHIP_ID_MASK) != ADUX1020_CHIP_ID) {
+ dev_err(&client->dev, "invalid chip id 0x%04x\n", val);
+ return -ENODEV;
+ }
+
+ dev_dbg(&client->dev, "Detected ADUX1020 with chip id: 0x%04x\n", val);
+
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_SW_RESET,
+ ADUX1020_SW_RESET, ADUX1020_SW_RESET);
+ if (ret < 0)
+ return ret;
+
+ /* Load default configuration */
+ ret = regmap_multi_reg_write(data->regmap, adux1020_def_conf,
+ ARRAY_SIZE(adux1020_def_conf));
+ if (ret < 0)
+ return ret;
+
+ ret = adux1020_flush_fifo(data);
+ if (ret < 0)
+ return ret;
+
+ /* Use LED_IREF for proximity mode */
+ ret = regmap_update_bits(data->regmap, ADUX1020_REG_LED_CURRENT,
+ ADUX1020_LED_PIREF_EN, 0);
+ if (ret < 0)
+ return ret;
+
+ /* Mask all interrupts */
+ return regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK,
+ ADUX1020_MODE_INT_MASK, ADUX1020_MODE_INT_DISABLE);
+}
+
+static int adux1020_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adux1020_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &adux1020_info;
+ indio_dev->name = ADUX1020_DRV_NAME;
+ indio_dev->channels = adux1020_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adux1020_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ data = iio_priv(indio_dev);
+
+ data->regmap = devm_regmap_init_i2c(client, &adux1020_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ dev_err(&client->dev, "regmap initialization failed.\n");
+ return PTR_ERR(data->regmap);
+ }
+
+ data->client = client;
+ data->indio_dev = indio_dev;
+ mutex_init(&data->lock);
+
+ ret = adux1020_chip_init(data);
+ if (ret)
+ return ret;
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, adux1020_interrupt_handler,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ ADUX1020_DRV_NAME, indio_dev);
+ if (ret) {
+ dev_err(&client->dev, "irq request error %d\n", -ret);
+ return ret;
+ }
+ }
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id adux1020_id[] = {
+ { "adux1020", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, adux1020_id);
+
+static const struct of_device_id adux1020_of_match[] = {
+ { .compatible = "adi,adux1020" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, adux1020_of_match);
+
+static struct i2c_driver adux1020_driver = {
+ .driver = {
+ .name = ADUX1020_DRV_NAME,
+ .of_match_table = adux1020_of_match,
+ },
+ .probe = adux1020_probe,
+ .id_table = adux1020_id,
+};
+module_i2c_driver(adux1020_driver);
+
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
+MODULE_DESCRIPTION("ADUX1020 photometric sensor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c
index 28347df78cff..adb5ab9e3439 100644
--- a/drivers/iio/light/bh1750.c
+++ b/drivers/iio/light/bh1750.c
@@ -59,9 +59,9 @@ struct bh1750_chip_info {
u16 int_time_low_mask;
u16 int_time_high_mask;
-}
+};
-static const bh1750_chip_info_tbl[] = {
+static const struct bh1750_chip_info bh1750_chip_info_tbl[] = {
[BH1710] = { 140, 1022, 300, 400, 250000000, 2, 0x001F, 0x03E0 },
[BH1721] = { 140, 1020, 300, 400, 250000000, 2, 0x0010, 0x03E0 },
[BH1750] = { 31, 254, 69, 1740, 57500000, 1, 0x001F, 0x00E0 },
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index 1019d625adb1..90e38fcc974b 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -532,7 +532,7 @@ static int cm36651_write_prox_event_config(struct iio_dev *indio_dev,
int state)
{
struct cm36651_data *cm36651 = iio_priv(indio_dev);
- int cmd, ret = -EINVAL;
+ int cmd, ret;
mutex_lock(&cm36651->lock);
diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c
index 7c0291c5fe76..b542e5619ead 100644
--- a/drivers/iio/light/tcs3414.c
+++ b/drivers/iio/light/tcs3414.c
@@ -240,32 +240,42 @@ static const struct iio_info tcs3414_info = {
.attrs = &tcs3414_attribute_group,
};
-static int tcs3414_buffer_preenable(struct iio_dev *indio_dev)
+static int tcs3414_buffer_postenable(struct iio_dev *indio_dev)
{
struct tcs3414_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_triggered_buffer_postenable(indio_dev);
+ if (ret)
+ return ret;
data->control |= TCS3414_CONTROL_ADC_EN;
- return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
data->control);
+ if (ret)
+ iio_triggered_buffer_predisable(indio_dev);
+
+ return ret;
}
static int tcs3414_buffer_predisable(struct iio_dev *indio_dev)
{
struct tcs3414_data *data = iio_priv(indio_dev);
- int ret;
-
- ret = iio_triggered_buffer_predisable(indio_dev);
- if (ret < 0)
- return ret;
+ int ret, ret2;
data->control &= ~TCS3414_CONTROL_ADC_EN;
- return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
data->control);
+
+ ret2 = iio_triggered_buffer_predisable(indio_dev);
+ if (!ret)
+ ret = ret2;
+
+ return ret;
}
static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops = {
- .preenable = tcs3414_buffer_preenable,
- .postenable = &iio_triggered_buffer_postenable,
+ .postenable = tcs3414_buffer_postenable,
.predisable = tcs3414_buffer_predisable,
};
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index a3a268ee2896..e68184a93a6d 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -14,7 +14,6 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index 8d0f15f27dc5..29c209cc1108 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -74,6 +74,12 @@ struct bmp280_calib {
s8 H6;
};
+static const char *const bmp280_supply_names[] = {
+ "vddd", "vdda"
+};
+
+#define BMP280_NUM_SUPPLIES ARRAY_SIZE(bmp280_supply_names)
+
struct bmp280_data {
struct device *dev;
struct mutex lock;
@@ -85,8 +91,7 @@ struct bmp280_data {
struct bmp180_calib bmp180;
struct bmp280_calib bmp280;
} calib;
- struct regulator *vddd;
- struct regulator *vdda;
+ struct regulator_bulk_data supplies[BMP280_NUM_SUPPLIES];
unsigned int start_up_time; /* in microseconds */
/* log of base 2 of oversampling rate */
@@ -148,6 +153,8 @@ static int bmp280_read_calib(struct bmp280_data *data,
{
int ret;
unsigned int tmp;
+ __le16 l16;
+ __be16 b16;
struct device *dev = data->dev;
__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
@@ -207,12 +214,12 @@ static int bmp280_read_calib(struct bmp280_data *data,
}
calib->H1 = tmp;
- ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &tmp, 2);
+ ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &l16, 2);
if (ret < 0) {
dev_err(dev, "failed to read H2 comp value\n");
return ret;
}
- calib->H2 = sign_extend32(le16_to_cpu(tmp), 15);
+ calib->H2 = sign_extend32(le16_to_cpu(l16), 15);
ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &tmp);
if (ret < 0) {
@@ -221,20 +228,20 @@ static int bmp280_read_calib(struct bmp280_data *data,
}
calib->H3 = tmp;
- ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &tmp, 2);
+ ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &b16, 2);
if (ret < 0) {
dev_err(dev, "failed to read H4 comp value\n");
return ret;
}
- calib->H4 = sign_extend32(((be16_to_cpu(tmp) >> 4) & 0xff0) |
- (be16_to_cpu(tmp) & 0xf), 11);
+ calib->H4 = sign_extend32(((be16_to_cpu(b16) >> 4) & 0xff0) |
+ (be16_to_cpu(b16) & 0xf), 11);
- ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, &tmp, 2);
+ ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, &l16, 2);
if (ret < 0) {
dev_err(dev, "failed to read H5 comp value\n");
return ret;
}
- calib->H5 = sign_extend32(((le16_to_cpu(tmp) >> 4) & 0xfff), 11);
+ calib->H5 = sign_extend32(((le16_to_cpu(l16) >> 4) & 0xfff), 11);
ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
if (ret < 0) {
@@ -979,6 +986,22 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
return 0;
}
+static void bmp280_pm_disable(void *data)
+{
+ struct device *dev = data;
+
+ pm_runtime_get_sync(dev);
+ pm_runtime_put_noidle(dev);
+ pm_runtime_disable(dev);
+}
+
+static void bmp280_regulators_disable(void *data)
+{
+ struct regulator_bulk_data *supplies = data;
+
+ regulator_bulk_disable(BMP280_NUM_SUPPLIES, supplies);
+}
+
int bmp280_common_probe(struct device *dev,
struct regmap *regmap,
unsigned int chip,
@@ -1033,27 +1056,28 @@ int bmp280_common_probe(struct device *dev,
}
/* Bring up regulators */
- data->vddd = devm_regulator_get(dev, "vddd");
- if (IS_ERR(data->vddd)) {
- dev_err(dev, "failed to get VDDD regulator\n");
- return PTR_ERR(data->vddd);
- }
- ret = regulator_enable(data->vddd);
+ regulator_bulk_set_supply_names(data->supplies,
+ bmp280_supply_names,
+ BMP280_NUM_SUPPLIES);
+
+ ret = devm_regulator_bulk_get(dev,
+ BMP280_NUM_SUPPLIES, data->supplies);
if (ret) {
- dev_err(dev, "failed to enable VDDD regulator\n");
+ dev_err(dev, "failed to get regulators\n");
return ret;
}
- data->vdda = devm_regulator_get(dev, "vdda");
- if (IS_ERR(data->vdda)) {
- dev_err(dev, "failed to get VDDA regulator\n");
- ret = PTR_ERR(data->vdda);
- goto out_disable_vddd;
- }
- ret = regulator_enable(data->vdda);
+
+ ret = regulator_bulk_enable(BMP280_NUM_SUPPLIES, data->supplies);
if (ret) {
- dev_err(dev, "failed to enable VDDA regulator\n");
- goto out_disable_vddd;
+ dev_err(dev, "failed to enable regulators\n");
+ return ret;
}
+
+ ret = devm_add_action_or_reset(dev, bmp280_regulators_disable,
+ data->supplies);
+ if (ret)
+ return ret;
+
/* Wait to make sure we started up properly */
usleep_range(data->start_up_time, data->start_up_time + 100);
@@ -1068,17 +1092,16 @@ int bmp280_common_probe(struct device *dev,
data->regmap = regmap;
ret = regmap_read(regmap, BMP280_REG_ID, &chip_id);
if (ret < 0)
- goto out_disable_vdda;
+ return ret;
if (chip_id != chip) {
dev_err(dev, "bad chip id: expected %x got %x\n",
chip, chip_id);
- ret = -EINVAL;
- goto out_disable_vdda;
+ return -EINVAL;
}
ret = data->chip_info->chip_config(data);
if (ret < 0)
- goto out_disable_vdda;
+ return ret;
dev_set_drvdata(dev, indio_dev);
@@ -1092,14 +1115,14 @@ int bmp280_common_probe(struct device *dev,
if (ret < 0) {
dev_err(data->dev,
"failed to read calibration coefficients\n");
- goto out_disable_vdda;
+ return ret;
}
} else if (chip_id == BMP280_CHIP_ID || chip_id == BME280_CHIP_ID) {
ret = bmp280_read_calib(data, &data->calib.bmp280, chip_id);
if (ret < 0) {
dev_err(data->dev,
"failed to read calibration coefficients\n");
- goto out_disable_vdda;
+ return ret;
}
}
@@ -1111,7 +1134,7 @@ int bmp280_common_probe(struct device *dev,
if (irq > 0 || (chip_id == BMP180_CHIP_ID)) {
ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
if (ret)
- goto out_disable_vdda;
+ return ret;
}
/* Enable runtime PM */
@@ -1126,51 +1149,21 @@ int bmp280_common_probe(struct device *dev,
pm_runtime_use_autosuspend(dev);
pm_runtime_put(dev);
- ret = iio_device_register(indio_dev);
+ ret = devm_add_action_or_reset(dev, bmp280_pm_disable, dev);
if (ret)
- goto out_runtime_pm_disable;
-
-
- return 0;
+ return ret;
-out_runtime_pm_disable:
- pm_runtime_get_sync(data->dev);
- pm_runtime_put_noidle(data->dev);
- pm_runtime_disable(data->dev);
-out_disable_vdda:
- regulator_disable(data->vdda);
-out_disable_vddd:
- regulator_disable(data->vddd);
- return ret;
+ return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL(bmp280_common_probe);
-int bmp280_common_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct bmp280_data *data = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- pm_runtime_get_sync(data->dev);
- pm_runtime_put_noidle(data->dev);
- pm_runtime_disable(data->dev);
- regulator_disable(data->vdda);
- regulator_disable(data->vddd);
- return 0;
-}
-EXPORT_SYMBOL(bmp280_common_remove);
-
#ifdef CONFIG_PM
static int bmp280_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmp280_data *data = iio_priv(indio_dev);
- int ret;
- ret = regulator_disable(data->vdda);
- if (ret)
- return ret;
- return regulator_disable(data->vddd);
+ return regulator_bulk_disable(BMP280_NUM_SUPPLIES, data->supplies);
}
static int bmp280_runtime_resume(struct device *dev)
@@ -1179,10 +1172,7 @@ static int bmp280_runtime_resume(struct device *dev)
struct bmp280_data *data = iio_priv(indio_dev);
int ret;
- ret = regulator_enable(data->vddd);
- if (ret)
- return ret;
- ret = regulator_enable(data->vdda);
+ ret = regulator_bulk_enable(BMP280_NUM_SUPPLIES, data->supplies);
if (ret)
return ret;
usleep_range(data->start_up_time, data->start_up_time + 100);
diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c
index acd9a3784fb4..3109c8e2cc11 100644
--- a/drivers/iio/pressure/bmp280-i2c.c
+++ b/drivers/iio/pressure/bmp280-i2c.c
@@ -38,11 +38,6 @@ static int bmp280_i2c_probe(struct i2c_client *client,
client->irq);
}
-static int bmp280_i2c_remove(struct i2c_client *client)
-{
- return bmp280_common_remove(&client->dev);
-}
-
static const struct acpi_device_id bmp280_acpi_i2c_match[] = {
{"BMP0280", BMP280_CHIP_ID },
{"BMP0180", BMP180_CHIP_ID },
@@ -82,7 +77,6 @@ static struct i2c_driver bmp280_i2c_driver = {
.pm = &bmp280_dev_pm_ops,
},
.probe = bmp280_i2c_probe,
- .remove = bmp280_i2c_remove,
.id_table = bmp280_i2c_id,
};
module_i2c_driver(bmp280_i2c_driver);
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index 9d57b7a3b134..625b86878ad8 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -86,11 +86,6 @@ static int bmp280_spi_probe(struct spi_device *spi)
spi->irq);
}
-static int bmp280_spi_remove(struct spi_device *spi)
-{
- return bmp280_common_remove(&spi->dev);
-}
-
static const struct of_device_id bmp280_of_spi_match[] = {
{ .compatible = "bosch,bmp085", },
{ .compatible = "bosch,bmp180", },
@@ -118,7 +113,6 @@ static struct spi_driver bmp280_spi_driver = {
},
.id_table = bmp280_spi_id,
.probe = bmp280_spi_probe,
- .remove = bmp280_spi_remove,
};
module_spi_driver(bmp280_spi_driver);
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index eda50ef65706..57ba0e85db91 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -112,7 +112,6 @@ int bmp280_common_probe(struct device *dev,
unsigned int chip,
const char *name,
int irq);
-int bmp280_common_remove(struct device *dev);
/* PM ops */
extern const struct dev_pm_ops bmp280_dev_pm_ops;
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index ca6863b32a5f..bd972cec4830 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -14,7 +14,6 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
index 9d0d07930236..99dfe33ee402 100644
--- a/drivers/iio/pressure/zpa2326.c
+++ b/drivers/iio/pressure/zpa2326.c
@@ -1243,6 +1243,11 @@ static int zpa2326_postenable_buffer(struct iio_dev *indio_dev)
const struct zpa2326_private *priv = iio_priv(indio_dev);
int err;
+ /* Plug our own trigger event handler. */
+ err = iio_triggered_buffer_postenable(indio_dev);
+ if (err)
+ goto err;
+
if (!priv->waken) {
/*
* We were already power supplied. Just clear hardware FIFO to
@@ -1250,7 +1255,7 @@ static int zpa2326_postenable_buffer(struct iio_dev *indio_dev)
*/
err = zpa2326_clear_fifo(indio_dev, 0);
if (err)
- goto err;
+ goto err_buffer_predisable;
}
if (!iio_trigger_using_own(indio_dev) && priv->waken) {
@@ -1260,16 +1265,13 @@ static int zpa2326_postenable_buffer(struct iio_dev *indio_dev)
*/
err = zpa2326_config_oneshot(indio_dev, priv->irq);
if (err)
- goto err;
+ goto err_buffer_predisable;
}
- /* Plug our own trigger event handler. */
- err = iio_triggered_buffer_postenable(indio_dev);
- if (err)
- goto err;
-
return 0;
+err_buffer_predisable:
+ iio_triggered_buffer_predisable(indio_dev);
err:
zpa2326_err(indio_dev, "failed to enable buffering (%d)", err);
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
index 47af54f14756..5b369645ef49 100644
--- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
+++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
@@ -136,12 +136,13 @@ static inline int lidar_write_power(struct lidar_data *data, int val)
static int lidar_read_measurement(struct lidar_data *data, u16 *reg)
{
+ __be16 value;
int ret = data->xfer(data, LIDAR_REG_DATA_HBYTE |
(data->i2c_enabled ? LIDAR_REG_DATA_WORD_READ : 0),
- (u8 *) reg, 2);
+ (u8 *) &value, 2);
if (!ret)
- *reg = be16_to_cpu(*reg);
+ *reg = be16_to_cpu(value);
return ret;
}
diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c
index 612f79c53cfc..287d288e40c2 100644
--- a/drivers/iio/proximity/sx9500.c
+++ b/drivers/iio/proximity/sx9500.c
@@ -675,11 +675,15 @@ out:
return IRQ_HANDLED;
}
-static int sx9500_buffer_preenable(struct iio_dev *indio_dev)
+static int sx9500_buffer_postenable(struct iio_dev *indio_dev)
{
struct sx9500_data *data = iio_priv(indio_dev);
int ret = 0, i;
+ ret = iio_triggered_buffer_postenable(indio_dev);
+ if (ret)
+ return ret;
+
mutex_lock(&data->mutex);
for (i = 0; i < SX9500_NUM_CHANNELS; i++)
@@ -696,6 +700,9 @@ static int sx9500_buffer_preenable(struct iio_dev *indio_dev)
mutex_unlock(&data->mutex);
+ if (ret)
+ iio_triggered_buffer_predisable(indio_dev);
+
return ret;
}
@@ -704,8 +711,6 @@ static int sx9500_buffer_predisable(struct iio_dev *indio_dev)
struct sx9500_data *data = iio_priv(indio_dev);
int ret = 0, i;
- iio_triggered_buffer_predisable(indio_dev);
-
mutex_lock(&data->mutex);
for (i = 0; i < SX9500_NUM_CHANNELS; i++)
@@ -722,12 +727,13 @@ static int sx9500_buffer_predisable(struct iio_dev *indio_dev)
mutex_unlock(&data->mutex);
+ iio_triggered_buffer_predisable(indio_dev);
+
return ret;
}
static const struct iio_buffer_setup_ops sx9500_buffer_setup_ops = {
- .preenable = sx9500_buffer_preenable,
- .postenable = iio_triggered_buffer_postenable,
+ .postenable = sx9500_buffer_postenable,
.predisable = sx9500_buffer_predisable,
};
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
index 737faa0901fe..e1ccb4003015 100644
--- a/drivers/iio/temperature/Kconfig
+++ b/drivers/iio/temperature/Kconfig
@@ -4,6 +4,17 @@
#
menu "Temperature sensors"
+config LTC2983
+ tristate "Analog Devices Multi-Sensor Digital Temperature Measurement System"
+ depends on SPI
+ select REGMAP_SPI
+ help
+ Say yes here to build support for the LTC2983 Multi-Sensor
+ high accuracy digital temperature measurement system.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ltc2983.
+
config MAXIM_THERMOCOUPLE
tristate "Maxim thermocouple sensors"
depends on SPI
diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile
index baca4776ca0d..d6b850b0cf63 100644
--- a/drivers/iio/temperature/Makefile
+++ b/drivers/iio/temperature/Makefile
@@ -3,6 +3,7 @@
# Makefile for industrial I/O temperature drivers
#
+obj-$(CONFIG_LTC2983) += ltc2983.o
obj-$(CONFIG_HID_SENSOR_TEMP) += hid-sensor-temperature.o
obj-$(CONFIG_MAXIM_THERMOCOUPLE) += maxim_thermocouple.o
obj-$(CONFIG_MAX31856) += max31856.o
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
new file mode 100644
index 000000000000..ddf47023364b
--- /dev/null
+++ b/drivers/iio/temperature/ltc2983.c
@@ -0,0 +1,1557 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Analog Devices LTC2983 Multi-Sensor Digital Temperature Measurement System
+ * driver
+ *
+ * Copyright 2019 Analog Devices Inc.
+ */
+#include <linux/bitfield.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/iio/iio.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+/* register map */
+#define LTC2983_STATUS_REG 0x0000
+#define LTC2983_TEMP_RES_START_REG 0x0010
+#define LTC2983_TEMP_RES_END_REG 0x005F
+#define LTC2983_GLOBAL_CONFIG_REG 0x00F0
+#define LTC2983_MULT_CHANNEL_START_REG 0x00F4
+#define LTC2983_MULT_CHANNEL_END_REG 0x00F7
+#define LTC2983_MUX_CONFIG_REG 0x00FF
+#define LTC2983_CHAN_ASSIGN_START_REG 0x0200
+#define LTC2983_CHAN_ASSIGN_END_REG 0x024F
+#define LTC2983_CUST_SENS_TBL_START_REG 0x0250
+#define LTC2983_CUST_SENS_TBL_END_REG 0x03CF
+
+#define LTC2983_DIFFERENTIAL_CHAN_MIN 2
+#define LTC2983_MAX_CHANNELS_NR 20
+#define LTC2983_MIN_CHANNELS_NR 1
+#define LTC2983_SLEEP 0x97
+#define LTC2983_CUSTOM_STEINHART_SIZE 24
+#define LTC2983_CUSTOM_SENSOR_ENTRY_SZ 6
+#define LTC2983_CUSTOM_STEINHART_ENTRY_SZ 4
+
+#define LTC2983_CHAN_START_ADDR(chan) \
+ (((chan - 1) * 4) + LTC2983_CHAN_ASSIGN_START_REG)
+#define LTC2983_CHAN_RES_ADDR(chan) \
+ (((chan - 1) * 4) + LTC2983_TEMP_RES_START_REG)
+#define LTC2983_THERMOCOUPLE_DIFF_MASK BIT(3)
+#define LTC2983_THERMOCOUPLE_SGL(x) \
+ FIELD_PREP(LTC2983_THERMOCOUPLE_DIFF_MASK, x)
+#define LTC2983_THERMOCOUPLE_OC_CURR_MASK GENMASK(1, 0)
+#define LTC2983_THERMOCOUPLE_OC_CURR(x) \
+ FIELD_PREP(LTC2983_THERMOCOUPLE_OC_CURR_MASK, x)
+#define LTC2983_THERMOCOUPLE_OC_CHECK_MASK BIT(2)
+#define LTC2983_THERMOCOUPLE_OC_CHECK(x) \
+ FIELD_PREP(LTC2983_THERMOCOUPLE_OC_CHECK_MASK, x)
+
+#define LTC2983_THERMISTOR_DIFF_MASK BIT(2)
+#define LTC2983_THERMISTOR_SGL(x) \
+ FIELD_PREP(LTC2983_THERMISTOR_DIFF_MASK, x)
+#define LTC2983_THERMISTOR_R_SHARE_MASK BIT(1)
+#define LTC2983_THERMISTOR_R_SHARE(x) \
+ FIELD_PREP(LTC2983_THERMISTOR_R_SHARE_MASK, x)
+#define LTC2983_THERMISTOR_C_ROTATE_MASK BIT(0)
+#define LTC2983_THERMISTOR_C_ROTATE(x) \
+ FIELD_PREP(LTC2983_THERMISTOR_C_ROTATE_MASK, x)
+
+#define LTC2983_DIODE_DIFF_MASK BIT(2)
+#define LTC2983_DIODE_SGL(x) \
+ FIELD_PREP(LTC2983_DIODE_DIFF_MASK, x)
+#define LTC2983_DIODE_3_CONV_CYCLE_MASK BIT(1)
+#define LTC2983_DIODE_3_CONV_CYCLE(x) \
+ FIELD_PREP(LTC2983_DIODE_3_CONV_CYCLE_MASK, x)
+#define LTC2983_DIODE_AVERAGE_ON_MASK BIT(0)
+#define LTC2983_DIODE_AVERAGE_ON(x) \
+ FIELD_PREP(LTC2983_DIODE_AVERAGE_ON_MASK, x)
+
+#define LTC2983_RTD_4_WIRE_MASK BIT(3)
+#define LTC2983_RTD_ROTATION_MASK BIT(1)
+#define LTC2983_RTD_C_ROTATE(x) \
+ FIELD_PREP(LTC2983_RTD_ROTATION_MASK, x)
+#define LTC2983_RTD_KELVIN_R_SENSE_MASK GENMASK(3, 2)
+#define LTC2983_RTD_N_WIRES_MASK GENMASK(3, 2)
+#define LTC2983_RTD_N_WIRES(x) \
+ FIELD_PREP(LTC2983_RTD_N_WIRES_MASK, x)
+#define LTC2983_RTD_R_SHARE_MASK BIT(0)
+#define LTC2983_RTD_R_SHARE(x) \
+ FIELD_PREP(LTC2983_RTD_R_SHARE_MASK, 1)
+
+#define LTC2983_COMMON_HARD_FAULT_MASK GENMASK(31, 30)
+#define LTC2983_COMMON_SOFT_FAULT_MASK GENMASK(27, 25)
+
+#define LTC2983_STATUS_START_MASK BIT(7)
+#define LTC2983_STATUS_START(x) FIELD_PREP(LTC2983_STATUS_START_MASK, x)
+
+#define LTC2983_STATUS_CHAN_SEL_MASK GENMASK(4, 0)
+#define LTC2983_STATUS_CHAN_SEL(x) \
+ FIELD_PREP(LTC2983_STATUS_CHAN_SEL_MASK, x)
+
+#define LTC2983_TEMP_UNITS_MASK BIT(2)
+#define LTC2983_TEMP_UNITS(x) FIELD_PREP(LTC2983_TEMP_UNITS_MASK, x)
+
+#define LTC2983_NOTCH_FREQ_MASK GENMASK(1, 0)
+#define LTC2983_NOTCH_FREQ(x) FIELD_PREP(LTC2983_NOTCH_FREQ_MASK, x)
+
+#define LTC2983_RES_VALID_MASK BIT(24)
+#define LTC2983_DATA_MASK GENMASK(23, 0)
+#define LTC2983_DATA_SIGN_BIT 23
+
+#define LTC2983_CHAN_TYPE_MASK GENMASK(31, 27)
+#define LTC2983_CHAN_TYPE(x) FIELD_PREP(LTC2983_CHAN_TYPE_MASK, x)
+
+/* cold junction for thermocouples and rsense for rtd's and thermistor's */
+#define LTC2983_CHAN_ASSIGN_MASK GENMASK(26, 22)
+#define LTC2983_CHAN_ASSIGN(x) FIELD_PREP(LTC2983_CHAN_ASSIGN_MASK, x)
+
+#define LTC2983_CUSTOM_LEN_MASK GENMASK(5, 0)
+#define LTC2983_CUSTOM_LEN(x) FIELD_PREP(LTC2983_CUSTOM_LEN_MASK, x)
+
+#define LTC2983_CUSTOM_ADDR_MASK GENMASK(11, 6)
+#define LTC2983_CUSTOM_ADDR(x) FIELD_PREP(LTC2983_CUSTOM_ADDR_MASK, x)
+
+#define LTC2983_THERMOCOUPLE_CFG_MASK GENMASK(21, 18)
+#define LTC2983_THERMOCOUPLE_CFG(x) \
+ FIELD_PREP(LTC2983_THERMOCOUPLE_CFG_MASK, x)
+#define LTC2983_THERMOCOUPLE_HARD_FAULT_MASK GENMASK(31, 29)
+#define LTC2983_THERMOCOUPLE_SOFT_FAULT_MASK GENMASK(28, 25)
+
+#define LTC2983_RTD_CFG_MASK GENMASK(21, 18)
+#define LTC2983_RTD_CFG(x) FIELD_PREP(LTC2983_RTD_CFG_MASK, x)
+#define LTC2983_RTD_EXC_CURRENT_MASK GENMASK(17, 14)
+#define LTC2983_RTD_EXC_CURRENT(x) \
+ FIELD_PREP(LTC2983_RTD_EXC_CURRENT_MASK, x)
+#define LTC2983_RTD_CURVE_MASK GENMASK(13, 12)
+#define LTC2983_RTD_CURVE(x) FIELD_PREP(LTC2983_RTD_CURVE_MASK, x)
+
+#define LTC2983_THERMISTOR_CFG_MASK GENMASK(21, 19)
+#define LTC2983_THERMISTOR_CFG(x) \
+ FIELD_PREP(LTC2983_THERMISTOR_CFG_MASK, x)
+#define LTC2983_THERMISTOR_EXC_CURRENT_MASK GENMASK(18, 15)
+#define LTC2983_THERMISTOR_EXC_CURRENT(x) \
+ FIELD_PREP(LTC2983_THERMISTOR_EXC_CURRENT_MASK, x)
+
+#define LTC2983_DIODE_CFG_MASK GENMASK(26, 24)
+#define LTC2983_DIODE_CFG(x) FIELD_PREP(LTC2983_DIODE_CFG_MASK, x)
+#define LTC2983_DIODE_EXC_CURRENT_MASK GENMASK(23, 22)
+#define LTC2983_DIODE_EXC_CURRENT(x) \
+ FIELD_PREP(LTC2983_DIODE_EXC_CURRENT_MASK, x)
+#define LTC2983_DIODE_IDEAL_FACTOR_MASK GENMASK(21, 0)
+#define LTC2983_DIODE_IDEAL_FACTOR(x) \
+ FIELD_PREP(LTC2983_DIODE_IDEAL_FACTOR_MASK, x)
+
+#define LTC2983_R_SENSE_VAL_MASK GENMASK(26, 0)
+#define LTC2983_R_SENSE_VAL(x) FIELD_PREP(LTC2983_R_SENSE_VAL_MASK, x)
+
+#define LTC2983_ADC_SINGLE_ENDED_MASK BIT(26)
+#define LTC2983_ADC_SINGLE_ENDED(x) \
+ FIELD_PREP(LTC2983_ADC_SINGLE_ENDED_MASK, x)
+
+enum {
+ LTC2983_SENSOR_THERMOCOUPLE = 1,
+ LTC2983_SENSOR_THERMOCOUPLE_CUSTOM = 9,
+ LTC2983_SENSOR_RTD = 10,
+ LTC2983_SENSOR_RTD_CUSTOM = 18,
+ LTC2983_SENSOR_THERMISTOR = 19,
+ LTC2983_SENSOR_THERMISTOR_STEINHART = 26,
+ LTC2983_SENSOR_THERMISTOR_CUSTOM = 27,
+ LTC2983_SENSOR_DIODE = 28,
+ LTC2983_SENSOR_SENSE_RESISTOR = 29,
+ LTC2983_SENSOR_DIRECT_ADC = 30,
+};
+
+#define to_thermocouple(_sensor) \
+ container_of(_sensor, struct ltc2983_thermocouple, sensor)
+
+#define to_rtd(_sensor) \
+ container_of(_sensor, struct ltc2983_rtd, sensor)
+
+#define to_thermistor(_sensor) \
+ container_of(_sensor, struct ltc2983_thermistor, sensor)
+
+#define to_diode(_sensor) \
+ container_of(_sensor, struct ltc2983_diode, sensor)
+
+#define to_rsense(_sensor) \
+ container_of(_sensor, struct ltc2983_rsense, sensor)
+
+#define to_adc(_sensor) \
+ container_of(_sensor, struct ltc2983_adc, sensor)
+
+struct ltc2983_data {
+ struct regmap *regmap;
+ struct spi_device *spi;
+ struct mutex lock;
+ struct completion completion;
+ struct iio_chan_spec *iio_chan;
+ struct ltc2983_sensor **sensors;
+ u32 mux_delay_config;
+ u32 filter_notch_freq;
+ u16 custom_table_size;
+ u8 num_channels;
+ u8 iio_channels;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ * Holds the converted temperature
+ */
+ __be32 temp ____cacheline_aligned;
+};
+
+struct ltc2983_sensor {
+ int (*fault_handler)(const struct ltc2983_data *st, const u32 result);
+ int (*assign_chan)(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor);
+ /* specifies the sensor channel */
+ u32 chan;
+ /* sensor type */
+ u32 type;
+};
+
+struct ltc2983_custom_sensor {
+ /* raw table sensor data */
+ u8 *table;
+ size_t size;
+ /* address offset */
+ s8 offset;
+ bool is_steinhart;
+};
+
+struct ltc2983_thermocouple {
+ struct ltc2983_sensor sensor;
+ struct ltc2983_custom_sensor *custom;
+ u32 sensor_config;
+ u32 cold_junction_chan;
+};
+
+struct ltc2983_rtd {
+ struct ltc2983_sensor sensor;
+ struct ltc2983_custom_sensor *custom;
+ u32 sensor_config;
+ u32 r_sense_chan;
+ u32 excitation_current;
+ u32 rtd_curve;
+};
+
+struct ltc2983_thermistor {
+ struct ltc2983_sensor sensor;
+ struct ltc2983_custom_sensor *custom;
+ u32 sensor_config;
+ u32 r_sense_chan;
+ u32 excitation_current;
+};
+
+struct ltc2983_diode {
+ struct ltc2983_sensor sensor;
+ u32 sensor_config;
+ u32 excitation_current;
+ u32 ideal_factor_value;
+};
+
+struct ltc2983_rsense {
+ struct ltc2983_sensor sensor;
+ u32 r_sense_val;
+};
+
+struct ltc2983_adc {
+ struct ltc2983_sensor sensor;
+ bool single_ended;
+};
+
+/*
+ * Convert to Q format numbers. These number's are integers where
+ * the number of integer and fractional bits are specified. The resolution
+ * is given by 1/@resolution and tell us the number of fractional bits. For
+ * instance a resolution of 2^-10 means we have 10 fractional bits.
+ */
+static u32 __convert_to_raw(const u64 val, const u32 resolution)
+{
+ u64 __res = val * resolution;
+
+ /* all values are multiplied by 1000000 to remove the fraction */
+ do_div(__res, 1000000);
+
+ return __res;
+}
+
+static u32 __convert_to_raw_sign(const u64 val, const u32 resolution)
+{
+ s64 __res = -(s32)val;
+
+ __res = __convert_to_raw(__res, resolution);
+
+ return (u32)-__res;
+}
+
+static int __ltc2983_fault_handler(const struct ltc2983_data *st,
+ const u32 result, const u32 hard_mask,
+ const u32 soft_mask)
+{
+ const struct device *dev = &st->spi->dev;
+
+ if (result & hard_mask) {
+ dev_err(dev, "Invalid conversion: Sensor HARD fault\n");
+ return -EIO;
+ } else if (result & soft_mask) {
+ /* just print a warning */
+ dev_warn(dev, "Suspicious conversion: Sensor SOFT fault\n");
+ }
+
+ return 0;
+}
+
+static int __ltc2983_chan_assign_common(const struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor,
+ u32 chan_val)
+{
+ u32 reg = LTC2983_CHAN_START_ADDR(sensor->chan);
+ __be32 __chan_val;
+
+ chan_val |= LTC2983_CHAN_TYPE(sensor->type);
+ dev_dbg(&st->spi->dev, "Assign reg:0x%04X, val:0x%08X\n", reg,
+ chan_val);
+ __chan_val = cpu_to_be32(chan_val);
+ return regmap_bulk_write(st->regmap, reg, &__chan_val,
+ sizeof(__chan_val));
+}
+
+static int __ltc2983_chan_custom_sensor_assign(struct ltc2983_data *st,
+ struct ltc2983_custom_sensor *custom,
+ u32 *chan_val)
+{
+ u32 reg;
+ u8 mult = custom->is_steinhart ? LTC2983_CUSTOM_STEINHART_ENTRY_SZ :
+ LTC2983_CUSTOM_SENSOR_ENTRY_SZ;
+ const struct device *dev = &st->spi->dev;
+ /*
+ * custom->size holds the raw size of the table. However, when
+ * configuring the sensor channel, we must write the number of
+ * entries of the table minus 1. For steinhart sensors 0 is written
+ * since the size is constant!
+ */
+ const u8 len = custom->is_steinhart ? 0 :
+ (custom->size / LTC2983_CUSTOM_SENSOR_ENTRY_SZ) - 1;
+ /*
+ * Check if the offset was assigned already. It should be for steinhart
+ * sensors. When coming from sleep, it should be assigned for all.
+ */
+ if (custom->offset < 0) {
+ /*
+ * This needs to be done again here because, from the moment
+ * when this test was done (successfully) for this custom
+ * sensor, a steinhart sensor might have been added changing
+ * custom_table_size...
+ */
+ if (st->custom_table_size + custom->size >
+ (LTC2983_CUST_SENS_TBL_END_REG -
+ LTC2983_CUST_SENS_TBL_START_REG) + 1) {
+ dev_err(dev,
+ "Not space left(%d) for new custom sensor(%zu)",
+ st->custom_table_size,
+ custom->size);
+ return -EINVAL;
+ }
+
+ custom->offset = st->custom_table_size /
+ LTC2983_CUSTOM_SENSOR_ENTRY_SZ;
+ st->custom_table_size += custom->size;
+ }
+
+ reg = (custom->offset * mult) + LTC2983_CUST_SENS_TBL_START_REG;
+
+ *chan_val |= LTC2983_CUSTOM_LEN(len);
+ *chan_val |= LTC2983_CUSTOM_ADDR(custom->offset);
+ dev_dbg(dev, "Assign custom sensor, reg:0x%04X, off:%d, sz:%zu",
+ reg, custom->offset,
+ custom->size);
+ /* write custom sensor table */
+ return regmap_bulk_write(st->regmap, reg, custom->table, custom->size);
+}
+
+static struct ltc2983_custom_sensor *__ltc2983_custom_sensor_new(
+ struct ltc2983_data *st,
+ const struct device_node *np,
+ const char *propname,
+ const bool is_steinhart,
+ const u32 resolution,
+ const bool has_signed)
+{
+ struct ltc2983_custom_sensor *new_custom;
+ u8 index, n_entries, tbl = 0;
+ struct device *dev = &st->spi->dev;
+ /*
+ * For custom steinhart, the full u32 is taken. For all the others
+ * the MSB is discarded.
+ */
+ const u8 n_size = (is_steinhart == true) ? 4 : 3;
+ const u8 e_size = (is_steinhart == true) ? sizeof(u32) : sizeof(u64);
+
+ n_entries = of_property_count_elems_of_size(np, propname, e_size);
+ /* n_entries must be an even number */
+ if (!n_entries || (n_entries % 2) != 0) {
+ dev_err(dev, "Number of entries either 0 or not even\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ new_custom = devm_kzalloc(dev, sizeof(*new_custom), GFP_KERNEL);
+ if (!new_custom)
+ return ERR_PTR(-ENOMEM);
+
+ new_custom->size = n_entries * n_size;
+ /* check Steinhart size */
+ if (is_steinhart && new_custom->size != LTC2983_CUSTOM_STEINHART_SIZE) {
+ dev_err(dev, "Steinhart sensors size(%zu) must be 24",
+ new_custom->size);
+ return ERR_PTR(-EINVAL);
+ }
+ /* Check space on the table. */
+ if (st->custom_table_size + new_custom->size >
+ (LTC2983_CUST_SENS_TBL_END_REG -
+ LTC2983_CUST_SENS_TBL_START_REG) + 1) {
+ dev_err(dev, "No space left(%d) for new custom sensor(%zu)",
+ st->custom_table_size, new_custom->size);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* allocate the table */
+ new_custom->table = devm_kzalloc(dev, new_custom->size, GFP_KERNEL);
+ if (!new_custom->table)
+ return ERR_PTR(-ENOMEM);
+
+ for (index = 0; index < n_entries; index++) {
+ u64 temp = 0, j;
+ /*
+ * Steinhart sensors are configured with raw values in the
+ * devicetree. For the other sensors we must convert the
+ * value to raw. The odd index's correspond to temperarures
+ * and always have 1/1024 of resolution. Temperatures also
+ * come in kelvin, so signed values is not possible
+ */
+ if (!is_steinhart) {
+ of_property_read_u64_index(np, propname, index, &temp);
+
+ if ((index % 2) != 0)
+ temp = __convert_to_raw(temp, 1024);
+ else if (has_signed && (s64)temp < 0)
+ temp = __convert_to_raw_sign(temp, resolution);
+ else
+ temp = __convert_to_raw(temp, resolution);
+ } else {
+ of_property_read_u32_index(np, propname, index,
+ (u32 *)&temp);
+ }
+
+ for (j = 0; j < n_size; j++)
+ new_custom->table[tbl++] =
+ temp >> (8 * (n_size - j - 1));
+ }
+
+ new_custom->is_steinhart = is_steinhart;
+ /*
+ * This is done to first add all the steinhart sensors to the table,
+ * in order to maximize the table usage. If we mix adding steinhart
+ * with the other sensors, we might have to do some roundup to make
+ * sure that sensor_addr - 0x250(start address) is a multiple of 4
+ * (for steinhart), and a multiple of 6 for all the other sensors.
+ * Since we have const 24 bytes for steinhart sensors and 24 is
+ * also a multiple of 6, we guarantee that the first non-steinhart
+ * sensor will sit in a correct address without the need of filling
+ * addresses.
+ */
+ if (is_steinhart) {
+ new_custom->offset = st->custom_table_size /
+ LTC2983_CUSTOM_STEINHART_ENTRY_SZ;
+ st->custom_table_size += new_custom->size;
+ } else {
+ /* mark as unset. This is checked later on the assign phase */
+ new_custom->offset = -1;
+ }
+
+ return new_custom;
+}
+
+static int ltc2983_thermocouple_fault_handler(const struct ltc2983_data *st,
+ const u32 result)
+{
+ return __ltc2983_fault_handler(st, result,
+ LTC2983_THERMOCOUPLE_HARD_FAULT_MASK,
+ LTC2983_THERMOCOUPLE_SOFT_FAULT_MASK);
+}
+
+static int ltc2983_common_fault_handler(const struct ltc2983_data *st,
+ const u32 result)
+{
+ return __ltc2983_fault_handler(st, result,
+ LTC2983_COMMON_HARD_FAULT_MASK,
+ LTC2983_COMMON_SOFT_FAULT_MASK);
+}
+
+static int ltc2983_thermocouple_assign_chan(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_thermocouple *thermo = to_thermocouple(sensor);
+ u32 chan_val;
+
+ chan_val = LTC2983_CHAN_ASSIGN(thermo->cold_junction_chan);
+ chan_val |= LTC2983_THERMOCOUPLE_CFG(thermo->sensor_config);
+
+ if (thermo->custom) {
+ int ret;
+
+ ret = __ltc2983_chan_custom_sensor_assign(st, thermo->custom,
+ &chan_val);
+ if (ret)
+ return ret;
+ }
+ return __ltc2983_chan_assign_common(st, sensor, chan_val);
+}
+
+static int ltc2983_rtd_assign_chan(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_rtd *rtd = to_rtd(sensor);
+ u32 chan_val;
+
+ chan_val = LTC2983_CHAN_ASSIGN(rtd->r_sense_chan);
+ chan_val |= LTC2983_RTD_CFG(rtd->sensor_config);
+ chan_val |= LTC2983_RTD_EXC_CURRENT(rtd->excitation_current);
+ chan_val |= LTC2983_RTD_CURVE(rtd->rtd_curve);
+
+ if (rtd->custom) {
+ int ret;
+
+ ret = __ltc2983_chan_custom_sensor_assign(st, rtd->custom,
+ &chan_val);
+ if (ret)
+ return ret;
+ }
+ return __ltc2983_chan_assign_common(st, sensor, chan_val);
+}
+
+static int ltc2983_thermistor_assign_chan(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_thermistor *thermistor = to_thermistor(sensor);
+ u32 chan_val;
+
+ chan_val = LTC2983_CHAN_ASSIGN(thermistor->r_sense_chan);
+ chan_val |= LTC2983_THERMISTOR_CFG(thermistor->sensor_config);
+ chan_val |=
+ LTC2983_THERMISTOR_EXC_CURRENT(thermistor->excitation_current);
+
+ if (thermistor->custom) {
+ int ret;
+
+ ret = __ltc2983_chan_custom_sensor_assign(st,
+ thermistor->custom,
+ &chan_val);
+ if (ret)
+ return ret;
+ }
+ return __ltc2983_chan_assign_common(st, sensor, chan_val);
+}
+
+static int ltc2983_diode_assign_chan(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_diode *diode = to_diode(sensor);
+ u32 chan_val;
+
+ chan_val = LTC2983_DIODE_CFG(diode->sensor_config);
+ chan_val |= LTC2983_DIODE_EXC_CURRENT(diode->excitation_current);
+ chan_val |= LTC2983_DIODE_IDEAL_FACTOR(diode->ideal_factor_value);
+
+ return __ltc2983_chan_assign_common(st, sensor, chan_val);
+}
+
+static int ltc2983_r_sense_assign_chan(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_rsense *rsense = to_rsense(sensor);
+ u32 chan_val;
+
+ chan_val = LTC2983_R_SENSE_VAL(rsense->r_sense_val);
+
+ return __ltc2983_chan_assign_common(st, sensor, chan_val);
+}
+
+static int ltc2983_adc_assign_chan(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_adc *adc = to_adc(sensor);
+ u32 chan_val;
+
+ chan_val = LTC2983_ADC_SINGLE_ENDED(adc->single_ended);
+
+ return __ltc2983_chan_assign_common(st, sensor, chan_val);
+}
+
+static struct ltc2983_sensor *ltc2983_thermocouple_new(
+ const struct device_node *child,
+ struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_thermocouple *thermo;
+ struct device_node *phandle;
+ u32 oc_current;
+ int ret;
+
+ thermo = devm_kzalloc(&st->spi->dev, sizeof(*thermo), GFP_KERNEL);
+ if (!thermo)
+ return ERR_PTR(-ENOMEM);
+
+ if (of_property_read_bool(child, "adi,single-ended"))
+ thermo->sensor_config = LTC2983_THERMOCOUPLE_SGL(1);
+
+ ret = of_property_read_u32(child, "adi,sensor-oc-current-microamp",
+ &oc_current);
+ if (!ret) {
+ switch (oc_current) {
+ case 10:
+ thermo->sensor_config |=
+ LTC2983_THERMOCOUPLE_OC_CURR(0);
+ break;
+ case 100:
+ thermo->sensor_config |=
+ LTC2983_THERMOCOUPLE_OC_CURR(1);
+ break;
+ case 500:
+ thermo->sensor_config |=
+ LTC2983_THERMOCOUPLE_OC_CURR(2);
+ break;
+ case 1000:
+ thermo->sensor_config |=
+ LTC2983_THERMOCOUPLE_OC_CURR(3);
+ break;
+ default:
+ dev_err(&st->spi->dev,
+ "Invalid open circuit current:%u", oc_current);
+ return ERR_PTR(-EINVAL);
+ }
+
+ thermo->sensor_config |= LTC2983_THERMOCOUPLE_OC_CHECK(1);
+ }
+ /* validate channel index */
+ if (!(thermo->sensor_config & LTC2983_THERMOCOUPLE_DIFF_MASK) &&
+ sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
+ dev_err(&st->spi->dev,
+ "Invalid chann:%d for differential thermocouple",
+ sensor->chan);
+ return ERR_PTR(-EINVAL);
+ }
+
+ phandle = of_parse_phandle(child, "adi,cold-junction-handle", 0);
+ if (phandle) {
+ int ret;
+
+ ret = of_property_read_u32(phandle, "reg",
+ &thermo->cold_junction_chan);
+ if (ret) {
+ /*
+ * This would be catched later but we can just return
+ * the error right away.
+ */
+ dev_err(&st->spi->dev, "Property reg must be given\n");
+ of_node_put(phandle);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
+ /* check custom sensor */
+ if (sensor->type == LTC2983_SENSOR_THERMOCOUPLE_CUSTOM) {
+ const char *propname = "adi,custom-thermocouple";
+
+ thermo->custom = __ltc2983_custom_sensor_new(st, child,
+ propname, false,
+ 16384, true);
+ if (IS_ERR(thermo->custom)) {
+ of_node_put(phandle);
+ return ERR_CAST(thermo->custom);
+ }
+ }
+
+ /* set common parameters */
+ thermo->sensor.fault_handler = ltc2983_thermocouple_fault_handler;
+ thermo->sensor.assign_chan = ltc2983_thermocouple_assign_chan;
+
+ of_node_put(phandle);
+ return &thermo->sensor;
+}
+
+static struct ltc2983_sensor *ltc2983_rtd_new(const struct device_node *child,
+ struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_rtd *rtd;
+ int ret = 0;
+ struct device *dev = &st->spi->dev;
+ struct device_node *phandle;
+ u32 excitation_current = 0, n_wires = 0;
+
+ rtd = devm_kzalloc(dev, sizeof(*rtd), GFP_KERNEL);
+ if (!rtd)
+ return ERR_PTR(-ENOMEM);
+
+ phandle = of_parse_phandle(child, "adi,rsense-handle", 0);
+ if (!phandle) {
+ dev_err(dev, "Property adi,rsense-handle missing or invalid");
+ return ERR_PTR(-EINVAL);
+ }
+
+ ret = of_property_read_u32(phandle, "reg", &rtd->r_sense_chan);
+ if (ret) {
+ dev_err(dev, "Property reg must be given\n");
+ goto fail;
+ }
+
+ ret = of_property_read_u32(child, "adi,number-of-wires", &n_wires);
+ if (!ret) {
+ switch (n_wires) {
+ case 2:
+ rtd->sensor_config = LTC2983_RTD_N_WIRES(0);
+ break;
+ case 3:
+ rtd->sensor_config = LTC2983_RTD_N_WIRES(1);
+ break;
+ case 4:
+ rtd->sensor_config = LTC2983_RTD_N_WIRES(2);
+ break;
+ case 5:
+ /* 4 wires, Kelvin Rsense */
+ rtd->sensor_config = LTC2983_RTD_N_WIRES(3);
+ break;
+ default:
+ dev_err(dev, "Invalid number of wires:%u\n", n_wires);
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+
+ if (of_property_read_bool(child, "adi,rsense-share")) {
+ /* Current rotation is only available with rsense sharing */
+ if (of_property_read_bool(child, "adi,current-rotate")) {
+ if (n_wires == 2 || n_wires == 3) {
+ dev_err(dev,
+ "Rotation not allowed for 2/3 Wire RTDs");
+ ret = -EINVAL;
+ goto fail;
+ }
+ rtd->sensor_config |= LTC2983_RTD_C_ROTATE(1);
+ } else {
+ rtd->sensor_config |= LTC2983_RTD_R_SHARE(1);
+ }
+ }
+ /*
+ * rtd channel indexes are a bit more complicated to validate.
+ * For 4wire RTD with rotation, the channel selection cannot be
+ * >=19 since the chann + 1 is used in this configuration.
+ * For 4wire RTDs with kelvin rsense, the rsense channel cannot be
+ * <=1 since chanel - 1 and channel - 2 are used.
+ */
+ if (rtd->sensor_config & LTC2983_RTD_4_WIRE_MASK) {
+ /* 4-wire */
+ u8 min = LTC2983_DIFFERENTIAL_CHAN_MIN,
+ max = LTC2983_MAX_CHANNELS_NR;
+
+ if (rtd->sensor_config & LTC2983_RTD_ROTATION_MASK)
+ max = LTC2983_MAX_CHANNELS_NR - 1;
+
+ if (((rtd->sensor_config & LTC2983_RTD_KELVIN_R_SENSE_MASK)
+ == LTC2983_RTD_KELVIN_R_SENSE_MASK) &&
+ (rtd->r_sense_chan <= min)) {
+ /* kelvin rsense*/
+ dev_err(dev,
+ "Invalid rsense chann:%d to use in kelvin rsense",
+ rtd->r_sense_chan);
+
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (sensor->chan < min || sensor->chan > max) {
+ dev_err(dev, "Invalid chann:%d for the rtd config",
+ sensor->chan);
+
+ ret = -EINVAL;
+ goto fail;
+ }
+ } else {
+ /* same as differential case */
+ if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
+ dev_err(&st->spi->dev,
+ "Invalid chann:%d for RTD", sensor->chan);
+
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+
+ /* check custom sensor */
+ if (sensor->type == LTC2983_SENSOR_RTD_CUSTOM) {
+ rtd->custom = __ltc2983_custom_sensor_new(st, child,
+ "adi,custom-rtd",
+ false, 2048, false);
+ if (IS_ERR(rtd->custom)) {
+ of_node_put(phandle);
+ return ERR_CAST(rtd->custom);
+ }
+ }
+
+ /* set common parameters */
+ rtd->sensor.fault_handler = ltc2983_common_fault_handler;
+ rtd->sensor.assign_chan = ltc2983_rtd_assign_chan;
+
+ ret = of_property_read_u32(child, "adi,excitation-current-microamp",
+ &excitation_current);
+ if (ret) {
+ /* default to 5uA */
+ rtd->excitation_current = 1;
+ } else {
+ switch (excitation_current) {
+ case 5:
+ rtd->excitation_current = 0x01;
+ break;
+ case 10:
+ rtd->excitation_current = 0x02;
+ break;
+ case 25:
+ rtd->excitation_current = 0x03;
+ break;
+ case 50:
+ rtd->excitation_current = 0x04;
+ break;
+ case 100:
+ rtd->excitation_current = 0x05;
+ break;
+ case 250:
+ rtd->excitation_current = 0x06;
+ break;
+ case 500:
+ rtd->excitation_current = 0x07;
+ break;
+ case 1000:
+ rtd->excitation_current = 0x08;
+ break;
+ default:
+ dev_err(&st->spi->dev,
+ "Invalid value for excitation current(%u)",
+ excitation_current);
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+
+ of_property_read_u32(child, "adi,rtd-curve", &rtd->rtd_curve);
+
+ of_node_put(phandle);
+ return &rtd->sensor;
+fail:
+ of_node_put(phandle);
+ return ERR_PTR(ret);
+}
+
+static struct ltc2983_sensor *ltc2983_thermistor_new(
+ const struct device_node *child,
+ struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_thermistor *thermistor;
+ struct device *dev = &st->spi->dev;
+ struct device_node *phandle;
+ u32 excitation_current = 0;
+ int ret = 0;
+
+ thermistor = devm_kzalloc(dev, sizeof(*thermistor), GFP_KERNEL);
+ if (!thermistor)
+ return ERR_PTR(-ENOMEM);
+
+ phandle = of_parse_phandle(child, "adi,rsense-handle", 0);
+ if (!phandle) {
+ dev_err(dev, "Property adi,rsense-handle missing or invalid");
+ return ERR_PTR(-EINVAL);
+ }
+
+ ret = of_property_read_u32(phandle, "reg", &thermistor->r_sense_chan);
+ if (ret) {
+ dev_err(dev, "rsense channel must be configured...\n");
+ goto fail;
+ }
+
+ if (of_property_read_bool(child, "adi,single-ended")) {
+ thermistor->sensor_config = LTC2983_THERMISTOR_SGL(1);
+ } else if (of_property_read_bool(child, "adi,rsense-share")) {
+ /* rotation is only possible if sharing rsense */
+ if (of_property_read_bool(child, "adi,current-rotate"))
+ thermistor->sensor_config =
+ LTC2983_THERMISTOR_C_ROTATE(1);
+ else
+ thermistor->sensor_config =
+ LTC2983_THERMISTOR_R_SHARE(1);
+ }
+ /* validate channel index */
+ if (!(thermistor->sensor_config & LTC2983_THERMISTOR_DIFF_MASK) &&
+ sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
+ dev_err(&st->spi->dev,
+ "Invalid chann:%d for differential thermistor",
+ sensor->chan);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ /* check custom sensor */
+ if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART) {
+ bool steinhart = false;
+ const char *propname;
+
+ if (sensor->type == LTC2983_SENSOR_THERMISTOR_STEINHART) {
+ steinhart = true;
+ propname = "adi,custom-steinhart";
+ } else {
+ propname = "adi,custom-thermistor";
+ }
+
+ thermistor->custom = __ltc2983_custom_sensor_new(st, child,
+ propname,
+ steinhart,
+ 64, false);
+ if (IS_ERR(thermistor->custom)) {
+ of_node_put(phandle);
+ return ERR_CAST(thermistor->custom);
+ }
+ }
+ /* set common parameters */
+ thermistor->sensor.fault_handler = ltc2983_common_fault_handler;
+ thermistor->sensor.assign_chan = ltc2983_thermistor_assign_chan;
+
+ ret = of_property_read_u32(child, "adi,excitation-current-nanoamp",
+ &excitation_current);
+ if (ret) {
+ /* Auto range is not allowed for custom sensors */
+ if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART)
+ /* default to 1uA */
+ thermistor->excitation_current = 0x03;
+ else
+ /* default to auto-range */
+ thermistor->excitation_current = 0x0c;
+ } else {
+ switch (excitation_current) {
+ case 0:
+ /* auto range */
+ if (sensor->type >=
+ LTC2983_SENSOR_THERMISTOR_STEINHART) {
+ dev_err(&st->spi->dev,
+ "Auto Range not allowed for custom sensors\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ thermistor->excitation_current = 0x0c;
+ break;
+ case 250:
+ thermistor->excitation_current = 0x01;
+ break;
+ case 500:
+ thermistor->excitation_current = 0x02;
+ break;
+ case 1000:
+ thermistor->excitation_current = 0x03;
+ break;
+ case 5000:
+ thermistor->excitation_current = 0x04;
+ break;
+ case 10000:
+ thermistor->excitation_current = 0x05;
+ break;
+ case 25000:
+ thermistor->excitation_current = 0x06;
+ break;
+ case 50000:
+ thermistor->excitation_current = 0x07;
+ break;
+ case 100000:
+ thermistor->excitation_current = 0x08;
+ break;
+ case 250000:
+ thermistor->excitation_current = 0x09;
+ break;
+ case 500000:
+ thermistor->excitation_current = 0x0a;
+ break;
+ case 1000000:
+ thermistor->excitation_current = 0x0b;
+ break;
+ default:
+ dev_err(&st->spi->dev,
+ "Invalid value for excitation current(%u)",
+ excitation_current);
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+
+ of_node_put(phandle);
+ return &thermistor->sensor;
+fail:
+ of_node_put(phandle);
+ return ERR_PTR(ret);
+}
+
+static struct ltc2983_sensor *ltc2983_diode_new(
+ const struct device_node *child,
+ const struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_diode *diode;
+ u32 temp = 0, excitation_current = 0;
+ int ret;
+
+ diode = devm_kzalloc(&st->spi->dev, sizeof(*diode), GFP_KERNEL);
+ if (!diode)
+ return ERR_PTR(-ENOMEM);
+
+ if (of_property_read_bool(child, "adi,single-ended"))
+ diode->sensor_config = LTC2983_DIODE_SGL(1);
+
+ if (of_property_read_bool(child, "adi,three-conversion-cycles"))
+ diode->sensor_config |= LTC2983_DIODE_3_CONV_CYCLE(1);
+
+ if (of_property_read_bool(child, "adi,average-on"))
+ diode->sensor_config |= LTC2983_DIODE_AVERAGE_ON(1);
+
+ /* validate channel index */
+ if (!(diode->sensor_config & LTC2983_DIODE_DIFF_MASK) &&
+ sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
+ dev_err(&st->spi->dev,
+ "Invalid chann:%d for differential thermistor",
+ sensor->chan);
+ return ERR_PTR(-EINVAL);
+ }
+ /* set common parameters */
+ diode->sensor.fault_handler = ltc2983_common_fault_handler;
+ diode->sensor.assign_chan = ltc2983_diode_assign_chan;
+
+ ret = of_property_read_u32(child, "adi,excitation-current-microamp",
+ &excitation_current);
+ if (!ret) {
+ switch (excitation_current) {
+ case 10:
+ diode->excitation_current = 0x00;
+ break;
+ case 20:
+ diode->excitation_current = 0x01;
+ break;
+ case 40:
+ diode->excitation_current = 0x02;
+ break;
+ case 80:
+ diode->excitation_current = 0x03;
+ break;
+ default:
+ dev_err(&st->spi->dev,
+ "Invalid value for excitation current(%u)",
+ excitation_current);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
+ of_property_read_u32(child, "adi,ideal-factor-value", &temp);
+
+ /* 2^20 resolution */
+ diode->ideal_factor_value = __convert_to_raw(temp, 1048576);
+
+ return &diode->sensor;
+}
+
+static struct ltc2983_sensor *ltc2983_r_sense_new(struct device_node *child,
+ struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_rsense *rsense;
+ int ret;
+ u32 temp;
+
+ rsense = devm_kzalloc(&st->spi->dev, sizeof(*rsense), GFP_KERNEL);
+ if (!rsense)
+ return ERR_PTR(-ENOMEM);
+
+ /* validate channel index */
+ if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
+ dev_err(&st->spi->dev, "Invalid chann:%d for r_sense",
+ sensor->chan);
+ return ERR_PTR(-EINVAL);
+ }
+
+ ret = of_property_read_u32(child, "adi,rsense-val-milli-ohms", &temp);
+ if (ret) {
+ dev_err(&st->spi->dev, "Property adi,rsense-val-milli-ohms missing\n");
+ return ERR_PTR(-EINVAL);
+ }
+ /*
+ * Times 1000 because we have milli-ohms and __convert_to_raw
+ * expects scales of 1000000 which are used for all other
+ * properties.
+ * 2^10 resolution
+ */
+ rsense->r_sense_val = __convert_to_raw((u64)temp * 1000, 1024);
+
+ /* set common parameters */
+ rsense->sensor.assign_chan = ltc2983_r_sense_assign_chan;
+
+ return &rsense->sensor;
+}
+
+static struct ltc2983_sensor *ltc2983_adc_new(struct device_node *child,
+ struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_adc *adc;
+
+ adc = devm_kzalloc(&st->spi->dev, sizeof(*adc), GFP_KERNEL);
+ if (!adc)
+ return ERR_PTR(-ENOMEM);
+
+ if (of_property_read_bool(child, "adi,single-ended"))
+ adc->single_ended = true;
+
+ if (!adc->single_ended &&
+ sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
+ dev_err(&st->spi->dev, "Invalid chan:%d for differential adc\n",
+ sensor->chan);
+ return ERR_PTR(-EINVAL);
+ }
+ /* set common parameters */
+ adc->sensor.assign_chan = ltc2983_adc_assign_chan;
+ adc->sensor.fault_handler = ltc2983_common_fault_handler;
+
+ return &adc->sensor;
+}
+
+static int ltc2983_chan_read(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor, int *val)
+{
+ u32 start_conversion = 0;
+ int ret;
+ unsigned long time;
+
+ start_conversion = LTC2983_STATUS_START(true);
+ start_conversion |= LTC2983_STATUS_CHAN_SEL(sensor->chan);
+ dev_dbg(&st->spi->dev, "Start conversion on chan:%d, status:%02X\n",
+ sensor->chan, start_conversion);
+ /* start conversion */
+ ret = regmap_write(st->regmap, LTC2983_STATUS_REG, start_conversion);
+ if (ret)
+ return ret;
+
+ reinit_completion(&st->completion);
+ /*
+ * wait for conversion to complete.
+ * 300 ms should be more than enough to complete the conversion.
+ * Depending on the sensor configuration, there are 2/3 conversions
+ * cycles of 82ms.
+ */
+ time = wait_for_completion_timeout(&st->completion,
+ msecs_to_jiffies(300));
+ if (!time) {
+ dev_warn(&st->spi->dev, "Conversion timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ /* read the converted data */
+ ret = regmap_bulk_read(st->regmap, LTC2983_CHAN_RES_ADDR(sensor->chan),
+ &st->temp, sizeof(st->temp));
+ if (ret)
+ return ret;
+
+ *val = __be32_to_cpu(st->temp);
+
+ if (!(LTC2983_RES_VALID_MASK & *val)) {
+ dev_err(&st->spi->dev, "Invalid conversion detected\n");
+ return -EIO;
+ }
+
+ ret = sensor->fault_handler(st, *val);
+ if (ret)
+ return ret;
+
+ *val = sign_extend32((*val) & LTC2983_DATA_MASK, LTC2983_DATA_SIGN_BIT);
+ return 0;
+}
+
+static int ltc2983_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ltc2983_data *st = iio_priv(indio_dev);
+ int ret;
+
+ /* sanity check */
+ if (chan->address >= st->num_channels) {
+ dev_err(&st->spi->dev, "Invalid chan address:%ld",
+ chan->address);
+ return -EINVAL;
+ }
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&st->lock);
+ ret = ltc2983_chan_read(st, st->sensors[chan->address], val);
+ mutex_unlock(&st->lock);
+ return ret ?: IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ /* value in milli degrees */
+ *val = 1000;
+ /* 2^10 */
+ *val2 = 1024;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_VOLTAGE:
+ /* value in millivolt */
+ *val = 1000;
+ /* 2^21 */
+ *val2 = 2097152;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ltc2983_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int writeval,
+ unsigned int *readval)
+{
+ struct ltc2983_data *st = iio_priv(indio_dev);
+
+ if (readval)
+ return regmap_read(st->regmap, reg, readval);
+ else
+ return regmap_write(st->regmap, reg, writeval);
+}
+
+static irqreturn_t ltc2983_irq_handler(int irq, void *data)
+{
+ struct ltc2983_data *st = data;
+
+ complete(&st->completion);
+ return IRQ_HANDLED;
+}
+
+#define LTC2983_CHAN(__type, index, __address) ({ \
+ struct iio_chan_spec __chan = { \
+ .type = __type, \
+ .indexed = 1, \
+ .channel = index, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .address = __address, \
+ }; \
+ __chan; \
+})
+
+static int ltc2983_parse_dt(struct ltc2983_data *st)
+{
+ struct device_node *child;
+ struct device *dev = &st->spi->dev;
+ int ret = 0, chan = 0, channel_avail_mask = 0;
+
+ of_property_read_u32(dev->of_node, "adi,mux-delay-config-us",
+ &st->mux_delay_config);
+
+ of_property_read_u32(dev->of_node, "adi,filter-notch-freq",
+ &st->filter_notch_freq);
+
+ st->num_channels = of_get_available_child_count(dev->of_node);
+ st->sensors = devm_kcalloc(dev, st->num_channels, sizeof(*st->sensors),
+ GFP_KERNEL);
+ if (!st->sensors)
+ return -ENOMEM;
+
+ st->iio_channels = st->num_channels;
+ for_each_available_child_of_node(dev->of_node, child) {
+ struct ltc2983_sensor sensor;
+
+ ret = of_property_read_u32(child, "reg", &sensor.chan);
+ if (ret) {
+ dev_err(dev, "reg property must given for child nodes\n");
+ return ret;
+ }
+
+ /* check if we have a valid channel */
+ if (sensor.chan < LTC2983_MIN_CHANNELS_NR ||
+ sensor.chan > LTC2983_MAX_CHANNELS_NR) {
+ dev_err(dev,
+ "chan:%d must be from 1 to 20\n", sensor.chan);
+ return -EINVAL;
+ } else if (channel_avail_mask & BIT(sensor.chan)) {
+ dev_err(dev, "chan:%d already in use\n", sensor.chan);
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32(child, "adi,sensor-type",
+ &sensor.type);
+ if (ret) {
+ dev_err(dev,
+ "adi,sensor-type property must given for child nodes\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "Create new sensor, type %u, chann %u",
+ sensor.type,
+ sensor.chan);
+
+ if (sensor.type >= LTC2983_SENSOR_THERMOCOUPLE &&
+ sensor.type <= LTC2983_SENSOR_THERMOCOUPLE_CUSTOM) {
+ st->sensors[chan] = ltc2983_thermocouple_new(child, st,
+ &sensor);
+ } else if (sensor.type >= LTC2983_SENSOR_RTD &&
+ sensor.type <= LTC2983_SENSOR_RTD_CUSTOM) {
+ st->sensors[chan] = ltc2983_rtd_new(child, st, &sensor);
+ } else if (sensor.type >= LTC2983_SENSOR_THERMISTOR &&
+ sensor.type <= LTC2983_SENSOR_THERMISTOR_CUSTOM) {
+ st->sensors[chan] = ltc2983_thermistor_new(child, st,
+ &sensor);
+ } else if (sensor.type == LTC2983_SENSOR_DIODE) {
+ st->sensors[chan] = ltc2983_diode_new(child, st,
+ &sensor);
+ } else if (sensor.type == LTC2983_SENSOR_SENSE_RESISTOR) {
+ st->sensors[chan] = ltc2983_r_sense_new(child, st,
+ &sensor);
+ /* don't add rsense to iio */
+ st->iio_channels--;
+ } else if (sensor.type == LTC2983_SENSOR_DIRECT_ADC) {
+ st->sensors[chan] = ltc2983_adc_new(child, st, &sensor);
+ } else {
+ dev_err(dev, "Unknown sensor type %d\n", sensor.type);
+ return -EINVAL;
+ }
+
+ if (IS_ERR(st->sensors[chan])) {
+ dev_err(dev, "Failed to create sensor %ld",
+ PTR_ERR(st->sensors[chan]));
+ return PTR_ERR(st->sensors[chan]);
+ }
+ /* set generic sensor parameters */
+ st->sensors[chan]->chan = sensor.chan;
+ st->sensors[chan]->type = sensor.type;
+
+ channel_avail_mask |= BIT(sensor.chan);
+ chan++;
+ }
+
+ return 0;
+}
+
+static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
+{
+ u32 iio_chan_t = 0, iio_chan_v = 0, chan, iio_idx = 0;
+ int ret;
+ unsigned long time;
+
+ /* make sure the device is up */
+ time = wait_for_completion_timeout(&st->completion,
+ msecs_to_jiffies(250));
+
+ if (!time) {
+ dev_err(&st->spi->dev, "Device startup timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ st->iio_chan = devm_kzalloc(&st->spi->dev,
+ st->iio_channels * sizeof(*st->iio_chan),
+ GFP_KERNEL);
+
+ if (!st->iio_chan)
+ return -ENOMEM;
+
+ ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG,
+ LTC2983_NOTCH_FREQ_MASK,
+ LTC2983_NOTCH_FREQ(st->filter_notch_freq));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->regmap, LTC2983_MUX_CONFIG_REG,
+ st->mux_delay_config);
+ if (ret)
+ return ret;
+
+ for (chan = 0; chan < st->num_channels; chan++) {
+ u32 chan_type = 0, *iio_chan;
+
+ ret = st->sensors[chan]->assign_chan(st, st->sensors[chan]);
+ if (ret)
+ return ret;
+ /*
+ * The assign_iio flag is necessary for when the device is
+ * coming out of sleep. In that case, we just need to
+ * re-configure the device channels.
+ * We also don't assign iio channels for rsense.
+ */
+ if (st->sensors[chan]->type == LTC2983_SENSOR_SENSE_RESISTOR ||
+ !assign_iio)
+ continue;
+
+ /* assign iio channel */
+ if (st->sensors[chan]->type != LTC2983_SENSOR_DIRECT_ADC) {
+ chan_type = IIO_TEMP;
+ iio_chan = &iio_chan_t;
+ } else {
+ chan_type = IIO_VOLTAGE;
+ iio_chan = &iio_chan_v;
+ }
+
+ /*
+ * add chan as the iio .address so that, we can directly
+ * reference the sensor given the iio_chan_spec
+ */
+ st->iio_chan[iio_idx++] = LTC2983_CHAN(chan_type, (*iio_chan)++,
+ chan);
+ }
+
+ return 0;
+}
+
+static const struct regmap_range ltc2983_reg_ranges[] = {
+ regmap_reg_range(LTC2983_STATUS_REG, LTC2983_STATUS_REG),
+ regmap_reg_range(LTC2983_TEMP_RES_START_REG, LTC2983_TEMP_RES_END_REG),
+ regmap_reg_range(LTC2983_GLOBAL_CONFIG_REG, LTC2983_GLOBAL_CONFIG_REG),
+ regmap_reg_range(LTC2983_MULT_CHANNEL_START_REG,
+ LTC2983_MULT_CHANNEL_END_REG),
+ regmap_reg_range(LTC2983_MUX_CONFIG_REG, LTC2983_MUX_CONFIG_REG),
+ regmap_reg_range(LTC2983_CHAN_ASSIGN_START_REG,
+ LTC2983_CHAN_ASSIGN_END_REG),
+ regmap_reg_range(LTC2983_CUST_SENS_TBL_START_REG,
+ LTC2983_CUST_SENS_TBL_END_REG),
+};
+
+static const struct regmap_access_table ltc2983_reg_table = {
+ .yes_ranges = ltc2983_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ltc2983_reg_ranges),
+};
+
+/*
+ * The reg_bits are actually 12 but the device needs the first *complete*
+ * byte for the command (R/W).
+ */
+static const struct regmap_config ltc2983_regmap_config = {
+ .reg_bits = 24,
+ .val_bits = 8,
+ .wr_table = &ltc2983_reg_table,
+ .rd_table = &ltc2983_reg_table,
+ .read_flag_mask = GENMASK(1, 0),
+ .write_flag_mask = BIT(1),
+};
+
+static const struct iio_info ltc2983_iio_info = {
+ .read_raw = ltc2983_read_raw,
+ .debugfs_reg_access = ltc2983_reg_access,
+};
+
+static int ltc2983_probe(struct spi_device *spi)
+{
+ struct ltc2983_data *st;
+ struct iio_dev *indio_dev;
+ const char *name = spi_get_device_id(spi)->name;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ st->regmap = devm_regmap_init_spi(spi, &ltc2983_regmap_config);
+ if (IS_ERR(st->regmap)) {
+ dev_err(&spi->dev, "Failed to initialize regmap\n");
+ return PTR_ERR(st->regmap);
+ }
+
+ mutex_init(&st->lock);
+ init_completion(&st->completion);
+ st->spi = spi;
+ spi_set_drvdata(spi, st);
+
+ ret = ltc2983_parse_dt(st);
+ if (ret)
+ return ret;
+ /*
+ * let's request the irq now so it is used to sync the device
+ * startup in ltc2983_setup()
+ */
+ ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler,
+ IRQF_TRIGGER_RISING, name, st);
+ if (ret) {
+ dev_err(&spi->dev, "failed to request an irq, %d", ret);
+ return ret;
+ }
+
+ ret = ltc2983_setup(st, true);
+ if (ret)
+ return ret;
+
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = name;
+ indio_dev->num_channels = st->iio_channels;
+ indio_dev->channels = st->iio_chan;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &ltc2983_iio_info;
+
+ return devm_iio_device_register(&spi->dev, indio_dev);
+}
+
+static int __maybe_unused ltc2983_resume(struct device *dev)
+{
+ struct ltc2983_data *st = spi_get_drvdata(to_spi_device(dev));
+ int dummy;
+
+ /* dummy read to bring the device out of sleep */
+ regmap_read(st->regmap, LTC2983_STATUS_REG, &dummy);
+ /* we need to re-assign the channels */
+ return ltc2983_setup(st, false);
+}
+
+static int __maybe_unused ltc2983_suspend(struct device *dev)
+{
+ struct ltc2983_data *st = spi_get_drvdata(to_spi_device(dev));
+
+ return regmap_write(st->regmap, LTC2983_STATUS_REG, LTC2983_SLEEP);
+}
+
+static SIMPLE_DEV_PM_OPS(ltc2983_pm_ops, ltc2983_suspend, ltc2983_resume);
+
+static const struct spi_device_id ltc2983_id_table[] = {
+ { "ltc2983" },
+ {},
+};
+MODULE_DEVICE_TABLE(spi, ltc2983_id_table);
+
+static const struct of_device_id ltc2983_of_match[] = {
+ { .compatible = "adi,ltc2983" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ltc2983_of_match);
+
+static struct spi_driver ltc2983_driver = {
+ .driver = {
+ .name = "ltc2983",
+ .of_match_table = ltc2983_of_match,
+ .pm = &ltc2983_pm_ops,
+ },
+ .probe = ltc2983_probe,
+ .id_table = ltc2983_id_table,
+};
+
+module_spi_driver(ltc2983_driver);
+
+MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
+MODULE_DESCRIPTION("Analog Devices LTC2983 SPI Temperature sensors");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/temperature/max31856.c b/drivers/iio/temperature/max31856.c
index f184ba5601d9..73ed550e3fc9 100644
--- a/drivers/iio/temperature/max31856.c
+++ b/drivers/iio/temperature/max31856.c
@@ -284,6 +284,8 @@ static int max31856_probe(struct spi_device *spi)
spi_set_drvdata(spi, indio_dev);
indio_dev->info = &max31856_info;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = id->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = max31856_channels;
diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c
index 2ab68282d0b6..d1360605209c 100644
--- a/drivers/iio/temperature/maxim_thermocouple.c
+++ b/drivers/iio/temperature/maxim_thermocouple.c
@@ -194,7 +194,7 @@ static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev,
default:
*val = 250; /* 1000 * 0.25 */
ret = IIO_VAL_INT;
- };
+ }
break;
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index ae24d3ea68ea..420900852166 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1210,13 +1210,6 @@ config AB8500_DEBUG
Select this option if you want debug information using the debug
filesystem, debugfs.
-config AB8500_GPADC
- bool "ST-Ericsson AB8500 GPADC driver"
- depends on AB8500_CORE && REGULATOR_AB8500
- default y
- help
- AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage
-
config MFD_DB8500_PRCMU
bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
depends on UX500_SOC_DB8500
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c1067ea46204..aed99f08739f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -177,7 +177,6 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o
obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o
-obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
# ab8500-core need to come after db8500-prcmu (which provides the channel)
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index f4e26b6e5362..1a9a3414d4fa 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -84,7 +84,6 @@
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
#ifdef CONFIG_DEBUG_FS
#include <linux/string.h>
@@ -103,11 +102,6 @@ static int num_irqs;
static struct device_attribute **dev_attr;
static char **event_name;
-static u8 avg_sample = SAMPLE_16;
-static u8 trig_edge = RISING_EDGE;
-static u8 conv_type = ADC_SW;
-static u8 trig_timer;
-
/**
* struct ab8500_reg_range
* @first: the first address of the range
@@ -152,7 +146,6 @@ static struct hwreg_cfg hwreg_cfg = {
};
#define AB8500_NAME_STRING "ab8500"
-#define AB8500_ADC_NAME_STRING "gpadc"
#define AB8500_NUM_BANKS AB8500_DEBUG_FIELD_LAST
#define AB8500_REV_REG 0x80
@@ -1646,633 +1639,6 @@ report_write_failure:
DEFINE_SHOW_ATTRIBUTE(ab8500_modem);
-static int ab8500_gpadc_bat_ctrl_show(struct seq_file *s, void *p)
-{
- int bat_ctrl_raw;
- int bat_ctrl_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL,
- avg_sample, trig_edge, trig_timer, conv_type);
- bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc,
- BAT_CTRL, bat_ctrl_raw);
-
- seq_printf(s, "%d,0x%X\n", bat_ctrl_convert, bat_ctrl_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_bat_ctrl);
-
-static int ab8500_gpadc_btemp_ball_show(struct seq_file *s, void *p)
-{
- int btemp_ball_raw;
- int btemp_ball_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL,
- avg_sample, trig_edge, trig_timer, conv_type);
- btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
- btemp_ball_raw);
-
- seq_printf(s, "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_btemp_ball);
-
-static int ab8500_gpadc_main_charger_v_show(struct seq_file *s, void *p)
-{
- int main_charger_v_raw;
- int main_charger_v_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V,
- avg_sample, trig_edge, trig_timer, conv_type);
- main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
- MAIN_CHARGER_V, main_charger_v_raw);
-
- seq_printf(s, "%d,0x%X\n", main_charger_v_convert, main_charger_v_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_charger_v);
-
-static int ab8500_gpadc_acc_detect1_show(struct seq_file *s, void *p)
-{
- int acc_detect1_raw;
- int acc_detect1_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1,
- avg_sample, trig_edge, trig_timer, conv_type);
- acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1,
- acc_detect1_raw);
-
- seq_printf(s, "%d,0x%X\n", acc_detect1_convert, acc_detect1_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_acc_detect1);
-
-static int ab8500_gpadc_acc_detect2_show(struct seq_file *s, void *p)
-{
- int acc_detect2_raw;
- int acc_detect2_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2,
- avg_sample, trig_edge, trig_timer, conv_type);
- acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc,
- ACC_DETECT2, acc_detect2_raw);
-
- seq_printf(s, "%d,0x%X\n", acc_detect2_convert, acc_detect2_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_acc_detect2);
-
-static int ab8500_gpadc_aux1_show(struct seq_file *s, void *p)
-{
- int aux1_raw;
- int aux1_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1,
- avg_sample, trig_edge, trig_timer, conv_type);
- aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1,
- aux1_raw);
-
- seq_printf(s, "%d,0x%X\n", aux1_convert, aux1_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_aux1);
-
-static int ab8500_gpadc_aux2_show(struct seq_file *s, void *p)
-{
- int aux2_raw;
- int aux2_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2,
- avg_sample, trig_edge, trig_timer, conv_type);
- aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2,
- aux2_raw);
-
- seq_printf(s, "%d,0x%X\n", aux2_convert, aux2_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_aux2);
-
-static int ab8500_gpadc_main_bat_v_show(struct seq_file *s, void *p)
-{
- int main_bat_v_raw;
- int main_bat_v_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V,
- avg_sample, trig_edge, trig_timer, conv_type);
- main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
- main_bat_v_raw);
-
- seq_printf(s, "%d,0x%X\n", main_bat_v_convert, main_bat_v_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_bat_v);
-
-static int ab8500_gpadc_vbus_v_show(struct seq_file *s, void *p)
-{
- int vbus_v_raw;
- int vbus_v_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V,
- avg_sample, trig_edge, trig_timer, conv_type);
- vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V,
- vbus_v_raw);
-
- seq_printf(s, "%d,0x%X\n", vbus_v_convert, vbus_v_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_vbus_v);
-
-static int ab8500_gpadc_main_charger_c_show(struct seq_file *s, void *p)
-{
- int main_charger_c_raw;
- int main_charger_c_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C,
- avg_sample, trig_edge, trig_timer, conv_type);
- main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
- MAIN_CHARGER_C, main_charger_c_raw);
-
- seq_printf(s, "%d,0x%X\n", main_charger_c_convert, main_charger_c_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_charger_c);
-
-static int ab8500_gpadc_usb_charger_c_show(struct seq_file *s, void *p)
-{
- int usb_charger_c_raw;
- int usb_charger_c_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C,
- avg_sample, trig_edge, trig_timer, conv_type);
- usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
- USB_CHARGER_C, usb_charger_c_raw);
-
- seq_printf(s, "%d,0x%X\n", usb_charger_c_convert, usb_charger_c_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_usb_charger_c);
-
-static int ab8500_gpadc_bk_bat_v_show(struct seq_file *s, void *p)
-{
- int bk_bat_v_raw;
- int bk_bat_v_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V,
- avg_sample, trig_edge, trig_timer, conv_type);
- bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
- BK_BAT_V, bk_bat_v_raw);
-
- seq_printf(s, "%d,0x%X\n", bk_bat_v_convert, bk_bat_v_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_bk_bat_v);
-
-static int ab8500_gpadc_die_temp_show(struct seq_file *s, void *p)
-{
- int die_temp_raw;
- int die_temp_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP,
- avg_sample, trig_edge, trig_timer, conv_type);
- die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP,
- die_temp_raw);
-
- seq_printf(s, "%d,0x%X\n", die_temp_convert, die_temp_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_die_temp);
-
-static int ab8500_gpadc_usb_id_show(struct seq_file *s, void *p)
-{
- int usb_id_raw;
- int usb_id_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- usb_id_raw = ab8500_gpadc_read_raw(gpadc, USB_ID,
- avg_sample, trig_edge, trig_timer, conv_type);
- usb_id_convert = ab8500_gpadc_ad_to_voltage(gpadc, USB_ID,
- usb_id_raw);
-
- seq_printf(s, "%d,0x%X\n", usb_id_convert, usb_id_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_usb_id);
-
-static int ab8540_gpadc_xtal_temp_show(struct seq_file *s, void *p)
-{
- int xtal_temp_raw;
- int xtal_temp_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- xtal_temp_raw = ab8500_gpadc_read_raw(gpadc, XTAL_TEMP,
- avg_sample, trig_edge, trig_timer, conv_type);
- xtal_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, XTAL_TEMP,
- xtal_temp_raw);
-
- seq_printf(s, "%d,0x%X\n", xtal_temp_convert, xtal_temp_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_xtal_temp);
-
-static int ab8540_gpadc_vbat_true_meas_show(struct seq_file *s, void *p)
-{
- int vbat_true_meas_raw;
- int vbat_true_meas_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS,
- avg_sample, trig_edge, trig_timer, conv_type);
- vbat_true_meas_convert =
- ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
- vbat_true_meas_raw);
-
- seq_printf(s, "%d,0x%X\n", vbat_true_meas_convert, vbat_true_meas_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_true_meas);
-
-static int ab8540_gpadc_bat_ctrl_and_ibat_show(struct seq_file *s, void *p)
-{
- int bat_ctrl_raw;
- int bat_ctrl_convert;
- int ibat_raw;
- int ibat_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- bat_ctrl_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_CTRL_AND_IBAT,
- avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
-
- bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, BAT_CTRL,
- bat_ctrl_raw);
- ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
- ibat_raw);
-
- seq_printf(s,
- "%d,0x%X\n"
- "%d,0x%X\n",
- bat_ctrl_convert, bat_ctrl_raw,
- ibat_convert, ibat_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_bat_ctrl_and_ibat);
-
-static int ab8540_gpadc_vbat_meas_and_ibat_show(struct seq_file *s, void *p)
-{
- int vbat_meas_raw;
- int vbat_meas_convert;
- int ibat_raw;
- int ibat_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- vbat_meas_raw = ab8500_gpadc_double_read_raw(gpadc, VBAT_MEAS_AND_IBAT,
- avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
- vbat_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
- vbat_meas_raw);
- ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
- ibat_raw);
-
- seq_printf(s,
- "%d,0x%X\n"
- "%d,0x%X\n",
- vbat_meas_convert, vbat_meas_raw,
- ibat_convert, ibat_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_meas_and_ibat);
-
-static int ab8540_gpadc_vbat_true_meas_and_ibat_show(struct seq_file *s, void *p)
-{
- int vbat_true_meas_raw;
- int vbat_true_meas_convert;
- int ibat_raw;
- int ibat_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- vbat_true_meas_raw = ab8500_gpadc_double_read_raw(gpadc,
- VBAT_TRUE_MEAS_AND_IBAT, avg_sample, trig_edge,
- trig_timer, conv_type, &ibat_raw);
- vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc,
- VBAT_TRUE_MEAS, vbat_true_meas_raw);
- ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
- ibat_raw);
-
- seq_printf(s,
- "%d,0x%X\n"
- "%d,0x%X\n",
- vbat_true_meas_convert, vbat_true_meas_raw,
- ibat_convert, ibat_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_true_meas_and_ibat);
-
-static int ab8540_gpadc_bat_temp_and_ibat_show(struct seq_file *s, void *p)
-{
- int bat_temp_raw;
- int bat_temp_convert;
- int ibat_raw;
- int ibat_convert;
- struct ab8500_gpadc *gpadc;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- bat_temp_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_TEMP_AND_IBAT,
- avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
- bat_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
- bat_temp_raw);
- ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
- ibat_raw);
-
- seq_printf(s,
- "%d,0x%X\n"
- "%d,0x%X\n",
- bat_temp_convert, bat_temp_raw,
- ibat_convert, ibat_raw);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_bat_temp_and_ibat);
-
-static int ab8540_gpadc_otp_calib_show(struct seq_file *s, void *p)
-{
- struct ab8500_gpadc *gpadc;
- u16 vmain_l, vmain_h, btemp_l, btemp_h;
- u16 vbat_l, vbat_h, ibat_l, ibat_h;
-
- gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h,
- &vbat_l, &vbat_h, &ibat_l, &ibat_h);
- seq_printf(s,
- "VMAIN_L:0x%X\n"
- "VMAIN_H:0x%X\n"
- "BTEMP_L:0x%X\n"
- "BTEMP_H:0x%X\n"
- "VBAT_L:0x%X\n"
- "VBAT_H:0x%X\n"
- "IBAT_L:0x%X\n"
- "IBAT_H:0x%X\n",
- vmain_l, vmain_h, btemp_l, btemp_h,
- vbat_l, vbat_h, ibat_l, ibat_h);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_otp_calib);
-
-static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p)
-{
- seq_printf(s, "%d\n", avg_sample);
-
- return 0;
-}
-
-static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_avg_sample_print,
- inode->i_private);
-}
-
-static ssize_t ab8500_gpadc_avg_sample_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct device *dev = ((struct seq_file *)(file->private_data))->private;
- unsigned long user_avg_sample;
- int err;
-
- err = kstrtoul_from_user(user_buf, count, 0, &user_avg_sample);
- if (err)
- return err;
-
- if ((user_avg_sample == SAMPLE_1) || (user_avg_sample == SAMPLE_4)
- || (user_avg_sample == SAMPLE_8)
- || (user_avg_sample == SAMPLE_16)) {
- avg_sample = (u8) user_avg_sample;
- } else {
- dev_err(dev,
- "debugfs err input: should be egal to 1, 4, 8 or 16\n");
- return -EINVAL;
- }
-
- return count;
-}
-
-static const struct file_operations ab8500_gpadc_avg_sample_fops = {
- .open = ab8500_gpadc_avg_sample_open,
- .read = seq_read,
- .write = ab8500_gpadc_avg_sample_write,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p)
-{
- seq_printf(s, "%d\n", trig_edge);
-
- return 0;
-}
-
-static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_trig_edge_print,
- inode->i_private);
-}
-
-static ssize_t ab8500_gpadc_trig_edge_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct device *dev = ((struct seq_file *)(file->private_data))->private;
- unsigned long user_trig_edge;
- int err;
-
- err = kstrtoul_from_user(user_buf, count, 0, &user_trig_edge);
- if (err)
- return err;
-
- if ((user_trig_edge == RISING_EDGE)
- || (user_trig_edge == FALLING_EDGE)) {
- trig_edge = (u8) user_trig_edge;
- } else {
- dev_err(dev, "Wrong input:\n"
- "Enter 0. Rising edge\n"
- "Enter 1. Falling edge\n");
- return -EINVAL;
- }
-
- return count;
-}
-
-static const struct file_operations ab8500_gpadc_trig_edge_fops = {
- .open = ab8500_gpadc_trig_edge_open,
- .read = seq_read,
- .write = ab8500_gpadc_trig_edge_write,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p)
-{
- seq_printf(s, "%d\n", trig_timer);
-
- return 0;
-}
-
-static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_trig_timer_print,
- inode->i_private);
-}
-
-static ssize_t ab8500_gpadc_trig_timer_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct device *dev = ((struct seq_file *)(file->private_data))->private;
- unsigned long user_trig_timer;
- int err;
-
- err = kstrtoul_from_user(user_buf, count, 0, &user_trig_timer);
- if (err)
- return err;
-
- if (user_trig_timer & ~0xFF) {
- dev_err(dev,
- "debugfs error input: should be between 0 to 255\n");
- return -EINVAL;
- }
-
- trig_timer = (u8) user_trig_timer;
-
- return count;
-}
-
-static const struct file_operations ab8500_gpadc_trig_timer_fops = {
- .open = ab8500_gpadc_trig_timer_open,
- .read = seq_read,
- .write = ab8500_gpadc_trig_timer_write,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p)
-{
- seq_printf(s, "%d\n", conv_type);
-
- return 0;
-}
-
-static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_conv_type_print,
- inode->i_private);
-}
-
-static ssize_t ab8500_gpadc_conv_type_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct device *dev = ((struct seq_file *)(file->private_data))->private;
- unsigned long user_conv_type;
- int err;
-
- err = kstrtoul_from_user(user_buf, count, 0, &user_conv_type);
- if (err)
- return err;
-
- if ((user_conv_type == ADC_SW)
- || (user_conv_type == ADC_HW)) {
- conv_type = (u8) user_conv_type;
- } else {
- dev_err(dev, "Wrong input:\n"
- "Enter 0. ADC SW conversion\n"
- "Enter 1. ADC HW conversion\n");
- return -EINVAL;
- }
-
- return count;
-}
-
-static const struct file_operations ab8500_gpadc_conv_type_fops = {
- .open = ab8500_gpadc_conv_type_open,
- .read = seq_read,
- .write = ab8500_gpadc_conv_type_write,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
/*
* return length of an ASCII numerical value, 0 is string is not a
* numerical value.
@@ -2647,7 +2013,6 @@ static const struct file_operations ab8500_hwreg_fops = {
static int ab8500_debug_probe(struct platform_device *plf)
{
struct dentry *ab8500_dir;
- struct dentry *ab8500_gpadc_dir;
struct ab8500 *ab8500;
struct resource *res;
@@ -2689,9 +2054,6 @@ static int ab8500_debug_probe(struct platform_device *plf)
ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
- ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
- ab8500_dir);
-
debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir,
&plf->dev, &ab8500_bank_registers_fops);
debugfs_create_file("all-banks", S_IRUGO, ab8500_dir,
@@ -2727,83 +2089,6 @@ static int ab8500_debug_probe(struct platform_device *plf)
&plf->dev, &ab8500_hwreg_fops);
debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUSR | S_IWGRP),
ab8500_dir, &plf->dev, &ab8500_modem_fops);
- debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_bat_ctrl_fops);
- debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_btemp_ball_fops);
- debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_main_charger_v_fops);
- debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_acc_detect1_fops);
- debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_acc_detect2_fops);
- debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_aux1_fops);
- debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_aux2_fops);
- debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_main_bat_v_fops);
- debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_vbus_v_fops);
- debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_main_charger_c_fops);
- debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_usb_charger_c_fops);
- debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_bk_bat_v_fops);
- debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_die_temp_fops);
- debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_usb_id_fops);
- if (is_ab8540(ab8500)) {
- debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_xtal_temp_fops);
- debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_vbat_true_meas_fops);
- debugfs_create_file("batctrl_and_ibat", (S_IRUGO | S_IWUGO),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_bat_ctrl_and_ibat_fops);
- debugfs_create_file("vbatmeas_and_ibat", (S_IRUGO | S_IWUGO),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_vbat_meas_and_ibat_fops);
- debugfs_create_file("vbattruemeas_and_ibat", (S_IRUGO | S_IWUGO),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_vbat_true_meas_and_ibat_fops);
- debugfs_create_file("battemp_and_ibat", (S_IRUGO | S_IWUGO),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_bat_temp_and_ibat_fops);
- debugfs_create_file("otp_calib", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_otp_calib_fops);
- }
- debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_avg_sample_fops);
- debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_trig_edge_fops);
- debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_trig_timer_fops);
- debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8500_gpadc_conv_type_fops);
return 0;
}
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
deleted file mode 100644
index 005f9ee34cd1..000000000000
--- a/drivers/mfd/ab8500-gpadc.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Arun R Murthy <arun.murthy@stericsson.com>
- * Author: Daniel Willerud <daniel.willerud@stericsson.com>
- * Author: Johan Palsson <johan.palsson@stericsson.com>
- * Author: M'boumba Cedric Madianga
- */
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/pm_runtime.h>
-#include <linux/platform_device.h>
-#include <linux/completion.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
-
-/*
- * GPADC register offsets
- * Bank : 0x0A
- */
-#define AB8500_GPADC_CTRL1_REG 0x00
-#define AB8500_GPADC_CTRL2_REG 0x01
-#define AB8500_GPADC_CTRL3_REG 0x02
-#define AB8500_GPADC_AUTO_TIMER_REG 0x03
-#define AB8500_GPADC_STAT_REG 0x04
-#define AB8500_GPADC_MANDATAL_REG 0x05
-#define AB8500_GPADC_MANDATAH_REG 0x06
-#define AB8500_GPADC_AUTODATAL_REG 0x07
-#define AB8500_GPADC_AUTODATAH_REG 0x08
-#define AB8500_GPADC_MUX_CTRL_REG 0x09
-#define AB8540_GPADC_MANDATA2L_REG 0x09
-#define AB8540_GPADC_MANDATA2H_REG 0x0A
-#define AB8540_GPADC_APEAAX_REG 0x10
-#define AB8540_GPADC_APEAAT_REG 0x11
-#define AB8540_GPADC_APEAAM_REG 0x12
-#define AB8540_GPADC_APEAAH_REG 0x13
-#define AB8540_GPADC_APEAAL_REG 0x14
-
-/*
- * OTP register offsets
- * Bank : 0x15
- */
-#define AB8500_GPADC_CAL_1 0x0F
-#define AB8500_GPADC_CAL_2 0x10
-#define AB8500_GPADC_CAL_3 0x11
-#define AB8500_GPADC_CAL_4 0x12
-#define AB8500_GPADC_CAL_5 0x13
-#define AB8500_GPADC_CAL_6 0x14
-#define AB8500_GPADC_CAL_7 0x15
-/* New calibration for 8540 */
-#define AB8540_GPADC_OTP4_REG_7 0x38
-#define AB8540_GPADC_OTP4_REG_6 0x39
-#define AB8540_GPADC_OTP4_REG_5 0x3A
-
-/* gpadc constants */
-#define EN_VINTCORE12 0x04
-#define EN_VTVOUT 0x02
-#define EN_GPADC 0x01
-#define DIS_GPADC 0x00
-#define AVG_1 0x00
-#define AVG_4 0x20
-#define AVG_8 0x40
-#define AVG_16 0x60
-#define ADC_SW_CONV 0x04
-#define EN_ICHAR 0x80
-#define BTEMP_PULL_UP 0x08
-#define EN_BUF 0x40
-#define DIS_ZERO 0x00
-#define GPADC_BUSY 0x01
-#define EN_FALLING 0x10
-#define EN_TRIG_EDGE 0x02
-#define EN_VBIAS_XTAL_TEMP 0x02
-
-/* GPADC constants from AB8500 spec, UM0836 */
-#define ADC_RESOLUTION 1024
-#define ADC_CH_BTEMP_MIN 0
-#define ADC_CH_BTEMP_MAX 1350
-#define ADC_CH_DIETEMP_MIN 0
-#define ADC_CH_DIETEMP_MAX 1350
-#define ADC_CH_CHG_V_MIN 0
-#define ADC_CH_CHG_V_MAX 20030
-#define ADC_CH_ACCDET2_MIN 0
-#define ADC_CH_ACCDET2_MAX 2500
-#define ADC_CH_VBAT_MIN 2300
-#define ADC_CH_VBAT_MAX 4800
-#define ADC_CH_CHG_I_MIN 0
-#define ADC_CH_CHG_I_MAX 1500
-#define ADC_CH_BKBAT_MIN 0
-#define ADC_CH_BKBAT_MAX 3200
-
-/* GPADC constants from AB8540 spec */
-#define ADC_CH_IBAT_MIN (-6000) /* mA range measured by ADC for ibat */
-#define ADC_CH_IBAT_MAX 6000
-#define ADC_CH_IBAT_MIN_V (-60) /* mV range measured by ADC for ibat */
-#define ADC_CH_IBAT_MAX_V 60
-#define IBAT_VDROP_L (-56) /* mV */
-#define IBAT_VDROP_H 56
-
-/* This is used to not lose precision when dividing to get gain and offset */
-#define CALIB_SCALE 1000
-/*
- * Number of bits shift used to not lose precision
- * when dividing to get ibat gain.
- */
-#define CALIB_SHIFT_IBAT 20
-
-/* Time in ms before disabling regulator */
-#define GPADC_AUDOSUSPEND_DELAY 1
-
-#define CONVERSION_TIME 500 /* ms */
-
-enum cal_channels {
- ADC_INPUT_VMAIN = 0,
- ADC_INPUT_BTEMP,
- ADC_INPUT_VBAT,
- ADC_INPUT_IBAT,
- NBR_CAL_INPUTS,
-};
-
-/**
- * struct adc_cal_data - Table for storing gain and offset for the calibrated
- * ADC channels
- * @gain: Gain of the ADC channel
- * @offset: Offset of the ADC channel
- */
-struct adc_cal_data {
- s64 gain;
- s64 offset;
- u16 otp_calib_hi;
- u16 otp_calib_lo;
-};
-
-/**
- * struct ab8500_gpadc - AB8500 GPADC device information
- * @dev: pointer to the struct device
- * @node: a list of AB8500 GPADCs, hence prepared for
- reentrance
- * @parent: pointer to the struct ab8500
- * @ab8500_gpadc_complete: pointer to the struct completion, to indicate
- * the completion of gpadc conversion
- * @ab8500_gpadc_lock: structure of type mutex
- * @regu: pointer to the struct regulator
- * @irq_sw: interrupt number that is used by gpadc for Sw
- * conversion
- * @irq_hw: interrupt number that is used by gpadc for Hw
- * conversion
- * @cal_data array of ADC calibration data structs
- */
-struct ab8500_gpadc {
- struct device *dev;
- struct list_head node;
- struct ab8500 *parent;
- struct completion ab8500_gpadc_complete;
- struct mutex ab8500_gpadc_lock;
- struct regulator *regu;
- int irq_sw;
- int irq_hw;
- struct adc_cal_data cal_data[NBR_CAL_INPUTS];
-};
-
-static LIST_HEAD(ab8500_gpadc_list);
-
-/**
- * ab8500_gpadc_get() - returns a reference to the primary AB8500 GPADC
- * (i.e. the first GPADC in the instance list)
- */
-struct ab8500_gpadc *ab8500_gpadc_get(char *name)
-{
- struct ab8500_gpadc *gpadc;
-
- list_for_each_entry(gpadc, &ab8500_gpadc_list, node) {
- if (!strcmp(name, dev_name(gpadc->dev)))
- return gpadc;
- }
-
- return ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(ab8500_gpadc_get);
-
-/**
- * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage
- */
-int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel,
- int ad_value)
-{
- int res;
-
- switch (channel) {
- case MAIN_CHARGER_V:
- /* For some reason we don't have calibrated data */
- if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) {
- res = ADC_CH_CHG_V_MIN + (ADC_CH_CHG_V_MAX -
- ADC_CH_CHG_V_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
- }
- /* Here we can use the calibrated data */
- res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_VMAIN].gain +
- gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE;
- break;
-
- case XTAL_TEMP:
- case BAT_CTRL:
- case BTEMP_BALL:
- case ACC_DETECT1:
- case ADC_AUX1:
- case ADC_AUX2:
- /* For some reason we don't have calibrated data */
- if (!gpadc->cal_data[ADC_INPUT_BTEMP].gain) {
- res = ADC_CH_BTEMP_MIN + (ADC_CH_BTEMP_MAX -
- ADC_CH_BTEMP_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
- }
- /* Here we can use the calibrated data */
- res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_BTEMP].gain +
- gpadc->cal_data[ADC_INPUT_BTEMP].offset) / CALIB_SCALE;
- break;
-
- case MAIN_BAT_V:
- case VBAT_TRUE_MEAS:
- /* For some reason we don't have calibrated data */
- if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) {
- res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX -
- ADC_CH_VBAT_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
- }
- /* Here we can use the calibrated data */
- res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_VBAT].gain +
- gpadc->cal_data[ADC_INPUT_VBAT].offset) / CALIB_SCALE;
- break;
-
- case DIE_TEMP:
- res = ADC_CH_DIETEMP_MIN +
- (ADC_CH_DIETEMP_MAX - ADC_CH_DIETEMP_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
-
- case ACC_DETECT2:
- res = ADC_CH_ACCDET2_MIN +
- (ADC_CH_ACCDET2_MAX - ADC_CH_ACCDET2_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
-
- case VBUS_V:
- res = ADC_CH_CHG_V_MIN +
- (ADC_CH_CHG_V_MAX - ADC_CH_CHG_V_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
-
- case MAIN_CHARGER_C:
- case USB_CHARGER_C:
- res = ADC_CH_CHG_I_MIN +
- (ADC_CH_CHG_I_MAX - ADC_CH_CHG_I_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
-
- case BK_BAT_V:
- res = ADC_CH_BKBAT_MIN +
- (ADC_CH_BKBAT_MAX - ADC_CH_BKBAT_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
-
- case IBAT_VIRTUAL_CHANNEL:
- /* For some reason we don't have calibrated data */
- if (!gpadc->cal_data[ADC_INPUT_IBAT].gain) {
- res = ADC_CH_IBAT_MIN + (ADC_CH_IBAT_MAX -
- ADC_CH_IBAT_MIN) * ad_value /
- ADC_RESOLUTION;
- break;
- }
- /* Here we can use the calibrated data */
- res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_IBAT].gain +
- gpadc->cal_data[ADC_INPUT_IBAT].offset)
- >> CALIB_SHIFT_IBAT;
- break;
-
- default:
- dev_err(gpadc->dev,
- "unknown channel, not possible to convert\n");
- res = -EINVAL;
- break;
-
- }
- return res;
-}
-EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage);
-
-/**
- * ab8500_gpadc_sw_hw_convert() - gpadc conversion
- * @channel: analog channel to be converted to digital data
- * @avg_sample: number of ADC sample to average
- * @trig_egde: selected ADC trig edge
- * @trig_timer: selected ADC trigger delay timer
- * @conv_type: selected conversion type (HW or SW conversion)
- *
- * This function converts the selected analog i/p to digital
- * data.
- */
-int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel,
- u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type)
-{
- int ad_value;
- int voltage;
-
- ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample,
- trig_edge, trig_timer, conv_type);
-
- /* On failure retry a second time */
- if (ad_value < 0)
- ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample,
- trig_edge, trig_timer, conv_type);
- if (ad_value < 0) {
- dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n",
- channel);
- return ad_value;
- }
-
- voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value);
- if (voltage < 0)
- dev_err(gpadc->dev,
- "GPADC to voltage conversion failed ch: %d AD: 0x%x\n",
- channel, ad_value);
-
- return voltage;
-}
-EXPORT_SYMBOL(ab8500_gpadc_sw_hw_convert);
-
-/**
- * ab8500_gpadc_read_raw() - gpadc read
- * @channel: analog channel to be read
- * @avg_sample: number of ADC sample to average
- * @trig_edge: selected trig edge
- * @trig_timer: selected ADC trigger delay timer
- * @conv_type: selected conversion type (HW or SW conversion)
- *
- * This function obtains the raw ADC value for an hardware conversion,
- * this then needs to be converted by calling ab8500_gpadc_ad_to_voltage()
- */
-int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
- u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type)
-{
- return ab8500_gpadc_double_read_raw(gpadc, channel, avg_sample,
- trig_edge, trig_timer, conv_type,
- NULL);
-}
-
-int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
- u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type,
- int *ibat)
-{
- int ret;
- int looplimit = 0;
- unsigned long completion_timeout;
- u8 val, low_data, high_data, low_data2, high_data2;
- u8 val_reg1 = 0;
- unsigned int delay_min = 0;
- unsigned int delay_max = 0;
- u8 data_low_addr, data_high_addr;
-
- if (!gpadc)
- return -ENODEV;
-
- /* check if convertion is supported */
- if ((gpadc->irq_sw < 0) && (conv_type == ADC_SW))
- return -ENOTSUPP;
- if ((gpadc->irq_hw < 0) && (conv_type == ADC_HW))
- return -ENOTSUPP;
-
- mutex_lock(&gpadc->ab8500_gpadc_lock);
- /* Enable VTVout LDO this is required for GPADC */
- pm_runtime_get_sync(gpadc->dev);
-
- /* Check if ADC is not busy, lock and proceed */
- do {
- ret = abx500_get_register_interruptible(gpadc->dev,
- AB8500_GPADC, AB8500_GPADC_STAT_REG, &val);
- if (ret < 0)
- goto out;
- if (!(val & GPADC_BUSY))
- break;
- msleep(20);
- } while (++looplimit < 10);
- if (looplimit >= 10 && (val & GPADC_BUSY)) {
- dev_err(gpadc->dev, "gpadc_conversion: GPADC busy");
- ret = -EINVAL;
- goto out;
- }
-
- /* Enable GPADC */
- val_reg1 |= EN_GPADC;
-
- /* Select the channel source and set average samples */
- switch (avg_sample) {
- case SAMPLE_1:
- val = channel | AVG_1;
- break;
- case SAMPLE_4:
- val = channel | AVG_4;
- break;
- case SAMPLE_8:
- val = channel | AVG_8;
- break;
- default:
- val = channel | AVG_16;
- break;
- }
-
- if (conv_type == ADC_HW) {
- ret = abx500_set_register_interruptible(gpadc->dev,
- AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val);
- val_reg1 |= EN_TRIG_EDGE;
- if (trig_edge)
- val_reg1 |= EN_FALLING;
- } else
- ret = abx500_set_register_interruptible(gpadc->dev,
- AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val);
- if (ret < 0) {
- dev_err(gpadc->dev,
- "gpadc_conversion: set avg samples failed\n");
- goto out;
- }
-
- /*
- * Enable ADC, buffering, select rising edge and enable ADC path
- * charging current sense if it needed, ABB 3.0 needs some special
- * treatment too.
- */
- switch (channel) {
- case MAIN_CHARGER_C:
- case USB_CHARGER_C:
- val_reg1 |= EN_BUF | EN_ICHAR;
- break;
- case BTEMP_BALL:
- if (!is_ab8500_2p0_or_earlier(gpadc->parent)) {
- val_reg1 |= EN_BUF | BTEMP_PULL_UP;
- /*
- * Delay might be needed for ABB8500 cut 3.0, if not,
- * remove when hardware will be availible
- */
- delay_min = 1000; /* Delay in micro seconds */
- delay_max = 10000; /* large range optimises sleepmode */
- break;
- }
- /* Intentional fallthrough */
- default:
- val_reg1 |= EN_BUF;
- break;
- }
-
- /* Write configuration to register */
- ret = abx500_set_register_interruptible(gpadc->dev,
- AB8500_GPADC, AB8500_GPADC_CTRL1_REG, val_reg1);
- if (ret < 0) {
- dev_err(gpadc->dev,
- "gpadc_conversion: set Control register failed\n");
- goto out;
- }
-
- if (delay_min != 0)
- usleep_range(delay_min, delay_max);
-
- if (conv_type == ADC_HW) {
- /* Set trigger delay timer */
- ret = abx500_set_register_interruptible(gpadc->dev,
- AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer);
- if (ret < 0) {
- dev_err(gpadc->dev,
- "gpadc_conversion: trig timer failed\n");
- goto out;
- }
- completion_timeout = 2 * HZ;
- data_low_addr = AB8500_GPADC_AUTODATAL_REG;
- data_high_addr = AB8500_GPADC_AUTODATAH_REG;
- } else {
- /* Start SW conversion */
- ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
- AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
- ADC_SW_CONV, ADC_SW_CONV);
- if (ret < 0) {
- dev_err(gpadc->dev,
- "gpadc_conversion: start s/w conv failed\n");
- goto out;
- }
- completion_timeout = msecs_to_jiffies(CONVERSION_TIME);
- data_low_addr = AB8500_GPADC_MANDATAL_REG;
- data_high_addr = AB8500_GPADC_MANDATAH_REG;
- }
-
- /* wait for completion of conversion */
- if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete,
- completion_timeout)) {
- dev_err(gpadc->dev,
- "timeout didn't receive GPADC conv interrupt\n");
- ret = -EINVAL;
- goto out;
- }
-
- /* Read the converted RAW data */
- ret = abx500_get_register_interruptible(gpadc->dev,
- AB8500_GPADC, data_low_addr, &low_data);
- if (ret < 0) {
- dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n");
- goto out;
- }
-
- ret = abx500_get_register_interruptible(gpadc->dev,
- AB8500_GPADC, data_high_addr, &high_data);
- if (ret < 0) {
- dev_err(gpadc->dev, "gpadc_conversion: read high data failed\n");
- goto out;
- }
-
- /* Check if double convertion is required */
- if ((channel == BAT_CTRL_AND_IBAT) ||
- (channel == VBAT_MEAS_AND_IBAT) ||
- (channel == VBAT_TRUE_MEAS_AND_IBAT) ||
- (channel == BAT_TEMP_AND_IBAT)) {
-
- if (conv_type == ADC_HW) {
- /* not supported */
- ret = -ENOTSUPP;
- dev_err(gpadc->dev,
- "gpadc_conversion: only SW double conversion supported\n");
- goto out;
- } else {
- /* Read the converted RAW data 2 */
- ret = abx500_get_register_interruptible(gpadc->dev,
- AB8500_GPADC, AB8540_GPADC_MANDATA2L_REG,
- &low_data2);
- if (ret < 0) {
- dev_err(gpadc->dev,
- "gpadc_conversion: read sw low data 2 failed\n");
- goto out;
- }
-
- ret = abx500_get_register_interruptible(gpadc->dev,
- AB8500_GPADC, AB8540_GPADC_MANDATA2H_REG,
- &high_data2);
- if (ret < 0) {
- dev_err(gpadc->dev,
- "gpadc_conversion: read sw high data 2 failed\n");
- goto out;
- }
- if (ibat != NULL) {
- *ibat = (high_data2 << 8) | low_data2;
- } else {
- dev_warn(gpadc->dev,
- "gpadc_conversion: ibat not stored\n");
- }
-
- }
- }
-
- /* Disable GPADC */
- ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
- AB8500_GPADC_CTRL1_REG, DIS_GPADC);
- if (ret < 0) {
- dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n");
- goto out;
- }
-
- /* Disable VTVout LDO this is required for GPADC */
- pm_runtime_mark_last_busy(gpadc->dev);
- pm_runtime_put_autosuspend(gpadc->dev);
-
- mutex_unlock(&gpadc->ab8500_gpadc_lock);
-
- return (high_data << 8) | low_data;
-
-out:
- /*
- * It has shown to be needed to turn off the GPADC if an error occurs,
- * otherwise we might have problem when waiting for the busy bit in the
- * GPADC status register to go low. In V1.1 there wait_for_completion
- * seems to timeout when waiting for an interrupt.. Not seen in V2.0
- */
- (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
- AB8500_GPADC_CTRL1_REG, DIS_GPADC);
- pm_runtime_put(gpadc->dev);
- mutex_unlock(&gpadc->ab8500_gpadc_lock);
- dev_err(gpadc->dev,
- "gpadc_conversion: Failed to AD convert channel %d\n", channel);
- return ret;
-}
-EXPORT_SYMBOL(ab8500_gpadc_read_raw);
-
-/**
- * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion
- * @irq: irq number
- * @data: pointer to the data passed during request irq
- *
- * This is a interrupt service routine for gpadc conversion completion.
- * Notifies the gpadc completion is completed and the converted raw value
- * can be read from the registers.
- * Returns IRQ status(IRQ_HANDLED)
- */
-static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *_gpadc)
-{
- struct ab8500_gpadc *gpadc = _gpadc;
-
- complete(&gpadc->ab8500_gpadc_complete);
-
- return IRQ_HANDLED;
-}
-
-static int otp_cal_regs[] = {
- AB8500_GPADC_CAL_1,
- AB8500_GPADC_CAL_2,
- AB8500_GPADC_CAL_3,
- AB8500_GPADC_CAL_4,
- AB8500_GPADC_CAL_5,
- AB8500_GPADC_CAL_6,
- AB8500_GPADC_CAL_7,
-};
-
-static int otp4_cal_regs[] = {
- AB8540_GPADC_OTP4_REG_7,
- AB8540_GPADC_OTP4_REG_6,
- AB8540_GPADC_OTP4_REG_5,
-};
-
-static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
-{
- int i;
- int ret[ARRAY_SIZE(otp_cal_regs)];
- u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)];
- int ret_otp4[ARRAY_SIZE(otp4_cal_regs)];
- u8 gpadc_otp4[ARRAY_SIZE(otp4_cal_regs)];
- int vmain_high, vmain_low;
- int btemp_high, btemp_low;
- int vbat_high, vbat_low;
- int ibat_high, ibat_low;
- s64 V_gain, V_offset, V2A_gain, V2A_offset;
- struct ab8500 *ab8500;
-
- ab8500 = gpadc->parent;
-
- /* First we read all OTP registers and store the error code */
- for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) {
- ret[i] = abx500_get_register_interruptible(gpadc->dev,
- AB8500_OTP_EMUL, otp_cal_regs[i], &gpadc_cal[i]);
- if (ret[i] < 0)
- dev_err(gpadc->dev, "%s: read otp reg 0x%02x failed\n",
- __func__, otp_cal_regs[i]);
- }
-
- /*
- * The ADC calibration data is stored in OTP registers.
- * The layout of the calibration data is outlined below and a more
- * detailed description can be found in UM0836
- *
- * vm_h/l = vmain_high/low
- * bt_h/l = btemp_high/low
- * vb_h/l = vbat_high/low
- *
- * Data bits 8500/9540:
- * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | | vm_h9 | vm_h8
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
- * |.......|.......|.......|.......|.......|.......|.......|.......
- *
- * Data bits 8540:
- * OTP2
- * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * |
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | vm_h9 | vm_h8 | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
- * |.......|.......|.......|.......|.......|.......|.......|.......
- *
- * Data bits 8540:
- * OTP4
- * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | | ib_h9 | ib_h8 | ib_h7
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | ib_h6 | ib_h5 | ib_h4 | ib_h3 | ib_h2 | ib_h1 | ib_h0 | ib_l5
- * |.......|.......|.......|.......|.......|.......|.......|.......
- * | ib_l4 | ib_l3 | ib_l2 | ib_l1 | ib_l0 |
- *
- *
- * Ideal output ADC codes corresponding to injected input voltages
- * during manufacturing is:
- *
- * vmain_high: Vin = 19500mV / ADC ideal code = 997
- * vmain_low: Vin = 315mV / ADC ideal code = 16
- * btemp_high: Vin = 1300mV / ADC ideal code = 985
- * btemp_low: Vin = 21mV / ADC ideal code = 16
- * vbat_high: Vin = 4700mV / ADC ideal code = 982
- * vbat_low: Vin = 2380mV / ADC ideal code = 33
- */
-
- if (is_ab8540(ab8500)) {
- /* Calculate gain and offset for VMAIN if all reads succeeded*/
- if (!(ret[1] < 0 || ret[2] < 0)) {
- vmain_high = (((gpadc_cal[1] & 0xFF) << 2) |
- ((gpadc_cal[2] & 0xC0) >> 6));
- vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
-
- gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi =
- (u16)vmain_high;
- gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo =
- (u16)vmain_low;
-
- gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE *
- (19500 - 315) / (vmain_high - vmain_low);
- gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE *
- 19500 - (CALIB_SCALE * (19500 - 315) /
- (vmain_high - vmain_low)) * vmain_high;
- } else {
- gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0;
- }
-
- /* Read IBAT calibration Data */
- for (i = 0; i < ARRAY_SIZE(otp4_cal_regs); i++) {
- ret_otp4[i] = abx500_get_register_interruptible(
- gpadc->dev, AB8500_OTP_EMUL,
- otp4_cal_regs[i], &gpadc_otp4[i]);
- if (ret_otp4[i] < 0)
- dev_err(gpadc->dev,
- "%s: read otp4 reg 0x%02x failed\n",
- __func__, otp4_cal_regs[i]);
- }
-
- /* Calculate gain and offset for IBAT if all reads succeeded */
- if (!(ret_otp4[0] < 0 || ret_otp4[1] < 0 || ret_otp4[2] < 0)) {
- ibat_high = (((gpadc_otp4[0] & 0x07) << 7) |
- ((gpadc_otp4[1] & 0xFE) >> 1));
- ibat_low = (((gpadc_otp4[1] & 0x01) << 5) |
- ((gpadc_otp4[2] & 0xF8) >> 3));
-
- gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi =
- (u16)ibat_high;
- gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo =
- (u16)ibat_low;
-
- V_gain = ((IBAT_VDROP_H - IBAT_VDROP_L)
- << CALIB_SHIFT_IBAT) / (ibat_high - ibat_low);
-
- V_offset = (IBAT_VDROP_H << CALIB_SHIFT_IBAT) -
- (((IBAT_VDROP_H - IBAT_VDROP_L) <<
- CALIB_SHIFT_IBAT) / (ibat_high - ibat_low))
- * ibat_high;
- /*
- * Result obtained is in mV (at a scale factor),
- * we need to calculate gain and offset to get mA
- */
- V2A_gain = (ADC_CH_IBAT_MAX - ADC_CH_IBAT_MIN)/
- (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V);
- V2A_offset = ((ADC_CH_IBAT_MAX_V * ADC_CH_IBAT_MIN -
- ADC_CH_IBAT_MAX * ADC_CH_IBAT_MIN_V)
- << CALIB_SHIFT_IBAT)
- / (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V);
-
- gpadc->cal_data[ADC_INPUT_IBAT].gain =
- V_gain * V2A_gain;
- gpadc->cal_data[ADC_INPUT_IBAT].offset =
- V_offset * V2A_gain + V2A_offset;
- } else {
- gpadc->cal_data[ADC_INPUT_IBAT].gain = 0;
- }
-
- dev_dbg(gpadc->dev, "IBAT gain %llu offset %llu\n",
- gpadc->cal_data[ADC_INPUT_IBAT].gain,
- gpadc->cal_data[ADC_INPUT_IBAT].offset);
- } else {
- /* Calculate gain and offset for VMAIN if all reads succeeded */
- if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) {
- vmain_high = (((gpadc_cal[0] & 0x03) << 8) |
- ((gpadc_cal[1] & 0x3F) << 2) |
- ((gpadc_cal[2] & 0xC0) >> 6));
- vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
-
- gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi =
- (u16)vmain_high;
- gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo =
- (u16)vmain_low;
-
- gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE *
- (19500 - 315) / (vmain_high - vmain_low);
-
- gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE *
- 19500 - (CALIB_SCALE * (19500 - 315) /
- (vmain_high - vmain_low)) * vmain_high;
- } else {
- gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0;
- }
- }
-
- /* Calculate gain and offset for BTEMP if all reads succeeded */
- if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) {
- btemp_high = (((gpadc_cal[2] & 0x01) << 9) |
- (gpadc_cal[3] << 1) | ((gpadc_cal[4] & 0x80) >> 7));
- btemp_low = ((gpadc_cal[4] & 0x7C) >> 2);
-
- gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi = (u16)btemp_high;
- gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo = (u16)btemp_low;
-
- gpadc->cal_data[ADC_INPUT_BTEMP].gain =
- CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low);
- gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 -
- (CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low))
- * btemp_high;
- } else {
- gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0;
- }
-
- /* Calculate gain and offset for VBAT if all reads succeeded */
- if (!(ret[4] < 0 || ret[5] < 0 || ret[6] < 0)) {
- vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]);
- vbat_low = ((gpadc_cal[6] & 0xFC) >> 2);
-
- gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi = (u16)vbat_high;
- gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo = (u16)vbat_low;
-
- gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE *
- (4700 - 2380) / (vbat_high - vbat_low);
- gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 -
- (CALIB_SCALE * (4700 - 2380) /
- (vbat_high - vbat_low)) * vbat_high;
- } else {
- gpadc->cal_data[ADC_INPUT_VBAT].gain = 0;
- }
-
- dev_dbg(gpadc->dev, "VMAIN gain %llu offset %llu\n",
- gpadc->cal_data[ADC_INPUT_VMAIN].gain,
- gpadc->cal_data[ADC_INPUT_VMAIN].offset);
-
- dev_dbg(gpadc->dev, "BTEMP gain %llu offset %llu\n",
- gpadc->cal_data[ADC_INPUT_BTEMP].gain,
- gpadc->cal_data[ADC_INPUT_BTEMP].offset);
-
- dev_dbg(gpadc->dev, "VBAT gain %llu offset %llu\n",
- gpadc->cal_data[ADC_INPUT_VBAT].gain,
- gpadc->cal_data[ADC_INPUT_VBAT].offset);
-}
-
-#ifdef CONFIG_PM
-static int ab8500_gpadc_runtime_suspend(struct device *dev)
-{
- struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
-
- regulator_disable(gpadc->regu);
- return 0;
-}
-
-static int ab8500_gpadc_runtime_resume(struct device *dev)
-{
- struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
- int ret;
-
- ret = regulator_enable(gpadc->regu);
- if (ret)
- dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret);
- return ret;
-}
-#endif
-
-#ifdef CONFIG_PM_SLEEP
-static int ab8500_gpadc_suspend(struct device *dev)
-{
- struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
-
- mutex_lock(&gpadc->ab8500_gpadc_lock);
-
- pm_runtime_get_sync(dev);
-
- regulator_disable(gpadc->regu);
- return 0;
-}
-
-static int ab8500_gpadc_resume(struct device *dev)
-{
- struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
- int ret;
-
- ret = regulator_enable(gpadc->regu);
- if (ret)
- dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret);
-
- pm_runtime_mark_last_busy(gpadc->dev);
- pm_runtime_put_autosuspend(gpadc->dev);
-
- mutex_unlock(&gpadc->ab8500_gpadc_lock);
- return ret;
-}
-#endif
-
-static int ab8500_gpadc_probe(struct platform_device *pdev)
-{
- int ret = 0;
- struct ab8500_gpadc *gpadc;
-
- gpadc = devm_kzalloc(&pdev->dev,
- sizeof(struct ab8500_gpadc), GFP_KERNEL);
- if (!gpadc)
- return -ENOMEM;
-
- gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END");
- if (gpadc->irq_sw < 0)
- dev_err(gpadc->dev, "failed to get platform sw_conv_end irq\n");
-
- gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END");
- if (gpadc->irq_hw < 0)
- dev_err(gpadc->dev, "failed to get platform hw_conv_end irq\n");
-
- gpadc->dev = &pdev->dev;
- gpadc->parent = dev_get_drvdata(pdev->dev.parent);
- mutex_init(&gpadc->ab8500_gpadc_lock);
-
- /* Initialize completion used to notify completion of conversion */
- init_completion(&gpadc->ab8500_gpadc_complete);
-
- /* Register interrupts */
- if (gpadc->irq_sw >= 0) {
- ret = request_threaded_irq(gpadc->irq_sw, NULL,
- ab8500_bm_gpadcconvend_handler,
- IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT,
- "ab8500-gpadc-sw",
- gpadc);
- if (ret < 0) {
- dev_err(gpadc->dev,
- "Failed to register interrupt irq: %d\n",
- gpadc->irq_sw);
- goto fail;
- }
- }
-
- if (gpadc->irq_hw >= 0) {
- ret = request_threaded_irq(gpadc->irq_hw, NULL,
- ab8500_bm_gpadcconvend_handler,
- IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT,
- "ab8500-gpadc-hw",
- gpadc);
- if (ret < 0) {
- dev_err(gpadc->dev,
- "Failed to register interrupt irq: %d\n",
- gpadc->irq_hw);
- goto fail_irq;
- }
- }
-
- /* VTVout LDO used to power up ab8500-GPADC */
- gpadc->regu = devm_regulator_get(&pdev->dev, "vddadc");
- if (IS_ERR(gpadc->regu)) {
- ret = PTR_ERR(gpadc->regu);
- dev_err(gpadc->dev, "failed to get vtvout LDO\n");
- goto fail_irq;
- }
-
- platform_set_drvdata(pdev, gpadc);
-
- ret = regulator_enable(gpadc->regu);
- if (ret) {
- dev_err(gpadc->dev, "Failed to enable vtvout LDO: %d\n", ret);
- goto fail_enable;
- }
-
- pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY);
- pm_runtime_use_autosuspend(gpadc->dev);
- pm_runtime_set_active(gpadc->dev);
- pm_runtime_enable(gpadc->dev);
-
- ab8500_gpadc_read_calibration_data(gpadc);
- list_add_tail(&gpadc->node, &ab8500_gpadc_list);
- dev_dbg(gpadc->dev, "probe success\n");
-
- return 0;
-
-fail_enable:
-fail_irq:
- free_irq(gpadc->irq_sw, gpadc);
- free_irq(gpadc->irq_hw, gpadc);
-fail:
- return ret;
-}
-
-static int ab8500_gpadc_remove(struct platform_device *pdev)
-{
- struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev);
-
- /* remove this gpadc entry from the list */
- list_del(&gpadc->node);
- /* remove interrupt - completion of Sw ADC conversion */
- if (gpadc->irq_sw >= 0)
- free_irq(gpadc->irq_sw, gpadc);
- if (gpadc->irq_hw >= 0)
- free_irq(gpadc->irq_hw, gpadc);
-
- pm_runtime_get_sync(gpadc->dev);
- pm_runtime_disable(gpadc->dev);
-
- regulator_disable(gpadc->regu);
-
- pm_runtime_set_suspended(gpadc->dev);
-
- pm_runtime_put_noidle(gpadc->dev);
-
- return 0;
-}
-
-static const struct dev_pm_ops ab8500_gpadc_pm_ops = {
- SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend,
- ab8500_gpadc_runtime_resume,
- NULL)
- SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend,
- ab8500_gpadc_resume)
-
-};
-
-static struct platform_driver ab8500_gpadc_driver = {
- .probe = ab8500_gpadc_probe,
- .remove = ab8500_gpadc_remove,
- .driver = {
- .name = "ab8500-gpadc",
- .pm = &ab8500_gpadc_pm_ops,
- },
-};
-
-static int __init ab8500_gpadc_init(void)
-{
- return platform_driver_register(&ab8500_gpadc_driver);
-}
-subsys_initcall_sync(ab8500_gpadc_init);
-
-/**
- * ab8540_gpadc_get_otp() - returns OTP values
- *
- */
-void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc,
- u16 *vmain_l, u16 *vmain_h, u16 *btemp_l, u16 *btemp_h,
- u16 *vbat_l, u16 *vbat_h, u16 *ibat_l, u16 *ibat_h)
-{
- *vmain_l = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo;
- *vmain_h = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi;
- *btemp_l = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo;
- *btemp_h = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi;
- *vbat_l = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo;
- *vbat_h = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi;
- *ibat_l = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo;
- *ibat_h = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi;
-}
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index c84a7b1caeb6..27164a1d3c7c 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -629,7 +629,7 @@ config BATTERY_GAUGE_LTC2941
config AB8500_BM
bool "AB8500 Battery Management Driver"
- depends on AB8500_CORE && AB8500_GPADC
+ depends on AB8500_CORE && AB8500_GPADC && (IIO = y)
help
Say Y to include support for AB8500 battery management.
diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c
index 8fe81259bfd9..ad8c51ef8b8b 100644
--- a/drivers/power/supply/ab8500_btemp.c
+++ b/drivers/power/supply/ab8500_btemp.c
@@ -26,7 +26,7 @@
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
+#include <linux/iio/consumer.h>
#define VTVOUT_V 1800
@@ -79,7 +79,8 @@ struct ab8500_btemp_ranges {
* @bat_temp: Dispatched battery temperature in degree Celsius
* @prev_bat_temp Last measured battery temperature in degree Celsius
* @parent: Pointer to the struct ab8500
- * @gpadc: Pointer to the struct gpadc
+ * @adc_btemp_ball: ADC channel for the battery ball temperature
+ * @adc_bat_ctrl: ADC channel for the battery control
* @fg: Pointer to the struct fg
* @bm: Platform specific battery management information
* @btemp_psy: Structure for BTEMP specific battery properties
@@ -96,7 +97,8 @@ struct ab8500_btemp {
int bat_temp;
int prev_bat_temp;
struct ab8500 *parent;
- struct ab8500_gpadc *gpadc;
+ struct iio_channel *btemp_ball;
+ struct iio_channel *bat_ctrl;
struct ab8500_fg *fg;
struct abx500_bm_data *bm;
struct power_supply *btemp_psy;
@@ -177,13 +179,13 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
*/
static int ab8500_btemp_read_batctrl_voltage(struct ab8500_btemp *di)
{
- int vbtemp;
+ int vbtemp, ret;
static int prev;
- vbtemp = ab8500_gpadc_convert(di->gpadc, BAT_CTRL);
- if (vbtemp < 0) {
+ ret = iio_read_channel_processed(di->bat_ctrl, &vbtemp);
+ if (ret < 0) {
dev_err(di->dev,
- "%s gpadc conversion failed, using previous value",
+ "%s ADC conversion failed, using previous value",
__func__);
return prev;
}
@@ -455,7 +457,7 @@ static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di,
*/
static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
{
- int temp;
+ int temp, ret;
static int prev;
int rbat, rntc, vntc;
u8 id;
@@ -480,10 +482,10 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
di->bm->bat_type[id].r_to_t_tbl,
di->bm->bat_type[id].n_temp_tbl_elements, rbat);
} else {
- vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
- if (vntc < 0) {
+ ret = iio_read_channel_processed(di->btemp_ball, &vntc);
+ if (ret < 0) {
dev_err(di->dev,
- "%s gpadc conversion failed,"
+ "%s ADC conversion failed,"
" using previous value\n", __func__);
return prev;
}
@@ -1024,7 +1026,22 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
/* get parent data */
di->dev = &pdev->dev;
di->parent = dev_get_drvdata(pdev->dev.parent);
- di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+
+ /* Get ADC channels */
+ di->btemp_ball = devm_iio_channel_get(&pdev->dev, "btemp_ball");
+ if (IS_ERR(di->btemp_ball)) {
+ if (PTR_ERR(di->btemp_ball) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "failed to get BTEMP BALL ADC channel\n");
+ return PTR_ERR(di->btemp_ball);
+ }
+ di->bat_ctrl = devm_iio_channel_get(&pdev->dev, "bat_ctrl");
+ if (IS_ERR(di->bat_ctrl)) {
+ if (PTR_ERR(di->bat_ctrl) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "failed to get BAT CTRL ADC channel\n");
+ return PTR_ERR(di->bat_ctrl);
+ }
di->initialized = false;
diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index e51d0e72beea..c053ede47eb2 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -29,10 +29,10 @@
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
#include <linux/mfd/abx500/ux500_chargalg.h>
#include <linux/usb/otg.h>
#include <linux/mutex.h>
+#include <linux/iio/consumer.h>
/* Charger constants */
#define NO_PW_CONN 0
@@ -233,7 +233,10 @@ struct ab8500_charger_max_usb_in_curr {
* @current_stepping_sessions:
* Counter for current stepping sessions
* @parent: Pointer to the struct ab8500
- * @gpadc: Pointer to the struct gpadc
+ * @adc_main_charger_v ADC channel for main charger voltage
+ * @adc_main_charger_c ADC channel for main charger current
+ * @adc_vbus_v ADC channel for USB charger voltage
+ * @adc_usb_charger_c ADC channel for USB charger current
* @bm: Platform specific battery management information
* @flags: Structure for information about events triggered
* @usb_state: Structure for usb stack information
@@ -283,7 +286,10 @@ struct ab8500_charger {
int is_aca_rid;
atomic_t current_stepping_sessions;
struct ab8500 *parent;
- struct ab8500_gpadc *gpadc;
+ struct iio_channel *adc_main_charger_v;
+ struct iio_channel *adc_main_charger_c;
+ struct iio_channel *adc_vbus_v;
+ struct iio_channel *adc_usb_charger_c;
struct abx500_bm_data *bm;
struct ab8500_charger_event_flags flags;
struct ab8500_charger_usb_state usb_state;
@@ -459,13 +465,13 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di,
*/
static int ab8500_charger_get_ac_voltage(struct ab8500_charger *di)
{
- int vch;
+ int vch, ret;
/* Only measure voltage if the charger is connected */
if (di->ac.charger_connected) {
- vch = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_V);
- if (vch < 0)
- dev_err(di->dev, "%s gpadc conv failed,\n", __func__);
+ ret = iio_read_channel_processed(di->adc_main_charger_v, &vch);
+ if (ret < 0)
+ dev_err(di->dev, "%s ADC conv failed,\n", __func__);
} else {
vch = 0;
}
@@ -510,13 +516,13 @@ static int ab8500_charger_ac_cv(struct ab8500_charger *di)
*/
static int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di)
{
- int vch;
+ int vch, ret;
/* Only measure voltage if the charger is connected */
if (di->usb.charger_connected) {
- vch = ab8500_gpadc_convert(di->gpadc, VBUS_V);
- if (vch < 0)
- dev_err(di->dev, "%s gpadc conv failed\n", __func__);
+ ret = iio_read_channel_processed(di->adc_vbus_v, &vch);
+ if (ret < 0)
+ dev_err(di->dev, "%s ADC conv failed,\n", __func__);
} else {
vch = 0;
}
@@ -532,13 +538,13 @@ static int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di)
*/
static int ab8500_charger_get_usb_current(struct ab8500_charger *di)
{
- int ich;
+ int ich, ret;
/* Only measure current if the charger is online */
if (di->usb.charger_online) {
- ich = ab8500_gpadc_convert(di->gpadc, USB_CHARGER_C);
- if (ich < 0)
- dev_err(di->dev, "%s gpadc conv failed\n", __func__);
+ ret = iio_read_channel_processed(di->adc_usb_charger_c, &ich);
+ if (ret < 0)
+ dev_err(di->dev, "%s ADC conv failed,\n", __func__);
} else {
ich = 0;
}
@@ -554,13 +560,13 @@ static int ab8500_charger_get_usb_current(struct ab8500_charger *di)
*/
static int ab8500_charger_get_ac_current(struct ab8500_charger *di)
{
- int ich;
+ int ich, ret;
/* Only measure current if the charger is online */
if (di->ac.charger_online) {
- ich = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_C);
- if (ich < 0)
- dev_err(di->dev, "%s gpadc conv failed\n", __func__);
+ ret = iio_read_channel_processed(di->adc_main_charger_c, &ich);
+ if (ret < 0)
+ dev_err(di->dev, "%s ADC conv failed,\n", __func__);
} else {
ich = 0;
}
@@ -3371,7 +3377,39 @@ static int ab8500_charger_probe(struct platform_device *pdev)
/* get parent data */
di->dev = &pdev->dev;
di->parent = dev_get_drvdata(pdev->dev.parent);
- di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+
+ /* Get ADC channels */
+ di->adc_main_charger_v = devm_iio_channel_get(&pdev->dev,
+ "main_charger_v");
+ if (IS_ERR(di->adc_main_charger_v)) {
+ if (PTR_ERR(di->adc_main_charger_v) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "failed to get ADC main charger voltage\n");
+ return PTR_ERR(di->adc_main_charger_v);
+ }
+ di->adc_main_charger_c = devm_iio_channel_get(&pdev->dev,
+ "main_charger_c");
+ if (IS_ERR(di->adc_main_charger_c)) {
+ if (PTR_ERR(di->adc_main_charger_c) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "failed to get ADC main charger current\n");
+ return PTR_ERR(di->adc_main_charger_v);
+ }
+ di->adc_vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
+ if (IS_ERR(di->adc_vbus_v)) {
+ if (PTR_ERR(di->adc_vbus_v) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "failed to get ADC USB charger voltage\n");
+ return PTR_ERR(di->adc_vbus_v);
+ }
+ di->adc_usb_charger_c = devm_iio_channel_get(&pdev->dev,
+ "usb_charger_c");
+ if (IS_ERR(di->adc_usb_charger_c)) {
+ if (PTR_ERR(di->adc_usb_charger_c) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "failed to get ADC USB charger current\n");
+ return PTR_ERR(di->adc_usb_charger_c);
+ }
/* initialize lock */
spin_lock_init(&di->usb_state.usb_lock);
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index 6fc4bc30644c..f7909dfd3b61 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -32,7 +32,7 @@
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
+#include <linux/iio/consumer.h>
#include <linux/kernel.h>
#define MILLI_TO_MICRO 1000
@@ -182,7 +182,7 @@ struct inst_curr_result_list {
* @bat_cap: Structure for battery capacity specific parameters
* @avg_cap: Average capacity filter
* @parent: Pointer to the struct ab8500
- * @gpadc: Pointer to the struct gpadc
+ * @main_bat_v: ADC channel for the main battery voltage
* @bm: Platform specific battery management information
* @fg_psy: Structure that holds the FG specific battery properties
* @fg_wq: Work queue for running the FG algorithm
@@ -224,7 +224,7 @@ struct ab8500_fg {
struct ab8500_fg_battery_capacity bat_cap;
struct ab8500_fg_avg_cap avg_cap;
struct ab8500 *parent;
- struct ab8500_gpadc *gpadc;
+ struct iio_channel *main_bat_v;
struct abx500_bm_data *bm;
struct power_supply *fg_psy;
struct workqueue_struct *fg_wq;
@@ -829,13 +829,13 @@ exit:
*/
static int ab8500_fg_bat_voltage(struct ab8500_fg *di)
{
- int vbat;
+ int vbat, ret;
static int prev;
- vbat = ab8500_gpadc_convert(di->gpadc, MAIN_BAT_V);
- if (vbat < 0) {
+ ret = iio_read_channel_processed(di->main_bat_v, &vbat);
+ if (ret < 0) {
dev_err(di->dev,
- "%s gpadc conversion failed, using previous value\n",
+ "%s ADC conversion failed, using previous value\n",
__func__);
return prev;
}
@@ -3066,7 +3066,14 @@ static int ab8500_fg_probe(struct platform_device *pdev)
/* get parent data */
di->dev = &pdev->dev;
di->parent = dev_get_drvdata(pdev->dev.parent);
- di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+
+ di->main_bat_v = devm_iio_channel_get(&pdev->dev, "main_bat_v");
+ if (IS_ERR(di->main_bat_v)) {
+ if (PTR_ERR(di->main_bat_v) == -ENODEV)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "failed to get main battery ADC channel\n");
+ return PTR_ERR(di->main_bat_v);
+ }
psy_cfg.supplied_to = supply_interface;
psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index e3a2518503ed..bd21655c37a6 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -508,15 +508,6 @@ config PWM_TIEHRPWM
To compile this driver as a module, choose M here: the module
will be called pwm-tiehrpwm.
-config PWM_TIPWMSS
- bool
- default y if (ARCH_OMAP2PLUS) && (PWM_TIECAP || PWM_TIEHRPWM)
- help
- PWM Subsystem driver support for AM33xx SOC.
-
- PWM submodules require PWM config space access from submodule
- drivers and require common parent driver support.
-
config PWM_TWL
tristate "TWL4030/6030 PWM support"
depends on TWL4030_CORE
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 26326adf71d7..9a475073dafc 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -50,7 +50,6 @@ obj-$(CONFIG_PWM_SUN4I) += pwm-sun4i.o
obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o
-obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o
obj-$(CONFIG_PWM_TWL) += pwm-twl.o
obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o
obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 927d29eb92c6..0f19b086865a 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -127,4 +127,6 @@ source "drivers/staging/qlge/Kconfig"
source "drivers/staging/vboxsf/Kconfig"
+source "drivers/staging/wfx/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index f01f04199073..b7c31b9fe044 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -54,3 +54,4 @@ obj-$(CONFIG_USB_WUSB) += wusbcore/
obj-$(CONFIG_EXFAT_FS) += exfat/
obj-$(CONFIG_QLGE) += qlge/
obj-$(CONFIG_VBOXSF_FS) += vboxsf/
+obj-$(CONFIG_WFX) += wfx/
diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c
index 805437fa249a..39e6c59df1e9 100644
--- a/drivers/staging/axis-fifo/axis-fifo.c
+++ b/drivers/staging/axis-fifo/axis-fifo.c
@@ -125,7 +125,6 @@ MODULE_PARM_DESC(write_timeout, "ms to wait before blocking write() timing out;
struct axis_fifo {
int irq; /* interrupt */
- struct resource *mem; /* physical memory */
void __iomem *base_addr; /* kernel space memory */
unsigned int rx_fifo_depth; /* max words in the receive fifo */
@@ -701,6 +700,68 @@ static int get_dts_property(struct axis_fifo *fifo,
return 0;
}
+static int axis_fifo_parse_dt(struct axis_fifo *fifo)
+{
+ int ret;
+ unsigned int value;
+
+ ret = get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width", &value);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,axi-str-rxd-tdata-width property\n");
+ goto end;
+ } else if (value != 32) {
+ dev_err(fifo->dt_device, "xlnx,axi-str-rxd-tdata-width only supports 32 bits\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = get_dts_property(fifo, "xlnx,axi-str-txd-tdata-width", &value);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,axi-str-txd-tdata-width property\n");
+ goto end;
+ } else if (value != 32) {
+ dev_err(fifo->dt_device, "xlnx,axi-str-txd-tdata-width only supports 32 bits\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = get_dts_property(fifo, "xlnx,rx-fifo-depth",
+ &fifo->rx_fifo_depth);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,rx-fifo-depth property\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = get_dts_property(fifo, "xlnx,tx-fifo-depth",
+ &fifo->tx_fifo_depth);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,tx-fifo-depth property\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ /* IP sets TDFV to fifo depth - 4 so we will do the same */
+ fifo->tx_fifo_depth -= 4;
+
+ ret = get_dts_property(fifo, "xlnx,use-rx-data", &fifo->has_rx_fifo);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,use-rx-data property\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = get_dts_property(fifo, "xlnx,use-tx-data", &fifo->has_tx_fifo);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,use-tx-data property\n");
+ ret = -EIO;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
static int axis_fifo_probe(struct platform_device *pdev)
{
struct resource *r_irq; /* interrupt resources */
@@ -712,34 +773,6 @@ static int axis_fifo_probe(struct platform_device *pdev)
int rc = 0; /* error return value */
- /* IP properties from device tree */
- unsigned int rxd_tdata_width;
- unsigned int txc_tdata_width;
- unsigned int txd_tdata_width;
- unsigned int tdest_width;
- unsigned int tid_width;
- unsigned int tuser_width;
- unsigned int data_interface_type;
- unsigned int has_tdest;
- unsigned int has_tid;
- unsigned int has_tkeep;
- unsigned int has_tstrb;
- unsigned int has_tuser;
- unsigned int rx_fifo_depth;
- unsigned int rx_programmable_empty_threshold;
- unsigned int rx_programmable_full_threshold;
- unsigned int axi_id_width;
- unsigned int axi4_data_width;
- unsigned int select_xpm;
- unsigned int tx_fifo_depth;
- unsigned int tx_programmable_empty_threshold;
- unsigned int tx_programmable_full_threshold;
- unsigned int use_rx_cut_through;
- unsigned int use_rx_data;
- unsigned int use_tx_control;
- unsigned int use_tx_cut_through;
- unsigned int use_tx_data;
-
/* ----------------------------
* init wrapper device
* ----------------------------
@@ -772,32 +805,19 @@ static int axis_fifo_probe(struct platform_device *pdev)
goto err_initial;
}
- fifo->mem = r_mem;
-
/* request physical memory */
- if (!request_mem_region(fifo->mem->start, resource_size(fifo->mem),
- DRIVER_NAME)) {
- dev_err(fifo->dt_device,
- "couldn't lock memory region at 0x%pa\n",
- &fifo->mem->start);
- rc = -EBUSY;
+ fifo->base_addr = devm_ioremap_resource(fifo->dt_device, r_mem);
+ if (IS_ERR(fifo->base_addr)) {
+ rc = PTR_ERR(fifo->base_addr);
+ dev_err(fifo->dt_device, "can't remap IO resource (%d)\n", rc);
goto err_initial;
}
- dev_dbg(fifo->dt_device, "got memory location [0x%pa - 0x%pa]\n",
- &fifo->mem->start, &fifo->mem->end);
-
- /* map physical memory to kernel virtual address space */
- fifo->base_addr = ioremap(fifo->mem->start, resource_size(fifo->mem));
- if (!fifo->base_addr) {
- dev_err(fifo->dt_device, "couldn't map physical memory\n");
- rc = -ENOMEM;
- goto err_mem;
- }
+
dev_dbg(fifo->dt_device, "remapped memory to 0x%p\n", fifo->base_addr);
/* create unique device name */
snprintf(device_name, sizeof(device_name), "%s_%pa",
- DRIVER_NAME, &fifo->mem->start);
+ DRIVER_NAME, &r_mem->start);
dev_dbg(fifo->dt_device, "device name [%s]\n", device_name);
@@ -806,164 +826,9 @@ static int axis_fifo_probe(struct platform_device *pdev)
* ----------------------------
*/
- /* retrieve device tree properties */
- rc = get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width",
- &rxd_tdata_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axi-str-txc-tdata-width",
- &txc_tdata_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axi-str-txd-tdata-width",
- &txd_tdata_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axis-tdest-width", &tdest_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axis-tid-width", &tid_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axis-tuser-width", &tuser_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,data-interface-type",
- &data_interface_type);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tdest", &has_tdest);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tid", &has_tid);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tkeep", &has_tkeep);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tstrb", &has_tstrb);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tuser", &has_tuser);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,rx-fifo-depth", &rx_fifo_depth);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,rx-fifo-pe-threshold",
- &rx_programmable_empty_threshold);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,rx-fifo-pf-threshold",
- &rx_programmable_full_threshold);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,s-axi-id-width", &axi_id_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,s-axi4-data-width", &axi4_data_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,select-xpm", &select_xpm);
+ rc = axis_fifo_parse_dt(fifo);
if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,tx-fifo-depth", &tx_fifo_depth);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,tx-fifo-pe-threshold",
- &tx_programmable_empty_threshold);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,tx-fifo-pf-threshold",
- &tx_programmable_full_threshold);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-rx-cut-through",
- &use_rx_cut_through);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-rx-data", &use_rx_data);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-tx-ctrl", &use_tx_control);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-tx-cut-through",
- &use_tx_cut_through);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-tx-data", &use_tx_data);
- if (rc)
- goto err_unmap;
-
- /* check validity of device tree properties */
- if (rxd_tdata_width != 32) {
- dev_err(fifo->dt_device,
- "rxd_tdata_width width [%u] unsupported\n",
- rxd_tdata_width);
- rc = -EIO;
- goto err_unmap;
- }
- if (txd_tdata_width != 32) {
- dev_err(fifo->dt_device,
- "txd_tdata_width width [%u] unsupported\n",
- txd_tdata_width);
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tdest) {
- dev_err(fifo->dt_device, "tdest not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tid) {
- dev_err(fifo->dt_device, "tid not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tkeep) {
- dev_err(fifo->dt_device, "tkeep not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tstrb) {
- dev_err(fifo->dt_device, "tstrb not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tuser) {
- dev_err(fifo->dt_device, "tuser not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (use_rx_cut_through) {
- dev_err(fifo->dt_device, "rx cut-through not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (use_tx_cut_through) {
- dev_err(fifo->dt_device, "tx cut-through not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (use_tx_control) {
- dev_err(fifo->dt_device, "tx control not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
-
- /* TODO
- * these exist in the device tree but it's unclear what they do
- * - select-xpm
- * - data-interface-type
- */
-
- /* set device wrapper properties based on IP config */
- fifo->rx_fifo_depth = rx_fifo_depth;
- /* IP sets TDFV to fifo depth - 4 so we will do the same */
- fifo->tx_fifo_depth = tx_fifo_depth - 4;
- fifo->has_rx_fifo = use_rx_data;
- fifo->has_tx_fifo = use_tx_data;
+ goto err_initial;
reset_ip_core(fifo);
@@ -976,18 +841,19 @@ static int axis_fifo_probe(struct platform_device *pdev)
r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!r_irq) {
dev_err(fifo->dt_device, "no IRQ found for 0x%pa\n",
- &fifo->mem->start);
+ &r_mem->start);
rc = -EIO;
- goto err_unmap;
+ goto err_initial;
}
/* request IRQ */
fifo->irq = r_irq->start;
- rc = request_irq(fifo->irq, &axis_fifo_irq, 0, DRIVER_NAME, fifo);
+ rc = devm_request_irq(fifo->dt_device, fifo->irq, &axis_fifo_irq, 0,
+ DRIVER_NAME, fifo);
if (rc) {
dev_err(fifo->dt_device, "couldn't allocate interrupt %i\n",
fifo->irq);
- goto err_unmap;
+ goto err_initial;
}
/* ----------------------------
@@ -998,7 +864,7 @@ static int axis_fifo_probe(struct platform_device *pdev)
/* allocate device number */
rc = alloc_chrdev_region(&fifo->devt, 0, 1, DRIVER_NAME);
if (rc < 0)
- goto err_irq;
+ goto err_initial;
dev_dbg(fifo->dt_device, "allocated device number major %i minor %i\n",
MAJOR(fifo->devt), MINOR(fifo->devt));
@@ -1022,14 +888,14 @@ static int axis_fifo_probe(struct platform_device *pdev)
}
/* create sysfs entries */
- rc = sysfs_create_group(&fifo->device->kobj, &axis_fifo_attrs_group);
+ rc = devm_device_add_group(fifo->device, &axis_fifo_attrs_group);
if (rc < 0) {
dev_err(fifo->dt_device, "couldn't register sysfs group\n");
goto err_cdev;
}
dev_info(fifo->dt_device, "axis-fifo created at %pa mapped to 0x%pa, irq=%i, major=%i, minor=%i\n",
- &fifo->mem->start, &fifo->base_addr, fifo->irq,
+ &r_mem->start, &fifo->base_addr, fifo->irq,
MAJOR(fifo->devt), MINOR(fifo->devt));
return 0;
@@ -1040,12 +906,6 @@ err_dev:
device_destroy(axis_fifo_driver_class, fifo->devt);
err_chrdev_region:
unregister_chrdev_region(fifo->devt, 1);
-err_irq:
- free_irq(fifo->irq, fifo);
-err_unmap:
- iounmap(fifo->base_addr);
-err_mem:
- release_mem_region(fifo->mem->start, resource_size(fifo->mem));
err_initial:
dev_set_drvdata(dev, NULL);
return rc;
@@ -1056,15 +916,12 @@ static int axis_fifo_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct axis_fifo *fifo = dev_get_drvdata(dev);
- sysfs_remove_group(&fifo->device->kobj, &axis_fifo_attrs_group);
cdev_del(&fifo->char_device);
dev_set_drvdata(fifo->device, NULL);
device_destroy(axis_fifo_driver_class, fifo->devt);
unregister_chrdev_region(fifo->devt, 1);
- free_irq(fifo->irq, fifo);
- iounmap(fifo->base_addr);
- release_mem_region(fifo->mem->start, resource_size(fifo->mem));
dev_set_drvdata(dev, NULL);
+
return 0;
}
diff --git a/drivers/staging/axis-fifo/axis-fifo.txt b/drivers/staging/axis-fifo/axis-fifo.txt
index 85d88c010e72..5828e1b8e822 100644
--- a/drivers/staging/axis-fifo/axis-fifo.txt
+++ b/drivers/staging/axis-fifo/axis-fifo.txt
@@ -25,10 +25,10 @@ Required properties:
- xlnx,axi-str-txc-tdata-width: Should be <0x20>
- xlnx,axi-str-txd-protocol: Should be "XIL_AXI_STREAM_ETH_DATA"
- xlnx,axi-str-txd-tdata-width: Should be <0x20>
-- xlnx,axis-tdest-width: AXI-Stream TDEST width
-- xlnx,axis-tid-width: AXI-Stream TID width
-- xlnx,axis-tuser-width: AXI-Stream TUSER width
-- xlnx,data-interface-type: Should be <0x0>
+- xlnx,axis-tdest-width: AXI-Stream TDEST width (ignored by the driver)
+- xlnx,axis-tid-width: AXI-Stream TID width (ignored by the driver)
+- xlnx,axis-tuser-width: AXI-Stream TUSER width (ignored by the driver)
+- xlnx,data-interface-type: Should be <0x0> (ignored by the driver)
- xlnx,has-axis-tdest: Should be <0x0> (this feature isn't supported)
- xlnx,has-axis-tid: Should be <0x0> (this feature isn't supported)
- xlnx,has-axis-tkeep: Should be <0x0> (this feature isn't supported)
@@ -36,13 +36,17 @@ Required properties:
- xlnx,has-axis-tuser: Should be <0x0> (this feature isn't supported)
- xlnx,rx-fifo-depth: Depth of RX FIFO in words
- xlnx,rx-fifo-pe-threshold: RX programmable empty interrupt threshold
+ (ignored by the driver)
- xlnx,rx-fifo-pf-threshold: RX programmable full interrupt threshold
-- xlnx,s-axi-id-width: Should be <0x4>
-- xlnx,s-axi4-data-width: Should be <0x20>
-- xlnx,select-xpm: Should be <0x0>
+ (ignored by the driver)
+- xlnx,s-axi-id-width: Should be <0x4> (ignored by the driver)
+- xlnx,s-axi4-data-width: Should be <0x20> (ignored by the driver)
+- xlnx,select-xpm: Should be <0x0> (ignored by the driver)
- xlnx,tx-fifo-depth: Depth of TX FIFO in words
- xlnx,tx-fifo-pe-threshold: TX programmable empty interrupt threshold
+ (ignored by the driver)
- xlnx,tx-fifo-pf-threshold: TX programmable full interrupt threshold
+ (ignored by the driver)
- xlnx,use-rx-cut-through: Should be <0x0> (this feature isn't supported)
- xlnx,use-rx-data: <0x1> if RX FIFO is enabled, <0x0> otherwise
- xlnx,use-tx-ctrl: Should be <0x0> (this feature isn't supported)
diff --git a/drivers/staging/board/armadillo800eva.c b/drivers/staging/board/armadillo800eva.c
index 962cc0c79988..0225234dd7aa 100644
--- a/drivers/staging/board/armadillo800eva.c
+++ b/drivers/staging/board/armadillo800eva.c
@@ -50,16 +50,8 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
};
static struct resource lcdc0_resources[] = {
- [0] = {
- .name = "LCD0",
- .start = 0xfe940000,
- .end = 0xfe943fff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = 177 + 32,
- .flags = IORESOURCE_IRQ,
- },
+ DEFINE_RES_MEM_NAMED(0xfe940000, 0x4000, "LCD0"),
+ DEFINE_RES_IRQ(177 + 32),
};
static struct platform_device lcdc0_device = {
diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
index 15b7a82f4b1e..e52a64be93f3 100644
--- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
+++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
@@ -135,7 +135,6 @@ static int clk_wzrd_probe(struct platform_device *pdev)
unsigned long rate;
const char *clk_name;
struct clk_wzrd *clk_wzrd;
- struct resource *mem;
struct device_node *np = pdev->dev.of_node;
clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL);
@@ -143,8 +142,7 @@ static int clk_wzrd_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, clk_wzrd);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- clk_wzrd->base = devm_ioremap_resource(&pdev->dev, mem);
+ clk_wzrd->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(clk_wzrd->base))
return PTR_ERR(clk_wzrd->base);
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index caf4d4df4bd3..f7c365b70106 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -508,12 +508,11 @@ static int dt3k_ai_insn_read(struct comedi_device *dev,
unsigned int *data)
{
int i;
- unsigned int chan, gain, aref;
+ unsigned int chan, gain;
chan = CR_CHAN(insn->chanspec);
gain = CR_RANGE(insn->chanspec);
/* XXX docs don't explain how to select aref */
- aref = CR_AREF(insn->chanspec);
for (i = 0; i < insn->n; i++)
data[i] = dt3k_readsingle(dev, DPR_SUBSYS_AI, chan, gain);
diff --git a/drivers/staging/comedi/drivers/ni_routes.c b/drivers/staging/comedi/drivers/ni_routes.c
index eb61494dc2bd..673d732dcb8f 100644
--- a/drivers/staging/comedi/drivers/ni_routes.c
+++ b/drivers/staging/comedi/drivers/ni_routes.c
@@ -49,8 +49,6 @@
/* Helper for accessing data. */
#define RVi(table, src, dest) ((table)[(dest) * NI_NUM_NAMES + (src)])
-static const size_t route_table_size = NI_NUM_NAMES * NI_NUM_NAMES;
-
/*
* Find the proper route_values and ni_device_routes tables for this particular
* device.
diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c
index 147481bf680c..03929b9d3a8b 100644
--- a/drivers/staging/emxx_udc/emxx_udc.c
+++ b/drivers/staging/emxx_udc/emxx_udc.c
@@ -1072,9 +1072,8 @@ static int _nbu2ss_epn_in_pio(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep,
if (i_word_length > 0) {
for (i = 0; i < i_word_length; i++) {
_nbu2ss_writel(
- &preg->EP_REGS[ep->epnum - 1].EP_WRITE
- , p_buf_32->dw
- );
+ &preg->EP_REGS[ep->epnum - 1].EP_WRITE,
+ p_buf_32->dw);
p_buf_32++;
}
@@ -2661,20 +2660,18 @@ static int nbu2ss_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
/* make sure it's actually queued on this endpoint */
list_for_each_entry(req, &ep->queue, queue) {
- if (&req->req == _req)
- break;
- }
- if (&req->req != _req) {
- spin_unlock_irqrestore(&udc->lock, flags);
- pr_debug("%s no queue(EINVAL)\n", __func__);
- return -EINVAL;
+ if (&req->req == _req) {
+ _nbu2ss_ep_done(ep, req, -ECONNRESET);
+ spin_unlock_irqrestore(&udc->lock, flags);
+ return 0;
+ }
}
- _nbu2ss_ep_done(ep, req, -ECONNRESET);
-
spin_unlock_irqrestore(&udc->lock, flags);
- return 0;
+ pr_debug("%s no queue(EINVAL)\n", __func__);
+
+ return -EINVAL;
}
/*-------------------------------------------------------------------------*/
@@ -3078,7 +3075,6 @@ static int nbu2ss_drv_probe(struct platform_device *pdev)
{
int status = -ENODEV;
struct nbu2ss_udc *udc;
- struct resource *r;
int irq;
void __iomem *mmio_base;
@@ -3088,8 +3084,7 @@ static int nbu2ss_drv_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, udc);
/* require I/O memory and IRQ to be provided as resources */
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mmio_base = devm_ioremap_resource(&pdev->dev, r);
+ mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mmio_base))
return PTR_ERR(mmio_base);
diff --git a/drivers/staging/exfat/TODO b/drivers/staging/exfat/TODO
index a3eb282f9efc..b60e50b9cf4e 100644
--- a/drivers/staging/exfat/TODO
+++ b/drivers/staging/exfat/TODO
@@ -3,6 +3,15 @@ same for ffsWriteFile.
exfat_core.c - fs_sync(sb,0) all over the place looks fishy as hell.
There's only one place that calls it with a non-zero argument.
+Randomly removing fs_sync() calls is *not* the right answer, especially
+if the removal then leaves a call to fs_set_vol_flags(VOL_CLEAN), as that
+says the file system is clean and synced when we *know* it isn't.
+The proper fix here is to go through and actually analyze how DELAYED_SYNC
+should work, and any time we're setting VOL_CLEAN, ensure the file system
+has in fact been synced to disk. In other words, changing the 'false' to
+'true' is probably more correct. Also, it's likely that the one current
+place where it actually does an bdev_sync isn't sufficient in the DELAYED_SYNC
+case.
ffsTruncateFile - if (old_size <= new_size) {
That doesn't look right. How did it ever work? Are they relying on lazy
diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
index 3abab33e932c..acb73f47a253 100644
--- a/drivers/staging/exfat/exfat.h
+++ b/drivers/staging/exfat/exfat.h
@@ -214,18 +214,10 @@ static inline u16 get_row_index(u16 i)
#define FFS_NOTMOUNTED 4
#define FFS_ALIGNMENTERR 5
#define FFS_SEMAPHOREERR 6
-#define FFS_INVALIDPATH 7
#define FFS_INVALIDFID 8
-#define FFS_NOTFOUND 9
-#define FFS_FILEEXIST 10
-#define FFS_PERMISSIONERR 11
#define FFS_NOTOPENED 12
#define FFS_MAXOPENED 13
-#define FFS_FULL 14
#define FFS_EOF 15
-#define FFS_DIRBUSY 16
-#define FFS_MEMORYERR 17
-#define FFS_NAMETOOLONG 18
#define FFS_ERROR 19
#define NUM_UPCASE 2918
@@ -618,7 +610,7 @@ struct fs_info_t {
u32 dev_ejected; /* block device operation error flag */
struct fs_func *fs_func;
- struct semaphore v_sem;
+ struct mutex v_mutex;
/* FAT cache */
struct buf_cache_t FAT_cache_array[FAT_CACHE_SIZE];
diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c
index e1b001718709..467b93630d86 100644
--- a/drivers/staging/exfat/exfat_cache.c
+++ b/drivers/staging/exfat/exfat_cache.c
@@ -12,8 +12,8 @@
#define DIRTYBIT 0x02
/* Local variables */
-static DEFINE_SEMAPHORE(f_sem);
-static DEFINE_SEMAPHORE(b_sem);
+static DEFINE_MUTEX(f_mutex);
+static DEFINE_MUTEX(b_mutex);
static struct buf_cache_t *FAT_cache_find(struct super_block *sb, sector_t sec)
{
@@ -315,9 +315,9 @@ int FAT_read(struct super_block *sb, u32 loc, u32 *content)
{
s32 ret;
- down(&f_sem);
+ mutex_lock(&f_mutex);
ret = __FAT_read(sb, loc, content);
- up(&f_sem);
+ mutex_unlock(&f_mutex);
return ret;
}
@@ -434,9 +434,9 @@ int FAT_write(struct super_block *sb, u32 loc, u32 content)
{
s32 ret;
- down(&f_sem);
+ mutex_lock(&f_mutex);
ret = __FAT_write(sb, loc, content);
- up(&f_sem);
+ mutex_unlock(&f_mutex);
return ret;
}
@@ -490,7 +490,7 @@ void FAT_release_all(struct super_block *sb)
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&f_sem);
+ mutex_lock(&f_mutex);
bp = p_fs->FAT_cache_lru_list.next;
while (bp != &p_fs->FAT_cache_lru_list) {
@@ -507,7 +507,7 @@ void FAT_release_all(struct super_block *sb)
bp = bp->next;
}
- up(&f_sem);
+ mutex_unlock(&f_mutex);
}
void FAT_sync(struct super_block *sb)
@@ -515,7 +515,7 @@ void FAT_sync(struct super_block *sb)
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&f_sem);
+ mutex_lock(&f_mutex);
bp = p_fs->FAT_cache_lru_list.next;
while (bp != &p_fs->FAT_cache_lru_list) {
@@ -526,7 +526,7 @@ void FAT_sync(struct super_block *sb)
bp = bp->next;
}
- up(&f_sem);
+ mutex_unlock(&f_mutex);
}
static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec)
@@ -600,9 +600,9 @@ u8 *buf_getblk(struct super_block *sb, sector_t sec)
{
u8 *buf;
- down(&b_sem);
+ mutex_lock(&b_mutex);
buf = __buf_getblk(sb, sec);
- up(&b_sem);
+ mutex_unlock(&b_mutex);
return buf;
}
@@ -611,7 +611,7 @@ void buf_modify(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = buf_cache_find(sb, sec);
if (likely(bp))
@@ -620,14 +620,14 @@ void buf_modify(struct super_block *sb, sector_t sec)
WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
(unsigned long long)sec);
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
void buf_lock(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = buf_cache_find(sb, sec);
if (likely(bp))
@@ -636,14 +636,14 @@ void buf_lock(struct super_block *sb, sector_t sec)
WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
(unsigned long long)sec);
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
void buf_unlock(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = buf_cache_find(sb, sec);
if (likely(bp))
@@ -652,7 +652,7 @@ void buf_unlock(struct super_block *sb, sector_t sec)
WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
(unsigned long long)sec);
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
void buf_release(struct super_block *sb, sector_t sec)
@@ -660,7 +660,7 @@ void buf_release(struct super_block *sb, sector_t sec)
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = buf_cache_find(sb, sec);
if (likely(bp)) {
@@ -676,7 +676,7 @@ void buf_release(struct super_block *sb, sector_t sec)
move_to_lru(bp, &p_fs->buf_cache_lru_list);
}
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
void buf_release_all(struct super_block *sb)
@@ -684,7 +684,7 @@ void buf_release_all(struct super_block *sb)
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = p_fs->buf_cache_lru_list.next;
while (bp != &p_fs->buf_cache_lru_list) {
@@ -701,7 +701,7 @@ void buf_release_all(struct super_block *sb)
bp = bp->next;
}
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
void buf_sync(struct super_block *sb)
@@ -709,7 +709,7 @@ void buf_sync(struct super_block *sb)
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = p_fs->buf_cache_lru_list.next;
while (bp != &p_fs->buf_cache_lru_list) {
@@ -720,5 +720,5 @@ void buf_sync(struct super_block *sb)
bp = bp->next;
}
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
index 79174e5c4145..b23fbf3ebaa5 100644
--- a/drivers/staging/exfat/exfat_core.c
+++ b/drivers/staging/exfat/exfat_core.c
@@ -470,7 +470,8 @@ s32 exfat_count_used_clusters(struct super_block *sb)
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
- map_i = map_b = 0;
+ map_i = 0;
+ map_b = 0;
for (i = 2; i < p_fs->num_clusters; i += 8) {
k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b);
@@ -544,13 +545,13 @@ s32 load_alloc_bitmap(struct super_block *sb)
sizeof(struct buffer_head *),
GFP_KERNEL);
if (!p_fs->vol_amap)
- return FFS_MEMORYERR;
+ return -ENOMEM;
sector = START_SECTOR(p_fs->map_clu);
for (j = 0; j < p_fs->map_sectors; j++) {
p_fs->vol_amap[j] = NULL;
- ret = sector_read(sb, sector + j, &(p_fs->vol_amap[j]), 1);
+ ret = sector_read(sb, sector + j, &p_fs->vol_amap[j], 1);
if (ret != FFS_SUCCESS) {
/* release all buffers and free vol_amap */
i = 0;
@@ -712,10 +713,10 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
u32 checksum = 0;
- upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *),
- GFP_KERNEL);
+ upcase_table = kmalloc_array(UTBL_COL_COUNT, sizeof(u16 *), GFP_KERNEL);
+ p_fs->vol_utbl = upcase_table;
if (!upcase_table)
- return FFS_MEMORYERR;
+ return -ENOMEM;
memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
while (sector < end_sector) {
@@ -755,7 +756,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT,
sizeof(u16), GFP_KERNEL);
if (!upcase_table[col_index]) {
- ret = FFS_MEMORYERR;
+ ret = -ENOMEM;
goto error;
}
@@ -792,10 +793,10 @@ static s32 __load_default_upcase_table(struct super_block *sb)
u16 uni = 0;
u16 **upcase_table;
- upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *),
- GFP_KERNEL);
+ upcase_table = kmalloc_array(UTBL_COL_COUNT, sizeof(u16 *), GFP_KERNEL);
+ p_fs->vol_utbl = upcase_table;
if (!upcase_table)
- return FFS_MEMORYERR;
+ return -ENOMEM;
memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
for (i = 0; index <= 0xFFFF && i < NUM_UPCASE * 2; i += 2) {
@@ -818,7 +819,7 @@ static s32 __load_default_upcase_table(struct super_block *sb)
sizeof(u16),
GFP_KERNEL);
if (!upcase_table[col_index]) {
- ret = FFS_MEMORYERR;
+ ret = -ENOMEM;
goto error;
}
@@ -910,10 +911,10 @@ u32 fat_get_entry_type(struct dentry_t *p_entry)
{
struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
- if (*(ep->name) == 0x0)
+ if (*ep->name == 0x0)
return TYPE_UNUSED;
- else if (*(ep->name) == 0xE5)
+ else if (*ep->name == 0xE5)
return TYPE_DELETED;
else if (ep->attr == ATTR_EXTEND)
@@ -978,10 +979,10 @@ void fat_set_entry_type(struct dentry_t *p_entry, u32 type)
struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
if (type == TYPE_UNUSED)
- *(ep->name) = 0x0;
+ *ep->name = 0x0;
else if (type == TYPE_DELETED)
- *(ep->name) = 0xE5;
+ *ep->name = 0xE5;
else if (type == TYPE_EXTEND)
ep->attr = ATTR_EXTEND;
@@ -1502,7 +1503,7 @@ void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
}
void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 order, s32 num_entries)
+ s32 entry, s32 order, s32 num_entries)
{
int i;
sector_t sector;
@@ -1562,7 +1563,7 @@ void update_dir_checksum_with_entry_set(struct super_block *sb,
u16 chksum = 0;
s32 chksum_type = CS_DIR_ENTRY, i;
- ep = (struct dentry_t *)&(es->__buf);
+ ep = (struct dentry_t *)&es->__buf;
for (i = 0; i < es->num_entries; i++) {
pr_debug("%s ep %p\n", __func__, ep);
chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum,
@@ -1571,7 +1572,7 @@ void update_dir_checksum_with_entry_set(struct super_block *sb,
chksum_type = CS_DEFAULT;
}
- ep = (struct dentry_t *)&(es->__buf);
+ ep = (struct dentry_t *)&es->__buf;
SET16_A(((struct file_dentry_t *)ep)->checksum, chksum);
write_whole_entry_set(sb, es);
}
@@ -1703,7 +1704,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
size_t bufsize;
pr_debug("%s entered p_dir dir %u flags %x size %d\n",
- __func__, p_dir->dir, p_dir->flags, p_dir->size);
+ __func__, p_dir->dir, p_dir->flags, p_dir->size);
byte_offset = entry << DENTRY_SIZE_BITS;
ret = _walk_fat_chain(sb, p_dir, byte_offset, &clu);
@@ -1727,8 +1728,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
ep = (struct dentry_t *)(buf + off);
entry_type = p_fs->fs_func->get_entry_type(ep);
- if ((entry_type != TYPE_FILE)
- && (entry_type != TYPE_DIR))
+ if ((entry_type != TYPE_FILE) && (entry_type != TYPE_DIR))
goto err_out;
if (type == ES_ALL_ENTRIES)
@@ -1832,11 +1832,11 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
}
if (file_ep)
- *file_ep = (struct dentry_t *)&(es->__buf);
+ *file_ep = (struct dentry_t *)&es->__buf;
pr_debug("%s exiting es %p sec %llu offset %d flags %d, num_entries %u buf ptr %p\n",
- __func__, es, (unsigned long long)es->sector, es->offset,
- es->alloc_flag, es->num_entries, &es->__buf);
+ __func__, es, (unsigned long long)es->sector, es->offset,
+ es->alloc_flag, es->num_entries, &es->__buf);
return es;
err_out:
pr_debug("%s exited NULL (es %p)\n", __func__, es);
@@ -1859,10 +1859,10 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
u32 clu;
- u8 *buf, *esbuf = (u8 *)&(es->__buf);
+ u8 *buf, *esbuf = (u8 *)&es->__buf;
pr_debug("%s entered es %p sec %llu off %d count %d\n",
- __func__, es, (unsigned long long)sec, off, count);
+ __func__, es, (unsigned long long)sec, off, count);
num_entries = count;
while (num_entries) {
@@ -1876,8 +1876,8 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
goto err_out;
pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off);
pr_debug("copying %d entries from %p to sector %llu\n",
- copy_entries, (esbuf + buf_off),
- (unsigned long long)sec);
+ copy_entries, (esbuf + buf_off),
+ (unsigned long long)sec);
memcpy(buf + off, esbuf + buf_off,
copy_entries << DENTRY_SIZE_BITS);
buf_modify(sb, sec);
@@ -1919,7 +1919,8 @@ s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es)
/* write back some entries in entry set */
s32 write_partial_entries_in_entry_set(struct super_block *sb,
- struct entry_set_cache_t *es, struct dentry_t *ep, u32 count)
+ struct entry_set_cache_t *es,
+ struct dentry_t *ep, u32 count)
{
s32 ret, byte_offset, off;
u32 clu = 0;
@@ -1929,7 +1930,7 @@ s32 write_partial_entries_in_entry_set(struct super_block *sb,
struct chain_t dir;
/* vaidity check */
- if (ep + count > ((struct dentry_t *)&(es->__buf)) + es->num_entries)
+ if (ep + count > ((struct dentry_t *)&es->__buf) + es->num_entries)
return FFS_ERROR;
dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector);
@@ -1938,7 +1939,7 @@ s32 write_partial_entries_in_entry_set(struct super_block *sb,
byte_offset = (es->sector - START_SECTOR(dir.dir)) <<
p_bd->sector_size_bits;
- byte_offset += ((void **)ep - &(es->__buf)) + es->offset;
+ byte_offset += ((void **)ep - &es->__buf) + es->offset;
ret = _walk_fat_chain(sb, &dir, byte_offset, &clu);
if (ret != FFS_SUCCESS)
@@ -2122,7 +2123,7 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
p_fs->fs_func->set_entry_flag(ep, p_dir->flags);
buf_modify(sb, sector);
- update_dir_checksum(sb, &(fid->dir),
+ update_dir_checksum(sb, &fid->dir,
fid->entry);
}
}
@@ -2571,7 +2572,7 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
num_entries = p_fs->fs_func->calc_num_entries(p_uniname);
if (num_entries == 0)
- return FFS_INVALIDPATH;
+ return -EINVAL;
if (p_fs->vol_type != EXFAT) {
nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy);
@@ -2583,7 +2584,7 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
} else {
for (r = reserved_names; *r; r++) {
if (!strncmp((void *)p_dosname->name, *r, 8))
- return FFS_INVALIDPATH;
+ return -EINVAL;
}
if (p_dosname->name_case != 0xFF)
@@ -2828,7 +2829,7 @@ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
}
if ((count == 0) || (count >= 1024))
- return FFS_FILEEXIST;
+ return -EEXIST;
fat_attach_count_to_dos_name(p_dosname->name, count);
/* Now dos_name has DOS~????.EXT */
@@ -2962,11 +2963,11 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
struct file_id_t *fid = &(EXFAT_I(inode)->fid);
if (strscpy(name_buf, path, sizeof(name_buf)) < 0)
- return FFS_INVALIDPATH;
+ return -EINVAL;
nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy);
if (lossy)
- return FFS_INVALIDPATH;
+ return -EINVAL;
fid->size = i_size_read(inode);
@@ -3216,7 +3217,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
/* find_empty_entry must be called before alloc_cluster */
dentry = find_empty_entry(inode, p_dir, num_entries);
if (dentry < 0)
- return FFS_FULL;
+ return -ENOSPC;
clu.dir = CLUSTER_32(~0);
clu.size = 0;
@@ -3227,7 +3228,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
if (ret < 0)
return FFS_MEDIAERR;
else if (ret == 0)
- return FFS_FULL;
+ return -ENOSPC;
ret = clear_cluster(sb, clu.dir);
if (ret != FFS_SUCCESS)
@@ -3319,7 +3320,7 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir,
/* find_empty_entry must be called before alloc_cluster() */
dentry = find_empty_entry(inode, p_dir, num_entries);
if (dentry < 0)
- return FFS_FULL;
+ return -ENOSPC;
/* (1) update the directory entry */
/* fill the dos name directory entry information of the created file.
@@ -3418,7 +3419,7 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
newentry = find_empty_entry(inode, p_dir, num_new_entries);
if (newentry < 0) {
buf_unlock(sb, sector_old);
- return FFS_FULL;
+ return -ENOSPC;
}
epnew = get_entry_in_dir(sb, p_dir, newentry, &sector_new);
@@ -3506,7 +3507,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
/* check if the source and target directory is the same */
if (fs_func->get_entry_type(epmov) == TYPE_DIR &&
fs_func->get_entry_clu0(epmov) == p_newdir->dir)
- return FFS_INVALIDPATH;
+ return -EINVAL;
buf_lock(sb, sector_mov);
@@ -3529,7 +3530,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
newentry = find_empty_entry(inode, p_newdir, num_new_entries);
if (newentry < 0) {
buf_unlock(sb, sector_mov);
- return FFS_FULL;
+ return -ENOSPC;
}
epnew = get_entry_in_dir(sb, p_newdir, newentry, &sector_new);
diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
index 3b2b0ceb7297..1ae5a7750348 100644
--- a/drivers/staging/exfat/exfat_super.c
+++ b/drivers/staging/exfat/exfat_super.c
@@ -284,7 +284,7 @@ static const struct dentry_operations exfat_dentry_ops = {
.d_compare = exfat_cmp,
};
-static DEFINE_SEMAPHORE(z_sem);
+static DEFINE_MUTEX(z_mutex);
static inline void fs_sync(struct super_block *sb, bool do_sync)
{
@@ -353,11 +353,11 @@ static int ffsMountVol(struct super_block *sb)
pr_info("[EXFAT] trying to mount...\n");
- down(&z_sem);
+ mutex_lock(&z_mutex);
buf_init(sb);
- sema_init(&p_fs->v_sem, 1);
+ mutex_init(&p_fs->v_mutex);
p_fs->dev_ejected = 0;
/* open the block device */
@@ -396,7 +396,7 @@ static int ffsMountVol(struct super_block *sb)
if (i < 53) {
#ifdef CONFIG_EXFAT_DONT_MOUNT_VFAT
ret = -EINVAL;
- printk(KERN_INFO "EXFAT: Attempted to mount VFAT filesystem\n");
+ pr_info("EXFAT: Attempted to mount VFAT filesystem\n");
goto out;
#else
if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */
@@ -442,7 +442,7 @@ static int ffsMountVol(struct super_block *sb)
pr_info("[EXFAT] mounted successfully\n");
out:
- up(&z_sem);
+ mutex_unlock(&z_mutex);
return ret;
}
@@ -454,12 +454,12 @@ static int ffsUmountVol(struct super_block *sb)
pr_info("[EXFAT] trying to unmount...\n");
- down(&z_sem);
+ mutex_lock(&z_mutex);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
- fs_sync(sb, false);
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
if (p_fs->vol_type == EXFAT) {
@@ -481,8 +481,8 @@ static int ffsUmountVol(struct super_block *sb)
buf_shutdown(sb);
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
- up(&z_sem);
+ mutex_unlock(&p_fs->v_mutex);
+ mutex_unlock(&z_mutex);
pr_info("[EXFAT] unmounted successfully\n");
@@ -499,7 +499,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
return FFS_ERROR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
if (p_fs->used_clusters == UINT_MAX)
p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb);
@@ -514,7 +514,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
err = FFS_MEDIAERR;
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return err;
}
@@ -525,7 +525,7 @@ static int ffsSyncVol(struct super_block *sb, bool do_sync)
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* synchronize the file system */
fs_sync(sb, do_sync);
@@ -535,7 +535,7 @@ static int ffsSyncVol(struct super_block *sb, bool do_sync)
err = FFS_MEDIAERR;
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return err;
}
@@ -562,7 +562,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
return FFS_ERROR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check the validity of directory name in the given pathname */
ret = resolve_path(inode, path, &dir, &uni_name);
@@ -578,7 +578,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries,
&dos_name, TYPE_ALL);
if (dentry < -1) {
- ret = FFS_NOTFOUND;
+ ret = -ENOENT;
goto out;
}
@@ -636,7 +636,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
ret = FFS_MEDIAERR;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -655,7 +655,7 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
return FFS_ERROR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check the validity of directory name in the given pathname */
ret = resolve_path(inode, path, &dir, &uni_name);
@@ -667,8 +667,8 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
/* create a new file */
ret = create_file(inode, &dir, &uni_name, mode, fid);
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -677,7 +677,7 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -704,11 +704,11 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
return FFS_ERROR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check if the given file ID is opened */
if (fid->type != TYPE_FILE) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out;
}
@@ -743,8 +743,10 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
while (clu_offset > 0) {
/* clu = FAT_read(sb, clu); */
- if (FAT_read(sb, clu, &clu) == -1)
- return FFS_MEDIAERR;
+ if (FAT_read(sb, clu, &clu) == -1) {
+ ret = FFS_MEDIAERR;
+ goto out;
+ }
clu_offset--;
}
@@ -801,7 +803,7 @@ err_out:
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -834,11 +836,11 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
return FFS_ERROR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check if the given file ID is opened */
if (fid->type != TYPE_FILE) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out;
}
@@ -864,7 +866,8 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
while (count > 0) {
clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits);
- clu = last_clu = fid->start_clu;
+ clu = fid->start_clu;
+ last_clu = fid->start_clu;
if (fid->flags == 0x03) {
if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
@@ -1003,13 +1006,13 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
/* (3) update the direcoty entry */
if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
ES_ALL_ENTRIES, &ep);
if (!es)
goto err_out;
ep2 = ep + 1;
} else {
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
+ ep = get_entry_in_dir(sb, &fid->dir, fid->entry, &sector);
if (!ep)
goto err_out;
ep2 = ep;
@@ -1040,8 +1043,8 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
release_entry_set(es);
}
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -1051,14 +1054,14 @@ err_out:
*wcount = write_bytes;
if (num_alloced == 0)
- ret = FFS_FULL;
+ ret = -ENOSPC;
else if (p_fs->dev_ejected)
ret = FFS_MEDIAERR;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1081,11 +1084,11 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
new_size);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check if the given file ID is opened */
if (fid->type != TYPE_FILE) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out;
}
@@ -1142,7 +1145,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
}
ep2 = ep + 1;
} else {
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
+ ep = get_entry_in_dir(sb, &fid->dir, fid->entry, &sector);
if (!ep) {
ret = FFS_MEDIAERR;
goto out;
@@ -1180,8 +1183,8 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
if (fid->rwoffset > fid->size)
fid->rwoffset = fid->size;
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -1191,7 +1194,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
out:
pr_debug("%s exited (%d)\n", __func__, ret);
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1239,7 +1242,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
return FFS_ERROR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
update_parent_info(fid, old_parent_inode);
@@ -1252,7 +1255,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
/* check if the old file is "." or ".." */
if (p_fs->vol_type != EXFAT) {
if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out2;
}
}
@@ -1264,7 +1267,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
}
if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out2;
}
@@ -1277,7 +1280,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
update_parent_info(new_fid, new_parent_inode);
- p_dir = &(new_fid->dir);
+ p_dir = &new_fid->dir;
new_entry = new_fid->entry;
ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
if (!ep)
@@ -1294,7 +1297,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
new_clu.flags = new_fid->flags;
if (!is_dir_empty(sb, &new_clu)) {
- ret = FFS_FILEEXIST;
+ ret = -EEXIST;
goto out;
}
}
@@ -1328,8 +1331,8 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
num_entries + 1);
}
out:
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -1337,7 +1340,7 @@ out:
ret = FFS_MEDIAERR;
out2:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1356,7 +1359,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
return FFS_INVALIDFID;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
dir.dir = fid->dir.dir;
dir.size = fid->dir.size;
@@ -1371,7 +1374,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
}
if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out;
}
fs_set_vol_flags(sb, VOL_DIRTY);
@@ -1390,8 +1393,8 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
fid->start_clu = CLUSTER_32(~0);
fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -1399,7 +1402,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
ret = FFS_MEDIAERR;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1434,18 +1437,18 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
}
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* get the directory entry of given file */
if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
ES_ALL_ENTRIES, &ep);
if (!es) {
ret = FFS_MEDIAERR;
goto out;
}
} else {
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
+ ep = get_entry_in_dir(sb, &fid->dir, fid->entry, &sector);
if (!ep) {
ret = FFS_MEDIAERR;
goto out;
@@ -1479,8 +1482,8 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
release_entry_set(es);
}
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -1488,7 +1491,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
ret = FFS_MEDIAERR;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1512,7 +1515,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
pr_debug("%s entered\n", __func__);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
if (is_dir) {
if ((fid->dir.dir == p_fs->root_dir) &&
@@ -1554,7 +1557,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
/* get the directory entry of given file or directory */
if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
ES_2_ENTRIES, &ep);
if (!es) {
ret = FFS_MEDIAERR;
@@ -1562,7 +1565,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
}
ep2 = ep + 1;
} else {
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
+ ep = get_entry_in_dir(sb, &fid->dir, fid->entry, &sector);
if (!ep) {
ret = FFS_MEDIAERR;
goto out;
@@ -1594,11 +1597,11 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
memset((char *)&info->AccessTimestamp, 0, sizeof(struct date_time_t));
- *(uni_name.name) = 0x0;
+ *uni_name.name = 0x0;
/* XXX this is very bad for exfat cuz name is already included in es.
* API should be revised
*/
- p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry,
+ p_fs->fs_func->get_uni_name_from_ext_entry(sb, &fid->dir, fid->entry,
uni_name.name);
if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT)
get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep,
@@ -1641,7 +1644,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
pr_debug("%s exited successfully\n", __func__);
return ret;
@@ -1662,7 +1665,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
pr_debug("%s entered (inode %p info %p\n", __func__, inode, info);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
if (is_dir) {
if ((fid->dir.dir == p_fs->root_dir) &&
@@ -1678,7 +1681,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
/* get the directory entry of given file or directory */
if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
ES_ALL_ENTRIES, &ep);
if (!es) {
ret = FFS_MEDIAERR;
@@ -1687,7 +1690,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
ep2 = ep + 1;
} else {
/* for other than exfat */
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
+ ep = get_entry_in_dir(sb, &fid->dir, fid->entry, &sector);
if (!ep) {
ret = FFS_MEDIAERR;
goto out;
@@ -1728,7 +1731,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
pr_debug("%s exited (%d)\n", __func__, ret);
@@ -1754,7 +1757,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
return FFS_ERROR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
fid->rwoffset = (s64)(clu_offset) << p_fs->cluster_size_bits;
@@ -1807,7 +1810,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
ret = FFS_MEDIAERR;
goto out;
} else if (num_alloced == 0) {
- ret = FFS_FULL;
+ ret = -ENOSPC;
goto out;
}
@@ -1845,7 +1848,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
/* (3) update directory entry */
if (modified) {
if (p_fs->vol_type != EXFAT) {
- ep = get_entry_in_dir(sb, &(fid->dir),
+ ep = get_entry_in_dir(sb, &fid->dir,
fid->entry, &sector);
if (!ep) {
ret = FFS_MEDIAERR;
@@ -1882,7 +1885,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1906,7 +1909,7 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
return FFS_ERROR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check the validity of directory name in the given old pathname */
ret = resolve_path(inode, path, &dir, &uni_name);
@@ -1917,8 +1920,8 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
ret = create_dir(inode, &dir, &uni_name, fid);
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -1926,7 +1929,7 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
ret = FFS_MEDIAERR;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1953,10 +1956,10 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
/* check if the given file ID is opened */
if (fid->type != TYPE_DIR)
- return FFS_PERMISSIONERR;
+ return -EPERM;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
if (fid->entry == -1) {
dir.dir = p_fs->root_dir;
@@ -2058,7 +2061,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
memset((char *)&dir_entry->AccessTimestamp, 0,
sizeof(struct date_time_t));
- *(uni_name.name) = 0x0;
+ *uni_name.name = 0x0;
fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry,
uni_name.name);
if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT)
@@ -2116,7 +2119,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
}
}
- *(dir_entry->Name) = '\0';
+ *dir_entry->Name = '\0';
fid->rwoffset = (s64)(++dentry);
@@ -2125,7 +2128,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -2151,18 +2154,18 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
/* check if the file is "." or ".." */
if (p_fs->vol_type != EXFAT) {
if ((dir.dir != p_fs->root_dir) && (dentry < 2))
- return FFS_PERMISSIONERR;
+ return -EPERM;
}
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
clu_to_free.dir = fid->start_clu;
clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1;
clu_to_free.flags = fid->flags;
if (!is_dir_empty(sb, &clu_to_free)) {
- ret = FFS_FILEEXIST;
+ ret = -EEXIST;
goto out;
}
@@ -2178,8 +2181,8 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
fid->start_clu = CLUSTER_32(~0);
fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -2188,7 +2191,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -2202,7 +2205,7 @@ static int exfat_readdir(struct file *filp, struct dir_context *ctx)
struct inode *inode = file_inode(filp);
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
struct dir_entry_t de;
unsigned long inum;
@@ -2293,7 +2296,7 @@ static int exfat_ioctl_volume_id(struct inode *dir)
{
struct super_block *sb = dir->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
return p_fs->vol_id;
}
@@ -2351,6 +2354,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
bool excl)
{
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
struct inode *inode;
struct file_id_t fid;
loff_t i_pos;
@@ -2362,20 +2366,23 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_REGULAR, &fid);
if (err) {
- if (err == FFS_INVALIDPATH)
+ if (err == -EINVAL)
err = -EINVAL;
- else if (err == FFS_FILEEXIST)
+ else if (err == -EEXIST)
err = -EEXIST;
- else if (err == FFS_FULL)
+ else if (err == -ENOSPC)
err = -ENOSPC;
- else if (err == FFS_NAMETOOLONG)
+ else if (err == -ENAMETOOLONG)
err = -ENAMETOOLONG;
else
err = -EIO;
goto out;
}
INC_IVERSION(dir);
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_ctime = curtime;
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
@@ -2389,7 +2396,10 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
goto out;
}
INC_IVERSION(inode);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
+ inode->i_ctime = curtime;
/*
* timestamp is already written, so mark_inode_dirty() is unnecessary.
*/
@@ -2522,6 +2532,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
int err;
__lock_super(sb);
@@ -2532,21 +2543,25 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid));
if (err) {
- if (err == FFS_PERMISSIONERR)
+ if (err == -EPERM)
err = -EPERM;
else
err = -EIO;
goto out;
}
INC_IVERSION(dir);
- dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
mark_inode_dirty(dir);
clear_nlink(inode);
- inode->i_mtime = inode->i_atime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
exfat_detach(inode);
remove_inode_hash(inode);
@@ -2560,6 +2575,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
const char *target)
{
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
struct inode *inode;
struct file_id_t fid;
loff_t i_pos;
@@ -2573,11 +2589,11 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_SYMLINK, &fid);
if (err) {
- if (err == FFS_INVALIDPATH)
+ if (err == -EINVAL)
err = -EINVAL;
- else if (err == FFS_FILEEXIST)
+ else if (err == -EEXIST)
err = -EEXIST;
- else if (err == FFS_FULL)
+ else if (err == -ENOSPC)
err = -ENOSPC;
else
err = -EIO;
@@ -2589,7 +2605,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
if (err) {
ffsRemoveFile(dir, &fid);
- if (err == FFS_FULL)
+ if (err == -ENOSPC)
err = -ENOSPC;
else
err = -EIO;
@@ -2597,7 +2613,10 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
}
INC_IVERSION(dir);
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_ctime = curtime;
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
@@ -2611,7 +2630,10 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
goto out;
}
INC_IVERSION(inode);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
+ inode->i_ctime = curtime;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
EXFAT_I(inode)->target = kmemdup(target, len + 1, GFP_KERNEL);
@@ -2632,6 +2654,7 @@ out:
static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
struct inode *inode;
struct file_id_t fid;
loff_t i_pos;
@@ -2643,20 +2666,23 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
err = ffsCreateDir(dir, (u8 *)dentry->d_name.name, &fid);
if (err) {
- if (err == FFS_INVALIDPATH)
+ if (err == -EINVAL)
err = -EINVAL;
- else if (err == FFS_FILEEXIST)
+ else if (err == -EEXIST)
err = -EEXIST;
- else if (err == FFS_FULL)
+ else if (err == -ENOSPC)
err = -ENOSPC;
- else if (err == FFS_NAMETOOLONG)
+ else if (err == -ENAMETOOLONG)
err = -ENAMETOOLONG;
else
err = -EIO;
goto out;
}
INC_IVERSION(dir);
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_ctime = curtime;
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
@@ -2671,7 +2697,10 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
goto out;
}
INC_IVERSION(inode);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
+ inode->i_ctime = curtime;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode);
@@ -2687,6 +2716,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
int err;
__lock_super(sb);
@@ -2697,20 +2727,22 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid));
if (err) {
- if (err == FFS_INVALIDPATH)
+ if (err == -EINVAL)
err = -EINVAL;
- else if (err == FFS_FILEEXIST)
+ else if (err == -EEXIST)
err = -ENOTEMPTY;
- else if (err == FFS_NOTFOUND)
+ else if (err == -ENOENT)
err = -ENOENT;
- else if (err == FFS_DIRBUSY)
+ else if (err == -EBUSY)
err = -EBUSY;
else
err = -EIO;
goto out;
}
INC_IVERSION(dir);
- dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
@@ -2718,7 +2750,9 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
drop_nlink(dir);
clear_nlink(inode);
- inode->i_mtime = inode->i_atime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
exfat_detach(inode);
remove_inode_hash(inode);
@@ -2734,6 +2768,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
{
struct inode *old_inode, *new_inode;
struct super_block *sb = old_dir->i_sb;
+ struct timespec64 curtime;
loff_t i_pos;
int err;
@@ -2752,23 +2787,26 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir,
new_dentry);
if (err) {
- if (err == FFS_PERMISSIONERR)
+ if (err == -EPERM)
err = -EPERM;
- else if (err == FFS_INVALIDPATH)
+ else if (err == -EINVAL)
err = -EINVAL;
- else if (err == FFS_FILEEXIST)
+ else if (err == -EEXIST)
err = -EEXIST;
- else if (err == FFS_NOTFOUND)
+ else if (err == -ENOENT)
err = -ENOENT;
- else if (err == FFS_FULL)
+ else if (err == -ENOSPC)
err = -ENOSPC;
else
err = -EIO;
goto out;
}
INC_IVERSION(new_dir);
- new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime =
- current_time(new_dir);
+ curtime = current_time(new_dir);
+ new_dir->i_ctime = curtime;
+ new_dir->i_mtime = curtime;
+ new_dir->i_atime = curtime;
+
if (IS_DIRSYNC(new_dir))
(void)exfat_sync_inode(new_dir);
else
@@ -2790,7 +2828,9 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
inc_nlink(new_dir);
}
INC_IVERSION(old_dir);
- old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
+ curtime = current_time(old_dir);
+ old_dir->i_ctime = curtime;
+ old_dir->i_mtime = curtime;
if (IS_DIRSYNC(old_dir))
(void)exfat_sync_inode(old_dir);
else
@@ -2814,13 +2854,16 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
{
struct address_space *mapping = inode->i_mapping;
loff_t start = i_size_read(inode), count = size - i_size_read(inode);
+ struct timespec64 curtime;
int err, err2;
err = generic_cont_expand_simple(inode, size);
if (err != 0)
return err;
- inode->i_ctime = inode->i_mtime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_ctime = curtime;
+ inode->i_mtime = curtime;
mark_inode_dirty(inode);
if (IS_SYNC(inode)) {
@@ -2895,7 +2938,8 @@ static void exfat_truncate(struct inode *inode, loff_t old_size)
{
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
+ struct timespec64 curtime;
int err;
__lock_super(sb);
@@ -2914,7 +2958,9 @@ static void exfat_truncate(struct inode *inode, loff_t old_size)
if (err)
goto out;
- inode->i_ctime = inode->i_mtime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_ctime = curtime;
+ inode->i_mtime = curtime;
if (IS_DIRSYNC(inode))
(void)exfat_sync_inode(inode);
else
@@ -2936,8 +2982,8 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr)
pr_debug("%s entered\n", __func__);
- if ((attr->ia_valid & ATTR_SIZE)
- && (attr->ia_size > i_size_read(inode))) {
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size > i_size_read(inode)) {
error = exfat_cont_expand(inode, attr->ia_size);
if (error || attr->ia_valid == ATTR_SIZE)
return error;
@@ -2946,8 +2992,8 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr)
ia_valid = attr->ia_valid;
- if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET))
- && exfat_allow_set_time(sbi, inode)) {
+ if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) &&
+ exfat_allow_set_time(sbi, inode)) {
attr->ia_valid &= ~(ATTR_MTIME_SET |
ATTR_ATIME_SET |
ATTR_TIMES_SET);
@@ -3073,8 +3119,8 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
{
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
- struct bd_info_t *p_bd = &(sbi->bd_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
+ struct bd_info_t *p_bd = &sbi->bd_info;
const unsigned long blocksize = sb->s_blocksize;
const unsigned char blocksize_bits = sb->s_blocksize_bits;
sector_t last_block;
@@ -3115,7 +3161,7 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
err = ffsMapCluster(inode, clu_offset, &cluster);
if (err) {
- if (err == FFS_FULL)
+ if (err == -ENOSPC)
return -ENOSPC;
else
return -EIO;
@@ -3215,6 +3261,7 @@ static int exfat_write_end(struct file *file, struct address_space *mapping,
{
struct inode *inode = mapping->host;
struct file_id_t *fid = &(EXFAT_I(inode)->fid);
+ struct timespec64 curtime;
int err;
err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
@@ -3223,7 +3270,9 @@ static int exfat_write_end(struct file *file, struct address_space *mapping,
exfat_write_failed(mapping, pos + len);
if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) {
- inode->i_mtime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_ctime = curtime;
fid->attr |= ATTR_ARCHIVE;
mark_inode_dirty(inode);
}
@@ -3302,7 +3351,7 @@ static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos)
static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid)
{
struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
struct dir_entry_t info;
memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(struct file_id_t));
@@ -3674,7 +3723,8 @@ static int parse_options(char *options, int silent, int *debug,
opts->fs_uid = current_uid();
opts->fs_gid = current_gid();
- opts->fs_fmask = opts->fs_dmask = current->fs->umask;
+ opts->fs_fmask = current->fs->umask;
+ opts->fs_dmask = current->fs->umask;
opts->allow_utime = U16_MAX;
opts->codepage = exfat_default_codepage;
opts->iocharset = exfat_default_iocharset;
@@ -3787,7 +3837,8 @@ static int exfat_read_root(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
+ struct timespec64 curtime;
struct dir_entry_t info;
EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir;
@@ -3818,7 +3869,10 @@ static int exfat_read_root(struct inode *inode)
EXFAT_I(inode)->mmu_private = i_size_read(inode);
exfat_save_attr(inode, ATTR_SUBDIR);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
+ inode->i_ctime = curtime;
set_nlink(inode, info.NumSubdirs + 2);
return 0;
@@ -3984,10 +4038,10 @@ static void exfat_debug_kill_sb(struct super_block *sb)
* invalidate_bdev drops all device cache include
* dirty. We use this to simulate device removal.
*/
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
FAT_release_all(sb);
buf_release_all(sb);
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
invalidate_bdev(bdev);
}
diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig
index cb61c2a772bd..d994aea84b21 100644
--- a/drivers/staging/fbtft/Kconfig
+++ b/drivers/staging/fbtft/Kconfig
@@ -112,6 +112,13 @@ config FB_TFT_S6D1121
help
Generic Framebuffer support for S6D1121
+config FB_TFT_SEPS525
+ tristate "FB driver for the SEPS525 LCD Controller"
+ depends on FB_TFT
+ help
+ Generic Framebuffer support for SEPS525
+ Say Y if you have such a display that utilizes this controller.
+
config FB_TFT_SH1106
tristate "FB driver for the SH1106 OLED Controller"
depends on FB_TFT
diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile
index 27af43f32f81..e87193f7df14 100644
--- a/drivers/staging/fbtft/Makefile
+++ b/drivers/staging/fbtft/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_FB_TFT_PCD8544) += fb_pcd8544.o
obj-$(CONFIG_FB_TFT_RA8875) += fb_ra8875.o
obj-$(CONFIG_FB_TFT_S6D02A1) += fb_s6d02a1.o
obj-$(CONFIG_FB_TFT_S6D1121) += fb_s6d1121.o
+obj-$(CONFIG_FB_TFT_SEPS525) += fb_seps525.o
obj-$(CONFIG_FB_TFT_SH1106) += fb_sh1106.o
obj-$(CONFIG_FB_TFT_SSD1289) += fb_ssd1289.o
obj-$(CONFIG_FB_TFT_SSD1305) += fb_ssd1305.o
diff --git a/drivers/staging/fbtft/fb_seps525.c b/drivers/staging/fbtft/fb_seps525.c
new file mode 100644
index 000000000000..05882e2cde7f
--- /dev/null
+++ b/drivers/staging/fbtft/fb_seps525.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FB driver for the NHD-1.69-160128UGC3 (Newhaven Display International, Inc.)
+ * using the SEPS525 (Syncoam) LCD Controller
+ *
+ * Copyright (C) 2016 Analog Devices Inc.
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include "fbtft.h"
+
+#define DRVNAME "fb_seps525"
+#define WIDTH 160
+#define HEIGHT 128
+
+#define SEPS525_INDEX 0x00
+#define SEPS525_STATUS_RD 0x01
+#define SEPS525_OSC_CTL 0x02
+#define SEPS525_IREF 0x80
+#define SEPS525_CLOCK_DIV 0x03
+#define SEPS525_REDUCE_CURRENT 0x04
+#define SEPS525_SOFT_RST 0x05
+#define SEPS525_DISP_ONOFF 0x06
+#define SEPS525_PRECHARGE_TIME_R 0x08
+#define SEPS525_PRECHARGE_TIME_G 0x09
+#define SEPS525_PRECHARGE_TIME_B 0x0A
+#define SEPS525_PRECHARGE_CURRENT_R 0x0B
+#define SEPS525_PRECHARGE_CURRENT_G 0x0C
+#define SEPS525_PRECHARGE_CURRENT_B 0x0D
+#define SEPS525_DRIVING_CURRENT_R 0x10
+#define SEPS525_DRIVING_CURRENT_G 0x11
+#define SEPS525_DRIVING_CURRENT_B 0x12
+#define SEPS525_DISPLAYMODE_SET 0x13
+#define SEPS525_RGBIF 0x14
+#define SEPS525_RGB_POL 0x15
+#define SEPS525_MEMORY_WRITEMODE 0x16
+#define SEPS525_MX1_ADDR 0x17
+#define SEPS525_MX2_ADDR 0x18
+#define SEPS525_MY1_ADDR 0x19
+#define SEPS525_MY2_ADDR 0x1A
+#define SEPS525_MEMORY_ACCESS_POINTER_X 0x20
+#define SEPS525_MEMORY_ACCESS_POINTER_Y 0x21
+#define SEPS525_DDRAM_DATA_ACCESS_PORT 0x22
+#define SEPS525_GRAY_SCALE_TABLE_INDEX 0x50
+#define SEPS525_GRAY_SCALE_TABLE_DATA 0x51
+#define SEPS525_DUTY 0x28
+#define SEPS525_DSL 0x29
+#define SEPS525_D1_DDRAM_FAC 0x2E
+#define SEPS525_D1_DDRAM_FAR 0x2F
+#define SEPS525_D2_DDRAM_SAC 0x31
+#define SEPS525_D2_DDRAM_SAR 0x32
+#define SEPS525_SCR1_FX1 0x33
+#define SEPS525_SCR1_FX2 0x34
+#define SEPS525_SCR1_FY1 0x35
+#define SEPS525_SCR1_FY2 0x36
+#define SEPS525_SCR2_SX1 0x37
+#define SEPS525_SCR2_SX2 0x38
+#define SEPS525_SCR2_SY1 0x39
+#define SEPS525_SCR2_SY2 0x3A
+#define SEPS525_SCREEN_SAVER_CONTEROL 0x3B
+#define SEPS525_SS_SLEEP_TIMER 0x3C
+#define SEPS525_SCREEN_SAVER_MODE 0x3D
+#define SEPS525_SS_SCR1_FU 0x3E
+#define SEPS525_SS_SCR1_MXY 0x3F
+#define SEPS525_SS_SCR2_FU 0x40
+#define SEPS525_SS_SCR2_MXY 0x41
+#define SEPS525_MOVING_DIRECTION 0x42
+#define SEPS525_SS_SCR2_SX1 0x47
+#define SEPS525_SS_SCR2_SX2 0x48
+#define SEPS525_SS_SCR2_SY1 0x49
+#define SEPS525_SS_SCR2_SY2 0x4A
+
+/* SEPS525_DISPLAYMODE_SET */
+#define MODE_SWAP_BGR BIT(7)
+#define MODE_SM BIT(6)
+#define MODE_RD BIT(5)
+#define MODE_CD BIT(4)
+
+#define seps525_use_window 0 /* FBTFT doesn't really use it today */
+
+/* Init sequence taken from: Arduino Library for the Adafruit 2.2" display */
+static int init_display(struct fbtft_par *par)
+{
+ par->fbtftops.reset(par);
+
+ usleep_range(1000, 5000);
+
+ /* Disable Oscillator Power Down */
+ write_reg(par, SEPS525_REDUCE_CURRENT, 0x03);
+ usleep_range(1000, 5000);
+ /* Set Normal Driving Current */
+ write_reg(par, SEPS525_REDUCE_CURRENT, 0x00);
+ usleep_range(1000, 5000);
+
+ write_reg(par, SEPS525_SCREEN_SAVER_CONTEROL, 0x00);
+ /* Set EXPORT1 Pin at Internal Clock */
+ write_reg(par, SEPS525_OSC_CTL, 0x01);
+ /* Set Clock as 120 Frames/Sec */
+ write_reg(par, SEPS525_CLOCK_DIV, 0x90);
+ /* Set Reference Voltage Controlled by External Resister */
+ write_reg(par, SEPS525_IREF, 0x01);
+
+ /* precharge time R G B */
+ write_reg(par, SEPS525_PRECHARGE_TIME_R, 0x04);
+ write_reg(par, SEPS525_PRECHARGE_TIME_G, 0x05);
+ write_reg(par, SEPS525_PRECHARGE_TIME_B, 0x05);
+
+ /* precharge current R G B (uA) */
+ write_reg(par, SEPS525_PRECHARGE_CURRENT_R, 0x9D);
+ write_reg(par, SEPS525_PRECHARGE_CURRENT_G, 0x8C);
+ write_reg(par, SEPS525_PRECHARGE_CURRENT_B, 0x57);
+
+ /* driving current R G B (uA) */
+ write_reg(par, SEPS525_DRIVING_CURRENT_R, 0x56);
+ write_reg(par, SEPS525_DRIVING_CURRENT_G, 0x4D);
+ write_reg(par, SEPS525_DRIVING_CURRENT_B, 0x46);
+ /* Set Color Sequence */
+ write_reg(par, SEPS525_DISPLAYMODE_SET, 0xA0);
+ write_reg(par, SEPS525_RGBIF, 0x01); /* Set MCU Interface Mode */
+ /* Set Memory Write Mode */
+ write_reg(par, SEPS525_MEMORY_WRITEMODE, 0x66);
+ write_reg(par, SEPS525_DUTY, 0x7F); /* 1/128 Duty (0x0F~0x7F) */
+ /* Set Mapping RAM Display Start Line (0x00~0x7F) */
+ write_reg(par, SEPS525_DSL, 0x00);
+ write_reg(par, SEPS525_DISP_ONOFF, 0x01); /* Display On (0x00/0x01) */
+ /* Set All Internal Register Value as Normal Mode */
+ write_reg(par, SEPS525_SOFT_RST, 0x00);
+ /* Set RGB Interface Polarity as Active Low */
+ write_reg(par, SEPS525_RGB_POL, 0x00);
+
+ write_reg(par, SEPS525_DDRAM_DATA_ACCESS_PORT);
+
+ return 0;
+}
+
+static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
+{
+ if (seps525_use_window) {
+ /* Set Window Xs,Ys Xe,Ye*/
+ write_reg(par, SEPS525_MX1_ADDR, xs);
+ write_reg(par, SEPS525_MX2_ADDR, xe);
+ write_reg(par, SEPS525_MY1_ADDR, ys);
+ write_reg(par, SEPS525_MY2_ADDR, ye);
+ }
+ /* start position X,Y */
+ write_reg(par, SEPS525_MEMORY_ACCESS_POINTER_X, xs);
+ write_reg(par, SEPS525_MEMORY_ACCESS_POINTER_Y, ys);
+
+ write_reg(par, SEPS525_DDRAM_DATA_ACCESS_PORT);
+}
+
+static int set_var(struct fbtft_par *par)
+{
+ u8 val;
+
+ switch (par->info->var.rotate) {
+ case 0:
+ val = 0;
+ break;
+ case 180:
+ val = MODE_RD | MODE_CD;
+ break;
+ case 90:
+ case 270:
+
+ default:
+ return -EINVAL;
+ }
+ /* Memory Access Control */
+ write_reg(par, SEPS525_DISPLAYMODE_SET, val |
+ (par->bgr ? MODE_SWAP_BGR : 0));
+
+ write_reg(par, SEPS525_DDRAM_DATA_ACCESS_PORT);
+
+ return 0;
+}
+
+static struct fbtft_display display = {
+ .regwidth = 8,
+ .width = WIDTH,
+ .height = HEIGHT,
+ .fbtftops = {
+ .init_display = init_display,
+ .set_addr_win = set_addr_win,
+ .set_var = set_var,
+ },
+};
+
+FBTFT_REGISTER_DRIVER(DRVNAME, "syncoam,seps525", &display);
+
+MODULE_ALIAS("spi:" DRVNAME);
+MODULE_ALIAS("platform:" DRVNAME);
+MODULE_ALIAS("spi:seps525");
+MODULE_ALIAS("platform:seps525");
+
+MODULE_DESCRIPTION("FB driver for the SEPS525 LCD Controller");
+MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/fbtft/fb_uc1611.c b/drivers/staging/fbtft/fb_uc1611.c
index 65681d0fe200..e763205e9e4f 100644
--- a/drivers/staging/fbtft/fb_uc1611.c
+++ b/drivers/staging/fbtft/fb_uc1611.c
@@ -91,7 +91,7 @@ static int init_display(struct fbtft_par *par)
write_reg(par, 0x2C | (pump & 0x03));
/* Set inverse display */
- write_reg(par, 0xA6 | (0x01 & 0x01));
+ write_reg(par, 0xA6 | 0x01);
/* Set 4-bit grayscale mode */
write_reg(par, 0xD0 | (0x02 & 0x03));
@@ -157,8 +157,8 @@ static int set_var(struct fbtft_par *par)
/* Set RAM address control */
write_reg(par, 0x88
| (0x0 & 0x1) << 2 /* Increment positively */
- | (0x1 & 0x1) << 1 /* Increment page first */
- | (0x1 & 0x1)); /* Wrap around (default) */
+ | (0x1 << 1) /* Increment page first */
+ | 0x1); /* Wrap around (default) */
/* Set LCD mapping */
write_reg(par, 0xC0
@@ -171,11 +171,11 @@ static int set_var(struct fbtft_par *par)
write_reg(par, 0x88
| (0x0 & 0x1) << 2 /* Increment positively */
| (0x0 & 0x1) << 1 /* Increment column first */
- | (0x1 & 0x1)); /* Wrap around (default) */
+ | 0x1); /* Wrap around (default) */
/* Set LCD mapping */
write_reg(par, 0xC0
- | (0x1 & 0x1) << 2 /* Mirror Y ON */
+ | (0x1 << 2) /* Mirror Y ON */
| (0x0 & 0x1) << 1 /* Mirror X OFF */
| (0x0 & 0x1)); /* MS nibble last (default) */
break;
@@ -183,13 +183,13 @@ static int set_var(struct fbtft_par *par)
/* Set RAM address control */
write_reg(par, 0x88
| (0x0 & 0x1) << 2 /* Increment positively */
- | (0x1 & 0x1) << 1 /* Increment page first */
- | (0x1 & 0x1)); /* Wrap around (default) */
+ | (0x1 << 1) /* Increment page first */
+ | 0x1); /* Wrap around (default) */
/* Set LCD mapping */
write_reg(par, 0xC0
- | (0x1 & 0x1) << 2 /* Mirror Y ON */
- | (0x1 & 0x1) << 1 /* Mirror X ON */
+ | (0x1 << 2) /* Mirror Y ON */
+ | (0x1 << 1) /* Mirror X ON */
| (0x0 & 0x1)); /* MS nibble last (default) */
break;
default:
@@ -197,12 +197,12 @@ static int set_var(struct fbtft_par *par)
write_reg(par, 0x88
| (0x0 & 0x1) << 2 /* Increment positively */
| (0x0 & 0x1) << 1 /* Increment column first */
- | (0x1 & 0x1)); /* Wrap around (default) */
+ | 0x1); /* Wrap around (default) */
/* Set LCD mapping */
write_reg(par, 0xC0
| (0x0 & 0x1) << 2 /* Mirror Y OFF */
- | (0x1 & 0x1) << 1 /* Mirror X ON */
+ | (0x1 << 1) /* Mirror X ON */
| (0x0 & 0x1)); /* MS nibble last (default) */
break;
}
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index a0a67aa517f0..63d36f21eb98 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -317,7 +317,7 @@ static void fbtft_mkdirty(struct fb_info *info, int y, int height)
/* special case, needed ? */
if (y == -1) {
y = 0;
- height = info->var.yres - 1;
+ height = info->var.yres;
}
/* Mark display lines/area as dirty */
diff --git a/drivers/staging/fieldbus/anybuss/anybuss-client.h b/drivers/staging/fieldbus/anybuss/anybuss-client.h
index 0c4b6a1ffe10..8ee1f1baccf1 100644
--- a/drivers/staging/fieldbus/anybuss/anybuss-client.h
+++ b/drivers/staging/fieldbus/anybuss/anybuss-client.h
@@ -12,6 +12,9 @@
#include <linux/types.h>
#include <linux/poll.h>
+/* move to <linux/fieldbus_dev.h> when taking this out of staging */
+#include "../fieldbus_dev.h"
+
struct anybuss_host;
struct anybuss_client {
@@ -61,12 +64,6 @@ anybuss_set_drvdata(struct anybuss_client *client, void *data)
int anybuss_set_power(struct anybuss_client *client, bool power_on);
-enum anybuss_offl_mode {
- AB_OFFL_MODE_CLEAR = 0,
- AB_OFFL_MODE_FREEZE,
- AB_OFFL_MODE_SET
-};
-
struct anybuss_memcfg {
u16 input_io;
u16 input_dpram;
@@ -76,7 +73,7 @@ struct anybuss_memcfg {
u16 output_dpram;
u16 output_total;
- enum anybuss_offl_mode offl_mode;
+ enum fieldbus_dev_offl_mode offl_mode;
};
int anybuss_start_init(struct anybuss_client *client,
diff --git a/drivers/staging/fieldbus/anybuss/arcx-anybus.c b/drivers/staging/fieldbus/anybuss/arcx-anybus.c
index 2ecffa42e561..5b8d0bae9ff3 100644
--- a/drivers/staging/fieldbus/anybuss/arcx-anybus.c
+++ b/drivers/staging/fieldbus/anybuss/arcx-anybus.c
@@ -127,12 +127,10 @@ static const struct regmap_config arcx_regmap_cfg = {
static struct regmap *create_parallel_regmap(struct platform_device *pdev,
int idx)
{
- struct resource *res;
void __iomem *base;
struct device *dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, idx + 1);
if (IS_ERR(base))
return ERR_CAST(base);
return devm_regmap_init_mmio(dev, base, &arcx_regmap_cfg);
@@ -230,7 +228,6 @@ static int controller_probe(struct platform_device *pdev)
struct regulator_config config = { };
struct regulator_dev *regulator;
int err, id;
- struct resource *res;
struct anybuss_host *host;
u8 status1, cap;
@@ -244,8 +241,7 @@ static int controller_probe(struct platform_device *pdev)
return PTR_ERR(cd->reset_gpiod);
/* CPLD control memory, sits at index 0 */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- cd->cpld_base = devm_ioremap_resource(dev, res);
+ cd->cpld_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cd->cpld_base)) {
dev_err(dev,
"failed to map cpld base address\n");
diff --git a/drivers/staging/fieldbus/anybuss/hms-profinet.c b/drivers/staging/fieldbus/anybuss/hms-profinet.c
index 5446843e35f4..31c43a0a5776 100644
--- a/drivers/staging/fieldbus/anybuss/hms-profinet.c
+++ b/drivers/staging/fieldbus/anybuss/hms-profinet.c
@@ -96,7 +96,7 @@ static int __profi_enable(struct profi_priv *priv)
.output_io = 220,
.output_dpram = PROFI_DPRAM_SIZE,
.output_total = PROFI_DPRAM_SIZE,
- .offl_mode = AB_OFFL_MODE_CLEAR,
+ .offl_mode = FIELDBUS_DEV_OFFL_MODE_CLEAR,
};
/*
diff --git a/drivers/staging/fieldbus/anybuss/host.c b/drivers/staging/fieldbus/anybuss/host.c
index f69dc4930457..549cb7d51af8 100644
--- a/drivers/staging/fieldbus/anybuss/host.c
+++ b/drivers/staging/fieldbus/anybuss/host.c
@@ -1022,13 +1022,13 @@ int anybuss_start_init(struct anybuss_client *client,
};
switch (cfg->offl_mode) {
- case AB_OFFL_MODE_CLEAR:
+ case FIELDBUS_DEV_OFFL_MODE_CLEAR:
op_mode = 0;
break;
- case AB_OFFL_MODE_FREEZE:
+ case FIELDBUS_DEV_OFFL_MODE_FREEZE:
op_mode = OP_MODE_FBFC;
break;
- case AB_OFFL_MODE_SET:
+ case FIELDBUS_DEV_OFFL_MODE_SET:
op_mode = OP_MODE_FBS;
break;
default:
diff --git a/drivers/staging/fieldbus/dev_core.c b/drivers/staging/fieldbus/dev_core.c
index f6f5b92ba914..1ba0234cc60d 100644
--- a/drivers/staging/fieldbus/dev_core.c
+++ b/drivers/staging/fieldbus/dev_core.c
@@ -23,9 +23,6 @@ static dev_t fieldbus_devt;
static DEFINE_IDA(fieldbus_ida);
static DEFINE_MUTEX(fieldbus_mtx);
-static const char ctrl_enabled[] = "enabled";
-static const char ctrl_disabled[] = "disabled";
-
static ssize_t online_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
diff --git a/drivers/staging/fieldbus/fieldbus_dev.h b/drivers/staging/fieldbus/fieldbus_dev.h
index a10fc3b446dc..301dca3b8d71 100644
--- a/drivers/staging/fieldbus/fieldbus_dev.h
+++ b/drivers/staging/fieldbus/fieldbus_dev.h
@@ -15,6 +15,12 @@ enum fieldbus_dev_type {
FIELDBUS_DEV_TYPE_PROFINET,
};
+enum fieldbus_dev_offl_mode {
+ FIELDBUS_DEV_OFFL_MODE_CLEAR = 0,
+ FIELDBUS_DEV_OFFL_MODE_FREEZE,
+ FIELDBUS_DEV_OFFL_MODE_SET
+};
+
/**
* struct fieldbus_dev - Fieldbus device
* @read_area: [DRIVER] function to read the process data area of the
diff --git a/drivers/staging/gasket/gasket_ioctl.c b/drivers/staging/gasket/gasket_ioctl.c
index 240f9bb10b71..e3047d36d8db 100644
--- a/drivers/staging/gasket/gasket_ioctl.c
+++ b/drivers/staging/gasket/gasket_ioctl.c
@@ -34,8 +34,8 @@ static int gasket_set_event_fd(struct gasket_dev *gasket_dev,
trace_gasket_ioctl_eventfd_data(die.interrupt, die.event_fd);
- return gasket_interrupt_set_eventfd(
- gasket_dev->interrupt_data, die.interrupt, die.event_fd);
+ return gasket_interrupt_set_eventfd(gasket_dev->interrupt_data,
+ die.interrupt, die.event_fd);
}
/* Read the size of the page table. */
@@ -54,9 +54,9 @@ static int gasket_read_page_table_size(struct gasket_dev *gasket_dev,
ibuf.size = gasket_page_table_num_entries(
gasket_dev->page_table[ibuf.page_table_index]);
- trace_gasket_ioctl_page_table_data(
- ibuf.page_table_index, ibuf.size, ibuf.host_address,
- ibuf.device_address);
+ trace_gasket_ioctl_page_table_data(ibuf.page_table_index, ibuf.size,
+ ibuf.host_address,
+ ibuf.device_address);
if (copy_to_user(argp, &ibuf, sizeof(ibuf)))
return -EFAULT;
@@ -101,9 +101,9 @@ static int gasket_partition_page_table(struct gasket_dev *gasket_dev,
if (copy_from_user(&ibuf, argp, sizeof(struct gasket_page_table_ioctl)))
return -EFAULT;
- trace_gasket_ioctl_page_table_data(
- ibuf.page_table_index, ibuf.size, ibuf.host_address,
- ibuf.device_address);
+ trace_gasket_ioctl_page_table_data(ibuf.page_table_index, ibuf.size,
+ ibuf.host_address,
+ ibuf.device_address);
if (ibuf.page_table_index >= gasket_dev->num_page_tables)
return -EFAULT;
diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c
index 82099db4bf0c..a480409090c0 100644
--- a/drivers/staging/iio/accel/adis16240.c
+++ b/drivers/staging/iio/accel/adis16240.c
@@ -7,7 +7,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index e6b660489165..bf3e2a9cc07f 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -155,6 +155,11 @@
* The DOUT/RDY output must also be wired to an interrupt capable GPIO.
*/
+enum {
+ AD7192_SYSCALIB_ZERO_SCALE,
+ AD7192_SYSCALIB_FULL_SCALE,
+};
+
struct ad7192_state {
struct regulator *avdd;
struct regulator *dvdd;
@@ -169,10 +174,80 @@ struct ad7192_state {
u8 devid;
u8 clock_sel;
struct mutex lock; /* protect sensor state */
+ u8 syscalib_mode[8];
struct ad_sigma_delta sd;
};
+static const char * const ad7192_syscalib_modes[] = {
+ [AD7192_SYSCALIB_ZERO_SCALE] = "zero_scale",
+ [AD7192_SYSCALIB_FULL_SCALE] = "full_scale",
+};
+
+static int ad7192_set_syscalib_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ unsigned int mode)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+
+ st->syscalib_mode[chan->channel] = mode;
+
+ return 0;
+}
+
+static int ad7192_get_syscalib_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+
+ return st->syscalib_mode[chan->channel];
+}
+
+static ssize_t ad7192_write_syscalib(struct iio_dev *indio_dev,
+ uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+ bool sys_calib;
+ int ret, temp;
+
+ ret = strtobool(buf, &sys_calib);
+ if (ret)
+ return ret;
+
+ temp = st->syscalib_mode[chan->channel];
+ if (sys_calib) {
+ if (temp == AD7192_SYSCALIB_ZERO_SCALE)
+ ret = ad_sd_calibrate(&st->sd, AD7192_MODE_CAL_SYS_ZERO,
+ chan->address);
+ else
+ ret = ad_sd_calibrate(&st->sd, AD7192_MODE_CAL_SYS_FULL,
+ chan->address);
+ }
+
+ return ret ? ret : len;
+}
+
+static const struct iio_enum ad7192_syscalib_mode_enum = {
+ .items = ad7192_syscalib_modes,
+ .num_items = ARRAY_SIZE(ad7192_syscalib_modes),
+ .set = ad7192_set_syscalib_mode,
+ .get = ad7192_get_syscalib_mode
+};
+
+static const struct iio_chan_spec_ext_info ad7192_calibsys_ext_info[] = {
+ {
+ .name = "sys_calibration",
+ .write = ad7192_write_syscalib,
+ .shared = IIO_SEPARATE,
+ },
+ IIO_ENUM("sys_calibration_mode", IIO_SEPARATE,
+ &ad7192_syscalib_mode_enum),
+ IIO_ENUM_AVAILABLE("sys_calibration_mode", &ad7192_syscalib_mode_enum),
+ {}
+};
+
static struct ad7192_state *ad_sigma_delta_to_ad7192(struct ad_sigma_delta *sd)
{
return container_of(sd, struct ad7192_state, sd);
@@ -770,9 +845,11 @@ static int ad7192_channels_config(struct iio_dev *indio_dev)
*chan = channels[i];
chan->info_mask_shared_by_all |=
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY);
- if (chan->type != IIO_TEMP)
+ if (chan->type != IIO_TEMP) {
chan->info_mask_shared_by_type_available |=
BIT(IIO_CHAN_INFO_SCALE);
+ chan->ext_info = ad7192_calibsys_ext_info;
+ }
chan++;
}
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index 038d6732c3fd..23026978a5a5 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -417,6 +417,10 @@ static int ad9834_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
mutex_init(&st->lock);
st->mclk = devm_clk_get(&spi->dev, NULL);
+ if (IS_ERR(st->mclk)) {
+ ret = PTR_ERR(st->mclk);
+ goto error_disable_reg;
+ }
ret = clk_prepare_enable(st->mclk);
if (ret) {
diff --git a/drivers/staging/isdn/avm/b1.c b/drivers/staging/isdn/avm/b1.c
index 40ca1e8fa09f..32ec8cf31fd0 100644
--- a/drivers/staging/isdn/avm/b1.c
+++ b/drivers/staging/isdn/avm/b1.c
@@ -261,9 +261,10 @@ int b1_loaded(avmcard *card)
b1_put_byte(base, SEND_POLL);
for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
if (b1_rx_full(base)) {
- if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
+ ans = b1_get_byte(base);
+ if (ans == RECEIVE_POLL)
return 1;
- }
+
printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n",
card->name, ans);
return 0;
@@ -284,8 +285,9 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
int retval;
b1_reset(port);
+ retval = b1_load_t4file(card, &data->firmware);
- if ((retval = b1_load_t4file(card, &data->firmware))) {
+ if (retval) {
b1_reset(port);
printk(KERN_ERR "%s: failed to load t4file!!\n",
card->name);
@@ -295,7 +297,8 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
b1_disable_irq(port);
if (data->configuration.len > 0 && data->configuration.data) {
- if ((retval = b1_load_config(card, &data->configuration))) {
+ retval = b1_load_config(card, &data->configuration);
+ if (retval) {
b1_reset(port);
printk(KERN_ERR "%s: failed to load config!!\n",
card->name);
@@ -525,7 +528,9 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr)
MsgLen = 30;
CAPIMSG_SETLEN(card->msgbuf, 30);
}
- if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) {
+
+ skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC);
+ if (!skb) {
printk(KERN_ERR "%s: incoming packet dropped\n",
card->name);
} else {
@@ -539,7 +544,9 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr)
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = b1_get_slice(card->port, card->msgbuf);
- if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
+ skb = alloc_skb(MsgLen, GFP_ATOMIC);
+
+ if (!skb) {
printk(KERN_ERR "%s: incoming packet dropped\n",
card->name);
spin_unlock_irqrestore(&card->lock, flags);
@@ -663,11 +670,17 @@ int b1_proc_show(struct seq_file *m, void *v)
seq_printf(m, "%-16s %s\n", "type", s);
if (card->cardtype == avm_t1isa)
seq_printf(m, "%-16s %d\n", "cardnr", card->cardnr);
- if ((s = cinfo->version[VER_DRIVER]) != NULL)
+
+ s = cinfo->version[VER_DRIVER];
+ if (s)
seq_printf(m, "%-16s %s\n", "ver_driver", s);
- if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
+
+ s = cinfo->version[VER_CARDTYPE];
+ if (s)
seq_printf(m, "%-16s %s\n", "ver_cardtype", s);
- if ((s = cinfo->version[VER_SERIAL]) != NULL)
+
+ s = cinfo->version[VER_SERIAL];
+ if (s)
seq_printf(m, "%-16s %s\n", "ver_serial", s);
if (card->cardtype != avm_m1) {
@@ -784,13 +797,15 @@ static int __init b1_init(void)
char *p;
char rev[32];
- if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ p = strchr(revision, ':');
+ if (p && p[1]) {
strlcpy(rev, p + 2, 32);
- if ((p = strchr(rev, '$')) != NULL && p > rev)
+ p = strchr(rev, '$');
+ if (p && p > rev)
*(p - 1) = 0;
- } else
+ } else {
strcpy(rev, "1.0");
-
+ }
printk(KERN_INFO "b1: revision %s\n", rev);
return 0;
diff --git a/drivers/staging/isdn/gigaset/interface.c b/drivers/staging/isdn/gigaset/interface.c
index 17fa615a8c68..9ddadd07e707 100644
--- a/drivers/staging/isdn/gigaset/interface.c
+++ b/drivers/staging/isdn/gigaset/interface.c
@@ -518,7 +518,7 @@ void gigaset_if_init(struct cardstate *cs)
if (!IS_ERR(cs->tty_dev))
dev_set_drvdata(cs->tty_dev, cs);
else {
- pr_warning("could not register device to the tty subsystem\n");
+ pr_warn("could not register device to the tty subsystem\n");
cs->tty_dev = NULL;
}
mutex_unlock(&cs->mutex);
diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c
index bc02534d8dc3..5460bf973c9c 100644
--- a/drivers/staging/kpc2000/kpc2000_i2c.c
+++ b/drivers/staging/kpc2000/kpc2000_i2c.c
@@ -99,7 +99,8 @@ struct i2c_device {
#define SMBHSTSTS_INTR 0x02
#define SMBHSTSTS_HOST_BUSY 0x01
-#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTR)
+#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \
+ SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTR)
/* Older devices have their ID defined in <linux/pci_ids.h> */
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
@@ -136,17 +137,18 @@ static int i801_check_pre(struct i2c_device *priv)
status = inb_p(SMBHSTSTS(priv));
if (status & SMBHSTSTS_HOST_BUSY) {
- dev_err(&priv->adapter.dev, "SMBus is busy, can't use it! (status=%x)\n", status);
+ dev_err(&priv->adapter.dev,
+ "SMBus is busy, can't use it! (status=%x)\n", status);
return -EBUSY;
}
status &= STATUS_FLAGS;
if (status) {
- //dev_dbg(&priv->adapter.dev, "Clearing status flags (%02x)\n", status);
outb_p(status, SMBHSTSTS(priv));
status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
if (status) {
- dev_err(&priv->adapter.dev, "Failed clearing status flags (%02x)\n", status);
+ dev_err(&priv->adapter.dev,
+ "Failed clearing status flags (%02x)\n", status);
return -EBUSY;
}
}
@@ -162,15 +164,20 @@ static int i801_check_post(struct i2c_device *priv, int status, int timeout)
if (timeout) {
dev_err(&priv->adapter.dev, "Transaction timeout\n");
/* try to stop the current command */
- dev_dbg(&priv->adapter.dev, "Terminating the current operation\n");
- outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, SMBHSTCNT(priv));
+ dev_dbg(&priv->adapter.dev,
+ "Terminating the current operation\n");
+ outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
+ SMBHSTCNT(priv));
usleep_range(1000, 2000);
- outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), SMBHSTCNT(priv));
+ outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
+ SMBHSTCNT(priv));
/* Check if it worked */
status = inb_p(SMBHSTSTS(priv));
- if ((status & SMBHSTSTS_HOST_BUSY) || !(status & SMBHSTSTS_FAILED))
- dev_err(&priv->adapter.dev, "Failed terminating the transaction\n");
+ if ((status & SMBHSTSTS_HOST_BUSY) ||
+ !(status & SMBHSTSTS_FAILED))
+ dev_err(&priv->adapter.dev,
+ "Failed terminating the transaction\n");
outb_p(STATUS_FLAGS, SMBHSTSTS(priv));
return -ETIMEDOUT;
}
@@ -244,7 +251,9 @@ static void i801_wait_hwpec(struct i2c_device *priv)
outb_p(status, SMBHSTSTS(priv));
}
-static int i801_block_transaction_by_block(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int hwpec)
+static int i801_block_transaction_by_block(struct i2c_device *priv,
+ union i2c_smbus_data *data,
+ char read_write, int hwpec)
{
int i, len;
int status;
@@ -259,7 +268,8 @@ static int i801_block_transaction_by_block(struct i2c_device *priv, union i2c_sm
outb_p(data->block[i + 1], SMBBLKDAT(priv));
}
- status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 | I801_PEC_EN * hwpec);
+ status = i801_transaction(priv,
+ I801_BLOCK_DATA | ENABLE_INT9 | I801_PEC_EN * hwpec);
if (status)
return status;
@@ -275,7 +285,10 @@ static int i801_block_transaction_by_block(struct i2c_device *priv, union i2c_sm
return 0;
}
-static int i801_block_transaction_byte_by_byte(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int command, int hwpec)
+static int i801_block_transaction_byte_by_byte(struct i2c_device *priv,
+ union i2c_smbus_data *data,
+ char read_write, int command,
+ int hwpec)
{
int i, len;
int smbcmd;
@@ -301,7 +314,8 @@ static int i801_block_transaction_byte_by_byte(struct i2c_device *priv, union i2
else
smbcmd = I801_BLOCK_LAST;
} else {
- if (command == I2C_SMBUS_I2C_BLOCK_DATA && read_write == I2C_SMBUS_READ)
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
+ read_write == I2C_SMBUS_READ)
smbcmd = I801_I2C_BLOCK_DATA;
else
smbcmd = I801_BLOCK_DATA;
@@ -309,25 +323,33 @@ static int i801_block_transaction_byte_by_byte(struct i2c_device *priv, union i2
outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv));
if (i == 1)
- outb_p(inb(SMBHSTCNT(priv)) | I801_START, SMBHSTCNT(priv));
+ outb_p(inb(SMBHSTCNT(priv)) | I801_START,
+ SMBHSTCNT(priv));
/* We will always wait for a fraction of a second! */
timeout = 0;
do {
usleep_range(250, 500);
status = inb_p(SMBHSTSTS(priv));
- } while ((!(status & SMBHSTSTS_BYTE_DONE)) && (timeout++ < MAX_RETRIES));
+ } while (!(status & SMBHSTSTS_BYTE_DONE) &&
+ (timeout++ < MAX_RETRIES));
result = i801_check_post(priv, status, timeout > MAX_RETRIES);
if (result < 0)
return result;
- if (i == 1 && read_write == I2C_SMBUS_READ && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (i == 1 && read_write == I2C_SMBUS_READ &&
+ command != I2C_SMBUS_I2C_BLOCK_DATA) {
len = inb_p(SMBHSTDAT0(priv));
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
- dev_err(&priv->adapter.dev, "Illegal SMBus block read size %d\n", len);
+ dev_err(&priv->adapter.dev,
+ "Illegal SMBus block read size %d\n",
+ len);
/* Recover */
- while (inb_p(SMBHSTSTS(priv)) & SMBHSTSTS_HOST_BUSY)
- outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
- outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
+ while (inb_p(SMBHSTSTS(priv)) &
+ SMBHSTSTS_HOST_BUSY)
+ outb_p(SMBHSTSTS_BYTE_DONE,
+ SMBHSTSTS(priv));
+ outb_p(SMBHSTSTS_INTR,
+ SMBHSTSTS(priv));
return -EPROTO;
}
data->block[0] = len;
@@ -354,7 +376,9 @@ static int i801_set_block_buffer_mode(struct i2c_device *priv)
}
/* Block transaction function */
-static int i801_block_transaction(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int command, int hwpec)
+static int i801_block_transaction(struct i2c_device *priv,
+ union i2c_smbus_data *data, char read_write,
+ int command, int hwpec)
{
int result = 0;
//unsigned char hostc;
@@ -366,12 +390,14 @@ static int i801_block_transaction(struct i2c_device *priv, union i2c_smbus_data
//pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
//pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN);
} else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
- dev_err(&priv->adapter.dev, "I2C block read is unsupported!\n");
+ dev_err(&priv->adapter.dev,
+ "I2C block read is unsupported!\n");
return -EOPNOTSUPP;
}
}
- if (read_write == I2C_SMBUS_WRITE || command == I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (read_write == I2C_SMBUS_WRITE ||
+ command == I2C_SMBUS_I2C_BLOCK_DATA) {
if (data->block[0] < 1)
data->block[0] = 1;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
@@ -384,13 +410,21 @@ static int i801_block_transaction(struct i2c_device *priv, union i2c_smbus_data
* SMBus (not I2C) block transactions, even though the datasheet
* doesn't mention this limitation.
*/
- if ((priv->features & FEATURE_BLOCK_BUFFER) && command != I2C_SMBUS_I2C_BLOCK_DATA && i801_set_block_buffer_mode(priv) == 0)
- result = i801_block_transaction_by_block(priv, data, read_write, hwpec);
- else
- result = i801_block_transaction_byte_by_byte(priv, data, read_write, command, hwpec);
+ if ((priv->features & FEATURE_BLOCK_BUFFER) &&
+ command != I2C_SMBUS_I2C_BLOCK_DATA &&
+ i801_set_block_buffer_mode(priv) == 0) {
+ result = i801_block_transaction_by_block(priv, data,
+ read_write, hwpec);
+ } else {
+ result = i801_block_transaction_byte_by_byte(priv, data,
+ read_write,
+ command, hwpec);
+ }
+
if (result == 0 && hwpec)
i801_wait_hwpec(priv);
- if (command == I2C_SMBUS_I2C_BLOCK_DATA && read_write == I2C_SMBUS_WRITE) {
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
+ read_write == I2C_SMBUS_WRITE) {
/* restore saved configuration register value */
//TODO: Figure out the right thing to do here...
//pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
@@ -399,32 +433,41 @@ static int i801_block_transaction(struct i2c_device *priv, union i2c_smbus_data
}
/* Return negative errno on error. */
-static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data)
+static s32 i801_access(struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
{
int hwpec;
int block = 0;
int ret, xact = 0;
struct i2c_device *priv = i2c_get_adapdata(adap);
- hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA;
+ hwpec = (priv->features & FEATURE_SMBUS_PEC) &&
+ (flags & I2C_CLIENT_PEC) &&
+ size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA;
switch (size) {
case I2C_SMBUS_QUICK:
dev_dbg(&priv->adapter.dev, " [acc] SMBUS_QUICK\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+
xact = I801_QUICK;
break;
case I2C_SMBUS_BYTE:
dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
if (read_write == I2C_SMBUS_WRITE)
outb_p(command, SMBHSTCMD(priv));
xact = I801_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE_DATA\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+
outb_p(command, SMBHSTCMD(priv));
if (read_write == I2C_SMBUS_WRITE)
outb_p(data->byte, SMBHSTDAT0(priv));
@@ -432,7 +475,9 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
break;
case I2C_SMBUS_WORD_DATA:
dev_dbg(&priv->adapter.dev, " [acc] SMBUS_WORD_DATA\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+
outb_p(command, SMBHSTCMD(priv));
if (read_write == I2C_SMBUS_WRITE) {
outb_p(data->word & 0xff, SMBHSTDAT0(priv));
@@ -442,7 +487,9 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
break;
case I2C_SMBUS_BLOCK_DATA:
dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BLOCK_DATA\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+
outb_p(command, SMBHSTCMD(priv));
block = 1;
break;
@@ -463,7 +510,8 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
block = 1;
break;
default:
- dev_dbg(&priv->adapter.dev, " [acc] Unsupported transaction %d\n", size);
+ dev_dbg(&priv->adapter.dev,
+ " [acc] Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
}
@@ -472,13 +520,14 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
} else {
dev_dbg(&priv->adapter.dev, " [acc] hwpec: no\n");
- outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), SMBAUXCTL(priv));
+ outb_p(inb_p(SMBAUXCTL(priv)) &
+ (~SMBAUXCTL_CRC), SMBAUXCTL(priv));
}
if (block) {
- //ret = 0;
dev_dbg(&priv->adapter.dev, " [acc] block: yes\n");
- ret = i801_block_transaction(priv, data, read_write, size, hwpec);
+ ret = i801_block_transaction(priv, data, read_write, size,
+ hwpec);
} else {
dev_dbg(&priv->adapter.dev, " [acc] block: no\n");
ret = i801_transaction(priv, xact | ENABLE_INT9);
@@ -490,7 +539,8 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
*/
if (hwpec || block) {
dev_dbg(&priv->adapter.dev, " [acc] hwpec || block\n");
- outb_p(inb_p(SMBAUXCTL(priv)) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
+ outb_p(inb_p(SMBAUXCTL(priv)) & ~(SMBAUXCTL_CRC |
+ SMBAUXCTL_E32B), SMBAUXCTL(priv));
}
if (block) {
dev_dbg(&priv->adapter.dev, " [acc] block\n");
@@ -501,19 +551,22 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
return ret;
}
if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) {
- dev_dbg(&priv->adapter.dev, " [acc] I2C_SMBUS_WRITE || I801_QUICK -> ret 0\n");
+ dev_dbg(&priv->adapter.dev,
+ " [acc] I2C_SMBUS_WRITE || I801_QUICK -> ret 0\n");
return 0;
}
switch (xact & 0x7f) {
case I801_BYTE: /* Result put in SMBHSTDAT0 */
case I801_BYTE_DATA:
- dev_dbg(&priv->adapter.dev, " [acc] I801_BYTE or I801_BYTE_DATA\n");
+ dev_dbg(&priv->adapter.dev,
+ " [acc] I801_BYTE or I801_BYTE_DATA\n");
data->byte = inb_p(SMBHSTDAT0(priv));
break;
case I801_WORD_DATA:
dev_dbg(&priv->adapter.dev, " [acc] I801_WORD_DATA\n");
- data->word = inb_p(SMBHSTDAT0(priv)) + (inb_p(SMBHSTDAT1(priv)) << 8);
+ data->word = inb_p(SMBHSTDAT0(priv)) +
+ (inb_p(SMBHSTDAT1(priv)) << 8);
break;
}
return 0;
@@ -535,30 +588,47 @@ static u32 i801_func(struct i2c_adapter *adapter)
// http://lxr.free-electrons.com/source/include/uapi/linux/i2c.h#L85
u32 f =
- I2C_FUNC_I2C | /* 0x00000001 (I enabled this one) */
- !I2C_FUNC_10BIT_ADDR | /* 0x00000002 */
- !I2C_FUNC_PROTOCOL_MANGLING | /* 0x00000004 */
- ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | /* 0x00000008 */
- !I2C_FUNC_SMBUS_BLOCK_PROC_CALL | /* 0x00008000 */
- I2C_FUNC_SMBUS_QUICK | /* 0x00010000 */
- !I2C_FUNC_SMBUS_READ_BYTE | /* 0x00020000 */
- !I2C_FUNC_SMBUS_WRITE_BYTE | /* 0x00040000 */
- !I2C_FUNC_SMBUS_READ_BYTE_DATA | /* 0x00080000 */
- !I2C_FUNC_SMBUS_WRITE_BYTE_DATA | /* 0x00100000 */
- !I2C_FUNC_SMBUS_READ_WORD_DATA | /* 0x00200000 */
- !I2C_FUNC_SMBUS_WRITE_WORD_DATA | /* 0x00400000 */
- !I2C_FUNC_SMBUS_PROC_CALL | /* 0x00800000 */
- !I2C_FUNC_SMBUS_READ_BLOCK_DATA | /* 0x01000000 */
- !I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | /* 0x02000000 */
- ((priv->features & FEATURE_I2C_BLOCK_READ) ? I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) | /* 0x04000000 */
- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | /* 0x08000000 */
+ I2C_FUNC_I2C | /* 0x00000001(I enabled this
+ * one)
+ */
+ !I2C_FUNC_10BIT_ADDR | /* 0x00000002 */
+ !I2C_FUNC_PROTOCOL_MANGLING | /* 0x00000004 */
+ ((priv->features & FEATURE_SMBUS_PEC) ?
+ I2C_FUNC_SMBUS_PEC : 0) | /* 0x00000008 */
+ !I2C_FUNC_SMBUS_BLOCK_PROC_CALL | /* 0x00008000 */
+ I2C_FUNC_SMBUS_QUICK | /* 0x00010000 */
+ !I2C_FUNC_SMBUS_READ_BYTE | /* 0x00020000 */
+ !I2C_FUNC_SMBUS_WRITE_BYTE | /* 0x00040000 */
+ !I2C_FUNC_SMBUS_READ_BYTE_DATA | /* 0x00080000 */
+ !I2C_FUNC_SMBUS_WRITE_BYTE_DATA | /* 0x00100000 */
+ !I2C_FUNC_SMBUS_READ_WORD_DATA | /* 0x00200000 */
+ !I2C_FUNC_SMBUS_WRITE_WORD_DATA | /* 0x00400000 */
+ !I2C_FUNC_SMBUS_PROC_CALL | /* 0x00800000 */
+ !I2C_FUNC_SMBUS_READ_BLOCK_DATA | /* 0x01000000 */
+ !I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | /* 0x02000000 */
+ ((priv->features & FEATURE_I2C_BLOCK_READ) ?
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) | /* 0x04000000 */
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | /* 0x08000000 */
I2C_FUNC_SMBUS_BYTE | /* _READ_BYTE _WRITE_BYTE */
- I2C_FUNC_SMBUS_BYTE_DATA | /* _READ_BYTE_DATA _WRITE_BYTE_DATA */
- I2C_FUNC_SMBUS_WORD_DATA | /* _READ_WORD_DATA _WRITE_WORD_DATA */
- I2C_FUNC_SMBUS_BLOCK_DATA | /* _READ_BLOCK_DATA _WRITE_BLOCK_DATA */
- !I2C_FUNC_SMBUS_I2C_BLOCK | /* _READ_I2C_BLOCK _WRITE_I2C_BLOCK */
- !I2C_FUNC_SMBUS_EMUL; /* _QUICK _BYTE _BYTE_DATA _WORD_DATA _PROC_CALL _WRITE_BLOCK_DATA _I2C_BLOCK _PEC */
+ I2C_FUNC_SMBUS_BYTE_DATA | /* _READ_BYTE_DATA
+ * _WRITE_BYTE_DATA
+ */
+ I2C_FUNC_SMBUS_WORD_DATA | /* _READ_WORD_DATA
+ * _WRITE_WORD_DATA
+ */
+ I2C_FUNC_SMBUS_BLOCK_DATA | /* _READ_BLOCK_DATA
+ * _WRITE_BLOCK_DATA
+ */
+ !I2C_FUNC_SMBUS_I2C_BLOCK | /* _READ_I2C_BLOCK
+ * _WRITE_I2C_BLOCK
+ */
+ !I2C_FUNC_SMBUS_EMUL; /* _QUICK _BYTE
+ * _BYTE_DATA _WORD_DATA
+ * _PROC_CALL
+ * _WRITE_BLOCK_DATA
+ * _I2C_BLOCK _PEC
+ */
return f;
}
@@ -610,8 +680,8 @@ static int pi2c_probe(struct platform_device *pldev)
/* Retry up to 3 times on lost arbitration */
priv->adapter.retries = 3;
- //snprintf(priv->adapter.name, sizeof(priv->adapter.name), "Fake SMBus I801 adapter at %04lx", priv->smba);
- snprintf(priv->adapter.name, sizeof(priv->adapter.name), "Fake SMBus I801 adapter");
+ snprintf(priv->adapter.name, sizeof(priv->adapter.name),
+ "Fake SMBus I801 adapter");
err = i2c_add_adapter(&priv->adapter);
if (err) {
diff --git a/drivers/staging/kpc2000/kpc2000_spi.c b/drivers/staging/kpc2000/kpc2000_spi.c
index 3be33c450cab..8becf972af9c 100644
--- a/drivers/staging/kpc2000/kpc2000_spi.c
+++ b/drivers/staging/kpc2000/kpc2000_spi.c
@@ -50,6 +50,7 @@ static struct flash_platform_data p2kr0_spi0_pdata = {
.nr_parts = ARRAY_SIZE(p2kr0_spi0_parts),
.parts = p2kr0_spi0_parts,
};
+
static struct flash_platform_data p2kr0_spi1_pdata = {
.name = "SPI1",
.nr_parts = ARRAY_SIZE(p2kr0_spi1_parts),
@@ -162,14 +163,12 @@ union kp_spi_ffctrl {
kp_spi_read_reg(struct kp_spi_controller_state *cs, int idx)
{
u64 __iomem *addr = cs->base;
- u64 val;
addr += idx;
if ((idx == KP_SPI_REG_CONFIG) && (cs->conf_cache >= 0))
return cs->conf_cache;
- val = readq(addr);
- return val;
+ return readq(addr);
}
static inline void
@@ -227,8 +226,7 @@ kp_spi_txrx_pio(struct spi_device *spidev, struct spi_transfer *transfer)
kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, val);
processed++;
}
- }
- else if (rx) {
+ } else if (rx) {
for (i = 0 ; i < c ; i++) {
char test = 0;
@@ -315,19 +313,19 @@ kp_spi_transfer_one_message(struct spi_master *master, struct spi_message *m)
if (transfer->speed_hz > KP_SPI_CLK ||
(len && !(rx_buf || tx_buf))) {
dev_dbg(kpspi->dev, " transfer: %d Hz, %d %s%s, %d bpw\n",
- transfer->speed_hz,
- len,
- tx_buf ? "tx" : "",
- rx_buf ? "rx" : "",
- transfer->bits_per_word);
+ transfer->speed_hz,
+ len,
+ tx_buf ? "tx" : "",
+ rx_buf ? "rx" : "",
+ transfer->bits_per_word);
dev_dbg(kpspi->dev, " transfer -EINVAL\n");
return -EINVAL;
}
if (transfer->speed_hz &&
transfer->speed_hz < (KP_SPI_CLK >> 15)) {
dev_dbg(kpspi->dev, "speed_hz %d below minimum %d Hz\n",
- transfer->speed_hz,
- KP_SPI_CLK >> 15);
+ transfer->speed_hz,
+ KP_SPI_CLK >> 15);
dev_dbg(kpspi->dev, " speed_hz -EINVAL\n");
return -EINVAL;
}
@@ -478,7 +476,7 @@ kp_spi_probe(struct platform_device *pldev)
/* register the slave boards */
#define NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(table) \
for (i = 0 ; i < ARRAY_SIZE(table) ; i++) { \
- spi_new_device(master, &(table[i])); \
+ spi_new_device(master, &table[i]); \
}
switch ((drvdata->card_id & 0xFFFF0000) >> 16) {
diff --git a/drivers/staging/media/allegro-dvt/nal-h264.c b/drivers/staging/media/allegro-dvt/nal-h264.c
index 4e14b77851e1..bd48b8883572 100644
--- a/drivers/staging/media/allegro-dvt/nal-h264.c
+++ b/drivers/staging/media/allegro-dvt/nal-h264.c
@@ -235,7 +235,7 @@ static inline int rbsp_write_bit(struct rbsp *rbsp, bool value)
rbsp->pos++;
- if (value == 1 ||
+ if (value ||
(rbsp->num_consecutive_zeros < 7 && (rbsp->pos % 8 == 0))) {
rbsp->num_consecutive_zeros = 0;
} else {
diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c
index 025495657b68..c06cf849c04d 100644
--- a/drivers/staging/most/configfs.c
+++ b/drivers/staging/most/configfs.c
@@ -164,6 +164,7 @@ static ssize_t mdev_link_direction_store(struct config_item *item,
!sysfs_streq(page, "dir_tx") && !sysfs_streq(page, "tx"))
return -EINVAL;
strcpy(mdev_link->direction, page);
+ strim(mdev_link->direction);
return count;
}
@@ -182,6 +183,7 @@ static ssize_t mdev_link_datatype_store(struct config_item *item,
!sysfs_streq(page, "isoc_avp"))
return -EINVAL;
strcpy(mdev_link->datatype, page);
+ strim(mdev_link->datatype);
return count;
}
@@ -196,6 +198,7 @@ static ssize_t mdev_link_device_store(struct config_item *item,
struct mdev_link *mdev_link = to_mdev_link(item);
strcpy(mdev_link->device, page);
+ strim(mdev_link->device);
return count;
}
@@ -210,6 +213,7 @@ static ssize_t mdev_link_channel_store(struct config_item *item,
struct mdev_link *mdev_link = to_mdev_link(item);
strcpy(mdev_link->channel, page);
+ strim(mdev_link->channel);
return count;
}
@@ -487,7 +491,7 @@ static struct config_item *most_snd_grp_make_item(struct config_group *group,
return ERR_PTR(-ENOMEM);
config_item_init_type_name(&mdev_link->item, name, &mdev_link_type);
- mdev_link->create_link = 0;
+ mdev_link->create_link = false;
strcpy(mdev_link->name, name);
strcpy(mdev_link->comp, "sound");
return &mdev_link->item;
diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 8e9a0b67c6ed..f7d2c7850cf5 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -84,11 +84,11 @@ static const struct {
int most_ch_data_type;
const char *name;
} ch_data_type[] = {
- { MOST_CH_CONTROL, "control\n" },
- { MOST_CH_ASYNC, "async\n" },
- { MOST_CH_SYNC, "sync\n" },
- { MOST_CH_ISOC, "isoc\n"},
- { MOST_CH_ISOC, "isoc_avp\n"},
+ { MOST_CH_CONTROL, "control" },
+ { MOST_CH_ASYNC, "async" },
+ { MOST_CH_SYNC, "sync" },
+ { MOST_CH_ISOC, "isoc"},
+ { MOST_CH_ISOC, "isoc_avp"},
};
/**
@@ -675,13 +675,13 @@ int most_set_cfg_direction(char *mdev, char *mdev_ch, char *buf)
if (!c)
return -ENODEV;
- if (!strcmp(buf, "dir_rx\n")) {
+ if (!strcmp(buf, "dir_rx")) {
c->cfg.direction = MOST_CH_RX;
- } else if (!strcmp(buf, "rx\n")) {
+ } else if (!strcmp(buf, "rx")) {
c->cfg.direction = MOST_CH_RX;
- } else if (!strcmp(buf, "dir_tx\n")) {
+ } else if (!strcmp(buf, "dir_tx")) {
c->cfg.direction = MOST_CH_TX;
- } else if (!strcmp(buf, "tx\n")) {
+ } else if (!strcmp(buf, "tx")) {
c->cfg.direction = MOST_CH_TX;
} else {
pr_info("Invalid direction\n");
diff --git a/drivers/staging/mt7621-dma/mtk-hsdma.c b/drivers/staging/mt7621-dma/mtk-hsdma.c
index d964642d95a3..20b898954416 100644
--- a/drivers/staging/mt7621-dma/mtk-hsdma.c
+++ b/drivers/staging/mt7621-dma/mtk-hsdma.c
@@ -208,8 +208,8 @@ static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma,
static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma)
{
- dev_dbg(hsdma->ddev.dev, "tbase %08x, tcnt %08x, " \
- "tctx %08x, tdtx: %08x, rbase %08x, " \
+ dev_dbg(hsdma->ddev.dev, "tbase %08x, tcnt %08x, "
+ "tctx %08x, tdtx: %08x, rbase %08x, "
"rcnt %08x, rctx %08x, rdtx %08x\n",
mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE),
mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT),
@@ -220,7 +220,7 @@ static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma)
mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX),
mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX));
- dev_dbg(hsdma->ddev.dev, "info %08x, glo %08x, delay %08x, " \
+ dev_dbg(hsdma->ddev.dev, "info %08x, glo %08x, delay %08x, "
"intr_stat %08x, intr_mask %08x\n",
mtk_hsdma_read(hsdma, HSDMA_REG_INFO),
mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG),
@@ -243,9 +243,9 @@ static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma,
tx_desc = &chan->tx_ring[i];
rx_desc = &chan->rx_ring[i];
- dev_dbg(hsdma->ddev.dev, "%d tx addr0: %08x, flags %08x, " \
+ dev_dbg(hsdma->ddev.dev, "%d tx addr0: %08x, flags %08x, "
"tx addr1: %08x, rx addr0 %08x, flags %08x\n",
- i, tx_desc->addr0, tx_desc->flags, \
+ i, tx_desc->addr0, tx_desc->flags,
tx_desc->addr1, rx_desc->addr0, rx_desc->flags);
}
}
@@ -548,7 +548,8 @@ static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma,
int i;
chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev,
- 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring),
+ 2 * HSDMA_DESCS_NUM *
+ sizeof(*chan->tx_ring),
&chan->desc_addr, GFP_ATOMIC | __GFP_ZERO);
if (!chan->tx_ring)
goto no_mem;
@@ -569,8 +570,8 @@ static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma,
{
if (chan->tx_ring) {
dma_free_coherent(hsdma->ddev.dev,
- 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring),
- chan->tx_ring, chan->desc_addr);
+ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring),
+ chan->tx_ring, chan->desc_addr);
chan->tx_ring = NULL;
chan->rx_ring = NULL;
}
@@ -650,7 +651,6 @@ static int mtk_hsdma_probe(struct platform_device *pdev)
struct mtk_hsdma_chan *chan;
struct mtk_hsdam_engine *hsdma;
struct dma_device *dd;
- struct resource *res;
int ret;
int irq;
void __iomem *base;
@@ -667,8 +667,7 @@ static int mtk_hsdma_probe(struct platform_device *pdev)
if (!hsdma)
return -EINVAL;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
hsdma->base = base + HSDMA_BASE_OFFSET;
diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c
index 6b98827da57f..3633c924848e 100644
--- a/drivers/staging/mt7621-pci/pci-mt7621.c
+++ b/drivers/staging/mt7621-pci/pci-mt7621.c
@@ -29,15 +29,14 @@
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
+#include <linux/sys_soc.h>
#include <mt7621.h>
#include <ralink_regs.h>
#include "../../pci/pci.h"
/* sysctl */
-#define MT7621_CHIP_REV_ID 0x0c
#define MT7621_GPIO_MODE 0x60
-#define CHIP_REV_MT7621_E2 0x0101
/* MediaTek specific configuration registers */
#define PCIE_FTS_NUM 0x70c
@@ -126,6 +125,8 @@ struct mt7621_pcie_port {
* @ports: pointer to PCIe port information
* @perst: gpio reset
* @rst: pointer to pcie reset
+ * @resets_inverted: depends on chip revision
+ * reset lines are inverted.
*/
struct mt7621_pcie {
void __iomem *base;
@@ -140,6 +141,7 @@ struct mt7621_pcie {
struct list_head ports;
struct gpio_desc *perst;
struct reset_control *rst;
+ bool resets_inverted;
};
static inline u32 pcie_read(struct mt7621_pcie *pcie, u32 reg)
@@ -229,9 +231,9 @@ static inline void mt7621_pcie_port_clk_disable(struct mt7621_pcie_port *port)
static inline void mt7621_control_assert(struct mt7621_pcie_port *port)
{
- u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID);
+ struct mt7621_pcie *pcie = port->pcie;
- if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2)
+ if (pcie->resets_inverted)
reset_control_assert(port->pcie_rst);
else
reset_control_deassert(port->pcie_rst);
@@ -239,9 +241,9 @@ static inline void mt7621_control_assert(struct mt7621_pcie_port *port)
static inline void mt7621_control_deassert(struct mt7621_pcie_port *port)
{
- u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID);
+ struct mt7621_pcie *pcie = port->pcie;
- if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2)
+ if (pcie->resets_inverted)
reset_control_deassert(port->pcie_rst);
else
reset_control_assert(port->pcie_rst);
@@ -641,9 +643,14 @@ static int mt7621_pcie_register_host(struct pci_host_bridge *host,
return pci_host_probe(host);
}
+static const struct soc_device_attribute mt7621_pci_quirks_match[] = {
+ { .soc_id = "mt7621", .revision = "E2" }
+};
+
static int mt7621_pci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ const struct soc_device_attribute *attr;
struct mt7621_pcie *pcie;
struct pci_host_bridge *bridge;
int err;
@@ -661,6 +668,10 @@ static int mt7621_pci_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pcie);
INIT_LIST_HEAD(&pcie->ports);
+ attr = soc_device_match(mt7621_pci_quirks_match);
+ if (attr)
+ pcie->resets_inverted = true;
+
err = mt7621_pcie_parse_dt(pcie);
if (err) {
dev_err(dev, "Parsing DT failed\n");
diff --git a/drivers/staging/netlogic/TODO b/drivers/staging/netlogic/TODO
index 8f172b017b94..20e22ecb9903 100644
--- a/drivers/staging/netlogic/TODO
+++ b/drivers/staging/netlogic/TODO
@@ -1,6 +1,6 @@
* Implementing 64bit stat counter in software
* All memory allocation should be changed to DMA allocations
-* Changing comments in to linux standred format
+* Changing comments into linux standard format
Please send patches
To:
diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c
index 05079f7be841..204fcdfc022f 100644
--- a/drivers/staging/netlogic/xlr_net.c
+++ b/drivers/staging/netlogic/xlr_net.c
@@ -976,8 +976,7 @@ static int xlr_net_probe(struct platform_device *pdev)
priv->ndev = ndev;
priv->port_id = (pdev->id * 4) + port;
priv->nd = (struct xlr_net_data *)pdev->dev.platform_data;
- res = platform_get_resource(pdev, IORESOURCE_MEM, port);
- priv->base_addr = devm_ioremap_resource(&pdev->dev, res);
+ priv->base_addr = devm_platform_ioremap_resource(pdev, port);
if (IS_ERR(priv->base_addr)) {
err = PTR_ERR(priv->base_addr);
goto err_gmac;
diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c
index a5321cc692c5..582c9187559d 100644
--- a/drivers/staging/octeon-usb/octeon-hcd.c
+++ b/drivers/staging/octeon-usb/octeon-hcd.c
@@ -1836,8 +1836,7 @@ static void cvmx_usb_start_channel(struct octeon_hcd *usb, int channel,
*
* Returns: Pipe or NULL if none are ready
*/
-static struct cvmx_usb_pipe *cvmx_usb_find_ready_pipe(
- struct octeon_hcd *usb,
+static struct cvmx_usb_pipe *cvmx_usb_find_ready_pipe(struct octeon_hcd *usb,
enum cvmx_usb_transfer xfer_type)
{
struct list_head *list = usb->active_pipes + xfer_type;
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index ffac0c4b3f5c..c798672d61b2 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -65,7 +65,7 @@ int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
void cvm_oct_note_carrier(struct octeon_ethernet *priv,
- cvmx_helper_link_info_t li)
+ union cvmx_helper_link_info li)
{
if (li.s.link_up) {
pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d, queue %d\n",
@@ -81,7 +81,7 @@ void cvm_oct_note_carrier(struct octeon_ethernet *priv,
void cvm_oct_adjust_link(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
- cvmx_helper_link_info_t link_info;
+ union cvmx_helper_link_info link_info;
link_info.u64 = 0;
link_info.s.link_up = dev->phydev->link ? 1 : 0;
@@ -106,7 +106,7 @@ int cvm_oct_common_stop(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
int interface = INTERFACE(priv->port);
- cvmx_helper_link_info_t link_info;
+ union cvmx_helper_link_info link_info;
union cvmx_gmxx_prtx_cfg gmx_cfg;
int index = INDEX(priv->port);
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
index d91fd5ce9e68..0c4fac31540a 100644
--- a/drivers/staging/octeon/ethernet-rgmii.c
+++ b/drivers/staging/octeon/ethernet-rgmii.c
@@ -53,7 +53,7 @@ static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable)
static void cvm_oct_check_preamble_errors(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
- cvmx_helper_link_info_t link_info;
+ union cvmx_helper_link_info link_info;
unsigned long flags;
link_info.u64 = priv->link_info;
@@ -103,7 +103,7 @@ static void cvm_oct_check_preamble_errors(struct net_device *dev)
static void cvm_oct_rgmii_poll(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
- cvmx_helper_link_info_t link_info;
+ union cvmx_helper_link_info link_info;
bool status_change;
link_info = cvmx_helper_link_get(priv->port);
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
index 0e65955c746b..2c16230f993c 100644
--- a/drivers/staging/octeon/ethernet-rx.c
+++ b/drivers/staging/octeon/ethernet-rx.c
@@ -60,7 +60,7 @@ static irqreturn_t cvm_oct_do_interrupt(int irq, void *napi_id)
*
* Returns Non-zero if the packet can be dropped, zero otherwise.
*/
-static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
+static inline int cvm_oct_check_rcv_error(struct cvmx_wqe *work)
{
int port;
@@ -135,7 +135,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
return 0;
}
-static void copy_segments_to_skb(cvmx_wqe_t *work, struct sk_buff *skb)
+static void copy_segments_to_skb(struct cvmx_wqe *work, struct sk_buff *skb)
{
int segments = work->word2.s.bufs;
union cvmx_buf_ptr segment_ptr = work->packet_ptr;
@@ -215,7 +215,7 @@ static int cvm_oct_poll(struct oct_rx_group *rx_group, int budget)
struct sk_buff *skb = NULL;
struct sk_buff **pskb = NULL;
int skb_in_hw;
- cvmx_wqe_t *work;
+ struct cvmx_wqe *work;
int port;
if (USE_ASYNC_IOBDMA && did_work_request)
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 83469061a542..b334cf89794e 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -127,7 +127,7 @@ static void cvm_oct_free_tx_skbs(struct net_device *dev)
*/
int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
{
- cvmx_pko_command_word0_t pko_command;
+ union cvmx_pko_command_word0 pko_command;
union cvmx_buf_ptr hw_buffer;
u64 old_scratch;
u64 old_scratch2;
@@ -514,7 +514,7 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
void *copy_location;
/* Get a work queue entry */
- cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
+ struct cvmx_wqe *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
if (unlikely(!work)) {
printk_ratelimited("%s: Failed to allocate a work queue entry\n",
@@ -598,7 +598,7 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
#endif
work->word2.s.is_frag = !((ip_hdr(skb)->frag_off == 0) ||
(ip_hdr(skb)->frag_off ==
- 1 << 14));
+ cpu_to_be16(1 << 14)));
#if 0
/* Assume Linux is sending a good packet */
work->word2.s.IP_exc = 0;
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index cf8e9a23ebf9..f42c3816ce49 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -172,7 +172,7 @@ static void cvm_oct_configure_common_hw(void)
*/
int cvm_oct_free_work(void *work_queue_entry)
{
- cvmx_wqe_t *work = work_queue_entry;
+ struct cvmx_wqe *work = work_queue_entry;
int segments = work->word2.s.bufs;
union cvmx_buf_ptr segment_ptr = work->packet_ptr;
@@ -460,7 +460,7 @@ int cvm_oct_common_open(struct net_device *dev,
struct octeon_ethernet *priv = netdev_priv(dev);
int interface = INTERFACE(priv->port);
int index = INDEX(priv->port);
- cvmx_helper_link_info_t link_info;
+ union cvmx_helper_link_info link_info;
int rv;
rv = cvm_oct_phy_setup_device(dev);
@@ -496,7 +496,7 @@ int cvm_oct_common_open(struct net_device *dev,
void cvm_oct_link_poll(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
- cvmx_helper_link_info_t link_info;
+ union cvmx_helper_link_info link_info;
link_info = cvmx_helper_link_get(priv->port);
if (link_info.u64 == priv->link_info)
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h
index a8a864b40913..a6140705706f 100644
--- a/drivers/staging/octeon/octeon-ethernet.h
+++ b/drivers/staging/octeon/octeon-ethernet.h
@@ -14,7 +14,7 @@
#include <linux/of.h>
#include <linux/phy.h>
-#ifdef CONFIG_MIPS
+#ifdef CONFIG_CAVIUM_OCTEON_SOC
#include <asm/octeon/octeon.h>
@@ -91,7 +91,7 @@ int cvm_oct_common_stop(struct net_device *dev);
int cvm_oct_common_open(struct net_device *dev,
void (*link_poll)(struct net_device *));
void cvm_oct_note_carrier(struct octeon_ethernet *priv,
- cvmx_helper_link_info_t li);
+ union cvmx_helper_link_info li);
void cvm_oct_link_poll(struct net_device *dev);
extern int always_use_pow;
diff --git a/drivers/staging/octeon/octeon-stubs.h b/drivers/staging/octeon/octeon-stubs.h
index b78ce9eaab85..d53bd801f440 100644
--- a/drivers/staging/octeon/octeon-stubs.h
+++ b/drivers/staging/octeon/octeon-stubs.h
@@ -1,5 +1,8 @@
#define CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE 512
-#define XKPHYS_TO_PHYS(p) (p)
+
+#ifndef XKPHYS_TO_PHYS
+# define XKPHYS_TO_PHYS(p) (p)
+#endif
#define OCTEON_IRQ_WORKQ0 0
#define OCTEON_IRQ_RML 0
@@ -38,7 +41,7 @@
#define CVMX_NPI_RSL_INT_BLOCKS 0
#define CVMX_POW_WQ_INT_PC 0
-typedef union {
+union cvmx_pip_wqe_word2 {
uint64_t u64;
struct {
uint64_t bufs:8;
@@ -114,13 +117,13 @@ typedef union {
uint64_t err_code:8;
} snoip;
-} cvmx_pip_wqe_word2;
+};
union cvmx_pip_wqe_word0 {
struct {
uint64_t next_ptr:40;
uint8_t unused;
- uint16_t hw_chksum;
+ __wsum hw_chksum;
} cn38xx;
struct {
uint64_t pknd:6; /* 0..5 */
@@ -180,15 +183,15 @@ union cvmx_buf_ptr {
} s;
};
-typedef struct {
+struct cvmx_wqe {
union cvmx_wqe_word0 word0;
union cvmx_wqe_word1 word1;
- cvmx_pip_wqe_word2 word2;
+ union cvmx_pip_wqe_word2 word2;
union cvmx_buf_ptr packet_ptr;
uint8_t packet_data[96];
-} cvmx_wqe_t;
+};
-typedef union {
+union cvmx_helper_link_info {
uint64_t u64;
struct {
uint64_t reserved_20_63:44;
@@ -196,18 +199,18 @@ typedef union {
uint64_t full_duplex:1; /**< 1 if the link is full duplex */
uint64_t speed:18; /**< Speed of the link in Mbps */
} s;
-} cvmx_helper_link_info_t;
+};
-typedef enum {
+enum cvmx_fau_reg_32 {
CVMX_FAU_REG_32_START = 0,
-} cvmx_fau_reg_32_t;
+};
-typedef enum {
+enum cvmx_fau_op_size {
CVMX_FAU_OP_SIZE_8 = 0,
CVMX_FAU_OP_SIZE_16 = 1,
CVMX_FAU_OP_SIZE_32 = 2,
CVMX_FAU_OP_SIZE_64 = 3
-} cvmx_fau_op_size_t;
+};
typedef enum {
CVMX_SPI_MODE_UNKNOWN = 0,
@@ -1134,7 +1137,7 @@ union cvmx_npi_rsl_int_blocks {
} cn50xx;
};
-typedef union {
+union cvmx_pko_command_word0 {
uint64_t u64;
struct {
uint64_t total_bytes:16;
@@ -1154,7 +1157,7 @@ typedef union {
uint64_t size0:2;
uint64_t size1:2;
} s;
-} cvmx_pko_command_word0_t;
+};
union cvmx_ciu_timx {
uint64_t u64;
@@ -1175,16 +1178,18 @@ union cvmx_gmxx_rxx_rx_inbnd {
} s;
};
-static inline int32_t cvmx_fau_fetch_and_add32(cvmx_fau_reg_32_t reg,
+static inline int32_t cvmx_fau_fetch_and_add32(enum cvmx_fau_reg_32 reg,
int32_t value)
{
return value;
}
-static inline void cvmx_fau_atomic_add32(cvmx_fau_reg_32_t reg, int32_t value)
+static inline void cvmx_fau_atomic_add32(enum cvmx_fau_reg_32 reg,
+ int32_t value)
{ }
-static inline void cvmx_fau_atomic_write32(cvmx_fau_reg_32_t reg, int32_t value)
+static inline void cvmx_fau_atomic_write32(enum cvmx_fau_reg_32 reg,
+ int32_t value)
{ }
static inline uint64_t cvmx_scratch_read64(uint64_t address)
@@ -1195,7 +1200,7 @@ static inline uint64_t cvmx_scratch_read64(uint64_t address)
static inline void cvmx_scratch_write64(uint64_t address, uint64_t value)
{ }
-static inline int cvmx_wqe_get_grp(cvmx_wqe_t *work)
+static inline int cvmx_wqe_get_grp(struct cvmx_wqe *work)
{
return 0;
}
@@ -1264,15 +1269,15 @@ static inline cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int
return 0;
}
-static inline cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
+static inline union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port)
{
- cvmx_helper_link_info_t ret = { .u64 = 0 };
+ union cvmx_helper_link_info ret = { .u64 = 0 };
return ret;
}
static inline int cvmx_helper_link_set(int ipd_port,
- cvmx_helper_link_info_t link_info)
+ union cvmx_helper_link_info link_info)
{
return 0;
}
@@ -1342,14 +1347,14 @@ static inline void cvmx_pow_work_request_async(int scr_addr,
cvmx_pow_wait_t wait)
{ }
-static inline cvmx_wqe_t *cvmx_pow_work_response_async(int scr_addr)
+static inline struct cvmx_wqe *cvmx_pow_work_response_async(int scr_addr)
{
- cvmx_wqe_t *wqe = (void *)(unsigned long)scr_addr;
+ struct cvmx_wqe *wqe = (void *)(unsigned long)scr_addr;
return wqe;
}
-static inline cvmx_wqe_t *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait)
+static inline struct cvmx_wqe *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait)
{
return (void *)(unsigned long)wait;
}
@@ -1361,7 +1366,7 @@ static inline int cvmx_spi_restart_interface(int interface,
}
static inline void cvmx_fau_async_fetch_and_add32(uint64_t scraddr,
- cvmx_fau_reg_32_t reg,
+ enum cvmx_fau_reg_32 reg,
int32_t value)
{ }
@@ -1379,29 +1384,27 @@ static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue,
{ }
static inline cvmx_pko_status_t cvmx_pko_send_packet_finish(uint64_t port,
- uint64_t queue, cvmx_pko_command_word0_t pko_command,
+ uint64_t queue, union cvmx_pko_command_word0 pko_command,
union cvmx_buf_ptr packet, cvmx_pko_lock_t use_locking)
{
- cvmx_pko_status_t ret = 0;
-
- return ret;
+ return 0;
}
-static inline void cvmx_wqe_set_port(cvmx_wqe_t *work, int port)
+static inline void cvmx_wqe_set_port(struct cvmx_wqe *work, int port)
{ }
-static inline void cvmx_wqe_set_qos(cvmx_wqe_t *work, int qos)
+static inline void cvmx_wqe_set_qos(struct cvmx_wqe *work, int qos)
{ }
-static inline int cvmx_wqe_get_qos(cvmx_wqe_t *work)
+static inline int cvmx_wqe_get_qos(struct cvmx_wqe *work)
{
return 0;
}
-static inline void cvmx_wqe_set_grp(cvmx_wqe_t *work, int grp)
+static inline void cvmx_wqe_set_grp(struct cvmx_wqe *work, int grp)
{ }
-static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag,
+static inline void cvmx_pow_work_submit(struct cvmx_wqe *wqp, uint32_t tag,
enum cvmx_pow_tag_type tag_type,
uint64_t qos, uint64_t grp)
{ }
diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig
index f5c716bb3413..d1a0dea09ef0 100644
--- a/drivers/staging/olpc_dcon/Kconfig
+++ b/drivers/staging/olpc_dcon/Kconfig
@@ -3,7 +3,7 @@ config FB_OLPC_DCON
tristate "One Laptop Per Child Display CONtroller support"
depends on OLPC && FB
depends on I2C
- depends on (GPIO_CS5535 || GPIO_CS5535=n)
+ depends on GPIO_CS5535 && ACPI
select BACKLIGHT_CLASS_DEVICE
help
In order to support very low power operation, the XO laptop uses a
@@ -15,22 +15,3 @@ config FB_OLPC_DCON
This controller is only available on OLPC platforms. Unless you have
one of these platforms, you will want to say 'N'.
-config FB_OLPC_DCON_1
- bool "OLPC XO-1 DCON support"
- depends on FB_OLPC_DCON && GPIO_CS5535
- default y
- help
- Enable support for the DCON in XO-1 model laptops. The kernel
- communicates with the DCON using model-specific code. If you
- have an XO-1 (or if you're unsure what model you have), you should
- say 'Y'.
-
-config FB_OLPC_DCON_1_5
- bool "OLPC XO-1.5 DCON support"
- depends on FB_OLPC_DCON && ACPI
- default y
- help
- Enable support for the DCON in XO-1.5 model laptops. The kernel
- communicates with the DCON using model-specific code. If you
- have an XO-1.5 (or if you're unsure what model you have), you
- should say 'Y'.
diff --git a/drivers/staging/olpc_dcon/Makefile b/drivers/staging/olpc_dcon/Makefile
index cb1248c5c162..734b2ce26066 100644
--- a/drivers/staging/olpc_dcon/Makefile
+++ b/drivers/staging/olpc_dcon/Makefile
@@ -1,7 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-olpc-dcon-objs += olpc_dcon.o
-olpc-dcon-$(CONFIG_FB_OLPC_DCON_1) += olpc_dcon_xo_1.o
-olpc-dcon-$(CONFIG_FB_OLPC_DCON_1_5) += olpc_dcon_xo_1_5.o
+olpc-dcon-objs += olpc_dcon.o olpc_dcon_xo_1.o olpc_dcon_xo_1_5.o
obj-$(CONFIG_FB_OLPC_DCON) += olpc-dcon.o
diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO
index d8296f2ae872..7c263358b44a 100644
--- a/drivers/staging/olpc_dcon/TODO
+++ b/drivers/staging/olpc_dcon/TODO
@@ -8,7 +8,6 @@ TODO:
internals, but isn't properly integrated, is not the correct solution.
- see if vx855 gpio API can be made similar enough to cs5535 so we can
share more code
- - allow simultaneous XO-1 and XO-1.5 support
Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
copy:
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index a254238be181..a0d6d90f4cc8 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -790,15 +790,11 @@ static struct i2c_driver dcon_driver = {
static int __init olpc_dcon_init(void)
{
-#ifdef CONFIG_FB_OLPC_DCON_1_5
/* XO-1.5 */
if (olpc_board_at_least(olpc_board(0xd0)))
pdata = &dcon_pdata_xo_1_5;
-#endif
-#ifdef CONFIG_FB_OLPC_DCON_1
- if (!pdata)
+ else
pdata = &dcon_pdata_xo_1;
-#endif
return i2c_add_driver(&dcon_driver);
}
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h
index 22d976a09785..41bd1360b56e 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.h
+++ b/drivers/staging/olpc_dcon/olpc_dcon.h
@@ -106,12 +106,7 @@ struct dcon_gpio {
irqreturn_t dcon_interrupt(int irq, void *id);
-#ifdef CONFIG_FB_OLPC_DCON_1
extern struct dcon_platform_data dcon_pdata_xo_1;
-#endif
-
-#ifdef CONFIG_FB_OLPC_DCON_1_5
extern struct dcon_platform_data dcon_pdata_xo_1_5;
-#endif
#endif
diff --git a/drivers/staging/qlge/TODO b/drivers/staging/qlge/TODO
index 51c509084e80..f93f7428f5d5 100644
--- a/drivers/staging/qlge/TODO
+++ b/drivers/staging/qlge/TODO
@@ -1,6 +1,3 @@
-* reception stalls permanently (until admin intervention) if the rx buffer
- queues become empty because of allocation failures (ex. under memory
- pressure)
* commit 7c734359d350 ("qlge: Size RX buffers based on MTU.", v2.6.33-rc1)
introduced dead code in the receive routines, which should be rewritten
anyways by the admission of the author himself, see the comment above
diff --git a/drivers/staging/qlge/qlge.h b/drivers/staging/qlge/qlge.h
index ad7c5eb8a3b6..6ec7e3ce3863 100644
--- a/drivers/staging/qlge/qlge.h
+++ b/drivers/staging/qlge/qlge.h
@@ -34,8 +34,13 @@
#define NUM_TX_RING_ENTRIES 256
#define NUM_RX_RING_ENTRIES 256
-#define NUM_SMALL_BUFFERS 512
-#define NUM_LARGE_BUFFERS 512
+/* Use the same len for sbq and lbq. Note that it seems like the device might
+ * support different sizes.
+ */
+#define QLGE_BQ_SHIFT 9
+#define QLGE_BQ_LEN BIT(QLGE_BQ_SHIFT)
+#define QLGE_BQ_SIZE (QLGE_BQ_LEN * sizeof(__le64))
+
#define DB_PAGE_SIZE 4096
/* Calculate the number of (4k) pages required to
@@ -46,8 +51,8 @@
(((x * sizeof(u64)) % DB_PAGE_SIZE) ? 1 : 0))
#define RX_RING_SHADOW_SPACE (sizeof(u64) + \
- MAX_DB_PAGES_PER_BQ(NUM_SMALL_BUFFERS) * sizeof(u64) + \
- MAX_DB_PAGES_PER_BQ(NUM_LARGE_BUFFERS) * sizeof(u64))
+ MAX_DB_PAGES_PER_BQ(QLGE_BQ_LEN) * sizeof(u64) + \
+ MAX_DB_PAGES_PER_BQ(QLGE_BQ_LEN) * sizeof(u64))
#define LARGE_BUFFER_MAX_SIZE 8192
#define LARGE_BUFFER_MIN_SIZE 2048
@@ -77,6 +82,11 @@
#define LSD(x) ((u32)((u64)(x)))
#define MSD(x) ((u32)((((u64)(x)) >> 32)))
+/* In some cases, the device interprets a value of 0x0000 as 65536. These
+ * cases are marked using the following macro.
+ */
+#define QLGE_FIT16(value) ((u16)(value))
+
/* MPI test register definitions. This register
* is used for determining alternate NIC function's
* PCI->func number.
@@ -1358,25 +1368,6 @@ struct tx_ring_desc {
struct tx_ring_desc *next;
};
-struct page_chunk {
- struct page *page; /* master page */
- char *va; /* virt addr for this chunk */
- u64 map; /* mapping for master */
- unsigned int offset; /* offset for this chunk */
- unsigned int last_flag; /* flag set for last chunk in page */
-};
-
-struct bq_desc {
- union {
- struct page_chunk pg_chunk;
- struct sk_buff *skb;
- } p;
- __le64 *addr;
- u32 index;
- DEFINE_DMA_UNMAP_ADDR(mapaddr);
- DEFINE_DMA_UNMAP_LEN(maplen);
-};
-
#define QL_TXQ_IDX(qdev, skb) (smp_processor_id()%(qdev->tx_ring_count))
struct tx_ring {
@@ -1406,15 +1397,68 @@ struct tx_ring {
u64 tx_errors;
};
-/*
- * Type of inbound queue.
- */
-enum {
- DEFAULT_Q = 2, /* Handles slow queue and chip/MPI events. */
- TX_Q = 3, /* Handles outbound completions. */
- RX_Q = 4, /* Handles inbound completions. */
+struct qlge_page_chunk {
+ struct page *page;
+ void *va; /* virt addr including offset */
+ unsigned int offset;
};
+struct qlge_bq_desc {
+ union {
+ /* for large buffers */
+ struct qlge_page_chunk pg_chunk;
+ /* for small buffers */
+ struct sk_buff *skb;
+ } p;
+ dma_addr_t dma_addr;
+ /* address in ring where the buffer address is written for the device */
+ __le64 *buf_ptr;
+ u32 index;
+};
+
+/* buffer queue */
+struct qlge_bq {
+ __le64 *base;
+ dma_addr_t base_dma;
+ __le64 *base_indirect;
+ dma_addr_t base_indirect_dma;
+ struct qlge_bq_desc *queue;
+ /* prod_idx is the index of the first buffer that may NOT be used by
+ * hw, ie. one after the last. Advanced by sw.
+ */
+ void __iomem *prod_idx_db_reg;
+ /* next index where sw should refill a buffer for hw */
+ u16 next_to_use;
+ /* next index where sw expects to find a buffer filled by hw */
+ u16 next_to_clean;
+ enum {
+ QLGE_SB, /* small buffer */
+ QLGE_LB, /* large buffer */
+ } type;
+};
+
+#define QLGE_BQ_CONTAINER(bq) \
+({ \
+ typeof(bq) _bq = bq; \
+ (struct rx_ring *)((char *)_bq - (_bq->type == QLGE_SB ? \
+ offsetof(struct rx_ring, sbq) : \
+ offsetof(struct rx_ring, lbq))); \
+})
+
+/* Experience shows that the device ignores the low 4 bits of the tail index.
+ * Refill up to a x16 multiple.
+ */
+#define QLGE_BQ_ALIGN(index) ALIGN_DOWN(index, 16)
+
+#define QLGE_BQ_WRAP(index) ((index) & (QLGE_BQ_LEN - 1))
+
+#define QLGE_BQ_HW_OWNED(bq) \
+({ \
+ typeof(bq) _bq = bq; \
+ QLGE_BQ_WRAP(QLGE_BQ_ALIGN((_bq)->next_to_use) - \
+ (_bq)->next_to_clean); \
+})
+
struct rx_ring {
struct cqicb cqicb; /* The chip's completion queue init control block. */
@@ -1432,40 +1476,17 @@ struct rx_ring {
void __iomem *valid_db_reg; /* PCI doorbell mem area + 0x04 */
/* Large buffer queue elements. */
- u32 lbq_len; /* entry count */
- u32 lbq_size; /* size in bytes of queue */
- u32 lbq_buf_size;
- void *lbq_base;
- dma_addr_t lbq_base_dma;
- void *lbq_base_indirect;
- dma_addr_t lbq_base_indirect_dma;
- struct page_chunk pg_chunk; /* current page for chunks */
- struct bq_desc *lbq; /* array of control blocks */
- void __iomem *lbq_prod_idx_db_reg; /* PCI doorbell mem area + 0x18 */
- u32 lbq_prod_idx; /* current sw prod idx */
- u32 lbq_curr_idx; /* next entry we expect */
- u32 lbq_clean_idx; /* beginning of new descs */
- u32 lbq_free_cnt; /* free buffer desc cnt */
+ struct qlge_bq lbq;
+ struct qlge_page_chunk master_chunk;
+ dma_addr_t chunk_dma_addr;
/* Small buffer queue elements. */
- u32 sbq_len; /* entry count */
- u32 sbq_size; /* size in bytes of queue */
- u32 sbq_buf_size;
- void *sbq_base;
- dma_addr_t sbq_base_dma;
- void *sbq_base_indirect;
- dma_addr_t sbq_base_indirect_dma;
- struct bq_desc *sbq; /* array of control blocks */
- void __iomem *sbq_prod_idx_db_reg; /* PCI doorbell mem area + 0x1c */
- u32 sbq_prod_idx; /* current sw prod idx */
- u32 sbq_curr_idx; /* next entry we expect */
- u32 sbq_clean_idx; /* beginning of new descs */
- u32 sbq_free_cnt; /* free buffer desc cnt */
+ struct qlge_bq sbq;
/* Misc. handler elements. */
- u32 type; /* Type of queue, tx, rx. */
u32 irq; /* Which vector this ring is assigned. */
u32 cpu; /* Which CPU this should run on. */
+ struct delayed_work refill_work;
char name[IFNAMSIZ + 5];
struct napi_struct napi;
u8 reserved;
@@ -1982,11 +2003,6 @@ struct intr_context {
u32 intr_dis_mask; /* value/mask used to disable this intr */
u32 intr_read_mask; /* value/mask used to read this intr */
char name[IFNAMSIZ * 2];
- atomic_t irq_cnt; /* irq_cnt is used in single vector
- * environment. It's incremented for each
- * irq handler that is scheduled. When each
- * handler finishes it decrements irq_cnt and
- * enables interrupts if it's zero. */
irq_handler_t handler;
};
@@ -2074,7 +2090,6 @@ struct ql_adapter {
u32 port; /* Port number this adapter */
spinlock_t adapter_lock;
- spinlock_t hw_lock;
spinlock_t stats_lock;
/* PCI Bus Relative Register Addresses */
@@ -2115,6 +2130,7 @@ struct ql_adapter {
struct rx_ring rx_ring[MAX_RX_RINGS];
struct tx_ring tx_ring[MAX_TX_RINGS];
unsigned int lbq_buf_order;
+ u32 lbq_buf_size;
int rx_csum;
u32 default_rx_queue;
@@ -2235,7 +2251,6 @@ void ql_mpi_reset_work(struct work_struct *work);
void ql_mpi_core_to_log(struct work_struct *work);
int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit);
void ql_queue_asic_error(struct ql_adapter *qdev);
-u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr);
void ql_set_ethtool_ops(struct net_device *ndev);
int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data);
void ql_mpi_idc_work(struct work_struct *work);
diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c
index 31389ab8bdf7..83f34ca43aa4 100644
--- a/drivers/staging/qlge/qlge_dbg.c
+++ b/drivers/staging/qlge/qlge_dbg.c
@@ -7,7 +7,7 @@
/* Read a NIC register from the alternate function. */
static u32 ql_read_other_func_reg(struct ql_adapter *qdev,
- u32 reg)
+ u32 reg)
{
u32 register_to_read;
u32 reg_val;
@@ -26,7 +26,7 @@ static u32 ql_read_other_func_reg(struct ql_adapter *qdev,
/* Write a NIC register from the alternate function. */
static int ql_write_other_func_reg(struct ql_adapter *qdev,
- u32 reg, u32 reg_val)
+ u32 reg, u32 reg_val)
{
u32 register_to_read;
int status = 0;
@@ -41,7 +41,7 @@ static int ql_write_other_func_reg(struct ql_adapter *qdev,
}
static int ql_wait_other_func_reg_rdy(struct ql_adapter *qdev, u32 reg,
- u32 bit, u32 err_bit)
+ u32 bit, u32 err_bit)
{
u32 temp;
int count = 10;
@@ -61,22 +61,22 @@ static int ql_wait_other_func_reg_rdy(struct ql_adapter *qdev, u32 reg,
}
static int ql_read_other_func_serdes_reg(struct ql_adapter *qdev, u32 reg,
- u32 *data)
+ u32 *data)
{
int status;
/* wait for reg to come ready */
status = ql_wait_other_func_reg_rdy(qdev, XG_SERDES_ADDR / 4,
- XG_SERDES_ADDR_RDY, 0);
+ XG_SERDES_ADDR_RDY, 0);
if (status)
goto exit;
/* set up for reg read */
- ql_write_other_func_reg(qdev, XG_SERDES_ADDR/4, reg | PROC_ADDR_R);
+ ql_write_other_func_reg(qdev, XG_SERDES_ADDR / 4, reg | PROC_ADDR_R);
/* wait for reg to come ready */
status = ql_wait_other_func_reg_rdy(qdev, XG_SERDES_ADDR / 4,
- XG_SERDES_ADDR_RDY, 0);
+ XG_SERDES_ADDR_RDY, 0);
if (status)
goto exit;
@@ -111,8 +111,8 @@ exit:
}
static void ql_get_both_serdes(struct ql_adapter *qdev, u32 addr,
- u32 *direct_ptr, u32 *indirect_ptr,
- unsigned int direct_valid, unsigned int indirect_valid)
+ u32 *direct_ptr, u32 *indirect_ptr,
+ bool direct_valid, bool indirect_valid)
{
unsigned int status;
@@ -133,16 +133,15 @@ static void ql_get_both_serdes(struct ql_adapter *qdev, u32 addr,
}
static int ql_get_serdes_regs(struct ql_adapter *qdev,
- struct ql_mpi_coredump *mpi_coredump)
+ struct ql_mpi_coredump *mpi_coredump)
{
int status;
- unsigned int xfi_direct_valid, xfi_indirect_valid, xaui_direct_valid;
- unsigned int xaui_indirect_valid, i;
+ bool xfi_direct_valid = false, xfi_indirect_valid = false;
+ bool xaui_direct_valid = true, xaui_indirect_valid = true;
+ unsigned int i;
u32 *direct_ptr, temp;
u32 *indirect_ptr;
- xfi_direct_valid = xfi_indirect_valid = 0;
- xaui_direct_valid = xaui_indirect_valid = 1;
/* The XAUI needs to be read out per port */
status = ql_read_other_func_serdes_reg(qdev,
@@ -152,7 +151,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) ==
XG_SERDES_ADDR_XAUI_PWR_DOWN)
- xaui_indirect_valid = 0;
+ xaui_indirect_valid = false;
status = ql_read_serdes_reg(qdev, XG_SERDES_XAUI_HSS_PCS_START, &temp);
@@ -161,7 +160,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) ==
XG_SERDES_ADDR_XAUI_PWR_DOWN)
- xaui_direct_valid = 0;
+ xaui_direct_valid = false;
/*
* XFI register is shared so only need to read one
@@ -176,18 +175,18 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
/* now see if i'm NIC 1 or NIC 2 */
if (qdev->func & 1)
/* I'm NIC 2, so the indirect (NIC1) xfi is up. */
- xfi_indirect_valid = 1;
+ xfi_indirect_valid = true;
else
- xfi_direct_valid = 1;
+ xfi_direct_valid = true;
}
if ((temp & XG_SERDES_ADDR_XFI2_PWR_UP) ==
XG_SERDES_ADDR_XFI2_PWR_UP) {
/* now see if i'm NIC 1 or NIC 2 */
if (qdev->func & 1)
/* I'm NIC 2, so the indirect (NIC1) xfi is up. */
- xfi_direct_valid = 1;
+ xfi_direct_valid = true;
else
- xfi_indirect_valid = 1;
+ xfi_indirect_valid = true;
}
/* Get XAUI_AN register block. */
@@ -203,7 +202,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
for (i = 0; i <= 0x000000034; i += 4, direct_ptr++, indirect_ptr++)
ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
- xaui_direct_valid, xaui_indirect_valid);
+ xaui_direct_valid, xaui_indirect_valid);
/* Get XAUI_HSS_PCS register block. */
if (qdev->func & 1) {
@@ -220,7 +219,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
for (i = 0x800; i <= 0x880; i += 4, direct_ptr++, indirect_ptr++)
ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
- xaui_direct_valid, xaui_indirect_valid);
+ xaui_direct_valid, xaui_indirect_valid);
/* Get XAUI_XFI_AN register block. */
if (qdev->func & 1) {
@@ -233,7 +232,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
for (i = 0x1000; i <= 0x1034; i += 4, direct_ptr++, indirect_ptr++)
ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
- xfi_direct_valid, xfi_indirect_valid);
+ xfi_direct_valid, xfi_indirect_valid);
/* Get XAUI_XFI_TRAIN register block. */
if (qdev->func & 1) {
@@ -248,7 +247,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
for (i = 0x1050; i <= 0x107c; i += 4, direct_ptr++, indirect_ptr++)
ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
- xfi_direct_valid, xfi_indirect_valid);
+ xfi_direct_valid, xfi_indirect_valid);
/* Get XAUI_XFI_HSS_PCS register block. */
if (qdev->func & 1) {
@@ -265,7 +264,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
for (i = 0x1800; i <= 0x1838; i += 4, direct_ptr++, indirect_ptr++)
ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
- xfi_direct_valid, xfi_indirect_valid);
+ xfi_direct_valid, xfi_indirect_valid);
/* Get XAUI_XFI_HSS_TX register block. */
if (qdev->func & 1) {
@@ -280,7 +279,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
}
for (i = 0x1c00; i <= 0x1c1f; i++, direct_ptr++, indirect_ptr++)
ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
- xfi_direct_valid, xfi_indirect_valid);
+ xfi_direct_valid, xfi_indirect_valid);
/* Get XAUI_XFI_HSS_RX register block. */
if (qdev->func & 1) {
@@ -296,7 +295,7 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
for (i = 0x1c40; i <= 0x1c5f; i++, direct_ptr++, indirect_ptr++)
ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
- xfi_direct_valid, xfi_indirect_valid);
+ xfi_direct_valid, xfi_indirect_valid);
/* Get XAUI_XFI_HSS_PLL register block. */
@@ -313,18 +312,18 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
}
for (i = 0x1e00; i <= 0x1e1f; i++, direct_ptr++, indirect_ptr++)
ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
- xfi_direct_valid, xfi_indirect_valid);
+ xfi_direct_valid, xfi_indirect_valid);
return 0;
}
static int ql_read_other_func_xgmac_reg(struct ql_adapter *qdev, u32 reg,
- u32 *data)
+ u32 *data)
{
int status = 0;
/* wait for reg to come ready */
status = ql_wait_other_func_reg_rdy(qdev, XGMAC_ADDR / 4,
- XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
+ XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
if (status)
goto exit;
@@ -333,7 +332,7 @@ static int ql_read_other_func_xgmac_reg(struct ql_adapter *qdev, u32 reg,
/* wait for reg to come ready */
status = ql_wait_other_func_reg_rdy(qdev, XGMAC_ADDR / 4,
- XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
+ XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
if (status)
goto exit;
@@ -347,17 +346,17 @@ exit:
* skipping unused locations.
*/
static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 *buf,
- unsigned int other_function)
+ unsigned int other_function)
{
int status = 0;
int i;
for (i = PAUSE_SRC_LO; i < XGMAC_REGISTER_END; i += 4, buf++) {
/* We're reading 400 xgmac registers, but we filter out
- * serveral locations that are non-responsive to reads.
+ * several locations that are non-responsive to reads.
*/
if ((i == 0x00000114) ||
- (i == 0x00000118) ||
+ (i == 0x00000118) ||
(i == 0x0000013c) ||
(i == 0x00000140) ||
(i > 0x00000150 && i < 0x000001fc) ||
@@ -389,7 +388,6 @@ static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 *buf,
static int ql_get_ets_regs(struct ql_adapter *qdev, u32 *buf)
{
- int status = 0;
int i;
for (i = 0; i < 8; i++, buf++) {
@@ -402,7 +400,7 @@ static int ql_get_ets_regs(struct ql_adapter *qdev, u32 *buf)
*buf = ql_read32(qdev, CNA_ETS);
}
- return status;
+ return 0;
}
static void ql_get_intr_states(struct ql_adapter *qdev, u32 *buf)
@@ -411,7 +409,7 @@ static void ql_get_intr_states(struct ql_adapter *qdev, u32 *buf)
for (i = 0; i < qdev->rx_ring_count; i++, buf++) {
ql_write32(qdev, INTR_EN,
- qdev->intr_context[i].intr_read_mask);
+ qdev->intr_context[i].intr_read_mask);
*buf = ql_read32(qdev, INTR_EN);
}
}
@@ -427,7 +425,7 @@ static int ql_get_cam_entries(struct ql_adapter *qdev, u32 *buf)
for (i = 0; i < 16; i++) {
status = ql_get_mac_addr_reg(qdev,
- MAC_ADDR_TYPE_CAM_MAC, i, value);
+ MAC_ADDR_TYPE_CAM_MAC, i, value);
if (status) {
netif_err(qdev, drv, qdev->ndev,
"Failed read of mac index register\n");
@@ -439,7 +437,7 @@ static int ql_get_cam_entries(struct ql_adapter *qdev, u32 *buf)
}
for (i = 0; i < 32; i++) {
status = ql_get_mac_addr_reg(qdev,
- MAC_ADDR_TYPE_MULTI_MAC, i, value);
+ MAC_ADDR_TYPE_MULTI_MAC, i, value);
if (status) {
netif_err(qdev, drv, qdev->ndev,
"Failed read of mac index register\n");
@@ -498,7 +496,7 @@ end:
/* Read the MPI Processor core registers */
static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 *buf,
- u32 offset, u32 count)
+ u32 offset, u32 count)
{
int i, status = 0;
for (i = 0; i < count; i++, buf++) {
@@ -511,7 +509,7 @@ static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 *buf,
/* Read the ASIC probe dump */
static unsigned int *ql_get_probe(struct ql_adapter *qdev, u32 clock,
- u32 valid, u32 *buf)
+ u32 valid, u32 *buf)
{
u32 module, mux_sel, probe, lo_val, hi_val;
@@ -546,13 +544,13 @@ static int ql_get_probe_dump(struct ql_adapter *qdev, unsigned int *buf)
/* First we have to enable the probe mux */
ql_write_mpi_reg(qdev, MPI_TEST_FUNC_PRB_CTL, MPI_TEST_FUNC_PRB_EN);
buf = ql_get_probe(qdev, PRB_MX_ADDR_SYS_CLOCK,
- PRB_MX_ADDR_VALID_SYS_MOD, buf);
+ PRB_MX_ADDR_VALID_SYS_MOD, buf);
buf = ql_get_probe(qdev, PRB_MX_ADDR_PCI_CLOCK,
- PRB_MX_ADDR_VALID_PCI_MOD, buf);
+ PRB_MX_ADDR_VALID_PCI_MOD, buf);
buf = ql_get_probe(qdev, PRB_MX_ADDR_XGM_CLOCK,
- PRB_MX_ADDR_VALID_XGM_MOD, buf);
+ PRB_MX_ADDR_VALID_XGM_MOD, buf);
buf = ql_get_probe(qdev, PRB_MX_ADDR_FC_CLOCK,
- PRB_MX_ADDR_VALID_FC_MOD, buf);
+ PRB_MX_ADDR_VALID_FC_MOD, buf);
return 0;
}
@@ -667,7 +665,7 @@ static void ql_get_mac_protocol_registers(struct ql_adapter *qdev, u32 *buf)
result_index = 0;
while ((result_index & MAC_ADDR_MR) == 0) {
result_index = ql_read32(qdev,
- MAC_ADDR_IDX);
+ MAC_ADDR_IDX);
}
result_data = ql_read32(qdev, MAC_ADDR_DATA);
*buf = result_index;
@@ -741,7 +739,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Insert the global header */
memset(&(mpi_coredump->mpi_global_header), 0,
- sizeof(struct mpi_coredump_global_header));
+ sizeof(struct mpi_coredump_global_header));
mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE;
mpi_coredump->mpi_global_header.headerSize =
sizeof(struct mpi_coredump_global_header);
@@ -752,23 +750,23 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get generic NIC reg dump */
ql_build_coredump_seg_header(&mpi_coredump->nic_regs_seg_hdr,
- NIC1_CONTROL_SEG_NUM,
+ NIC1_CONTROL_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->nic_regs), "NIC1 Registers");
ql_build_coredump_seg_header(&mpi_coredump->nic2_regs_seg_hdr,
- NIC2_CONTROL_SEG_NUM,
+ NIC2_CONTROL_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->nic2_regs), "NIC2 Registers");
/* Get XGMac registers. (Segment 18, Rev C. step 21) */
ql_build_coredump_seg_header(&mpi_coredump->xgmac1_seg_hdr,
- NIC1_XGMAC_SEG_NUM,
+ NIC1_XGMAC_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->xgmac1), "NIC1 XGMac Registers");
ql_build_coredump_seg_header(&mpi_coredump->xgmac2_seg_hdr,
- NIC2_XGMAC_SEG_NUM,
+ NIC2_XGMAC_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->xgmac2), "NIC2 XGMac Registers");
@@ -799,97 +797,97 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Rev C. Step 20a */
ql_build_coredump_seg_header(&mpi_coredump->xaui_an_hdr,
- XAUI_AN_SEG_NUM,
+ XAUI_AN_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes_xaui_an),
"XAUI AN Registers");
/* Rev C. Step 20b */
ql_build_coredump_seg_header(&mpi_coredump->xaui_hss_pcs_hdr,
- XAUI_HSS_PCS_SEG_NUM,
+ XAUI_HSS_PCS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes_xaui_hss_pcs),
"XAUI HSS PCS Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi_an_hdr, XFI_AN_SEG_NUM,
- sizeof(struct mpi_coredump_segment_header) +
+ sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes_xfi_an),
"XFI AN Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi_train_hdr,
- XFI_TRAIN_SEG_NUM,
+ XFI_TRAIN_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes_xfi_train),
"XFI TRAIN Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_pcs_hdr,
- XFI_HSS_PCS_SEG_NUM,
+ XFI_HSS_PCS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes_xfi_hss_pcs),
"XFI HSS PCS Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_tx_hdr,
- XFI_HSS_TX_SEG_NUM,
+ XFI_HSS_TX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes_xfi_hss_tx),
"XFI HSS TX Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_rx_hdr,
- XFI_HSS_RX_SEG_NUM,
+ XFI_HSS_RX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes_xfi_hss_rx),
"XFI HSS RX Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_pll_hdr,
- XFI_HSS_PLL_SEG_NUM,
+ XFI_HSS_PLL_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes_xfi_hss_pll),
"XFI HSS PLL Registers");
ql_build_coredump_seg_header(&mpi_coredump->xaui2_an_hdr,
- XAUI2_AN_SEG_NUM,
+ XAUI2_AN_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes2_xaui_an),
"XAUI2 AN Registers");
ql_build_coredump_seg_header(&mpi_coredump->xaui2_hss_pcs_hdr,
- XAUI2_HSS_PCS_SEG_NUM,
+ XAUI2_HSS_PCS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes2_xaui_hss_pcs),
"XAUI2 HSS PCS Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi2_an_hdr,
- XFI2_AN_SEG_NUM,
+ XFI2_AN_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes2_xfi_an),
"XFI2 AN Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi2_train_hdr,
- XFI2_TRAIN_SEG_NUM,
+ XFI2_TRAIN_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes2_xfi_train),
"XFI2 TRAIN Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_pcs_hdr,
- XFI2_HSS_PCS_SEG_NUM,
+ XFI2_HSS_PCS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes2_xfi_hss_pcs),
"XFI2 HSS PCS Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_tx_hdr,
- XFI2_HSS_TX_SEG_NUM,
+ XFI2_HSS_TX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes2_xfi_hss_tx),
"XFI2 HSS TX Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_rx_hdr,
- XFI2_HSS_RX_SEG_NUM,
+ XFI2_HSS_RX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes2_xfi_hss_rx),
"XFI2 HSS RX Registers");
ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_pll_hdr,
- XFI2_HSS_PLL_SEG_NUM,
+ XFI2_HSS_PLL_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->serdes2_xfi_hss_pll),
"XFI2 HSS PLL Registers");
@@ -903,7 +901,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
}
ql_build_coredump_seg_header(&mpi_coredump->core_regs_seg_hdr,
- CORE_SEG_NUM,
+ CORE_SEG_NUM,
sizeof(mpi_coredump->core_regs_seg_hdr) +
sizeof(mpi_coredump->mpi_core_regs) +
sizeof(mpi_coredump->mpi_core_sh_regs),
@@ -922,7 +920,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the Test Logic Registers */
ql_build_coredump_seg_header(&mpi_coredump->test_logic_regs_seg_hdr,
- TEST_LOGIC_SEG_NUM,
+ TEST_LOGIC_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->test_logic_regs),
"Test Logic Regs");
@@ -933,7 +931,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the RMII Registers */
ql_build_coredump_seg_header(&mpi_coredump->rmii_regs_seg_hdr,
- RMII_SEG_NUM,
+ RMII_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->rmii_regs),
"RMII Registers");
@@ -944,7 +942,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the FCMAC1 Registers */
ql_build_coredump_seg_header(&mpi_coredump->fcmac1_regs_seg_hdr,
- FCMAC1_SEG_NUM,
+ FCMAC1_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->fcmac1_regs),
"FCMAC1 Registers");
@@ -956,7 +954,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the FCMAC2 Registers */
ql_build_coredump_seg_header(&mpi_coredump->fcmac2_regs_seg_hdr,
- FCMAC2_SEG_NUM,
+ FCMAC2_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->fcmac2_regs),
"FCMAC2 Registers");
@@ -968,7 +966,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the FC1 MBX Registers */
ql_build_coredump_seg_header(&mpi_coredump->fc1_mbx_regs_seg_hdr,
- FC1_MBOX_SEG_NUM,
+ FC1_MBOX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->fc1_mbx_regs),
"FC1 MBox Regs");
@@ -979,7 +977,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the IDE Registers */
ql_build_coredump_seg_header(&mpi_coredump->ide_regs_seg_hdr,
- IDE_SEG_NUM,
+ IDE_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->ide_regs),
"IDE Registers");
@@ -990,7 +988,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the NIC1 MBX Registers */
ql_build_coredump_seg_header(&mpi_coredump->nic1_mbx_regs_seg_hdr,
- NIC1_MBOX_SEG_NUM,
+ NIC1_MBOX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->nic1_mbx_regs),
"NIC1 MBox Regs");
@@ -1001,7 +999,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the SMBus Registers */
ql_build_coredump_seg_header(&mpi_coredump->smbus_regs_seg_hdr,
- SMBUS_SEG_NUM,
+ SMBUS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->smbus_regs),
"SMBus Registers");
@@ -1012,7 +1010,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the FC2 MBX Registers */
ql_build_coredump_seg_header(&mpi_coredump->fc2_mbx_regs_seg_hdr,
- FC2_MBOX_SEG_NUM,
+ FC2_MBOX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->fc2_mbx_regs),
"FC2 MBox Regs");
@@ -1023,7 +1021,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the NIC2 MBX Registers */
ql_build_coredump_seg_header(&mpi_coredump->nic2_mbx_regs_seg_hdr,
- NIC2_MBOX_SEG_NUM,
+ NIC2_MBOX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->nic2_mbx_regs),
"NIC2 MBox Regs");
@@ -1034,7 +1032,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the I2C Registers */
ql_build_coredump_seg_header(&mpi_coredump->i2c_regs_seg_hdr,
- I2C_SEG_NUM,
+ I2C_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->i2c_regs),
"I2C Registers");
@@ -1045,7 +1043,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the MEMC Registers */
ql_build_coredump_seg_header(&mpi_coredump->memc_regs_seg_hdr,
- MEMC_SEG_NUM,
+ MEMC_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->memc_regs),
"MEMC Registers");
@@ -1056,7 +1054,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the PBus Registers */
ql_build_coredump_seg_header(&mpi_coredump->pbus_regs_seg_hdr,
- PBUS_SEG_NUM,
+ PBUS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->pbus_regs),
"PBUS Registers");
@@ -1067,7 +1065,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the MDE Registers */
ql_build_coredump_seg_header(&mpi_coredump->mde_regs_seg_hdr,
- MDE_SEG_NUM,
+ MDE_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->mde_regs),
"MDE Registers");
@@ -1077,7 +1075,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
goto err;
ql_build_coredump_seg_header(&mpi_coredump->misc_nic_seg_hdr,
- MISC_NIC_INFO_SEG_NUM,
+ MISC_NIC_INFO_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->misc_nic_info),
"MISC NIC INFO");
@@ -1089,14 +1087,14 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Segment 31 */
/* Get indexed register values. */
ql_build_coredump_seg_header(&mpi_coredump->intr_states_seg_hdr,
- INTR_STATES_SEG_NUM,
+ INTR_STATES_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->intr_states),
"INTR States");
ql_get_intr_states(qdev, &mpi_coredump->intr_states[0]);
ql_build_coredump_seg_header(&mpi_coredump->cam_entries_seg_hdr,
- CAM_ENTRIES_SEG_NUM,
+ CAM_ENTRIES_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->cam_entries),
"CAM Entries");
@@ -1105,18 +1103,18 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
goto err;
ql_build_coredump_seg_header(&mpi_coredump->nic_routing_words_seg_hdr,
- ROUTING_WORDS_SEG_NUM,
+ ROUTING_WORDS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->nic_routing_words),
"Routing Words");
status = ql_get_routing_entries(qdev,
- &mpi_coredump->nic_routing_words[0]);
+ &mpi_coredump->nic_routing_words[0]);
if (status)
goto err;
/* Segment 34 (Rev C. step 23) */
ql_build_coredump_seg_header(&mpi_coredump->ets_seg_hdr,
- ETS_SEG_NUM,
+ ETS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->ets),
"ETS Registers");
@@ -1125,24 +1123,24 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
goto err;
ql_build_coredump_seg_header(&mpi_coredump->probe_dump_seg_hdr,
- PROBE_DUMP_SEG_NUM,
+ PROBE_DUMP_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->probe_dump),
"Probe Dump");
ql_get_probe_dump(qdev, &mpi_coredump->probe_dump[0]);
ql_build_coredump_seg_header(&mpi_coredump->routing_reg_seg_hdr,
- ROUTING_INDEX_SEG_NUM,
+ ROUTING_INDEX_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->routing_regs),
"Routing Regs");
status = ql_get_routing_index_registers(qdev,
- &mpi_coredump->routing_regs[0]);
+ &mpi_coredump->routing_regs[0]);
if (status)
goto err;
ql_build_coredump_seg_header(&mpi_coredump->mac_prot_reg_seg_hdr,
- MAC_PROTOCOL_SEG_NUM,
+ MAC_PROTOCOL_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->mac_prot_regs),
"MAC Prot Regs");
@@ -1150,7 +1148,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Get the semaphore registers for all 5 functions */
ql_build_coredump_seg_header(&mpi_coredump->sem_regs_seg_hdr,
- SEM_REGS_SEG_NUM,
+ SEM_REGS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header) +
sizeof(mpi_coredump->sem_regs), "Sem Registers");
@@ -1176,12 +1174,12 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
}
ql_build_coredump_seg_header(&mpi_coredump->code_ram_seg_hdr,
- WCS_RAM_SEG_NUM,
+ WCS_RAM_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->code_ram),
"WCS RAM");
status = ql_dump_risc_ram_area(qdev, &mpi_coredump->code_ram[0],
- CODE_RAM_ADDR, CODE_RAM_CNT);
+ CODE_RAM_ADDR, CODE_RAM_CNT);
if (status) {
netif_err(qdev, drv, qdev->ndev,
"Failed Dump of CODE RAM. Status = 0x%.08x\n",
@@ -1191,12 +1189,12 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
/* Insert the segment header */
ql_build_coredump_seg_header(&mpi_coredump->memc_ram_seg_hdr,
- MEMC_RAM_SEG_NUM,
+ MEMC_RAM_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->memc_ram),
"MEMC RAM");
status = ql_dump_risc_ram_area(qdev, &mpi_coredump->memc_ram[0],
- MEMC_RAM_ADDR, MEMC_RAM_CNT);
+ MEMC_RAM_ADDR, MEMC_RAM_CNT);
if (status) {
netif_err(qdev, drv, qdev->ndev,
"Failed Dump of MEMC RAM. Status = 0x%.08x\n",
@@ -1231,7 +1229,7 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev,
memset(&(mpi_coredump->mpi_global_header), 0,
- sizeof(struct mpi_coredump_global_header));
+ sizeof(struct mpi_coredump_global_header));
mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE;
mpi_coredump->mpi_global_header.headerSize =
sizeof(struct mpi_coredump_global_header);
@@ -1243,7 +1241,7 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev,
/* segment 16 */
ql_build_coredump_seg_header(&mpi_coredump->misc_nic_seg_hdr,
- MISC_NIC_INFO_SEG_NUM,
+ MISC_NIC_INFO_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->misc_nic_info),
"MISC NIC INFO");
@@ -1254,7 +1252,7 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev,
/* Segment 16, Rev C. Step 18 */
ql_build_coredump_seg_header(&mpi_coredump->nic_regs_seg_hdr,
- NIC1_CONTROL_SEG_NUM,
+ NIC1_CONTROL_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->nic_regs),
"NIC Registers");
@@ -1265,14 +1263,14 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev,
/* Segment 31 */
/* Get indexed register values. */
ql_build_coredump_seg_header(&mpi_coredump->intr_states_seg_hdr,
- INTR_STATES_SEG_NUM,
+ INTR_STATES_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->intr_states),
"INTR States");
ql_get_intr_states(qdev, &mpi_coredump->intr_states[0]);
ql_build_coredump_seg_header(&mpi_coredump->cam_entries_seg_hdr,
- CAM_ENTRIES_SEG_NUM,
+ CAM_ENTRIES_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->cam_entries),
"CAM Entries");
@@ -1281,18 +1279,18 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev,
return;
ql_build_coredump_seg_header(&mpi_coredump->nic_routing_words_seg_hdr,
- ROUTING_WORDS_SEG_NUM,
+ ROUTING_WORDS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->nic_routing_words),
"Routing Words");
status = ql_get_routing_entries(qdev,
- &mpi_coredump->nic_routing_words[0]);
+ &mpi_coredump->nic_routing_words[0]);
if (status)
return;
/* Segment 34 (Rev C. step 23) */
ql_build_coredump_seg_header(&mpi_coredump->ets_seg_hdr,
- ETS_SEG_NUM,
+ ETS_SEG_NUM,
sizeof(struct mpi_coredump_segment_header)
+ sizeof(mpi_coredump->ets),
"ETS Registers");
@@ -1630,6 +1628,7 @@ void ql_dump_qdev(struct ql_adapter *qdev)
DUMP_QDEV_FIELD(qdev, "0x%08x", xg_sem_mask);
DUMP_QDEV_FIELD(qdev, "0x%08x", port_link_up);
DUMP_QDEV_FIELD(qdev, "0x%08x", port_init);
+ DUMP_QDEV_FIELD(qdev, "%u", lbq_buf_size);
}
#endif
@@ -1650,7 +1649,7 @@ void ql_dump_wqicb(struct wqicb *wqicb)
void ql_dump_tx_ring(struct tx_ring *tx_ring)
{
- if (tx_ring == NULL)
+ if (!tx_ring)
return;
pr_err("===================== Dumping tx_ring %d ===============\n",
tx_ring->wq_id);
@@ -1730,16 +1729,24 @@ void ql_dump_cqicb(struct cqicb *cqicb)
le16_to_cpu(cqicb->sbq_len));
}
+static const char *qlge_rx_ring_type_name(struct rx_ring *rx_ring)
+{
+ struct ql_adapter *qdev = rx_ring->qdev;
+
+ if (rx_ring->cq_id < qdev->rss_ring_count)
+ return "RX COMPLETION";
+ else
+ return "TX COMPLETION";
+};
+
void ql_dump_rx_ring(struct rx_ring *rx_ring)
{
- if (rx_ring == NULL)
+ if (!rx_ring)
return;
pr_err("===================== Dumping rx_ring %d ===============\n",
rx_ring->cq_id);
- pr_err("Dumping rx_ring %d, type = %s%s%s\n",
- rx_ring->cq_id, rx_ring->type == DEFAULT_Q ? "DEFAULT" : "",
- rx_ring->type == TX_Q ? "OUTBOUND COMPLETIONS" : "",
- rx_ring->type == RX_Q ? "INBOUND_COMPLETIONS" : "");
+ pr_err("Dumping rx_ring %d, type = %s\n", rx_ring->cq_id,
+ qlge_rx_ring_type_name(rx_ring));
pr_err("rx_ring->cqicb = %p\n", &rx_ring->cqicb);
pr_err("rx_ring->cq_base = %p\n", rx_ring->cq_base);
pr_err("rx_ring->cq_base_dma = %llx\n",
@@ -1758,41 +1765,33 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring)
pr_err("rx_ring->curr_entry = %p\n", rx_ring->curr_entry);
pr_err("rx_ring->valid_db_reg = %p\n", rx_ring->valid_db_reg);
- pr_err("rx_ring->lbq_base = %p\n", rx_ring->lbq_base);
- pr_err("rx_ring->lbq_base_dma = %llx\n",
- (unsigned long long) rx_ring->lbq_base_dma);
- pr_err("rx_ring->lbq_base_indirect = %p\n",
- rx_ring->lbq_base_indirect);
- pr_err("rx_ring->lbq_base_indirect_dma = %llx\n",
- (unsigned long long) rx_ring->lbq_base_indirect_dma);
- pr_err("rx_ring->lbq = %p\n", rx_ring->lbq);
- pr_err("rx_ring->lbq_len = %d\n", rx_ring->lbq_len);
- pr_err("rx_ring->lbq_size = %d\n", rx_ring->lbq_size);
- pr_err("rx_ring->lbq_prod_idx_db_reg = %p\n",
- rx_ring->lbq_prod_idx_db_reg);
- pr_err("rx_ring->lbq_prod_idx = %d\n", rx_ring->lbq_prod_idx);
- pr_err("rx_ring->lbq_curr_idx = %d\n", rx_ring->lbq_curr_idx);
+ pr_err("rx_ring->lbq.base = %p\n", rx_ring->lbq.base);
+ pr_err("rx_ring->lbq.base_dma = %llx\n",
+ (unsigned long long)rx_ring->lbq.base_dma);
+ pr_err("rx_ring->lbq.base_indirect = %p\n",
+ rx_ring->lbq.base_indirect);
+ pr_err("rx_ring->lbq.base_indirect_dma = %llx\n",
+ (unsigned long long)rx_ring->lbq.base_indirect_dma);
+ pr_err("rx_ring->lbq = %p\n", rx_ring->lbq.queue);
+ pr_err("rx_ring->lbq.prod_idx_db_reg = %p\n",
+ rx_ring->lbq.prod_idx_db_reg);
+ pr_err("rx_ring->lbq.next_to_use = %d\n", rx_ring->lbq.next_to_use);
+ pr_err("rx_ring->lbq.next_to_clean = %d\n", rx_ring->lbq.next_to_clean);
pr_err("rx_ring->lbq_clean_idx = %d\n", rx_ring->lbq_clean_idx);
pr_err("rx_ring->lbq_free_cnt = %d\n", rx_ring->lbq_free_cnt);
- pr_err("rx_ring->lbq_buf_size = %d\n", rx_ring->lbq_buf_size);
-
- pr_err("rx_ring->sbq_base = %p\n", rx_ring->sbq_base);
- pr_err("rx_ring->sbq_base_dma = %llx\n",
- (unsigned long long) rx_ring->sbq_base_dma);
- pr_err("rx_ring->sbq_base_indirect = %p\n",
- rx_ring->sbq_base_indirect);
- pr_err("rx_ring->sbq_base_indirect_dma = %llx\n",
- (unsigned long long) rx_ring->sbq_base_indirect_dma);
- pr_err("rx_ring->sbq = %p\n", rx_ring->sbq);
- pr_err("rx_ring->sbq_len = %d\n", rx_ring->sbq_len);
- pr_err("rx_ring->sbq_size = %d\n", rx_ring->sbq_size);
- pr_err("rx_ring->sbq_prod_idx_db_reg addr = %p\n",
- rx_ring->sbq_prod_idx_db_reg);
- pr_err("rx_ring->sbq_prod_idx = %d\n", rx_ring->sbq_prod_idx);
- pr_err("rx_ring->sbq_curr_idx = %d\n", rx_ring->sbq_curr_idx);
- pr_err("rx_ring->sbq_clean_idx = %d\n", rx_ring->sbq_clean_idx);
- pr_err("rx_ring->sbq_free_cnt = %d\n", rx_ring->sbq_free_cnt);
- pr_err("rx_ring->sbq_buf_size = %d\n", rx_ring->sbq_buf_size);
+
+ pr_err("rx_ring->sbq.base = %p\n", rx_ring->sbq.base);
+ pr_err("rx_ring->sbq.base_dma = %llx\n",
+ (unsigned long long)rx_ring->sbq.base_dma);
+ pr_err("rx_ring->sbq.base_indirect = %p\n",
+ rx_ring->sbq.base_indirect);
+ pr_err("rx_ring->sbq.base_indirect_dma = %llx\n",
+ (unsigned long long)rx_ring->sbq.base_indirect_dma);
+ pr_err("rx_ring->sbq = %p\n", rx_ring->sbq.queue);
+ pr_err("rx_ring->sbq.prod_idx_db_reg addr = %p\n",
+ rx_ring->sbq.prod_idx_db_reg);
+ pr_err("rx_ring->sbq.next_to_use = %d\n", rx_ring->sbq.next_to_use);
+ pr_err("rx_ring->sbq.next_to_clean = %d\n", rx_ring->sbq.next_to_clean);
pr_err("rx_ring->cq_id = %d\n", rx_ring->cq_id);
pr_err("rx_ring->irq = %d\n", rx_ring->irq);
pr_err("rx_ring->cpu = %d\n", rx_ring->cpu);
@@ -1806,7 +1805,7 @@ void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id)
pr_err("%s: Enter\n", __func__);
ptr = kmalloc(size, GFP_ATOMIC);
- if (ptr == NULL)
+ if (!ptr)
return;
if (ql_write_cfg(qdev, ptr, size, bit, q_id)) {
@@ -1992,7 +1991,7 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp)
le16_to_cpu(ib_mac_rsp->vlan_id));
pr_err("flags4 = %s%s%s\n",
- ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV ? "HV " : "",
+ ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV ? "HV " : "",
ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS ? "HS " : "",
ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HL ? "HL " : "");
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index 6cae33072496..6ad4515311f7 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -167,9 +167,9 @@ void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask)
int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit)
{
u32 temp;
- int count = UDELAY_COUNT;
+ int count;
- while (count) {
+ for (count = 0; count < UDELAY_COUNT; count++) {
temp = ql_read32(qdev, reg);
/* check for errors */
@@ -181,7 +181,6 @@ int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit)
} else if (temp & bit)
return 0;
udelay(UDELAY_DELAY);
- count--;
}
netif_alert(qdev, probe, qdev->ndev,
"Timed out waiting for reg %x to come ready.\n", reg);
@@ -193,17 +192,16 @@ int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit)
*/
static int ql_wait_cfg(struct ql_adapter *qdev, u32 bit)
{
- int count = UDELAY_COUNT;
+ int count;
u32 temp;
- while (count) {
+ for (count = 0; count < UDELAY_COUNT; count++) {
temp = ql_read32(qdev, CFG);
if (temp & CFG_LE)
return -EIO;
if (!(temp & bit))
return 0;
udelay(UDELAY_DELAY);
- count--;
}
return -ETIMEDOUT;
}
@@ -625,75 +623,26 @@ static void ql_disable_interrupts(struct ql_adapter *qdev)
ql_write32(qdev, INTR_EN, (INTR_EN_EI << 16));
}
-/* If we're running with multiple MSI-X vectors then we enable on the fly.
- * Otherwise, we may have multiple outstanding workers and don't want to
- * enable until the last one finishes. In this case, the irq_cnt gets
- * incremented every time we queue a worker and decremented every time
- * a worker finishes. Once it hits zero we enable the interrupt.
- */
-u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
+static void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
- u32 var = 0;
- unsigned long hw_flags = 0;
- struct intr_context *ctx = qdev->intr_context + intr;
-
- if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr)) {
- /* Always enable if we're MSIX multi interrupts and
- * it's not the default (zeroeth) interrupt.
- */
- ql_write32(qdev, INTR_EN,
- ctx->intr_en_mask);
- var = ql_read32(qdev, STS);
- return var;
- }
+ struct intr_context *ctx = &qdev->intr_context[intr];
- spin_lock_irqsave(&qdev->hw_lock, hw_flags);
- if (atomic_dec_and_test(&ctx->irq_cnt)) {
- ql_write32(qdev, INTR_EN,
- ctx->intr_en_mask);
- var = ql_read32(qdev, STS);
- }
- spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
- return var;
+ ql_write32(qdev, INTR_EN, ctx->intr_en_mask);
}
-static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
+static void ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
- u32 var = 0;
- struct intr_context *ctx;
-
- /* HW disables for us if we're MSIX multi interrupts and
- * it's not the default (zeroeth) interrupt.
- */
- if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr))
- return 0;
+ struct intr_context *ctx = &qdev->intr_context[intr];
- ctx = qdev->intr_context + intr;
- spin_lock(&qdev->hw_lock);
- if (!atomic_read(&ctx->irq_cnt)) {
- ql_write32(qdev, INTR_EN,
- ctx->intr_dis_mask);
- var = ql_read32(qdev, STS);
- }
- atomic_inc(&ctx->irq_cnt);
- spin_unlock(&qdev->hw_lock);
- return var;
+ ql_write32(qdev, INTR_EN, ctx->intr_dis_mask);
}
static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev)
{
int i;
- for (i = 0; i < qdev->intr_count; i++) {
- /* The enable call does a atomic_dec_and_test
- * and enables only if the result is zero.
- * So we precharge it here.
- */
- if (unlikely(!test_bit(QL_MSIX_ENABLED, &qdev->flags) ||
- i == 0))
- atomic_set(&qdev->intr_context[i].irq_cnt, 1);
- ql_enable_completion_interrupt(qdev, i);
- }
+ for (i = 0; i < qdev->intr_count; i++)
+ ql_enable_completion_interrupt(qdev, i);
}
static int ql_validate_flash(struct ql_adapter *qdev, u32 size, const char *str)
@@ -1027,48 +976,32 @@ static inline unsigned int ql_lbq_block_size(struct ql_adapter *qdev)
return PAGE_SIZE << qdev->lbq_buf_order;
}
-/* Get the next large buffer. */
-static struct bq_desc *ql_get_curr_lbuf(struct rx_ring *rx_ring)
+static struct qlge_bq_desc *qlge_get_curr_buf(struct qlge_bq *bq)
{
- struct bq_desc *lbq_desc = &rx_ring->lbq[rx_ring->lbq_curr_idx];
- rx_ring->lbq_curr_idx++;
- if (rx_ring->lbq_curr_idx == rx_ring->lbq_len)
- rx_ring->lbq_curr_idx = 0;
- rx_ring->lbq_free_cnt++;
- return lbq_desc;
+ struct qlge_bq_desc *bq_desc;
+
+ bq_desc = &bq->queue[bq->next_to_clean];
+ bq->next_to_clean = QLGE_BQ_WRAP(bq->next_to_clean + 1);
+
+ return bq_desc;
}
-static struct bq_desc *ql_get_curr_lchunk(struct ql_adapter *qdev,
- struct rx_ring *rx_ring)
+static struct qlge_bq_desc *ql_get_curr_lchunk(struct ql_adapter *qdev,
+ struct rx_ring *rx_ring)
{
- struct bq_desc *lbq_desc = ql_get_curr_lbuf(rx_ring);
+ struct qlge_bq_desc *lbq_desc = qlge_get_curr_buf(&rx_ring->lbq);
- pci_dma_sync_single_for_cpu(qdev->pdev,
- dma_unmap_addr(lbq_desc, mapaddr),
- rx_ring->lbq_buf_size,
- PCI_DMA_FROMDEVICE);
+ pci_dma_sync_single_for_cpu(qdev->pdev, lbq_desc->dma_addr,
+ qdev->lbq_buf_size, PCI_DMA_FROMDEVICE);
- /* If it's the last chunk of our master page then
- * we unmap it.
- */
- if ((lbq_desc->p.pg_chunk.offset + rx_ring->lbq_buf_size)
- == ql_lbq_block_size(qdev))
- pci_unmap_page(qdev->pdev,
- lbq_desc->p.pg_chunk.map,
- ql_lbq_block_size(qdev),
- PCI_DMA_FROMDEVICE);
- return lbq_desc;
-}
+ if ((lbq_desc->p.pg_chunk.offset + qdev->lbq_buf_size) ==
+ ql_lbq_block_size(qdev)) {
+ /* last chunk of the master page */
+ pci_unmap_page(qdev->pdev, lbq_desc->dma_addr,
+ ql_lbq_block_size(qdev), PCI_DMA_FROMDEVICE);
+ }
-/* Get the next small buffer. */
-static struct bq_desc *ql_get_curr_sbuf(struct rx_ring *rx_ring)
-{
- struct bq_desc *sbq_desc = &rx_ring->sbq[rx_ring->sbq_curr_idx];
- rx_ring->sbq_curr_idx++;
- if (rx_ring->sbq_curr_idx == rx_ring->sbq_len)
- rx_ring->sbq_curr_idx = 0;
- rx_ring->sbq_free_cnt++;
- return sbq_desc;
+ return lbq_desc;
}
/* Update an rx ring index. */
@@ -1087,178 +1020,192 @@ static void ql_write_cq_idx(struct rx_ring *rx_ring)
ql_write_db_reg(rx_ring->cnsmr_idx, rx_ring->cnsmr_idx_db_reg);
}
-static int ql_get_next_chunk(struct ql_adapter *qdev, struct rx_ring *rx_ring,
- struct bq_desc *lbq_desc)
+static const char * const bq_type_name[] = {
+ [QLGE_SB] = "sbq",
+ [QLGE_LB] = "lbq",
+};
+
+/* return 0 or negative error */
+static int qlge_refill_sb(struct rx_ring *rx_ring,
+ struct qlge_bq_desc *sbq_desc, gfp_t gfp)
{
- if (!rx_ring->pg_chunk.page) {
- u64 map;
- rx_ring->pg_chunk.page = alloc_pages(__GFP_COMP | GFP_ATOMIC,
- qdev->lbq_buf_order);
- if (unlikely(!rx_ring->pg_chunk.page)) {
- netif_err(qdev, drv, qdev->ndev,
- "page allocation failed.\n");
+ struct ql_adapter *qdev = rx_ring->qdev;
+ struct sk_buff *skb;
+
+ if (sbq_desc->p.skb)
+ return 0;
+
+ netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
+ "ring %u sbq: getting new skb for index %d.\n",
+ rx_ring->cq_id, sbq_desc->index);
+
+ skb = __netdev_alloc_skb(qdev->ndev, SMALL_BUFFER_SIZE, gfp);
+ if (!skb)
+ return -ENOMEM;
+ skb_reserve(skb, QLGE_SB_PAD);
+
+ sbq_desc->dma_addr = pci_map_single(qdev->pdev, skb->data,
+ SMALL_BUF_MAP_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(qdev->pdev, sbq_desc->dma_addr)) {
+ netif_err(qdev, ifup, qdev->ndev, "PCI mapping failed.\n");
+ dev_kfree_skb_any(skb);
+ return -EIO;
+ }
+ *sbq_desc->buf_ptr = cpu_to_le64(sbq_desc->dma_addr);
+
+ sbq_desc->p.skb = skb;
+ return 0;
+}
+
+/* return 0 or negative error */
+static int qlge_refill_lb(struct rx_ring *rx_ring,
+ struct qlge_bq_desc *lbq_desc, gfp_t gfp)
+{
+ struct ql_adapter *qdev = rx_ring->qdev;
+ struct qlge_page_chunk *master_chunk = &rx_ring->master_chunk;
+
+ if (!master_chunk->page) {
+ struct page *page;
+ dma_addr_t dma_addr;
+
+ page = alloc_pages(gfp | __GFP_COMP, qdev->lbq_buf_order);
+ if (unlikely(!page))
return -ENOMEM;
- }
- rx_ring->pg_chunk.offset = 0;
- map = pci_map_page(qdev->pdev, rx_ring->pg_chunk.page,
- 0, ql_lbq_block_size(qdev),
+ dma_addr = pci_map_page(qdev->pdev, page, 0,
+ ql_lbq_block_size(qdev),
PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(qdev->pdev, map)) {
- __free_pages(rx_ring->pg_chunk.page,
- qdev->lbq_buf_order);
- rx_ring->pg_chunk.page = NULL;
+ if (pci_dma_mapping_error(qdev->pdev, dma_addr)) {
+ __free_pages(page, qdev->lbq_buf_order);
netif_err(qdev, drv, qdev->ndev,
"PCI mapping failed.\n");
- return -ENOMEM;
+ return -EIO;
}
- rx_ring->pg_chunk.map = map;
- rx_ring->pg_chunk.va = page_address(rx_ring->pg_chunk.page);
+ master_chunk->page = page;
+ master_chunk->va = page_address(page);
+ master_chunk->offset = 0;
+ rx_ring->chunk_dma_addr = dma_addr;
}
- /* Copy the current master pg_chunk info
- * to the current descriptor.
- */
- lbq_desc->p.pg_chunk = rx_ring->pg_chunk;
+ lbq_desc->p.pg_chunk = *master_chunk;
+ lbq_desc->dma_addr = rx_ring->chunk_dma_addr;
+ *lbq_desc->buf_ptr = cpu_to_le64(lbq_desc->dma_addr +
+ lbq_desc->p.pg_chunk.offset);
/* Adjust the master page chunk for next
* buffer get.
*/
- rx_ring->pg_chunk.offset += rx_ring->lbq_buf_size;
- if (rx_ring->pg_chunk.offset == ql_lbq_block_size(qdev)) {
- rx_ring->pg_chunk.page = NULL;
- lbq_desc->p.pg_chunk.last_flag = 1;
+ master_chunk->offset += qdev->lbq_buf_size;
+ if (master_chunk->offset == ql_lbq_block_size(qdev)) {
+ master_chunk->page = NULL;
} else {
- rx_ring->pg_chunk.va += rx_ring->lbq_buf_size;
- get_page(rx_ring->pg_chunk.page);
- lbq_desc->p.pg_chunk.last_flag = 0;
+ master_chunk->va += qdev->lbq_buf_size;
+ get_page(master_chunk->page);
}
+
return 0;
}
-/* Process (refill) a large buffer queue. */
-static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+
+/* return 0 or negative error */
+static int qlge_refill_bq(struct qlge_bq *bq, gfp_t gfp)
{
- u32 clean_idx = rx_ring->lbq_clean_idx;
- u32 start_idx = clean_idx;
- struct bq_desc *lbq_desc;
- u64 map;
+ struct rx_ring *rx_ring = QLGE_BQ_CONTAINER(bq);
+ struct ql_adapter *qdev = rx_ring->qdev;
+ struct qlge_bq_desc *bq_desc;
+ int refill_count;
+ int retval;
int i;
- while (rx_ring->lbq_free_cnt > 32) {
- for (i = (rx_ring->lbq_clean_idx % 16); i < 16; i++) {
- netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
- "lbq: try cleaning clean_idx = %d.\n",
- clean_idx);
- lbq_desc = &rx_ring->lbq[clean_idx];
- if (ql_get_next_chunk(qdev, rx_ring, lbq_desc)) {
- rx_ring->lbq_clean_idx = clean_idx;
- netif_err(qdev, ifup, qdev->ndev,
- "Could not get a page chunk, i=%d, clean_idx =%d .\n",
- i, clean_idx);
- return;
- }
+ refill_count = QLGE_BQ_WRAP(QLGE_BQ_ALIGN(bq->next_to_clean - 1) -
+ bq->next_to_use);
+ if (!refill_count)
+ return 0;
+
+ i = bq->next_to_use;
+ bq_desc = &bq->queue[i];
+ i -= QLGE_BQ_LEN;
+ do {
+ netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
+ "ring %u %s: try cleaning idx %d\n",
+ rx_ring->cq_id, bq_type_name[bq->type], i);
- map = lbq_desc->p.pg_chunk.map +
- lbq_desc->p.pg_chunk.offset;
- dma_unmap_addr_set(lbq_desc, mapaddr, map);
- dma_unmap_len_set(lbq_desc, maplen,
- rx_ring->lbq_buf_size);
- *lbq_desc->addr = cpu_to_le64(map);
-
- pci_dma_sync_single_for_device(qdev->pdev, map,
- rx_ring->lbq_buf_size,
- PCI_DMA_FROMDEVICE);
- clean_idx++;
- if (clean_idx == rx_ring->lbq_len)
- clean_idx = 0;
+ if (bq->type == QLGE_SB)
+ retval = qlge_refill_sb(rx_ring, bq_desc, gfp);
+ else
+ retval = qlge_refill_lb(rx_ring, bq_desc, gfp);
+ if (retval < 0) {
+ netif_err(qdev, ifup, qdev->ndev,
+ "ring %u %s: Could not get a page chunk, idx %d\n",
+ rx_ring->cq_id, bq_type_name[bq->type], i);
+ break;
}
- rx_ring->lbq_clean_idx = clean_idx;
- rx_ring->lbq_prod_idx += 16;
- if (rx_ring->lbq_prod_idx == rx_ring->lbq_len)
- rx_ring->lbq_prod_idx = 0;
- rx_ring->lbq_free_cnt -= 16;
- }
+ bq_desc++;
+ i++;
+ if (unlikely(!i)) {
+ bq_desc = &bq->queue[0];
+ i -= QLGE_BQ_LEN;
+ }
+ refill_count--;
+ } while (refill_count);
+ i += QLGE_BQ_LEN;
- if (start_idx != clean_idx) {
- netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
- "lbq: updating prod idx = %d.\n",
- rx_ring->lbq_prod_idx);
- ql_write_db_reg(rx_ring->lbq_prod_idx,
- rx_ring->lbq_prod_idx_db_reg);
+ if (bq->next_to_use != i) {
+ if (QLGE_BQ_ALIGN(bq->next_to_use) != QLGE_BQ_ALIGN(i)) {
+ netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
+ "ring %u %s: updating prod idx = %d.\n",
+ rx_ring->cq_id, bq_type_name[bq->type],
+ i);
+ ql_write_db_reg(i, bq->prod_idx_db_reg);
+ }
+ bq->next_to_use = i;
}
+
+ return retval;
}
-/* Process (refill) a small buffer queue. */
-static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+static void ql_update_buffer_queues(struct rx_ring *rx_ring, gfp_t gfp,
+ unsigned long delay)
{
- u32 clean_idx = rx_ring->sbq_clean_idx;
- u32 start_idx = clean_idx;
- struct bq_desc *sbq_desc;
- u64 map;
- int i;
-
- while (rx_ring->sbq_free_cnt > 16) {
- for (i = (rx_ring->sbq_clean_idx % 16); i < 16; i++) {
- sbq_desc = &rx_ring->sbq[clean_idx];
- netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
- "sbq: try cleaning clean_idx = %d.\n",
- clean_idx);
- if (sbq_desc->p.skb == NULL) {
- netif_printk(qdev, rx_status, KERN_DEBUG,
- qdev->ndev,
- "sbq: getting new skb for index %d.\n",
- sbq_desc->index);
- sbq_desc->p.skb =
- netdev_alloc_skb(qdev->ndev,
- SMALL_BUFFER_SIZE);
- if (sbq_desc->p.skb == NULL) {
- rx_ring->sbq_clean_idx = clean_idx;
- return;
- }
- skb_reserve(sbq_desc->p.skb, QLGE_SB_PAD);
- map = pci_map_single(qdev->pdev,
- sbq_desc->p.skb->data,
- rx_ring->sbq_buf_size,
- PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(qdev->pdev, map)) {
- netif_err(qdev, ifup, qdev->ndev,
- "PCI mapping failed.\n");
- rx_ring->sbq_clean_idx = clean_idx;
- dev_kfree_skb_any(sbq_desc->p.skb);
- sbq_desc->p.skb = NULL;
- return;
- }
- dma_unmap_addr_set(sbq_desc, mapaddr, map);
- dma_unmap_len_set(sbq_desc, maplen,
- rx_ring->sbq_buf_size);
- *sbq_desc->addr = cpu_to_le64(map);
- }
+ bool sbq_fail, lbq_fail;
- clean_idx++;
- if (clean_idx == rx_ring->sbq_len)
- clean_idx = 0;
- }
- rx_ring->sbq_clean_idx = clean_idx;
- rx_ring->sbq_prod_idx += 16;
- if (rx_ring->sbq_prod_idx == rx_ring->sbq_len)
- rx_ring->sbq_prod_idx = 0;
- rx_ring->sbq_free_cnt -= 16;
- }
+ sbq_fail = !!qlge_refill_bq(&rx_ring->sbq, gfp);
+ lbq_fail = !!qlge_refill_bq(&rx_ring->lbq, gfp);
- if (start_idx != clean_idx) {
- netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
- "sbq: updating prod idx = %d.\n",
- rx_ring->sbq_prod_idx);
- ql_write_db_reg(rx_ring->sbq_prod_idx,
- rx_ring->sbq_prod_idx_db_reg);
- }
+ /* Minimum number of buffers needed to be able to receive at least one
+ * frame of any format:
+ * sbq: 1 for header + 1 for data
+ * lbq: mtu 9000 / lb size
+ * Below this, the queue might stall.
+ */
+ if ((sbq_fail && QLGE_BQ_HW_OWNED(&rx_ring->sbq) < 2) ||
+ (lbq_fail && QLGE_BQ_HW_OWNED(&rx_ring->lbq) <
+ DIV_ROUND_UP(9000, LARGE_BUFFER_MAX_SIZE)))
+ /* Allocations can take a long time in certain cases (ex.
+ * reclaim). Therefore, use a workqueue for long-running
+ * work items.
+ */
+ queue_delayed_work_on(smp_processor_id(), system_long_wq,
+ &rx_ring->refill_work, delay);
}
-static void ql_update_buffer_queues(struct ql_adapter *qdev,
- struct rx_ring *rx_ring)
+static void qlge_slow_refill(struct work_struct *work)
{
- ql_update_sbq(qdev, rx_ring);
- ql_update_lbq(qdev, rx_ring);
+ struct rx_ring *rx_ring = container_of(work, struct rx_ring,
+ refill_work.work);
+ struct napi_struct *napi = &rx_ring->napi;
+
+ napi_disable(napi);
+ ql_update_buffer_queues(rx_ring, GFP_KERNEL, HZ / 2);
+ napi_enable(napi);
+
+ local_bh_disable();
+ /* napi_disable() might have prevented incomplete napi work from being
+ * rescheduled.
+ */
+ napi_schedule(napi);
+ /* trigger softirq processing */
+ local_bh_enable();
}
/* Unmaps tx buffers. Can be called from send() if a pci mapping
@@ -1495,7 +1442,7 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,
u16 vlan_id)
{
struct sk_buff *skb;
- struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
+ struct qlge_bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
struct napi_struct *napi = &rx_ring->napi;
/* Frame error, so drop the packet. */
@@ -1544,7 +1491,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
struct net_device *ndev = qdev->ndev;
struct sk_buff *skb = NULL;
void *addr;
- struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
+ struct qlge_bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
struct napi_struct *napi = &rx_ring->napi;
size_t hlen = ETH_HLEN;
@@ -1634,31 +1581,24 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
u32 length,
u16 vlan_id)
{
+ struct qlge_bq_desc *sbq_desc = qlge_get_curr_buf(&rx_ring->sbq);
struct net_device *ndev = qdev->ndev;
- struct sk_buff *skb = NULL;
- struct sk_buff *new_skb = NULL;
- struct bq_desc *sbq_desc = ql_get_curr_sbuf(rx_ring);
+ struct sk_buff *skb, *new_skb;
skb = sbq_desc->p.skb;
/* Allocate new_skb and copy */
new_skb = netdev_alloc_skb(qdev->ndev, length + NET_IP_ALIGN);
- if (new_skb == NULL) {
+ if (!new_skb) {
rx_ring->rx_dropped++;
return;
}
skb_reserve(new_skb, NET_IP_ALIGN);
- pci_dma_sync_single_for_cpu(qdev->pdev,
- dma_unmap_addr(sbq_desc, mapaddr),
- dma_unmap_len(sbq_desc, maplen),
- PCI_DMA_FROMDEVICE);
+ pci_dma_sync_single_for_cpu(qdev->pdev, sbq_desc->dma_addr,
+ SMALL_BUF_MAP_SIZE, PCI_DMA_FROMDEVICE);
skb_put_data(new_skb, skb->data, length);
- pci_dma_sync_single_for_device(qdev->pdev,
- dma_unmap_addr(sbq_desc, mapaddr),
- dma_unmap_len(sbq_desc, maplen),
- PCI_DMA_FROMDEVICE);
skb = new_skb;
/* Frame error, so drop the packet. */
@@ -1759,11 +1699,10 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
struct rx_ring *rx_ring,
struct ib_mac_iocb_rsp *ib_mac_rsp)
{
- struct bq_desc *lbq_desc;
- struct bq_desc *sbq_desc;
- struct sk_buff *skb = NULL;
u32 length = le32_to_cpu(ib_mac_rsp->data_len);
u32 hdr_len = le32_to_cpu(ib_mac_rsp->hdr_len);
+ struct qlge_bq_desc *lbq_desc, *sbq_desc;
+ struct sk_buff *skb = NULL;
size_t hlen = ETH_HLEN;
/*
@@ -1776,11 +1715,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
/*
* Headers fit nicely into a small buffer.
*/
- sbq_desc = ql_get_curr_sbuf(rx_ring);
- pci_unmap_single(qdev->pdev,
- dma_unmap_addr(sbq_desc, mapaddr),
- dma_unmap_len(sbq_desc, maplen),
- PCI_DMA_FROMDEVICE);
+ sbq_desc = qlge_get_curr_buf(&rx_ring->sbq);
+ pci_unmap_single(qdev->pdev, sbq_desc->dma_addr,
+ SMALL_BUF_MAP_SIZE, PCI_DMA_FROMDEVICE);
skb = sbq_desc->p.skb;
ql_realign_skb(skb, hdr_len);
skb_put(skb, hdr_len);
@@ -1808,35 +1745,22 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
* from the "data" small buffer to the "header" small
* buffer.
*/
- sbq_desc = ql_get_curr_sbuf(rx_ring);
+ sbq_desc = qlge_get_curr_buf(&rx_ring->sbq);
pci_dma_sync_single_for_cpu(qdev->pdev,
- dma_unmap_addr
- (sbq_desc, mapaddr),
- dma_unmap_len
- (sbq_desc, maplen),
+ sbq_desc->dma_addr,
+ SMALL_BUF_MAP_SIZE,
PCI_DMA_FROMDEVICE);
skb_put_data(skb, sbq_desc->p.skb->data, length);
- pci_dma_sync_single_for_device(qdev->pdev,
- dma_unmap_addr
- (sbq_desc,
- mapaddr),
- dma_unmap_len
- (sbq_desc,
- maplen),
- PCI_DMA_FROMDEVICE);
} else {
netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
"%d bytes in a single small buffer.\n",
length);
- sbq_desc = ql_get_curr_sbuf(rx_ring);
+ sbq_desc = qlge_get_curr_buf(&rx_ring->sbq);
skb = sbq_desc->p.skb;
ql_realign_skb(skb, length);
skb_put(skb, length);
- pci_unmap_single(qdev->pdev,
- dma_unmap_addr(sbq_desc,
- mapaddr),
- dma_unmap_len(sbq_desc,
- maplen),
+ pci_unmap_single(qdev->pdev, sbq_desc->dma_addr,
+ SMALL_BUF_MAP_SIZE,
PCI_DMA_FROMDEVICE);
sbq_desc->p.skb = NULL;
}
@@ -1868,15 +1792,13 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
*/
lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
skb = netdev_alloc_skb(qdev->ndev, length);
- if (skb == NULL) {
+ if (!skb) {
netif_printk(qdev, probe, KERN_DEBUG, qdev->ndev,
"No skb available, drop the packet.\n");
return NULL;
}
- pci_unmap_page(qdev->pdev,
- dma_unmap_addr(lbq_desc,
- mapaddr),
- dma_unmap_len(lbq_desc, maplen),
+ pci_unmap_page(qdev->pdev, lbq_desc->dma_addr,
+ qdev->lbq_buf_size,
PCI_DMA_FROMDEVICE);
skb_reserve(skb, NET_IP_ALIGN);
netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
@@ -1907,11 +1829,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
* eventually be in trouble.
*/
int size, i = 0;
- sbq_desc = ql_get_curr_sbuf(rx_ring);
- pci_unmap_single(qdev->pdev,
- dma_unmap_addr(sbq_desc, mapaddr),
- dma_unmap_len(sbq_desc, maplen),
- PCI_DMA_FROMDEVICE);
+ sbq_desc = qlge_get_curr_buf(&rx_ring->sbq);
+ pci_unmap_single(qdev->pdev, sbq_desc->dma_addr,
+ SMALL_BUF_MAP_SIZE, PCI_DMA_FROMDEVICE);
if (!(ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS)) {
/*
* This is an non TCP/UDP IP frame, so
@@ -1931,8 +1851,7 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
}
do {
lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
- size = (length < rx_ring->lbq_buf_size) ? length :
- rx_ring->lbq_buf_size;
+ size = min(length, qdev->lbq_buf_size);
netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
"Adding page %d to skb for %d bytes.\n",
@@ -2286,7 +2205,7 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
if (count == budget)
break;
}
- ql_update_buffer_queues(qdev, rx_ring);
+ ql_update_buffer_queues(rx_ring, GFP_ATOMIC, 0);
ql_write_cq_idx(rx_ring);
return count;
}
@@ -2500,21 +2419,22 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
u32 var;
int work_done = 0;
- spin_lock(&qdev->hw_lock);
- if (atomic_read(&qdev->intr_context[0].irq_cnt)) {
- netif_printk(qdev, intr, KERN_DEBUG, qdev->ndev,
- "Shared Interrupt, Not ours!\n");
- spin_unlock(&qdev->hw_lock);
- return IRQ_NONE;
- }
- spin_unlock(&qdev->hw_lock);
+ /* Experience shows that when using INTx interrupts, interrupts must
+ * be masked manually.
+ * When using MSI mode, INTR_EN_EN must be explicitly disabled
+ * (even though it is auto-masked), otherwise a later command to
+ * enable it is not effective.
+ */
+ if (!test_bit(QL_MSIX_ENABLED, &qdev->flags))
+ ql_disable_completion_interrupt(qdev, 0);
- var = ql_disable_completion_interrupt(qdev, intr_context->intr);
+ var = ql_read32(qdev, STS);
/*
* Check for fatal error.
*/
if (var & STS_FE) {
+ ql_disable_completion_interrupt(qdev, 0);
ql_queue_asic_error(qdev);
netdev_err(qdev->ndev, "Got fatal error, STS = %x.\n", var);
var = ql_read32(qdev, ERR_STS);
@@ -2534,7 +2454,6 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
*/
netif_err(qdev, intr, qdev->ndev,
"Got MPI processor interrupt.\n");
- ql_disable_completion_interrupt(qdev, intr_context->intr);
ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
queue_delayed_work_on(smp_processor_id(),
qdev->workqueue, &qdev->mpi_work, 0);
@@ -2550,11 +2469,18 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
if (var & intr_context->irq_mask) {
netif_info(qdev, intr, qdev->ndev,
"Waking handler for rx_ring[0].\n");
- ql_disable_completion_interrupt(qdev, intr_context->intr);
napi_schedule(&rx_ring->napi);
work_done++;
+ } else {
+ /* Experience shows that the device sometimes signals an
+ * interrupt but no work is scheduled from this function.
+ * Nevertheless, the interrupt is auto-masked. Therefore, we
+ * systematically re-enable the interrupt if we didn't
+ * schedule napi.
+ */
+ ql_enable_completion_interrupt(qdev, 0);
}
- ql_enable_completion_interrupt(qdev, intr_context->intr);
+
return work_done ? IRQ_HANDLED : IRQ_NONE;
}
@@ -2737,7 +2663,7 @@ static int ql_alloc_shadow_space(struct ql_adapter *qdev)
qdev->rx_ring_shadow_reg_area =
pci_zalloc_consistent(qdev->pdev, PAGE_SIZE,
&qdev->rx_ring_shadow_reg_dma);
- if (qdev->rx_ring_shadow_reg_area == NULL) {
+ if (!qdev->rx_ring_shadow_reg_area) {
netif_err(qdev, ifup, qdev->ndev,
"Allocation of RX shadow space failed.\n");
return -ENOMEM;
@@ -2746,7 +2672,7 @@ static int ql_alloc_shadow_space(struct ql_adapter *qdev)
qdev->tx_ring_shadow_reg_area =
pci_zalloc_consistent(qdev->pdev, PAGE_SIZE,
&qdev->tx_ring_shadow_reg_dma);
- if (qdev->tx_ring_shadow_reg_area == NULL) {
+ if (!qdev->tx_ring_shadow_reg_area) {
netif_err(qdev, ifup, qdev->ndev,
"Allocation of TX shadow space failed.\n");
goto err_wqp_sh_area;
@@ -2798,14 +2724,14 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev,
pci_alloc_consistent(qdev->pdev, tx_ring->wq_size,
&tx_ring->wq_base_dma);
- if ((tx_ring->wq_base == NULL) ||
+ if (!tx_ring->wq_base ||
tx_ring->wq_base_dma & WQ_ADDR_ALIGN)
goto pci_alloc_err;
tx_ring->q =
kmalloc_array(tx_ring->wq_len, sizeof(struct tx_ring_desc),
GFP_KERNEL);
- if (tx_ring->q == NULL)
+ if (!tx_ring->q)
goto err;
return 0;
@@ -2820,54 +2746,46 @@ pci_alloc_err:
static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
- struct bq_desc *lbq_desc;
+ struct qlge_bq *lbq = &rx_ring->lbq;
+ unsigned int last_offset;
- uint32_t curr_idx, clean_idx;
+ last_offset = ql_lbq_block_size(qdev) - qdev->lbq_buf_size;
+ while (lbq->next_to_clean != lbq->next_to_use) {
+ struct qlge_bq_desc *lbq_desc =
+ &lbq->queue[lbq->next_to_clean];
- curr_idx = rx_ring->lbq_curr_idx;
- clean_idx = rx_ring->lbq_clean_idx;
- while (curr_idx != clean_idx) {
- lbq_desc = &rx_ring->lbq[curr_idx];
-
- if (lbq_desc->p.pg_chunk.last_flag) {
- pci_unmap_page(qdev->pdev,
- lbq_desc->p.pg_chunk.map,
- ql_lbq_block_size(qdev),
+ if (lbq_desc->p.pg_chunk.offset == last_offset)
+ pci_unmap_page(qdev->pdev, lbq_desc->dma_addr,
+ ql_lbq_block_size(qdev),
PCI_DMA_FROMDEVICE);
- lbq_desc->p.pg_chunk.last_flag = 0;
- }
-
put_page(lbq_desc->p.pg_chunk.page);
- lbq_desc->p.pg_chunk.page = NULL;
-
- if (++curr_idx == rx_ring->lbq_len)
- curr_idx = 0;
+ lbq->next_to_clean = QLGE_BQ_WRAP(lbq->next_to_clean + 1);
}
- if (rx_ring->pg_chunk.page) {
- pci_unmap_page(qdev->pdev, rx_ring->pg_chunk.map,
- ql_lbq_block_size(qdev), PCI_DMA_FROMDEVICE);
- put_page(rx_ring->pg_chunk.page);
- rx_ring->pg_chunk.page = NULL;
+
+ if (rx_ring->master_chunk.page) {
+ pci_unmap_page(qdev->pdev, rx_ring->chunk_dma_addr,
+ ql_lbq_block_size(qdev), PCI_DMA_FROMDEVICE);
+ put_page(rx_ring->master_chunk.page);
+ rx_ring->master_chunk.page = NULL;
}
}
static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
int i;
- struct bq_desc *sbq_desc;
- for (i = 0; i < rx_ring->sbq_len; i++) {
- sbq_desc = &rx_ring->sbq[i];
- if (sbq_desc == NULL) {
+ for (i = 0; i < QLGE_BQ_LEN; i++) {
+ struct qlge_bq_desc *sbq_desc = &rx_ring->sbq.queue[i];
+
+ if (!sbq_desc) {
netif_err(qdev, ifup, qdev->ndev,
"sbq_desc %d is NULL.\n", i);
return;
}
if (sbq_desc->p.skb) {
- pci_unmap_single(qdev->pdev,
- dma_unmap_addr(sbq_desc, mapaddr),
- dma_unmap_len(sbq_desc, maplen),
+ pci_unmap_single(qdev->pdev, sbq_desc->dma_addr,
+ SMALL_BUF_MAP_SIZE,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(sbq_desc->p.skb);
sbq_desc->p.skb = NULL;
@@ -2881,89 +2799,83 @@ static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring
static void ql_free_rx_buffers(struct ql_adapter *qdev)
{
int i;
- struct rx_ring *rx_ring;
for (i = 0; i < qdev->rx_ring_count; i++) {
- rx_ring = &qdev->rx_ring[i];
- if (rx_ring->lbq)
+ struct rx_ring *rx_ring = &qdev->rx_ring[i];
+
+ if (rx_ring->lbq.queue)
ql_free_lbq_buffers(qdev, rx_ring);
- if (rx_ring->sbq)
+ if (rx_ring->sbq.queue)
ql_free_sbq_buffers(qdev, rx_ring);
}
}
static void ql_alloc_rx_buffers(struct ql_adapter *qdev)
{
- struct rx_ring *rx_ring;
int i;
- for (i = 0; i < qdev->rx_ring_count; i++) {
- rx_ring = &qdev->rx_ring[i];
- if (rx_ring->type != TX_Q)
- ql_update_buffer_queues(qdev, rx_ring);
- }
+ for (i = 0; i < qdev->rss_ring_count; i++)
+ ql_update_buffer_queues(&qdev->rx_ring[i], GFP_KERNEL,
+ HZ / 2);
}
-static void ql_init_lbq_ring(struct ql_adapter *qdev,
- struct rx_ring *rx_ring)
+static int qlge_init_bq(struct qlge_bq *bq)
{
+ struct rx_ring *rx_ring = QLGE_BQ_CONTAINER(bq);
+ struct ql_adapter *qdev = rx_ring->qdev;
+ struct qlge_bq_desc *bq_desc;
+ __le64 *buf_ptr;
int i;
- struct bq_desc *lbq_desc;
- __le64 *bq = rx_ring->lbq_base;
- memset(rx_ring->lbq, 0, rx_ring->lbq_len * sizeof(struct bq_desc));
- for (i = 0; i < rx_ring->lbq_len; i++) {
- lbq_desc = &rx_ring->lbq[i];
- memset(lbq_desc, 0, sizeof(*lbq_desc));
- lbq_desc->index = i;
- lbq_desc->addr = bq;
- bq++;
+ bq->base = pci_alloc_consistent(qdev->pdev, QLGE_BQ_SIZE,
+ &bq->base_dma);
+ if (!bq->base) {
+ netif_err(qdev, ifup, qdev->ndev,
+ "ring %u %s allocation failed.\n", rx_ring->cq_id,
+ bq_type_name[bq->type]);
+ return -ENOMEM;
}
-}
-static void ql_init_sbq_ring(struct ql_adapter *qdev,
- struct rx_ring *rx_ring)
-{
- int i;
- struct bq_desc *sbq_desc;
- __le64 *bq = rx_ring->sbq_base;
+ bq->queue = kmalloc_array(QLGE_BQ_LEN, sizeof(struct qlge_bq_desc),
+ GFP_KERNEL);
+ if (!bq->queue)
+ return -ENOMEM;
- memset(rx_ring->sbq, 0, rx_ring->sbq_len * sizeof(struct bq_desc));
- for (i = 0; i < rx_ring->sbq_len; i++) {
- sbq_desc = &rx_ring->sbq[i];
- memset(sbq_desc, 0, sizeof(*sbq_desc));
- sbq_desc->index = i;
- sbq_desc->addr = bq;
- bq++;
+ buf_ptr = bq->base;
+ bq_desc = &bq->queue[0];
+ for (i = 0; i < QLGE_BQ_LEN; i++, buf_ptr++, bq_desc++) {
+ bq_desc->p.skb = NULL;
+ bq_desc->index = i;
+ bq_desc->buf_ptr = buf_ptr;
}
+
+ return 0;
}
static void ql_free_rx_resources(struct ql_adapter *qdev,
struct rx_ring *rx_ring)
{
/* Free the small buffer queue. */
- if (rx_ring->sbq_base) {
- pci_free_consistent(qdev->pdev,
- rx_ring->sbq_size,
- rx_ring->sbq_base, rx_ring->sbq_base_dma);
- rx_ring->sbq_base = NULL;
+ if (rx_ring->sbq.base) {
+ pci_free_consistent(qdev->pdev, QLGE_BQ_SIZE,
+ rx_ring->sbq.base, rx_ring->sbq.base_dma);
+ rx_ring->sbq.base = NULL;
}
/* Free the small buffer queue control blocks. */
- kfree(rx_ring->sbq);
- rx_ring->sbq = NULL;
+ kfree(rx_ring->sbq.queue);
+ rx_ring->sbq.queue = NULL;
/* Free the large buffer queue. */
- if (rx_ring->lbq_base) {
- pci_free_consistent(qdev->pdev,
- rx_ring->lbq_size,
- rx_ring->lbq_base, rx_ring->lbq_base_dma);
- rx_ring->lbq_base = NULL;
+ if (rx_ring->lbq.base) {
+ pci_free_consistent(qdev->pdev, QLGE_BQ_SIZE,
+ rx_ring->lbq.base, rx_ring->lbq.base_dma);
+ rx_ring->lbq.base = NULL;
}
/* Free the large buffer queue control blocks. */
- kfree(rx_ring->lbq);
- rx_ring->lbq = NULL;
+ kfree(rx_ring->lbq.queue);
+ rx_ring->lbq.queue = NULL;
/* Free the rx queue. */
if (rx_ring->cq_base) {
@@ -2987,67 +2899,18 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev,
pci_alloc_consistent(qdev->pdev, rx_ring->cq_size,
&rx_ring->cq_base_dma);
- if (rx_ring->cq_base == NULL) {
+ if (!rx_ring->cq_base) {
netif_err(qdev, ifup, qdev->ndev, "rx_ring alloc failed.\n");
return -ENOMEM;
}
- if (rx_ring->sbq_len) {
- /*
- * Allocate small buffer queue.
- */
- rx_ring->sbq_base =
- pci_alloc_consistent(qdev->pdev, rx_ring->sbq_size,
- &rx_ring->sbq_base_dma);
-
- if (rx_ring->sbq_base == NULL) {
- netif_err(qdev, ifup, qdev->ndev,
- "Small buffer queue allocation failed.\n");
- goto err_mem;
- }
-
- /*
- * Allocate small buffer queue control blocks.
- */
- rx_ring->sbq = kmalloc_array(rx_ring->sbq_len,
- sizeof(struct bq_desc),
- GFP_KERNEL);
- if (rx_ring->sbq == NULL)
- goto err_mem;
-
- ql_init_sbq_ring(qdev, rx_ring);
- }
-
- if (rx_ring->lbq_len) {
- /*
- * Allocate large buffer queue.
- */
- rx_ring->lbq_base =
- pci_alloc_consistent(qdev->pdev, rx_ring->lbq_size,
- &rx_ring->lbq_base_dma);
-
- if (rx_ring->lbq_base == NULL) {
- netif_err(qdev, ifup, qdev->ndev,
- "Large buffer queue allocation failed.\n");
- goto err_mem;
- }
- /*
- * Allocate large buffer queue control blocks.
- */
- rx_ring->lbq = kmalloc_array(rx_ring->lbq_len,
- sizeof(struct bq_desc),
- GFP_KERNEL);
- if (rx_ring->lbq == NULL)
- goto err_mem;
-
- ql_init_lbq_ring(qdev, rx_ring);
+ if (rx_ring->cq_id < qdev->rss_ring_count &&
+ (qlge_init_bq(&rx_ring->sbq) || qlge_init_bq(&rx_ring->lbq))) {
+ ql_free_rx_resources(qdev, rx_ring);
+ return -ENOMEM;
}
return 0;
-
-err_mem:
- ql_free_rx_resources(qdev, rx_ring);
- return -ENOMEM;
}
static void ql_tx_ring_clean(struct ql_adapter *qdev)
@@ -3133,7 +2996,6 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
void __iomem *doorbell_area =
qdev->doorbell_area + (DB_PAGE_SIZE * (128 + rx_ring->cq_id));
int err = 0;
- u16 bq_len;
u64 tmp;
__le64 *base_indirect_ptr;
int page_entries;
@@ -3144,12 +3006,12 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
*rx_ring->prod_idx_sh_reg = 0;
shadow_reg += sizeof(u64);
shadow_reg_dma += sizeof(u64);
- rx_ring->lbq_base_indirect = shadow_reg;
- rx_ring->lbq_base_indirect_dma = shadow_reg_dma;
- shadow_reg += (sizeof(u64) * MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len));
- shadow_reg_dma += (sizeof(u64) * MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len));
- rx_ring->sbq_base_indirect = shadow_reg;
- rx_ring->sbq_base_indirect_dma = shadow_reg_dma;
+ rx_ring->lbq.base_indirect = shadow_reg;
+ rx_ring->lbq.base_indirect_dma = shadow_reg_dma;
+ shadow_reg += (sizeof(u64) * MAX_DB_PAGES_PER_BQ(QLGE_BQ_LEN));
+ shadow_reg_dma += (sizeof(u64) * MAX_DB_PAGES_PER_BQ(QLGE_BQ_LEN));
+ rx_ring->sbq.base_indirect = shadow_reg;
+ rx_ring->sbq.base_indirect_dma = shadow_reg_dma;
/* PCI doorbell mem area + 0x00 for consumer index register */
rx_ring->cnsmr_idx_db_reg = (u32 __iomem *) doorbell_area;
@@ -3160,16 +3022,16 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
rx_ring->valid_db_reg = doorbell_area + 0x04;
/* PCI doorbell mem area + 0x18 for large buffer consumer */
- rx_ring->lbq_prod_idx_db_reg = (u32 __iomem *) (doorbell_area + 0x18);
+ rx_ring->lbq.prod_idx_db_reg = (u32 __iomem *)(doorbell_area + 0x18);
/* PCI doorbell mem area + 0x1c */
- rx_ring->sbq_prod_idx_db_reg = (u32 __iomem *) (doorbell_area + 0x1c);
+ rx_ring->sbq.prod_idx_db_reg = (u32 __iomem *)(doorbell_area + 0x1c);
memset((void *)cqicb, 0, sizeof(struct cqicb));
cqicb->msix_vect = rx_ring->irq;
- bq_len = (rx_ring->cq_len == 65536) ? 0 : (u16) rx_ring->cq_len;
- cqicb->len = cpu_to_le16(bq_len | LEN_V | LEN_CPP_CONT);
+ cqicb->len = cpu_to_le16(QLGE_FIT16(rx_ring->cq_len) | LEN_V |
+ LEN_CPP_CONT);
cqicb->addr = cpu_to_le64(rx_ring->cq_base_dma);
@@ -3181,59 +3043,42 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
cqicb->flags = FLAGS_LC | /* Load queue base address */
FLAGS_LV | /* Load MSI-X vector */
FLAGS_LI; /* Load irq delay values */
- if (rx_ring->lbq_len) {
+ if (rx_ring->cq_id < qdev->rss_ring_count) {
cqicb->flags |= FLAGS_LL; /* Load lbq values */
- tmp = (u64)rx_ring->lbq_base_dma;
- base_indirect_ptr = rx_ring->lbq_base_indirect;
+ tmp = (u64)rx_ring->lbq.base_dma;
+ base_indirect_ptr = rx_ring->lbq.base_indirect;
page_entries = 0;
do {
*base_indirect_ptr = cpu_to_le64(tmp);
tmp += DB_PAGE_SIZE;
base_indirect_ptr++;
page_entries++;
- } while (page_entries < MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len));
- cqicb->lbq_addr =
- cpu_to_le64(rx_ring->lbq_base_indirect_dma);
- bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 :
- (u16) rx_ring->lbq_buf_size;
- cqicb->lbq_buf_size = cpu_to_le16(bq_len);
- bq_len = (rx_ring->lbq_len == 65536) ? 0 :
- (u16) rx_ring->lbq_len;
- cqicb->lbq_len = cpu_to_le16(bq_len);
- rx_ring->lbq_prod_idx = 0;
- rx_ring->lbq_curr_idx = 0;
- rx_ring->lbq_clean_idx = 0;
- rx_ring->lbq_free_cnt = rx_ring->lbq_len;
- }
- if (rx_ring->sbq_len) {
+ } while (page_entries < MAX_DB_PAGES_PER_BQ(QLGE_BQ_LEN));
+ cqicb->lbq_addr = cpu_to_le64(rx_ring->lbq.base_indirect_dma);
+ cqicb->lbq_buf_size =
+ cpu_to_le16(QLGE_FIT16(qdev->lbq_buf_size));
+ cqicb->lbq_len = cpu_to_le16(QLGE_FIT16(QLGE_BQ_LEN));
+ rx_ring->lbq.next_to_use = 0;
+ rx_ring->lbq.next_to_clean = 0;
+
cqicb->flags |= FLAGS_LS; /* Load sbq values */
- tmp = (u64)rx_ring->sbq_base_dma;
- base_indirect_ptr = rx_ring->sbq_base_indirect;
+ tmp = (u64)rx_ring->sbq.base_dma;
+ base_indirect_ptr = rx_ring->sbq.base_indirect;
page_entries = 0;
do {
*base_indirect_ptr = cpu_to_le64(tmp);
tmp += DB_PAGE_SIZE;
base_indirect_ptr++;
page_entries++;
- } while (page_entries < MAX_DB_PAGES_PER_BQ(rx_ring->sbq_len));
+ } while (page_entries < MAX_DB_PAGES_PER_BQ(QLGE_BQ_LEN));
cqicb->sbq_addr =
- cpu_to_le64(rx_ring->sbq_base_indirect_dma);
- cqicb->sbq_buf_size =
- cpu_to_le16((u16)(rx_ring->sbq_buf_size));
- bq_len = (rx_ring->sbq_len == 65536) ? 0 :
- (u16) rx_ring->sbq_len;
- cqicb->sbq_len = cpu_to_le16(bq_len);
- rx_ring->sbq_prod_idx = 0;
- rx_ring->sbq_curr_idx = 0;
- rx_ring->sbq_clean_idx = 0;
- rx_ring->sbq_free_cnt = rx_ring->sbq_len;
- }
- switch (rx_ring->type) {
- case TX_Q:
- cqicb->irq_delay = cpu_to_le16(qdev->tx_coalesce_usecs);
- cqicb->pkt_delay = cpu_to_le16(qdev->tx_max_coalesced_frames);
- break;
- case RX_Q:
+ cpu_to_le64(rx_ring->sbq.base_indirect_dma);
+ cqicb->sbq_buf_size = cpu_to_le16(SMALL_BUFFER_SIZE);
+ cqicb->sbq_len = cpu_to_le16(QLGE_FIT16(QLGE_BQ_LEN));
+ rx_ring->sbq.next_to_use = 0;
+ rx_ring->sbq.next_to_clean = 0;
+ }
+ if (rx_ring->cq_id < qdev->rss_ring_count) {
/* Inbound completion handling rx_rings run in
* separate NAPI contexts.
*/
@@ -3241,10 +3086,9 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
64);
cqicb->irq_delay = cpu_to_le16(qdev->rx_coalesce_usecs);
cqicb->pkt_delay = cpu_to_le16(qdev->rx_max_coalesced_frames);
- break;
- default:
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "Invalid rx_ring->type = %d.\n", rx_ring->type);
+ } else {
+ cqicb->irq_delay = cpu_to_le16(qdev->tx_coalesce_usecs);
+ cqicb->pkt_delay = cpu_to_le16(qdev->tx_max_coalesced_frames);
}
err = ql_write_cfg(qdev, cqicb, sizeof(struct cqicb),
CFG_LCQ, rx_ring->cq_id);
@@ -3366,6 +3210,7 @@ msi:
}
}
qlge_irq_type = LEG_IRQ;
+ set_bit(QL_LEGACY_ENABLED, &qdev->flags);
netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
"Running with legacy interrupts.\n");
}
@@ -3509,6 +3354,16 @@ static void ql_resolve_queues_to_irqs(struct ql_adapter *qdev)
intr_context->intr_dis_mask =
INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK |
INTR_EN_TYPE_DISABLE;
+ if (test_bit(QL_LEGACY_ENABLED, &qdev->flags)) {
+ /* Experience shows that when using INTx interrupts,
+ * the device does not always auto-mask INTR_EN_EN.
+ * Moreover, masking INTR_EN_EN manually does not
+ * immediately prevent interrupt generation.
+ */
+ intr_context->intr_en_mask |= INTR_EN_EI << 16 |
+ INTR_EN_EI;
+ intr_context->intr_dis_mask |= INTR_EN_EI << 16;
+ }
intr_context->intr_read_mask =
INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | INTR_EN_TYPE_READ;
/*
@@ -3557,7 +3412,6 @@ static int ql_request_irq(struct ql_adapter *qdev)
ql_resolve_queues_to_irqs(qdev);
for (i = 0; i < qdev->intr_count; i++, intr_context++) {
- atomic_set(&intr_context->irq_cnt, 0);
if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) {
status = request_irq(qdev->msi_x_entry[i].vector,
intr_context->handler,
@@ -3591,12 +3445,7 @@ static int ql_request_irq(struct ql_adapter *qdev)
goto err_irq;
netif_err(qdev, ifup, qdev->ndev,
- "Hooked intr %d, queue type %s, with name %s.\n",
- i,
- qdev->rx_ring[0].type == DEFAULT_Q ?
- "DEFAULT_Q" :
- qdev->rx_ring[0].type == TX_Q ? "TX_Q" :
- qdev->rx_ring[0].type == RX_Q ? "RX_Q" : "",
+ "Hooked intr 0, queue type RX_Q, with name %s.\n",
intr_context->name);
}
intr_context->hooked = 1;
@@ -4072,6 +3921,7 @@ static int ql_get_adapter_resources(struct ql_adapter *qdev)
static int qlge_close(struct net_device *ndev)
{
struct ql_adapter *qdev = netdev_priv(ndev);
+ int i;
/* If we hit pci_channel_io_perm_failure
* failure condition, then we already
@@ -4089,21 +3939,31 @@ static int qlge_close(struct net_device *ndev)
*/
while (!test_bit(QL_ADAPTER_UP, &qdev->flags))
msleep(1);
+
+ /* Make sure refill_work doesn't re-enable napi */
+ for (i = 0; i < qdev->rss_ring_count; i++)
+ cancel_delayed_work_sync(&qdev->rx_ring[i].refill_work);
+
ql_adapter_down(qdev);
ql_release_adapter_resources(qdev);
return 0;
}
+static void qlge_set_lb_size(struct ql_adapter *qdev)
+{
+ if (qdev->ndev->mtu <= 1500)
+ qdev->lbq_buf_size = LARGE_BUFFER_MIN_SIZE;
+ else
+ qdev->lbq_buf_size = LARGE_BUFFER_MAX_SIZE;
+ qdev->lbq_buf_order = get_order(qdev->lbq_buf_size);
+}
+
static int ql_configure_rings(struct ql_adapter *qdev)
{
int i;
struct rx_ring *rx_ring;
struct tx_ring *tx_ring;
int cpu_cnt = min(MAX_CPUS, (int)num_online_cpus());
- unsigned int lbq_buf_len = (qdev->ndev->mtu > 1500) ?
- LARGE_BUFFER_MAX_SIZE : LARGE_BUFFER_MIN_SIZE;
-
- qdev->lbq_buf_order = get_order(lbq_buf_len);
/* In a perfect world we have one RSS ring for each CPU
* and each has it's own vector. To do that we ask for
@@ -4148,15 +4008,10 @@ static int ql_configure_rings(struct ql_adapter *qdev)
rx_ring->cq_len = qdev->rx_ring_size;
rx_ring->cq_size =
rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
- rx_ring->lbq_len = NUM_LARGE_BUFFERS;
- rx_ring->lbq_size =
- rx_ring->lbq_len * sizeof(__le64);
- rx_ring->lbq_buf_size = (u16)lbq_buf_len;
- rx_ring->sbq_len = NUM_SMALL_BUFFERS;
- rx_ring->sbq_size =
- rx_ring->sbq_len * sizeof(__le64);
- rx_ring->sbq_buf_size = SMALL_BUF_MAP_SIZE;
- rx_ring->type = RX_Q;
+ rx_ring->lbq.type = QLGE_LB;
+ rx_ring->sbq.type = QLGE_SB;
+ INIT_DELAYED_WORK(&rx_ring->refill_work,
+ &qlge_slow_refill);
} else {
/*
* Outbound queue handles outbound completions only.
@@ -4165,13 +4020,6 @@ static int ql_configure_rings(struct ql_adapter *qdev)
rx_ring->cq_len = qdev->tx_ring_size;
rx_ring->cq_size =
rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
- rx_ring->lbq_len = 0;
- rx_ring->lbq_size = 0;
- rx_ring->lbq_buf_size = 0;
- rx_ring->sbq_len = 0;
- rx_ring->sbq_size = 0;
- rx_ring->sbq_buf_size = 0;
- rx_ring->type = TX_Q;
}
}
return 0;
@@ -4186,6 +4034,7 @@ static int qlge_open(struct net_device *ndev)
if (err)
return err;
+ qlge_set_lb_size(qdev);
err = ql_configure_rings(qdev);
if (err)
return err;
@@ -4207,9 +4056,7 @@ error_up:
static int ql_change_rx_buffers(struct ql_adapter *qdev)
{
- struct rx_ring *rx_ring;
- int i, status;
- u32 lbq_buf_len;
+ int status;
/* Wait for an outstanding reset to complete. */
if (!test_bit(QL_ADAPTER_UP, &qdev->flags)) {
@@ -4232,16 +4079,7 @@ static int ql_change_rx_buffers(struct ql_adapter *qdev)
if (status)
goto error;
- /* Get the new rx buffer size. */
- lbq_buf_len = (qdev->ndev->mtu > 1500) ?
- LARGE_BUFFER_MAX_SIZE : LARGE_BUFFER_MIN_SIZE;
- qdev->lbq_buf_order = get_order(lbq_buf_len);
-
- for (i = 0; i < qdev->rss_ring_count; i++) {
- rx_ring = &qdev->rx_ring[i];
- /* Set the new size. */
- rx_ring->lbq_buf_size = lbq_buf_len;
- }
+ qlge_set_lb_size(qdev);
status = ql_adapter_up(qdev);
if (status)
@@ -4642,13 +4480,12 @@ static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev,
goto err_out2;
}
qdev->msg_enable = netif_msg_init(debug, default_msg);
- spin_lock_init(&qdev->hw_lock);
spin_lock_init(&qdev->stats_lock);
if (qlge_mpi_coredump) {
qdev->mpi_coredump =
vmalloc(sizeof(struct ql_mpi_coredump));
- if (qdev->mpi_coredump == NULL) {
+ if (!qdev->mpi_coredump) {
err = -ENOMEM;
goto err_out2;
}
diff --git a/drivers/staging/qlge/qlge_mpi.c b/drivers/staging/qlge/qlge_mpi.c
index 957c72985a06..9e422bbbb6ab 100644
--- a/drivers/staging/qlge/qlge_mpi.c
+++ b/drivers/staging/qlge/qlge_mpi.c
@@ -1257,7 +1257,6 @@ void ql_mpi_work(struct work_struct *work)
/* End polled mode for MPI */
ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
mutex_unlock(&qdev->mpi_mutex);
- ql_enable_completion_interrupt(qdev, 0);
}
void ql_mpi_reset_work(struct work_struct *work)
diff --git a/drivers/staging/ralink-gdma/ralink-gdma.c b/drivers/staging/ralink-gdma/ralink-gdma.c
index 900424db9b97..eabf1093328e 100644
--- a/drivers/staging/ralink-gdma/ralink-gdma.c
+++ b/drivers/staging/ralink-gdma/ralink-gdma.c
@@ -796,7 +796,6 @@ static int gdma_dma_probe(struct platform_device *pdev)
struct gdma_dma_dev *dma_dev;
struct dma_device *dd;
unsigned int i;
- struct resource *res;
int ret;
int irq;
void __iomem *base;
@@ -818,8 +817,7 @@ static int gdma_dma_probe(struct platform_device *pdev)
return -EINVAL;
dma_dev->data = data;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
dma_dev->base = base;
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 51a5b71f8c25..88e42cc1d837 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -440,15 +440,9 @@ static void update_bmc_sta(struct adapter *padapter)
tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f);
}
- if (pcur_network->Configuration.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;
- }
+ /* force to b mode */
+ network_type = WIRELESS_11B;
+ tx_ra_bitmap = 0xf;
raid = networktype_to_raid(network_type);
init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f;
@@ -560,29 +554,24 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
static void update_hw_ht_param(struct adapter *padapter)
{
- unsigned char max_AMPDU_len;
- unsigned char min_MPDU_spacing;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 max_ampdu_len;
+ u8 min_mpdu_spacing;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
DBG_88E("%s\n", __func__);
- /* handle A-MPDU parameter field */
- /*
- 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.ampdu_params_info & 0x03;
-
- 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));
+ /* handle A-MPDU parameter field
+ * 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.ampdu_params_info & 0x03;
+ min_mpdu_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2;
- rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, &min_mpdu_spacing);
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, &max_ampdu_len);
- /* */
- /* Config SM Power Save setting */
- /* */
+ /* Config SM Power Save setting */
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_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
index 02c476f45b33..d9b0f9e6235c 100644
--- a/drivers/staging/rtl8188eu/core/rtw_efuse.c
+++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c
@@ -25,7 +25,7 @@ enum{
* 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.
*/
-void efuse_power_switch(struct adapter *pAdapter, u8 write, u8 pwrstate)
+static void efuse_power_switch(struct adapter *pAdapter, u8 write, u8 pwrstate)
{
u8 tempval;
u16 tmpv16;
@@ -615,10 +615,9 @@ static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuse
static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
{
u16 efuse_addr = *pAddr;
- u8 badworden = 0;
+ u8 badworden;
u32 PgWriteSuccess = 0;
- badworden = 0x0f;
badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data);
if (badworden == 0x0F) {
/* write ok */
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index 1ec3b237212e..e764436e120f 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -2045,9 +2045,9 @@ void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
while (1) {
do_join_r = rtw_do_join(padapter);
- if (do_join_r == _SUCCESS) {
+ if (do_join_r == _SUCCESS)
break;
- }
+
DBG_88E("roaming do_join return %d\n", do_join_r);
pmlmepriv->to_roaming--;
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index 18dc9fc1c04a..e984b4605e91 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -507,7 +507,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da)
pwps_ie = rtw_get_wps_ie(cur_network->ies+_FIXED_IE_LENGTH_, cur_network->ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
/* inerset & update wps_probe_resp_ie */
- if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
+ if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
uint wps_offset, remainder_ielen;
u8 *premainder_ie;
diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
index 7b16632048b7..03dc7e5fcc38 100644
--- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
@@ -514,7 +514,7 @@ void rtw_init_pwrctrl_priv(struct adapter *padapter)
pwrctrlpriv->power_mgnt = PS_MODE_ACTIVE;
else
pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/* PS_MODE_MIN; */
- pwrctrlpriv->bLeisurePs = (pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE) ? true : false;
+ pwrctrlpriv->bLeisurePs = (pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE);
pwrctrlpriv->bFwCurrentInPSMode = false;
@@ -621,7 +621,7 @@ int rtw_pm_set_lps(struct adapter *padapter, u8 mode)
else
pwrctrlpriv->LpsIdleCount = 2;
pwrctrlpriv->power_mgnt = mode;
- pwrctrlpriv->bLeisurePs = (pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE) ? true : false;
+ pwrctrlpriv->bLeisurePs = (pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE);
}
} else {
ret = -EINVAL;
diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
index 91a30142c567..73f2cb5ebaa6 100644
--- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
+++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
@@ -83,7 +83,8 @@ u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
INIT_LIST_HEAD(&pstapriv->sta_hash[i]);
- list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
+ list_add_tail(&psta->list,
+ get_list_head(&pstapriv->free_sta_queue));
psta++;
}
@@ -134,31 +135,30 @@ u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
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];
- plist = phead->next;
+ if (!pstapriv)
+ return _SUCCESS;
- while (phead != plist) {
- int i;
+ /* delete all reordering_ctrl_timer */
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ for (index = 0; index < NUM_STA; index++) {
+ phead = &pstapriv->sta_hash[index];
+ plist = phead->next;
- psta = container_of(plist, struct sta_info,
- hash_list);
- plist = plist->next;
+ while (phead != plist) {
+ int i;
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
- }
+ psta = container_of(plist, struct sta_info, hash_list);
+ plist = plist->next;
+
+ 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);
- /*===============================*/
-
- vfree(pstapriv->pallocated_stainfo_buf);
}
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ vfree(pstapriv->pallocated_stainfo_buf);
return _SUCCESS;
}
@@ -167,7 +167,7 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
{
s32 index;
struct list_head *phash_list;
- struct sta_info *psta;
+ struct sta_info *psta;
struct __queue *pfree_sta_queue;
struct recv_reorder_ctrl *preorder_ctrl;
int i = 0;
@@ -180,65 +180,70 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
struct sta_info, list);
if (!psta) {
spin_unlock_bh(&pfree_sta_queue->lock);
- } else {
- list_del_init(&psta->list);
- spin_unlock_bh(&pfree_sta_queue->lock);
- _rtw_init_stainfo(psta);
- memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
- index = wifi_mac_hash(hwaddr);
- RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("%s: index=%x", __func__, index));
- if (index >= NUM_STA) {
- RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => %s: index >= NUM_STA", __func__));
- psta = NULL;
- goto exit;
- }
- phash_list = &pstapriv->sta_hash[index];
-
- spin_lock_bh(&pstapriv->sta_hash_lock);
- list_add_tail(&psta->hash_list, phash_list);
- pstapriv->asoc_sta_count++;
- spin_unlock_bh(&pstapriv->sta_hash_lock);
+ return NULL;
+ }
-/* Commented by Albert 2009/08/13 */
-/* 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. */
+ list_del_init(&psta->list);
+ spin_unlock_bh(&pfree_sta_queue->lock);
+ _rtw_init_stainfo(psta);
+ memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
+ index = wifi_mac_hash(hwaddr);
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
+ ("%s: index=%x", __func__, index));
+ if (index >= NUM_STA) {
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
+ ("ERROR => %s: index >= NUM_STA", __func__));
+ return NULL;
+ }
+ phash_list = &pstapriv->sta_hash[index];
- for (i = 0; i < 16; i++)
- memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ list_add_tail(&psta->hash_list, phash_list);
+ pstapriv->asoc_sta_count++;
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
- RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
- ("alloc number_%d stainfo with hwaddr = %pM\n",
- pstapriv->asoc_sta_count, hwaddr));
+ /* Commented by Albert 2009/08/13
+ * 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.
+ */
- init_addba_retry_timer(pstapriv->padapter, psta);
+ for (i = 0; i < 16; i++)
+ memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
+ &wRxSeqInitialValue, 2);
- /* for A-MPDU Rx reordering buffer control */
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
+ ("alloc number_%d stainfo with hwaddr = %pM\n",
+ pstapriv->asoc_sta_count, hwaddr));
- preorder_ctrl->padapter = pstapriv->padapter;
+ init_addba_retry_timer(pstapriv->padapter, psta);
- preorder_ctrl->enable = false;
+ /* for A-MPDU Rx reordering buffer control */
+ for (i = 0; i < 16; i++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
- preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->wend_b = 0xffff;
- preorder_ctrl->wsize_b = 64;/* 64; */
+ preorder_ctrl->padapter = pstapriv->padapter;
- _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
+ preorder_ctrl->enable = false;
- rtw_init_recv_timer(preorder_ctrl);
- }
+ preorder_ctrl->indicate_seq = 0xffff;
+ preorder_ctrl->wend_b = 0xffff;
+ preorder_ctrl->wsize_b = 64;/* 64; */
- /* init for DM */
- psta->rssi_stat.UndecoratedSmoothedPWDB = -1;
- psta->rssi_stat.UndecoratedSmoothedCCK = -1;
+ _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
- /* init for the sequence number of received management frame */
- psta->RxMgmtFrameSeqNum = 0xffff;
+ rtw_init_recv_timer(preorder_ctrl);
}
-exit:
+ /* 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;
+
return psta;
}
@@ -296,7 +301,9 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
del_timer_sync(&psta->addba_retry_timer);
- /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_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;
@@ -311,7 +318,7 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
spin_lock_bh(&ppending_recvframe_queue->lock);
- phead = get_list_head(ppending_recvframe_queue);
+ phead = get_list_head(ppending_recvframe_queue);
plist = phead->next;
while (!list_empty(phead)) {
@@ -444,23 +451,21 @@ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
{
struct sta_info *psta;
- u32 res = _SUCCESS;
- unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct sta_priv *pstapriv = &padapter->stapriv;
- psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
+ psta = rtw_alloc_stainfo(pstapriv, bc_addr);
if (!psta) {
- res = _FAIL;
- RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail"));
- goto exit;
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
+ ("rtw_alloc_stainfo fail"));
+ return _FAIL;
}
/* default broadcast & multicast use macid 1 */
psta->mac_id = 1;
-exit:
- return res;
+ return _SUCCESS;
}
struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
@@ -471,13 +476,13 @@ struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
return rtw_get_stainfo(pstapriv, bc_addr);
}
-u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
+bool rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
{
- u8 res = true;
+ bool res = true;
#ifdef CONFIG_88EU_AP_MODE
struct list_head *plist, *phead;
struct rtw_wlan_acl_node *paclnode;
- u8 match = false;
+ bool match = false;
struct sta_priv *pstapriv = &padapter->stapriv;
struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
struct __queue *pacl_node_q = &pacl_list->acl_node_q;
@@ -499,9 +504,9 @@ u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
spin_unlock_bh(&pacl_node_q->lock);
if (pacl_list->mode == 1)/* accept unless in deny list */
- res = (match) ? false : true;
+ res = !match;
else if (pacl_list->mode == 2)/* deny unless in accept list */
- res = (match) ? true : false;
+ res = match;
else
res = true;
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
index c985b1468d41..af8a79ce8736 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -667,7 +667,7 @@ static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var
void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
{
unsigned int i;
- u8 max_AMPDU_len, min_MPDU_spacing;
+ 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;
@@ -689,16 +689,16 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
} else {
/* modify from fw by Thomas 2010/11/17 */
if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x3) > (pIE->data[i] & 0x3))
- max_AMPDU_len = pIE->data[i] & 0x3;
+ max_ampdu_len = pIE->data[i] & 0x3;
else
- max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x3;
+ max_ampdu_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x3;
if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) > (pIE->data[i] & 0x1c))
- min_MPDU_spacing = pmlmeinfo->HT_caps.ampdu_params_info & 0x1c;
+ min_mpdu_spacing = pmlmeinfo->HT_caps.ampdu_params_info & 0x1c;
else
- min_MPDU_spacing = pIE->data[i] & 0x1c;
+ min_mpdu_spacing = pIE->data[i] & 0x1c;
- pmlmeinfo->HT_caps.ampdu_params_info = max_AMPDU_len | min_MPDU_spacing;
+ pmlmeinfo->HT_caps.ampdu_params_info = max_ampdu_len | min_mpdu_spacing;
}
}
@@ -729,8 +729,8 @@ void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
void HTOnAssocRsp(struct adapter *padapter)
{
- unsigned char max_AMPDU_len;
- unsigned char min_MPDU_spacing;
+ u8 max_ampdu_len;
+ u8 min_mpdu_spacing;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -748,13 +748,11 @@ 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.ampdu_params_info & 0x03;
+ max_ampdu_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03;
+ min_mpdu_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 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));
-
- rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, &min_mpdu_spacing);
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, &max_ampdu_len);
}
void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
index 952f2ab51347..c37591657bac 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -776,7 +776,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN);
memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
- if (psta->qos_option)
+ if (psta && psta->qos_option)
qos_option = true;
} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
@@ -784,7 +784,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
- if (psta->qos_option)
+ if (psta && 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)));
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
index 47352f210c0b..7646167a0b36 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
@@ -47,8 +47,6 @@ static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
******************************************/
static s32 FillH2CCmd_88E(struct adapter *adapt, 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;
@@ -71,39 +69,34 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p
goto exit;
/* pay attention to if race condition happened in H2C cmd setting. */
- do {
- h2c_box_num = adapt->HalData->LastHMEBoxNum;
-
- if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) {
- DBG_88E(" fw read cmd failed...\n");
- goto exit;
- }
-
- *(u8 *)(&h2c_cmd) = ElementID;
-
- if (CmdLen <= 3) {
- memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
- } else {
- memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, 3);
- ext_cmd_len = CmdLen-3;
- memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer+3, ext_cmd_len);
+ h2c_box_num = adapt->HalData->LastHMEBoxNum;
- /* Write Ext command */
- msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE);
- for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++)
- usb_write8(adapt, msgbox_ex_addr+cmd_idx, *((u8 *)(&h2c_cmd_ex)+cmd_idx));
- }
- /* Write command */
- msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE);
- for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++)
- usb_write8(adapt, msgbox_addr+cmd_idx, *((u8 *)(&h2c_cmd)+cmd_idx));
+ if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) {
+ DBG_88E(" fw read cmd failed...\n");
+ goto exit;
+ }
- bcmd_down = true;
+ *(u8 *)(&h2c_cmd) = ElementID;
- adapt->HalData->LastHMEBoxNum =
- (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS;
+ if (CmdLen <= 3) {
+ memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, CmdLen);
+ } else {
+ memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, 3);
+ ext_cmd_len = CmdLen - 3;
+ memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer + 3, ext_cmd_len);
+
+ /* Write Ext command */
+ msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE);
+ for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++)
+ usb_write8(adapt, msgbox_ex_addr + cmd_idx, *((u8 *)(&h2c_cmd_ex) + cmd_idx));
+ }
+ /* Write command */
+ msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE);
+ for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++)
+ usb_write8(adapt, msgbox_addr + cmd_idx, *((u8 *)(&h2c_cmd) + cmd_idx));
- } while ((!bcmd_down) && (retry_cnts--));
+ adapt->HalData->LastHMEBoxNum =
+ (h2c_box_num + 1) % RTL88E_MAX_H2C_BOX_NUMS;
ret = _SUCCESS;
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
index 086f98d38cba..57ae0e83dd3e 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
@@ -552,7 +552,6 @@ void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool
pHalData->AntDivCfg = 1; /* 0xC1[3] is ignored. */
} else {
pHalData->AntDivCfg = 0;
- pHalData->TRxAntDivType = pHalData->TRxAntDivType; /* The value in the driver setting of device manager. */
}
DBG_88E("EEPROM : AntDivCfg = %x, TRxAntDivType = %x\n", pHalData->AntDivCfg, pHalData->TRxAntDivType);
}
diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h
index 3ec53761e9fd..7a9c8ff0daa9 100644
--- a/drivers/staging/rtl8188eu/include/rtw_efuse.h
+++ b/drivers/staging/rtl8188eu/include/rtw_efuse.h
@@ -82,7 +82,6 @@ u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data);
void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset,
u16 _size_byte, u8 *pbuf);
-void efuse_power_switch(struct adapter *adapt, u8 write, u8 pwrstate);
int Efuse_PgPacketRead(struct adapter *adapt, u8 offset, u8 *data);
bool Efuse_PgPacketWrite(struct adapter *adapter, u8 offset, u8 word, u8 *data);
void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata);
diff --git a/drivers/staging/rtl8188eu/include/sta_info.h b/drivers/staging/rtl8188eu/include/sta_info.h
index dc685a14aeb8..6165adafc451 100644
--- a/drivers/staging/rtl8188eu/include/sta_info.h
+++ b/drivers/staging/rtl8188eu/include/sta_info.h
@@ -354,6 +354,6 @@ void rtw_free_all_stainfo(struct adapter *adapt);
struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
u32 rtw_init_bcmc_stainfo(struct adapter *adapt);
struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter);
-u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
+bool rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
#endif /* _STA_INFO_H_ */
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index ec5835d1aa8c..710c33fd4965 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -148,17 +148,10 @@ static char *translate_scan(struct adapter *padapter,
else
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
} else {
- if (pnetwork->network.Configuration.DSConfig > 14) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
- } else {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
- }
+ if (ht_cap)
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
+ else
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
}
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
@@ -650,17 +643,10 @@ static int rtw_wx_get_name(struct net_device *dev,
else
snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
} else {
- if (pcur_bss->Configuration.DSConfig > 14) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
- } else {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
- }
+ if (ht_cap)
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
}
} else {
snprintf(wrqu->name, IFNAMSIZ, "unassociated");
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index f932cb15e4e5..dace81a7d1ba 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -715,8 +715,8 @@ void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode)
if ((wireless_mode == WIRELESS_MODE_N_24G) ||
(wireless_mode == WIRELESS_MODE_N_5G)) {
priv->rtllib->pHTInfo->bEnableHT = 1;
- RT_TRACE(COMP_DBG, "%s(), wireless_mode:%x, bEnableHT = 1\n",
- __func__, wireless_mode);
+ RT_TRACE(COMP_DBG, "%s(), wireless_mode:%x, bEnableHT = 1\n",
+ __func__, wireless_mode);
} else {
priv->rtllib->pHTInfo->bEnableHT = 0;
RT_TRACE(COMP_DBG, "%s(), wireless_mode:%x, bEnableHT = 0\n",
@@ -1616,14 +1616,15 @@ static void _rtl92e_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
skb_push(skb, priv->rtllib->tx_headroom);
ret = _rtl92e_tx(dev, skb);
- if (ret != 0)
- kfree_skb(skb);
if (queue_index != MGNT_QUEUE) {
priv->rtllib->stats.tx_bytes += (skb->len -
priv->rtllib->tx_headroom);
priv->rtllib->stats.tx_packets++;
}
+
+ if (ret != 0)
+ kfree_skb(skb);
}
static int _rtl92e_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index 5c33bcb0db2e..00fea127bdc3 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -1620,7 +1620,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
for (i = 0; i < network->rates_len; i++) {
network->rates[i] = info_element->data[i];
#ifdef CONFIG_IEEE80211_DEBUG
- p += snprintf(p, sizeof(rates_str) -
+ p += scnprintf(p, sizeof(rates_str) -
(p - rates_str), "%02X ",
network->rates[i]);
#endif
@@ -1647,7 +1647,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
for (i = 0; i < network->rates_ex_len; i++) {
network->rates_ex[i] = info_element->data[i];
#ifdef CONFIG_IEEE80211_DEBUG
- p += snprintf(p, sizeof(rates_str) -
+ p += scnprintf(p, sizeof(rates_str) -
(p - rates_str), "%02X ",
network->rates_ex[i]);
#endif
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
index 9dd5c04181ea..33c596f9ec96 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
@@ -109,7 +109,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
/* Add basic and extended rates */
max_rate = 0;
p = custom;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+ p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
for (i = 0, j = 0; i < network->rates_len; ) {
if (j < network->rates_ex_len &&
((network->rates_ex[j] & 0x7F) <
@@ -119,12 +119,12 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
rate = network->rates[i++] & 0x7F;
if (rate > max_rate)
max_rate = rate;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
"%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
}
for (; j < network->rates_ex_len; j++) {
rate = network->rates_ex[j] & 0x7F;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
"%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
if (rate > max_rate)
max_rate = rate;
@@ -214,7 +214,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
* for given network. */
iwe.cmd = IWEVCUSTOM;
p = custom;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
" Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c
index b169460b9f26..63e0f7b1b852 100644
--- a/drivers/staging/rtl8192u/r8190_rtl8256.c
+++ b/drivers/staging/rtl8192u/r8190_rtl8256.c
@@ -43,8 +43,8 @@ void phy_set_rf8256_bandwidth(struct net_device *dev, enum ht_channel_width Band
switch (Bandwidth) {
case HT_CHANNEL_WIDTH_20:
if (priv->card_8192_version == VERSION_819XU_A ||
- priv->card_8192_version ==
- VERSION_819XU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */
+ priv->card_8192_version == VERSION_819XU_B) {
+ /* 8256 D-cut, E-cut, xiong: consider it later! */
rtl8192_phy_SetRFReg(dev,
(enum rf90_radio_path_e)eRFPath,
0x0b, bMask12Bits, 0x100); /* phy para:1ba */
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 2821411878ce..48f1591ed5b4 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -98,8 +98,6 @@ static char *ifname = "wlan%d";
static int hwwep = 1; /* default use hw. set 0 to use software security */
static int channels = 0x3fff;
-
-
module_param(ifname, charp, 0644);
module_param(hwwep, int, 0644);
module_param(channels, int, 0644);
@@ -112,7 +110,6 @@ static int rtl8192_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id);
static void rtl8192_usb_disconnect(struct usb_interface *intf);
-
static struct usb_driver rtl8192_usb_driver = {
.name = RTL819XU_MODULE_NAME, /* Driver name */
.id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
@@ -122,7 +119,6 @@ static struct usb_driver rtl8192_usb_driver = {
.resume = NULL, /* PM resume fn */
};
-
struct CHANNEL_LIST {
u8 Channel[32];
u8 Len;
@@ -207,9 +203,6 @@ static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv *priv)
}
}
-
-
-
static void CamResetAllEntry(struct net_device *dev)
{
u32 ulcommand = 0;
@@ -297,7 +290,6 @@ int write_nic_byte(struct net_device *dev, int indx, u8 data)
return 0;
}
-
int write_nic_word(struct net_device *dev, int indx, u16 data)
{
int status;
@@ -324,7 +316,6 @@ int write_nic_word(struct net_device *dev, int indx, u16 data)
return 0;
}
-
int write_nic_dword(struct net_device *dev, int indx, u32 data)
{
int status;
@@ -343,7 +334,6 @@ int write_nic_dword(struct net_device *dev, int indx, u32 data)
usbdata, 4, HZ / 2);
kfree(usbdata);
-
if (status < 0) {
netdev_err(dev, "%s TimeOut! status: %d\n", __func__, status);
return status;
@@ -352,8 +342,6 @@ int write_nic_dword(struct net_device *dev, int indx, u32 data)
return 0;
}
-
-
int read_nic_byte(struct net_device *dev, int indx, u8 *data)
{
int status;
@@ -379,8 +367,6 @@ int read_nic_byte(struct net_device *dev, int indx, u8 *data)
return 0;
}
-
-
int read_nic_word(struct net_device *dev, int indx, u16 *data)
{
int status;
@@ -628,13 +614,13 @@ static void rtl8192_proc_init_one(struct net_device *dev)
return;
proc_create_single("stats-rx", S_IFREG | S_IRUGO, dir,
- proc_get_stats_rx);
+ proc_get_stats_rx);
proc_create_single("stats-tx", S_IFREG | S_IRUGO, dir,
- proc_get_stats_tx);
+ proc_get_stats_tx);
proc_create_single("stats-ap", S_IFREG | S_IRUGO, dir,
- proc_get_stats_ap);
+ proc_get_stats_ap);
proc_create_single("registers", S_IFREG | S_IRUGO, dir,
- proc_get_registers);
+ proc_get_registers);
}
static void rtl8192_proc_remove_one(struct net_device *dev)
@@ -788,7 +774,6 @@ void rtl8192_set_rxconf(struct net_device *dev)
rxconf = rxconf | RCR_CBSSID;
}
-
if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
rxconf = rxconf | RCR_AICV;
rxconf = rxconf | RCR_APWRMGT;
@@ -797,7 +782,6 @@ void rtl8192_set_rxconf(struct net_device *dev)
if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
rxconf = rxconf | RCR_ACRC32;
-
rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE << RX_FIFO_THRESHOLD_SHIFT);
rxconf = rxconf & ~MAX_RX_DMA_MASK;
@@ -901,13 +885,11 @@ static u32 rtl819xusb_rx_command_packet(struct net_device *dev,
return status;
}
-
static void rtl8192_data_hard_stop(struct net_device *dev)
{
/* FIXME !! */
}
-
static void rtl8192_data_hard_resume(struct net_device *dev)
{
/* FIXME !! */
@@ -951,7 +933,6 @@ static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
u8 queue_index = tcb_desc->queue_index;
-
spin_lock_irqsave(&priv->tx_lock, flags);
memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
@@ -1123,7 +1104,6 @@ static void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
}
}
-
#define SHORT_SLOT_TIME 9
#define NON_SHORT_SLOT_TIME 20
@@ -1188,7 +1168,6 @@ static void rtl8192_net_update(struct net_device *dev)
*/
void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate)
{
-
}
short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
@@ -1232,6 +1211,8 @@ short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
return 0;
DMESGE("Error TX CMD URB, error %d", status);
+ dev_kfree_skb(skb);
+ usb_free_urb(tx_urb);
return -1;
}
@@ -1389,7 +1370,6 @@ static u8 MRateToHwRate8190Pci(u8 rate)
return ret;
}
-
static u8 QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc)
{
u8 tmp_Short;
@@ -1422,7 +1402,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
(struct tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
struct usb_device *udev = priv->udev;
int pend;
- int status;
+ int status, rt = -1;
struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
unsigned int idx_pipe;
@@ -1566,8 +1546,10 @@ 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)
- return -ENOMEM;
+ if (!tx_urb_zero) {
+ rt = -ENOMEM;
+ goto error;
+ }
usb_fill_bulk_urb(tx_urb_zero, udev,
usb_sndbulkpipe(udev, idx_pipe),
&zero, 0, tx_zero_isr, dev);
@@ -1577,7 +1559,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
"Error TX URB for zero byte %d, error %d",
atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
status);
- return -1;
+ goto error;
}
}
netif_trans_update(dev);
@@ -1588,7 +1570,12 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
RT_TRACE(COMP_ERR, "Error TX URB %d, error %d",
atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
status);
- return -1;
+
+error:
+ dev_kfree_skb_any(skb);
+ usb_free_urb(tx_urb);
+ usb_free_urb(tx_urb_zero);
+ return rt;
}
static short rtl8192_usb_initendpoints(struct net_device *dev)
@@ -1742,7 +1729,6 @@ static const struct ieee80211_qos_parameters def_qos_parameters = {
{0, 0, 0, 0} /* tx_op_limit */
};
-
static void rtl8192_update_beacon(struct work_struct *work)
{
struct r8192_priv *priv = container_of(work, struct r8192_priv,
@@ -1913,15 +1899,12 @@ static int rtl8192_qos_association_resp(struct r8192_priv *priv,
if (set_qos_param == 1)
schedule_work(&priv->qos_activate);
-
return 0;
}
-
-static int rtl8192_handle_assoc_response(
- struct net_device *dev,
- struct ieee80211_assoc_response_frame *resp,
- struct ieee80211_network *network)
+static int rtl8192_handle_assoc_response(struct net_device *dev,
+ struct ieee80211_assoc_response_frame *resp,
+ struct ieee80211_network *network)
{
struct r8192_priv *priv = ieee80211_priv(dev);
@@ -1929,7 +1912,6 @@ static int rtl8192_handle_assoc_response(
return 0;
}
-
static void rtl8192_update_ratr_table(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
@@ -2218,7 +2200,6 @@ static void rtl8192_init_priv_task(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
-
INIT_WORK(&priv->reset_wq, rtl8192_restart);
INIT_DELAYED_WORK(&priv->watch_dog_wq,
@@ -2515,7 +2496,6 @@ static int rtl8192_read_eeprom_info(struct net_device *dev)
break;
}
-
if (priv->rf_type == RF_1T2R)
RT_TRACE(COMP_EPROM, "\n1T2R config\n");
else
@@ -2668,7 +2648,6 @@ static void rtl8192_hwconfig(struct net_device *dev)
/* Set Auto Rate fallback control */
}
-
/* InitializeAdapter and PhyCfg */
static bool rtl8192_adapter_start(struct net_device *dev)
{
@@ -2803,14 +2782,12 @@ static bool rtl8192_adapter_start(struct net_device *dev)
RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
}
-
if (priv->ieee80211->FwRWRF)
/* We can force firmware to do RF-R/W */
priv->Rf_Mode = RF_OP_By_FW;
else
priv->Rf_Mode = RF_OP_By_SW_3wire;
-
rtl8192_phy_updateInitGain(dev);
/*--set CCK and OFDM Block "ON"--*/
rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
@@ -2865,7 +2842,6 @@ static bool rtl8192_adapter_start(struct net_device *dev)
}
write_nic_byte(dev, 0x87, 0x0);
-
return init_status;
}
@@ -2996,7 +2972,6 @@ static RESET_TYPE RxCheckStuck(struct net_device *dev)
return RESET_TYPE_NORESET;
}
-
/**
* This function is called by Checkforhang to check whether we should
* ask OS to reset driver
@@ -3052,8 +3027,6 @@ static void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
static int _rtl8192_up(struct net_device *dev);
static int rtl8192_close(struct net_device *dev);
-
-
static void CamRestoreAllEntry(struct net_device *dev)
{
u8 EntryId = 0;
@@ -3070,7 +3043,6 @@ static void CamRestoreAllEntry(struct net_device *dev)
RT_TRACE(COMP_SEC, "%s:\n", __func__);
-
if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) ||
(priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
for (EntryId = 0; EntryId < 4; EntryId++) {
@@ -3096,8 +3068,6 @@ static void CamRestoreAllEntry(struct net_device *dev)
MacAddr, 0, NULL);
}
-
-
if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
MacAddr = CAM_CONST_BROAD;
for (EntryId = 1; EntryId < 4; EntryId++) {
@@ -3134,7 +3104,6 @@ static void rtl819x_ifsilentreset(struct net_device *dev)
int reset_status = 0;
struct ieee80211_device *ieee = priv->ieee80211;
-
/* If we need to check CCK stop, please uncomment this line. */
/* bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter); */
@@ -3258,7 +3227,6 @@ static void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
}
}
-
static void rtl819x_watchdog_wqcallback(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
@@ -3369,7 +3337,6 @@ static int _rtl8192_up(struct net_device *dev)
return 0;
}
-
static int rtl8192_open(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
@@ -3381,7 +3348,6 @@ static int rtl8192_open(struct net_device *dev)
return ret;
}
-
int rtl8192_up(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
@@ -3392,7 +3358,6 @@ int rtl8192_up(struct net_device *dev)
return _rtl8192_up(dev);
}
-
static int rtl8192_close(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
@@ -3440,7 +3405,6 @@ int rtl8192_down(struct net_device *dev)
deinit_hal_dm(dev);
del_timer_sync(&priv->watch_dog_timer);
-
ieee80211_softmac_stop_protocol(priv->ieee80211);
memset(&priv->ieee80211->current_network, 0,
offsetof(struct ieee80211_network, list));
@@ -3449,7 +3413,6 @@ int rtl8192_down(struct net_device *dev)
return 0;
}
-
void rtl8192_commit(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
@@ -3495,7 +3458,6 @@ static void r8192_set_multicast(struct net_device *dev)
priv->promisc = promisc;
}
-
static int r8192_set_mac_adr(struct net_device *dev, void *mac)
{
struct r8192_priv *priv = ieee80211_priv(dev);
@@ -3525,7 +3487,6 @@ static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
mutex_lock(&priv->wx_mutex);
-
if (p->length < sizeof(struct ieee_param) || !p->pointer) {
ret = -EINVAL;
goto out;
@@ -3778,7 +3739,6 @@ static long rtl819x_translate_todbm(u8 signal_strength_index)
return signal_power;
}
-
/* We can not declare RSSI/EVM total value of sliding window to
* be a local static. Otherwise, it may increase when we return from S3/S4. The
* value will be kept in memory or disk. Declare the value in the adaptor
@@ -3841,7 +3801,6 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
if (!bcheck)
return;
-
/* only rtl8190 supported
* rtl8190_process_cck_rxpathsel(priv,pprevious_stats);
*/
@@ -3851,17 +3810,15 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
/* record the general signal strength to the sliding window. */
-
/* <2> Showed on UI for engineering
* hardware does not provide rssi information for each rf path in CCK
*/
if (!pprevious_stats->bIsCCK &&
(pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
- if (!rtl8192_phy_CheckIsLegalRFPath(
- priv->ieee80211->dev, rfpath))
+ if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev,
+ rfpath))
continue;
-
if (priv->stats.rx_rssi_percentage[rfpath] == 0)
priv->stats.rx_rssi_percentage[rfpath] =
pprevious_stats->RxMIMOSignalStrength[rfpath];
@@ -3881,7 +3838,6 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
}
}
-
/* Check PWDB. */
RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
pprevious_stats->bIsCCK ? "CCK" : "OFDM",
@@ -3908,7 +3864,6 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
pprevious_stats->bIsCCK ? "CCK" : "OFDM",
pprevious_stats->RxPWDBAll);
-
if (pprevious_stats->bPacketToSelf ||
pprevious_stats->bPacketBeacon ||
pprevious_stats->bToSelfBA) {
@@ -4083,7 +4038,6 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
u8 rf_rx_num = 0;
u8 sq;
-
priv->stats.numqry_phystatus++;
is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
@@ -4192,8 +4146,7 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
else
continue;
- if (!rtl8192_phy_CheckIsLegalRFPath(
- priv->ieee80211->dev, i))
+ if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
continue;
rx_pwr[i] =
@@ -4214,7 +4167,6 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
precord_stats->RxMIMOSignalStrength[i] = (u8)RSSI;
}
-
/* (2)PWDB, Average PWDB calculated by hardware
* (for rate adaptive)
*/
@@ -4259,7 +4211,6 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
evm & 0xff;
}
-
/* record rx statistics for debug */
rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
prxsc = (struct phy_ofdm_rx_status_rxsc_sgien_exintfflag *)
@@ -4288,16 +4239,14 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
}
} /* QueryRxPhyStatus8190Pci */
-static void rtl8192_record_rxdesc_forlateruse(
- struct ieee80211_rx_stats *psrc_stats,
- struct ieee80211_rx_stats *ptarget_stats)
+static void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats,
+ struct ieee80211_rx_stats *ptarget_stats)
{
ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
}
-
static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
struct ieee80211_rx_stats *pstats,
struct rx_drvinfo_819x_usb *pdrvinfo)
@@ -4341,8 +4290,6 @@ static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
bToSelfBA = true;
}
-
-
if (bpacket_match_bssid)
priv->stats.numpacket_matchbssid++;
if (bpacket_toself)
@@ -4383,7 +4330,6 @@ UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
/* 1: short preamble/GI, 0: long preamble/GI */
u32 preamble_guardinterval;
-
if (stats->bCRC)
rcvType = 2;
else if (stats->bICV)
@@ -4491,7 +4437,6 @@ UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
priv->stats.received_rate_histogram[rcvType][rateIndex]++;
}
-
static void query_rxdesc_status(struct sk_buff *skb,
struct ieee80211_rx_stats *stats,
bool bIsRxAggrSubframe)
@@ -4526,8 +4471,7 @@ static void query_rxdesc_status(struct sk_buff *skb,
* Driver info are written to the RxBuffer following rx desc
*/
if (stats->RxDrvInfoSize != 0) {
- driver_info = (struct rx_drvinfo_819x_usb *)(
- skb->data
+ driver_info = (struct rx_drvinfo_819x_usb *)(skb->data
+ sizeof(struct rx_desc_819x_usb)
+ stats->RxBufShift
);
@@ -4556,7 +4500,6 @@ static void query_rxdesc_status(struct sk_buff *skb,
stats->bShortPreamble = driver_info->SPLCP;
-
UpdateReceivedRateHistogramStatistics8190(dev, stats);
stats->bIsAMPDU = (driver_info->PartAggr == 1);
@@ -4569,7 +4512,7 @@ static void query_rxdesc_status(struct sk_buff *skb,
/* Rx A-MPDU */
if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
RT_TRACE(COMP_RXDESC,
- "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
+ "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
driver_info->FirstAGGR, driver_info->PartAggr);
}
@@ -4636,9 +4579,8 @@ static void rtl8192_rx_nomal(struct sk_buff *skb)
}
}
-static void rtl819xusb_process_received_packet(
- struct net_device *dev,
- struct ieee80211_rx_stats *pstats)
+static void rtl819xusb_process_received_packet(struct net_device *dev,
+ struct ieee80211_rx_stats *pstats)
{
struct r8192_priv *priv = ieee80211_priv(dev);
@@ -4671,8 +4613,6 @@ static void rtl819xusb_process_received_packet(
#ifdef SW_CRC_CHECK
SwCrcCheck();
#endif
-
-
}
static void query_rx_cmdpkt_desc_status(struct sk_buff *skb,
@@ -4691,7 +4631,6 @@ static void query_rx_cmdpkt_desc_status(struct sk_buff *skb,
stats->ntotalfrag = 1;
}
-
static void rtl8192_rx_cmd(struct sk_buff *skb)
{
struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
@@ -4759,7 +4698,6 @@ static const struct net_device_ops rtl8192_netdev_ops = {
.ndo_start_xmit = ieee80211_xmit,
};
-
/****************************************************************************
* ---------------------------- USB_STUFF---------------------------
*****************************************************************************/
@@ -4815,7 +4753,6 @@ static int rtl8192_usb_probe(struct usb_interface *intf,
RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
rtl8192_proc_init_one(dev);
-
RT_TRACE(COMP_INIT, "Driver probe completed\n");
return 0;
@@ -4843,7 +4780,6 @@ static void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
cancel_work_sync(&priv->qos_activate);
}
-
static void rtl8192_usb_disconnect(struct usb_interface *intf)
{
struct net_device *dev = usb_get_intfdata(intf);
@@ -4907,7 +4843,6 @@ static int __init rtl8192_usb_module_init(void)
return usb_register(&rtl8192_usb_driver);
}
-
static void __exit rtl8192_usb_module_exit(void)
{
usb_deregister(&rtl8192_usb_driver);
@@ -4949,7 +4884,6 @@ void EnableHWSecurityConfig8192(struct net_device *dev)
write_nic_byte(dev, SECR, SECR_value);
}
-
void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
{
@@ -4970,7 +4904,6 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
else
usConfig |= BIT(15) | (KeyType << 2) | KeyIndex;
-
for (i = 0; i < CAM_CONTENT_COUNT; i++) {
TargetCommand = i + CAM_CONTENT_COUNT * EntryNo;
TargetCommand |= BIT(31) | BIT(16);
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
index db99129d3169..5901026949f2 100644
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ b/drivers/staging/rtl8712/rtl8712_led.c
@@ -75,7 +75,7 @@ static void BlinkWorkItemCallback(struct work_struct *work);
* Initialize an LED_871x object.
*/
static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed,
- enum LED_PIN_871x LedPin)
+ enum LED_PIN_871x LedPin)
{
pLed->padapter = padapter;
pLed->LedPin = LedPin;
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
index 9901815604f4..06de031be6a9 100644
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ b/drivers/staging/rtl8712/rtl8712_recv.c
@@ -61,13 +61,13 @@ void r8712_init_recv_priv(struct recv_priv *precvpriv,
precvbuf->ref_cnt = 0;
precvbuf->adapter = padapter;
list_add_tail(&precvbuf->list,
- &(precvpriv->free_recv_buf_queue.queue));
+ &(precvpriv->free_recv_buf_queue.queue));
precvbuf++;
}
precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
tasklet_init(&precvpriv->recv_tasklet,
- (void(*)(unsigned long))recv_tasklet,
- (unsigned long)padapter);
+ (void(*)(unsigned long))recv_tasklet,
+ (unsigned long)padapter);
skb_queue_head_init(&precvpriv->rx_skb_queue);
skb_queue_head_init(&precvpriv->free_recv_skb_queue);
@@ -119,7 +119,7 @@ void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf)
}
void r8712_free_recvframe(union recv_frame *precvframe,
- struct __queue *pfree_recv_queue)
+ struct __queue *pfree_recv_queue)
{
unsigned long irqL;
struct _adapter *padapter = precvframe->u.hdr.adapter;
@@ -140,7 +140,7 @@ void r8712_free_recvframe(union recv_frame *precvframe,
}
static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
- struct recv_stat *prxstat)
+ struct recv_stat *prxstat)
{
u16 drvinfo_sz;
@@ -177,7 +177,7 @@ static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
/*perform defrag*/
static union recv_frame *recvframe_defrag(struct _adapter *adapter,
- struct __queue *defrag_q)
+ struct __queue *defrag_q)
{
struct list_head *plist, *phead;
u8 wlanhdr_offset;
@@ -289,7 +289,6 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter,
r8712_free_recvframe(precv_frame, pfree_recv_queue);
prtnframe = NULL;
}
-
}
if ((ismfrag == 0) && (fragnum != 0)) {
/* the last fragment frame
@@ -379,26 +378,26 @@ static void amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe)
/* convert hdr + possible LLC headers into Ethernet header */
eth_type = (sub_skb->data[6] << 8) | sub_skb->data[7];
if (sub_skb->len >= 8 &&
- ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) &&
- eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
- !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) {
+ ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) &&
+ eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
+ !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) {
/* remove RFC1042 or Bridge-Tunnel encapsulation and
* replace EtherType
*/
skb_pull(sub_skb, SNAP_SIZE);
memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
- ETH_ALEN);
+ ETH_ALEN);
memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
- ETH_ALEN);
+ ETH_ALEN);
} else {
__be16 len;
/* Leave Ethernet header part of hdr and full payload */
len = htons(sub_skb->len);
memcpy(skb_push(sub_skb, 2), &len, 2);
memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
- ETH_ALEN);
+ ETH_ALEN);
memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
- ETH_ALEN);
+ ETH_ALEN);
}
/* Indicate the packets to upper layer */
if (sub_skb) {
@@ -438,7 +437,6 @@ void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf)
r8712_event_handle(padapter, (__le32 *)poffset);
poffset += (cmd_len + 8);/*8 bytes alignment*/
} while (le32_to_cpu(voffset) & BIT(31));
-
}
static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl,
@@ -472,7 +470,7 @@ static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl,
}
static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
- union recv_frame *prframe)
+ union recv_frame *prframe)
{
struct list_head *phead, *plist;
union recv_frame *pnextrframe;
@@ -499,8 +497,8 @@ static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
}
int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
- struct recv_reorder_ctrl *preorder_ctrl,
- int bforced)
+ struct recv_reorder_ctrl *preorder_ctrl,
+ int bforced)
{
struct list_head *phead, *plist;
union recv_frame *prframe;
@@ -530,7 +528,7 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
plist = plist->next;
list_del_init(&(prframe->u.hdr.list));
if (SN_EQUAL(preorder_ctrl->indicate_seq,
- pattrib->seq_num))
+ pattrib->seq_num))
preorder_ctrl->indicate_seq =
(preorder_ctrl->indicate_seq + 1) % 4096;
/*indicate this recv_frame*/
@@ -555,7 +553,7 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
}
static int recv_indicatepkt_reorder(struct _adapter *padapter,
- union recv_frame *prframe)
+ union recv_frame *prframe)
{
unsigned long irql;
struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
@@ -624,7 +622,7 @@ void r8712_reordering_ctrl_timeout_handler(void *pcontext)
}
static int r8712_process_recv_indicatepkts(struct _adapter *padapter,
- union recv_frame *prframe)
+ union recv_frame *prframe)
{
int retval = _SUCCESS;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index 944336e0d2e2..363b82e3e7c6 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -142,9 +142,9 @@ static noinline_for_stack char *translate_scan_wpa(struct iw_request_info *info,
memset(buf, 0, MAX_WPA_IE_LEN);
n = sprintf(buf, "wpa_ie=");
for (i = 0; i < wpa_len; i++) {
- n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
+ n += scnprintf(buf + n, MAX_WPA_IE_LEN - n,
"%02x", wpa_ie[i]);
- if (n >= MAX_WPA_IE_LEN)
+ if (n == MAX_WPA_IE_LEN-1)
break;
}
memset(iwe, 0, sizeof(*iwe));
@@ -162,9 +162,9 @@ static noinline_for_stack char *translate_scan_wpa(struct iw_request_info *info,
memset(buf, 0, MAX_WPA_IE_LEN);
n = sprintf(buf, "rsn_ie=");
for (i = 0; i < rsn_len; i++) {
- n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
+ n += scnprintf(buf + n, MAX_WPA_IE_LEN - n,
"%02x", rsn_ie[i]);
- if (n >= MAX_WPA_IE_LEN)
+ if (n == MAX_WPA_IE_LEN-1)
break;
}
memset(iwe, 0, sizeof(*iwe));
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
index aa8f8500cbb2..29b85330815f 100644
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
+++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
@@ -231,8 +231,7 @@ end_of_mp_stop_test:
return _SUCCESS;
}
-uint oid_rt_pro_set_data_rate_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -283,17 +282,15 @@ uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
if (poid_par_priv->type_of_oid != SET_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
if (mp_stop_test(Adapter) == _FAIL)
- status = RNDIS_STATUS_NOT_ACCEPTED;
- return status;
+ return RNDIS_STATUS_NOT_ACCEPTED;
+ return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -328,8 +325,7 @@ uint oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_set_tx_power_control_hdl(
- struct oid_par_priv *poid_par_priv)
+uint oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -347,71 +343,61 @@ uint oid_rt_pro_set_tx_power_control_hdl(
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_query_tx_packet_sent_hdl(
- struct oid_par_priv *poid_par_priv)
+uint oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
{
- uint status = RNDIS_STATUS_SUCCESS;
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
- if (poid_par_priv->type_of_oid != QUERY_OID) {
- status = RNDIS_STATUS_NOT_ACCEPTED;
- return status;
- }
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return RNDIS_STATUS_NOT_ACCEPTED;
+
if (poid_par_priv->information_buf_len == sizeof(u32)) {
*(u32 *)poid_par_priv->information_buf =
Adapter->mppriv.tx_pktcount;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else {
- status = RNDIS_STATUS_INVALID_LENGTH;
+ return RNDIS_STATUS_INVALID_LENGTH;
}
- return status;
+ return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_query_rx_packet_received_hdl(
- struct oid_par_priv *poid_par_priv)
+uint oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
{
- uint status = RNDIS_STATUS_SUCCESS;
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
- if (poid_par_priv->type_of_oid != QUERY_OID) {
- status = RNDIS_STATUS_NOT_ACCEPTED;
- return status;
- }
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return RNDIS_STATUS_NOT_ACCEPTED;
+
if (poid_par_priv->information_buf_len == sizeof(u32)) {
*(u32 *)poid_par_priv->information_buf =
Adapter->mppriv.rx_pktcount;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else {
- status = RNDIS_STATUS_INVALID_LENGTH;
+ return RNDIS_STATUS_INVALID_LENGTH;
}
- return status;
+ return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_query_rx_packet_crc32_error_hdl(
- struct oid_par_priv *poid_par_priv)
+uint oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
{
- uint status = RNDIS_STATUS_SUCCESS;
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
- if (poid_par_priv->type_of_oid != QUERY_OID) {
- status = RNDIS_STATUS_NOT_ACCEPTED;
- return status;
- }
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return RNDIS_STATUS_NOT_ACCEPTED;
+
if (poid_par_priv->information_buf_len == sizeof(u32)) {
*(u32 *)poid_par_priv->information_buf =
Adapter->mppriv.rx_crcerrpktcount;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else {
- status = RNDIS_STATUS_INVALID_LENGTH;
+ return RNDIS_STATUS_INVALID_LENGTH;
}
- return status;
+ return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -422,10 +408,8 @@ uint oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
{
- uint status = RNDIS_STATUS_SUCCESS;
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -435,13 +419,12 @@ uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv
Adapter->mppriv.rx_pktcount = 0;
Adapter->mppriv.rx_crcerrpktcount = 0;
} else {
- status = RNDIS_STATUS_INVALID_LENGTH;
+ return RNDIS_STATUS_INVALID_LENGTH;
}
- return status;
+ return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -452,8 +435,7 @@ uint oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -468,8 +450,7 @@ uint oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -484,8 +465,7 @@ uint oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -497,8 +477,7 @@ uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -511,8 +490,7 @@ uint oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -525,8 +503,7 @@ uint oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -539,8 +516,7 @@ uint oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -553,8 +529,7 @@ uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_pro_read_register_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -735,8 +710,7 @@ uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
}
/*----------------------------------------------------------------------*/
-uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
@@ -829,8 +803,7 @@ uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
return RNDIS_STATUS_SUCCESS;
}
-uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv
- *poid_par_priv)
+uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
{
struct _adapter *Adapter = (struct _adapter *)
(poid_par_priv->adapter_context);
diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c
index 6d18d23acdc0..7117d16a30f9 100644
--- a/drivers/staging/rtl8723bs/core/rtw_ap.c
+++ b/drivers/staging/rtl8723bs/core/rtw_ap.c
@@ -216,8 +216,9 @@ void expire_timeout_chk(struct adapter *padapter)
/* check auth_queue */
#ifdef DBG_EXPIRATION_CHK
if (phead != plist) {
- DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"
- , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);
+ DBG_871X(FUNC_NDEV_FMT " auth_list, cnt:%u\n",
+ FUNC_NDEV_ARG(padapter->pnetdev),
+ pstapriv->auth_list_cnt);
}
#endif
while (phead != plist) {
@@ -1446,14 +1447,14 @@ u8 rtw_ap_set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
u8 res = _SUCCESS;
ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
- if (ph2c == NULL) {
+ if (!ph2c) {
res = _FAIL;
goto exit;
}
psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm));
if (psetstakey_para == NULL) {
- kfree((u8 *)ph2c);
+ kfree(ph2c);
res = _FAIL;
goto exit;
}
@@ -1496,7 +1497,7 @@ static int rtw_ap_set_key(
}
psetkeyparm = rtw_zmalloc(sizeof(struct setkey_parm));
if (psetkeyparm == NULL) {
- kfree((unsigned char *)pcmd);
+ kfree(pcmd);
res = _FAIL;
goto exit;
}
diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c
index 8d93c2f26890..13a9b54b4561 100644
--- a/drivers/staging/rtl8723bs/core/rtw_cmd.c
+++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c
@@ -372,13 +372,13 @@ void rtw_free_cmd_obj(struct cmd_obj *pcmd)
if ((pcmd->cmdcode != _JoinBss_CMD_) &&
(pcmd->cmdcode != _CreateBss_CMD_)) {
/* free parmbuf in cmd_obj */
- kfree((unsigned char *)pcmd->parmbuf);
+ kfree(pcmd->parmbuf);
}
if (pcmd->rsp != NULL) {
if (pcmd->rspsz != 0) {
/* free rsp in cmd_obj */
- kfree((unsigned char *)pcmd->rsp);
+ kfree(pcmd->rsp);
}
}
@@ -507,19 +507,9 @@ post_process:
cmd_process_time = jiffies_to_msecs(jiffies - cmd_start_time);
if (cmd_process_time > 1000) {
- if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
- DBG_871X(ADPT_FMT" cmd =%d process_time =%lu > 1 sec\n",
- ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
- /* rtw_warn_on(1); */
- } else if (pcmd->cmdcode == GEN_CMD_CODE(_Set_MLME_EVT)) {
- DBG_871X(ADPT_FMT" cmd =%d, process_time =%lu > 1 sec\n",
- ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
- /* rtw_warn_on(1); */
- } else {
- DBG_871X(ADPT_FMT" cmd =%d, process_time =%lu > 1 sec\n",
- ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
- /* rtw_warn_on(1); */
- }
+ DBG_871X(ADPT_FMT "cmd= %d process_time= %lu > 1 sec\n",
+ ADPT_ARG(pcmd->padapter), pcmd->cmdcode,
+ cmd_process_time);
}
/* call callback function for post-processed */
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
index 34adf5789c98..71fcb466019a 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
@@ -19,7 +19,7 @@ int rtw_init_mlme_priv(struct adapter *padapter)
int i;
u8 *pbuf;
struct wlan_network *pnetwork;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int res = _SUCCESS;
pmlmepriv->nic_hdl = (u8 *)padapter;
@@ -40,7 +40,7 @@ int rtw_init_mlme_priv(struct adapter *padapter)
pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network)));
- if (pbuf == NULL) {
+ if (!pbuf) {
res = _FAIL;
goto exit;
}
@@ -112,9 +112,8 @@ void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
{
if (pmlmepriv) {
rtw_free_mlme_priv_ie_data(pmlmepriv);
- if (pmlmepriv->free_bss_buf) {
+ if (pmlmepriv->free_bss_buf)
vfree(pmlmepriv->free_bss_buf);
- }
}
}
@@ -185,10 +184,10 @@ void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwor
/* _irqL irqL; */
struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
- if (pnetwork == NULL)
+ if (!pnetwork)
return;
- if (pnetwork->fixed == true)
+ if (pnetwork->fixed)
return;
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
@@ -209,7 +208,6 @@ void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwor
pmlmepriv->num_of_scanned--;
-
/* DBG_871X("_rtw_free_network:SSID =%s\n", pnetwork->network.Ssid.Ssid); */
spin_unlock_bh(&free_queue->lock);
@@ -220,10 +218,10 @@ void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *
struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
- if (pnetwork == NULL)
+ if (!pnetwork)
return;
- if (pnetwork->fixed == true)
+ if (pnetwork->fixed)
return;
/* spin_lock_irqsave(&free_queue->lock, irqL); */
@@ -301,12 +299,8 @@ void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
spin_unlock_bh(&scanned_queue->lock);
}
-
-
-
sint rtw_if_up(struct adapter *padapter)
{
-
sint res;
if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
@@ -318,7 +312,6 @@ sint rtw_if_up(struct adapter *padapter)
return res;
}
-
void rtw_generate_random_ibss(u8 *pibss)
{
unsigned long curtime = jiffies;
@@ -329,7 +322,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)
@@ -337,7 +329,6 @@ u8 *rtw_get_capability_from_ie(u8 *ie)
return ie + 8 + 2;
}
-
u16 rtw_get_capability(struct wlan_bssid_ex *bss)
{
__le16 val;
@@ -425,7 +416,6 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst, u8 fea
memcpy((u8 *)&tmps, rtw_get_capability_from_ie(src->IEs), 2);
memcpy((u8 *)&tmpd, rtw_get_capability_from_ie(dst->IEs), 2);
-
s_cap = le16_to_cpu(tmps);
d_cap = le16_to_cpu(tmpd);
@@ -467,7 +457,6 @@ struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
{
struct list_head *plist, *phead;
-
struct wlan_network *pwlan = NULL;
struct wlan_network *oldest = NULL;
@@ -482,7 +471,7 @@ struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
pwlan = LIST_CONTAINOR(plist, struct wlan_network, list);
- if (pwlan->fixed != true) {
+ if (!pwlan->fixed) {
if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned))
oldest = pwlan;
}
@@ -579,12 +568,8 @@ static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex
}
}
-
/*
-
Caller must hold pmlmepriv->lock first.
-
-
*/
void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target)
{
@@ -625,7 +610,6 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
}
-
/* If we didn't find a match, then get a new network slot to initialize
* with this beacon's information */
/* if (phead == plist) { */
@@ -634,7 +618,7 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
/* If there are no more slots, expire the oldest */
/* list_del_init(&oldest->list); */
pnetwork = oldest;
- if (pnetwork == NULL) {
+ if (!pnetwork) {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n\nsomething wrong here\n\n\n"));
goto exit;
}
@@ -655,7 +639,7 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
pnetwork = rtw_alloc_network(pmlmepriv); /* will update scan_time */
- if (pnetwork == NULL) {
+ if (!pnetwork) {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n\nsomething wrong here\n\n\n"));
goto exit;
}
@@ -739,7 +723,7 @@ int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwor
privacy = pnetwork->network.Privacy;
if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
- if (rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen) != NULL)
+ if (rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen))
return true;
else
return false;
@@ -754,15 +738,13 @@ int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwor
if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_));
- if (p && ie_len > 0) {
+ if (p && ie_len > 0)
bselected = true;
- } else {
+ else
bselected = false;
- }
}
}
-
if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
DBG_871X("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
bselected = false;
@@ -773,7 +755,6 @@ int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwor
bselected = false;
}
-
return bselected;
}
@@ -783,7 +764,6 @@ void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf)
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_event\n"));
}
-
void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
{
u32 len;
@@ -800,7 +780,6 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
return;
}
-
spin_lock_bh(&pmlmepriv->lock);
/* update IBSS_network 's timestamp */
@@ -823,21 +802,16 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
/* lock pmlmepriv->lock when you accessing network_q */
if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false) {
- if (pnetwork->Ssid.Ssid[0] == 0) {
+ if (pnetwork->Ssid.Ssid[0] == 0)
pnetwork->Ssid.SsidLength = 0;
- }
rtw_add_network(adapter, pnetwork);
}
exit:
spin_unlock_bh(&pmlmepriv->lock);
-
- return;
}
-
-
void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
{
u8 timer_cancelled = false;
@@ -868,12 +842,11 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
if (timer_cancelled)
_cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled);
-
spin_lock_bh(&pmlmepriv->lock);
rtw_set_signal_stat_timer(&adapter->recvpriv);
- if (pmlmepriv->to_join == true) {
+ if (pmlmepriv->to_join) {
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
@@ -896,9 +869,8 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
- if (rtw_createbss_cmd(adapter) != _SUCCESS) {
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error =>rtw_createbss_cmd status FAIL\n"));
- }
+ if (rtw_createbss_cmd(adapter) != _SUCCESS)
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error =>rtw_createbss_cmd status FAIL\n"));
pmlmepriv->to_join = false;
}
@@ -1009,7 +981,6 @@ static void find_network(struct adapter *adapter)
else
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_assoc_resources : pwlan == NULL\n\n"));
-
if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
(adapter->stapriv.asoc_sta_count == 1))
rtw_free_network_nolock(adapter, pwlan);
@@ -1169,9 +1140,8 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress);
- if (psta == NULL) {
+ if (!psta)
psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
- }
if (psta) { /* update ptarget_sta */
@@ -1189,7 +1159,6 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
psta->wireless_mode = pmlmeext->cur_wireless_mode;
psta->raid = networktype_to_raid_ex(padapter, psta);
-
/* sta mode */
rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
@@ -1221,7 +1190,6 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
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 */
@@ -1238,7 +1206,6 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
preorder_ctrl->wsize_b = 64;/* max_ampdu_sz;ex. 32(kbytes) -> wsize_b =32 */
}
-
bmc_sta = rtw_get_bcmc_stainfo(padapter);
if (bmc_sta) {
for (i = 0; i < 16 ; i++) {
@@ -1272,7 +1239,6 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nfw_state:%x, BSSID:"MAC_FMT"\n"
, get_fwstate(pmlmepriv), MAC_ARG(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 */
@@ -1281,7 +1247,6 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
cur_network->aid = pnetwork->join_res;
-
rtw_set_signal_stat_timer(&padapter->recvpriv);
padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
@@ -1349,12 +1314,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
rtw_get_encrypt_decrypt_from_registrypriv(adapter);
-
- if (pmlmepriv->assoc_ssid.SsidLength == 0) {
+ if (pmlmepriv->assoc_ssid.SsidLength == 0)
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ joinbss event call back for Any SSid\n"));
- } else {
+ else
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
- }
the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
@@ -1377,7 +1340,7 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
/* s1. find ptarget_wlan */
if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (the_same_macaddr == true) {
+ if (the_same_macaddr) {
ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
} else {
pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
@@ -1412,11 +1375,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
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) == true) {
ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
- if (ptarget_sta == NULL) {
+ 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;
@@ -1432,7 +1394,6 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
}
-
/* s5. Cancel assoc_timer */
_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
@@ -1506,7 +1467,7 @@ void rtw_sta_media_status_rpt(struct adapter *adapter, struct sta_info *psta, u3
{
u16 media_status_rpt;
- if (psta == NULL)
+ if (!psta)
return;
media_status_rpt = (u16)((psta->mac_id<<8)|mstatus); /* MACID|OPMODE:1 connect */
@@ -1564,7 +1525,7 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
/* for AD-HOC mode */
psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
- if (psta != NULL) {
+ if (psta) {
/* the sta have been in sta_info_queue => do nothing */
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error: rtw_stassoc_event_callback: sta has been in sta_hash_queue\n"));
@@ -1573,7 +1534,7 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
}
psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
- if (psta == NULL) {
+ if (!psta) {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't alloc sta_info when rtw_stassoc_event_callback\n"));
return;
}
@@ -1591,7 +1552,6 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
-
psta->ieee8021x_blocked = false;
spin_lock_bh(&pmlmepriv->lock);
@@ -1612,7 +1572,6 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
spin_unlock_bh(&pmlmepriv->lock);
-
mlmeext_sta_add_event_callback(adapter, psta);
}
@@ -1648,7 +1607,6 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
return;
-
mlmeext_sta_del_event_callback(adapter);
spin_lock_bh(&pmlmepriv->lock);
@@ -1726,13 +1684,8 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
}
- if (rtw_createbss_cmd(adapter) != _SUCCESS) {
-
+ if (rtw_createbss_cmd(adapter) != _SUCCESS)
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>stadel_event_callback: rtw_createbss_cmd status FAIL***\n "));
-
- }
-
-
}
}
@@ -1750,7 +1703,6 @@ void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf)
cpwm_int_hdl(padapter, preportpwrstate);
}
-
void rtw_wmm_event_callback(struct adapter *padapter, u8 *pbuf)
{
WMMOnAssocRsp(padapter);
@@ -1840,8 +1792,6 @@ void rtw_mlme_reset_auto_scan_int(struct adapter *adapter)
mlme->auto_scan_int_ms = mlme->roam_scan_int_ms;
} else
mlme->auto_scan_int_ms = 0; /* disabled */
-
- return;
}
static void rtw_auto_scan_handler(struct adapter *padapter)
@@ -1859,7 +1809,7 @@ static void rtw_auto_scan_handler(struct adapter *padapter)
goto exit;
}
- if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
DBG_871X(FUNC_ADPT_FMT" exit BusyTraffic\n", FUNC_ADPT_ARG(padapter));
goto exit;
}
@@ -1879,20 +1829,20 @@ void rtw_dynamic_check_timer_handler(struct adapter *adapter)
if (!adapter)
return;
- if (adapter->hw_init_completed == false)
+ if (!adapter->hw_init_completed)
return;
- if ((adapter->bDriverStopped == true) || (adapter->bSurpriseRemoved == true))
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
return;
- if (adapter->net_closed == true)
+ if (adapter->net_closed)
return;
if (is_primary_adapter(adapter))
DBG_871X("IsBtDisabled =%d, IsBtControlLps =%d\n", hal_btcoex_IsBtDisabled(adapter), hal_btcoex_IsBtControlLps(adapter));
- if ((adapter_to_pwrctl(adapter)->bFwCurrentInPSMode == true)
- && (hal_btcoex_IsBtControlLps(adapter) == false)
+ if ((adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
+ && !(hal_btcoex_IsBtControlLps(adapter))
) {
u8 bEnterPS;
@@ -1907,16 +1857,14 @@ void rtw_dynamic_check_timer_handler(struct adapter *adapter)
}
} else {
- if (is_primary_adapter(adapter)) {
+ if (is_primary_adapter(adapter))
rtw_dynamic_chk_wk_cmd(adapter);
- }
}
/* auto site survey */
rtw_auto_scan_handler(adapter);
}
-
inline bool rtw_is_scan_deny(struct adapter *adapter)
{
struct mlme_priv *mlmepriv = &adapter->mlmepriv;
@@ -1994,26 +1942,24 @@ int rtw_select_roaming_candidate(struct mlme_priv *mlme)
{
int ret = _FAIL;
struct list_head *phead;
- struct adapter *adapter;
struct __queue *queue = &(mlme->scanned_queue);
struct wlan_network *pnetwork = NULL;
struct wlan_network *candidate = NULL;
- if (mlme->cur_network_scanned == NULL) {
+ if (!mlme->cur_network_scanned) {
rtw_warn_on(1);
return ret;
}
spin_lock_bh(&(mlme->scanned_queue.lock));
phead = get_list_head(queue);
- adapter = (struct adapter *)mlme->nic_hdl;
mlme->pscanned = get_next(phead);
while (phead != mlme->pscanned) {
pnetwork = LIST_CONTAINOR(mlme->pscanned, struct wlan_network, list);
- if (pnetwork == NULL) {
+ if (!pnetwork) {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork == NULL)\n", __func__));
ret = _FAIL;
goto exit;
@@ -2031,7 +1977,7 @@ int rtw_select_roaming_candidate(struct mlme_priv *mlme)
}
- if (candidate == NULL) {
+ if (!candidate) {
DBG_871X("%s: return _FAIL(candidate == NULL)\n", __func__);
ret = _FAIL;
goto exit;
@@ -2064,9 +2010,8 @@ static int rtw_check_join_candidate(struct mlme_priv *mlme
int updated = false;
struct adapter *adapter = container_of(mlme, struct adapter, mlmepriv);
-
/* check bssid, if needed */
- if (mlme->assoc_by_bssid == true) {
+ if (mlme->assoc_by_bssid) {
if (memcmp(competitor->network.MacAddress, mlme->assoc_bssid, ETH_ALEN))
goto exit;
}
@@ -2115,12 +2060,8 @@ exit:
/*
Calling context:
The caller of the sub-routine will be in critical section...
-
The caller must hold the following spinlock
-
pmlmepriv->lock
-
-
*/
int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
@@ -2148,7 +2089,7 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
while (phead != pmlmepriv->pscanned) {
pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
- if (pnetwork == NULL) {
+ if (!pnetwork) {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork == NULL)\n", __func__));
ret = _FAIL;
goto exit;
@@ -2166,7 +2107,7 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
}
- if (candidate == NULL) {
+ if (!candidate) {
DBG_871X("%s: return _FAIL(candidate == NULL)\n", __func__);
#ifdef CONFIG_WOWLAN
_clr_fwstate_(pmlmepriv, _FW_LINKED|_FW_UNDER_LINKING);
@@ -2207,14 +2148,14 @@ sint rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
sint res = _SUCCESS;
pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd == NULL) {
+ if (!pcmd) {
res = _FAIL; /* try again */
goto exit;
}
psetauthparm = rtw_zmalloc(sizeof(struct setauth_parm));
- if (psetauthparm == NULL) {
- kfree((unsigned char *)pcmd);
+ if (!psetauthparm) {
+ kfree(pcmd);
res = _FAIL;
goto exit;
}
@@ -2227,7 +2168,6 @@ sint rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
pcmd->rsp = NULL;
pcmd->rspsz = 0;
-
INIT_LIST_HEAD(&pcmd->list);
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("after enqueue set_auth_cmd, auth_mode =%x\n", psecuritypriv->dot11AuthAlgrthm));
@@ -2247,7 +2187,7 @@ sint rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, s
sint res = _SUCCESS;
psetkeyparm = rtw_zmalloc(sizeof(struct setkey_parm));
- if (psetkeyparm == NULL) {
+ if (!psetkeyparm) {
res = _FAIL;
goto exit;
}
@@ -2291,15 +2231,14 @@ sint rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, s
default:
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n", psecuritypriv->dot11PrivacyAlgrthm));
res = _FAIL;
- kfree((unsigned char *)psetkeyparm);
+ kfree(psetkeyparm);
goto exit;
}
-
if (enqueue) {
pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd == NULL) {
- kfree((unsigned char *)psetkeyparm);
+ if (!pcmd) {
+ kfree(psetkeyparm);
res = _FAIL; /* try again */
goto exit;
}
@@ -2315,7 +2254,7 @@ sint rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, s
res = rtw_enqueue_cmd(pcmdpriv, pcmd);
} else {
setkey_hdl(adapter, (u8 *)psetkeyparm);
- kfree((u8 *) psetkeyparm);
+ kfree(psetkeyparm);
}
exit:
return res;
@@ -2350,7 +2289,6 @@ int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_
}
-
/* */
/* Ported from 8185: IsInPreAuthKeyList(). (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
/* Added by Annie, 2006-05-07. */
@@ -2679,7 +2617,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SGI_20);
/* Get HT BW */
- if (in_ie == NULL) {
+ if (!in_ie) {
/* TDLS: TODO 20/40 issue */
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
operation_bw = padapter->mlmeextpriv.cur_bwmode;
@@ -2794,7 +2732,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
phtpriv->ht_option = true;
- if (in_ie != NULL) {
+ if (in_ie) {
p = rtw_get_ie(in_ie, _HT_ADD_INFO_IE_, &ielen, in_len);
if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
out_len = *pout_len;
@@ -2824,7 +2762,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channe
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
u8 cbw40_enable = 0;
-
if (!phtpriv->ht_option)
return;
@@ -2834,7 +2771,7 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channe
DBG_871X("+rtw_update_ht_cap()\n");
/* maybe needs check if ap supports rx ampdu. */
- if ((phtpriv->ampdu_enable == false) && (pregistrypriv->ampdu_enable == 1)) {
+ if (!(phtpriv->ampdu_enable) && pregistrypriv->ampdu_enable == 1) {
if (pregistrypriv->wifi_spec == 1) {
/* remove this part because testbed AP should disable RX AMPDU */
/* phtpriv->ampdu_enable = false; */
@@ -2847,7 +2784,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channe
/* phtpriv->ampdu_enable = true; */
}
-
/* check Max Rx A-MPDU Size */
len = 0;
p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fix_ie), _HT_CAPABILITY_IE_, &len, ie_len-sizeof(struct ndis_802_11_fix_ie));
@@ -2861,7 +2797,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channe
}
-
len = 0;
p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fix_ie), _HT_ADD_INFO_IE_, &len, ie_len-sizeof(struct ndis_802_11_fix_ie));
if (p && len > 0) {
@@ -2961,7 +2896,7 @@ void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitfr
return;
}
- if (psta == NULL) {
+ if (!psta) {
DBG_871X("%s, psta ==NUL\n", __func__);
return;
}
@@ -2971,10 +2906,9 @@ void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitfr
return;
}
-
phtpriv = &psta->htpriv;
- if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true)) {
+ if (phtpriv->ht_option && phtpriv->ampdu_enable) {
issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
@@ -2994,10 +2928,8 @@ void rtw_append_exented_cap(struct adapter *padapter, u8 *out_ie, uint *pout_len
u8 cap_content[8] = {0};
u8 *pframe;
-
- if (phtpriv->bss_coexist) {
+ if (phtpriv->bss_coexist)
SET_EXT_CAPABILITY_ELE_BSS_COEXIST(cap_content, 1);
- }
pframe = rtw_set_ie(out_ie + *pout_len, EID_EXTCapability, 8, cap_content, pout_len);
}
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
index 2128886c9924..5e687f6d2c3e 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
@@ -344,7 +344,7 @@ static void init_channel_list(struct adapter *padapter, RT_CHANNEL_INFO *channel
struct p2p_channels *channel_list)
{
- struct p2p_oper_class_map op_class[] = {
+ static const 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 },
@@ -363,7 +363,7 @@ static void init_channel_list(struct adapter *padapter, RT_CHANNEL_INFO *channel
for (op = 0; op_class[op].op_class; op++) {
u8 ch;
- struct p2p_oper_class_map *o = &op_class[op];
+ const 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) {
@@ -2922,7 +2922,8 @@ int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid,
int i = 0;
do {
- ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms > 0?true:false);
+ ret = _issue_probereq(padapter, pssid, da, ch, append_wps,
+ wait_ms > 0);
i++;
@@ -3086,8 +3087,6 @@ void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short
rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
DBG_871X("%s\n", __func__);
dump_mgntframe(padapter, pmgntframe);
-
- return;
}
@@ -3405,8 +3404,6 @@ exit:
rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
else
rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
-
- return;
}
/* when wait_ack is ture, this function shoule be called at process context */
@@ -3513,7 +3510,7 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int pow
}
do {
- ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0?true:false);
+ ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
i++;
@@ -3661,7 +3658,7 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int
da = get_my_bssid(&(pmlmeinfo->network));
do {
- ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0?true:false);
+ ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
i++;
@@ -3769,7 +3766,7 @@ int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int
int i = 0;
do {
- ret = _issue_deauth(padapter, da, reason, wait_ms > 0?true:false);
+ ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
i++;
@@ -5260,8 +5257,6 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi
DBG_871X("report_del_sta_event: delete STA, mac_id =%d\n", mac_id);
rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-
- return;
}
void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
@@ -5306,8 +5301,6 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int
DBG_871X("report_add_sta_event: add STA\n");
rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-
- return;
}
/****************************************************************************
@@ -5869,8 +5862,6 @@ void link_timer_hdl(struct timer_list *t)
issue_assocreq(padapter);
set_link_timer(pmlmeext, REASSOC_TO);
}
-
- return;
}
void addba_timer_hdl(struct timer_list *t)
diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
index 4075de07e0a9..30137f0bd984 100644
--- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
@@ -190,7 +190,6 @@ void rtw_ps_processor(struct adapter *padapter)
}
exit:
pwrpriv->ps_processing = false;
- return;
}
static void pwr_state_check_handler(struct timer_list *t)
diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c
index 687ff3c6f09f..7fa8c84cf5f4 100644
--- a/drivers/staging/rtl8723bs/core/rtw_recv.c
+++ b/drivers/staging/rtl8723bs/core/rtw_recv.c
@@ -1400,10 +1400,8 @@ static sint validate_80211w_mgmt(struct adapter *adapter, union recv_frame *prec
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
u8 *ptr = precv_frame->u.hdr.rx_data;
- u8 type;
u8 subtype;
- type = GetFrameType(ptr);
subtype = GetFrameSubType(ptr); /* bit(7)~bit(2) */
/* only support station mode */
@@ -1412,9 +1410,8 @@ static sint validate_80211w_mgmt(struct adapter *adapter, union recv_frame *prec
/* unicast management frame decrypt */
if (pattrib->privacy && !(IS_MCAST(GetAddr1Ptr(ptr))) &&
(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION)) {
- u8 *ppp, *mgmt_DATA;
+ u8 *mgmt_DATA;
u32 data_len = 0;
- ppp = GetAddr2Ptr(ptr);
pattrib->bdecrypted = 0;
pattrib->encrypt = _AES_;
@@ -1709,7 +1706,7 @@ static union recv_frame *recvframe_defrag(struct adapter *adapter,
struct __queue *defrag_q)
{
struct list_head *plist, *phead;
- u8 *data, wlanhdr_offset;
+ u8 wlanhdr_offset;
u8 curfragnum;
struct recv_frame_hdr *pfhdr, *pnfhdr;
union recv_frame *prframe, *pnextrframe;
@@ -1739,8 +1736,6 @@ static union recv_frame *recvframe_defrag(struct adapter *adapter,
plist = get_next(plist);
- data = get_recvframe_data(prframe);
-
while (phead != plist) {
pnextrframe = (union recv_frame *)plist;
pnfhdr = &pnextrframe->u.hdr;
diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c
index 57cfe06d7d73..5aa5910687d1 100644
--- a/drivers/staging/rtl8723bs/core/rtw_security.c
+++ b/drivers/staging/rtl8723bs/core/rtw_security.c
@@ -303,13 +303,18 @@ void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe)
*((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
if (crc[3] != payload[length-1] || crc[2] != payload[length-2] || crc[1] != payload[length-3] || crc[0] != payload[length-4]) {
- RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
- crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
+ RT_TRACE(_module_rtl871x_security_c_,
+ _drv_err_,
+ ("%s:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
+ __func__,
+ crc[3], payload[length - 1],
+ crc[2], payload[length - 2],
+ crc[1], payload[length - 3],
+ crc[0], payload[length - 4]));
}
WEP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
}
- return;
}
/* 3 =====TKIP related ===== */
@@ -657,11 +662,9 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
u8 hw_hdr_offset = 0;
struct arc4context mycontext;
sint curfragnum, length;
- u32 prwskeylen;
u8 *pframe, *payload, *iv, *prwskey;
union pn48 dot11txpn;
- /* struct sta_info *stainfo; */
struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
@@ -676,36 +679,14 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
/* 4 start to encrypt each fragment */
if (pattrib->encrypt == _TKIP_) {
-/*
- if (pattrib->psta)
- {
- stainfo = pattrib->psta;
- }
- else
- {
- DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
- stainfo =rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);
- }
-*/
- /* if (stainfo!= NULL) */
{
-/*
- if (!(stainfo->state &_FW_LINKED))
- {
- DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
- return _FAIL;
- }
-*/
- RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt: stainfo!= NULL!!!\n"));
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__));
if (IS_MCAST(pattrib->ra))
prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
else
- /* prwskey =&stainfo->dot118021x_UncstKey.skey[0]; */
prwskey = pattrib->dot118021x_UncstKey.skey;
- prwskeylen = 16;
-
for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
iv = pframe+pattrib->hdrlen;
payload = pframe+pattrib->iv_len+pattrib->hdrlen;
@@ -742,13 +723,6 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
TKIP_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
}
-/*
- else {
- RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt: stainfo == NULL!!!\n"));
- DBG_871X("%s, psta ==NUL\n", __func__);
- res = _FAIL;
- }
-*/
}
return res;
@@ -765,14 +739,12 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
u8 crc[4];
struct arc4context mycontext;
sint length;
- u32 prwskeylen;
u8 *pframe, *payload, *iv, *prwskey;
union pn48 dot11txpn;
struct sta_info *stainfo;
struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
struct security_priv *psecuritypriv = &padapter->securitypriv;
-/* struct recv_priv *precvpriv =&padapter->recvpriv; */
u32 res = _SUCCESS;
pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
@@ -817,13 +789,9 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
no_gkey_bc_cnt = 0;
no_gkey_mc_cnt = 0;
- /* DBG_871X("rx bc/mc packets, to perform sw rtw_tkip_decrypt\n"); */
- /* prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; */
prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
- prwskeylen = 16;
} else {
prwskey = &stainfo->dot118021x_UncstKey.skey[0];
- prwskeylen = 16;
}
iv = pframe+prxattrib->hdrlen;
@@ -846,15 +814,19 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
*((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
if (crc[3] != payload[length-1] || crc[2] != payload[length-2] || crc[1] != payload[length-3] || crc[0] != payload[length-4]) {
- RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
+ RT_TRACE(_module_rtl871x_security_c_,
+ _drv_err_,
("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
- crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
+ crc[3], payload[length - 1],
+ crc[2], payload[length - 2],
+ crc[1], payload[length - 3],
+ crc[0], payload[length - 4]));
res = _FAIL;
}
TKIP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
} else {
- RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt: stainfo == NULL!!!\n"));
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo == NULL!!!\n", __func__));
res = _FAIL;
}
@@ -1426,7 +1398,7 @@ static sint aes_cipher(u8 *key, uint hdrlen,
aes128k128d(key, chain_buffer, aes_out);
for (i = 0; i < num_blocks; i++) {
- bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */
+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
payload_index += 16;
aes128k128d(key, chain_buffer, aes_out);
@@ -1437,7 +1409,7 @@ static sint aes_cipher(u8 *key, uint hdrlen,
for (j = 0; j < 16; j++)
padded_buffer[j] = 0x00;
for (j = 0; j < payload_remainder; j++) {
- padded_buffer[j] = pframe[payload_index++];/* padded_buffer[j] = message[payload_index++]; */
+ padded_buffer[j] = pframe[payload_index++];
}
bitwise_xor(aes_out, padded_buffer, chain_buffer);
aes128k128d(key, chain_buffer, aes_out);
@@ -1449,7 +1421,7 @@ static sint aes_cipher(u8 *key, uint hdrlen,
/* Insert MIC into payload */
for (j = 0; j < 8; j++)
- pframe[payload_index+j] = mic[j]; /* message[payload_index+j] = mic[j]; */
+ pframe[payload_index+j] = mic[j];
payload_index = hdrlen + 8;
for (i = 0; i < num_blocks; i++) {
@@ -1463,9 +1435,9 @@ static sint aes_cipher(u8 *key, uint hdrlen,
frtype
); /* add for CONFIG_IEEE80211W, none 11w also can use */
aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */
+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
for (j = 0; j < 16; j++)
- pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<16;j++) message[payload_index++] = chain_buffer[j]; */
+ pframe[payload_index++] = chain_buffer[j];
}
if (payload_remainder > 0) {
@@ -1484,12 +1456,12 @@ static sint aes_cipher(u8 *key, uint hdrlen,
for (j = 0; j < 16; j++)
padded_buffer[j] = 0x00;
for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = pframe[payload_index+j];/* padded_buffer[j] = message[payload_index+j]; */
+ padded_buffer[j] = pframe[payload_index+j];
aes128k128d(key, ctr_preload, aes_out);
bitwise_xor(aes_out, padded_buffer, chain_buffer);
for (j = 0; j < payload_remainder; j++)
- pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<payload_remainder;j++) message[payload_index++] = chain_buffer[j]; */
+ pframe[payload_index++] = chain_buffer[j];
}
/* Encrypt the MIC */
@@ -1506,12 +1478,12 @@ static sint aes_cipher(u8 *key, uint hdrlen,
for (j = 0; j < 16; j++)
padded_buffer[j] = 0x00;
for (j = 0; j < 8; j++)
- padded_buffer[j] = pframe[j+hdrlen+8+plen];/* padded_buffer[j] = message[j+hdrlen+8+plen]; */
+ padded_buffer[j] = pframe[j+hdrlen+8+plen];
aes128k128d(key, ctr_preload, aes_out);
bitwise_xor(aes_out, padded_buffer, chain_buffer);
for (j = 0; j < 8; j++)
- pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<8;j++) message[payload_index++] = chain_buffer[j]; */
+ pframe[payload_index++] = chain_buffer[j];
return _SUCCESS;
}
@@ -1525,15 +1497,12 @@ u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
/* Intermediate Buffers */
sint curfragnum, length;
- u32 prwskeylen;
u8 *pframe, *prwskey; /* *payload,*iv */
u8 hw_hdr_offset = 0;
- /* struct sta_info *stainfo = NULL; */
struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-/* uint offset = 0; */
u32 res = _SUCCESS;
if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
@@ -1544,16 +1513,13 @@ u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
/* 4 start to encrypt each fragment */
if (pattrib->encrypt == _AES_) {
- RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_encrypt: stainfo!= NULL!!!\n"));
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__));
if (IS_MCAST(pattrib->ra))
prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
else
- /* prwskey =&stainfo->dot118021x_UncstKey.skey[0]; */
prwskey = pattrib->dot118021x_UncstKey.skey;
- prwskeylen = 16;
-
for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */
length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
@@ -1574,10 +1540,10 @@ u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
}
static sint aes_decipher(u8 *key, uint hdrlen,
- u8 *pframe, uint plen)
+ u8 *pframe, uint plen)
{
static u8 message[MAX_MSG_SIZE];
- uint qc_exists, a4_exists, i, j, payload_remainder,
+ uint qc_exists, a4_exists, i, j, payload_remainder,
num_blocks, payload_index;
sint res = _SUCCESS;
u8 pn_vector[6];
@@ -1593,9 +1559,8 @@ static sint aes_decipher(u8 *key, uint hdrlen,
u8 mic[8];
-/* uint offset = 0; */
- uint frtype = GetFrameType(pframe);
- uint frsubtype = GetFrameSubType(pframe);
+ uint frtype = GetFrameType(pframe);
+ uint frsubtype = GetFrameSubType(pframe);
frsubtype = frsubtype>>4;
@@ -1615,11 +1580,11 @@ static sint aes_decipher(u8 *key, uint hdrlen,
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];
+ 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 == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
a4_exists = 0;
@@ -1651,15 +1616,10 @@ static sint aes_decipher(u8 *key, uint hdrlen,
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,
- frtype /* add for CONFIG_IEEE80211W, none 11w also can use */
- );
+ construct_ctr_preload(ctr_preload, a4_exists,
+ qc_exists, pframe,
+ pn_vector, i + 1,
+ frtype); /* add for CONFIG_IEEE80211W, none 11w also can use */
aes128k128d(key, ctr_preload, aes_out);
bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
@@ -1835,10 +1795,18 @@ static sint aes_decipher(u8 *key, uint hdrlen,
/* 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_, ("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
- i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]));
- DBG_871X("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
- i, 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_871X("%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;
}
}
@@ -1861,7 +1829,6 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
struct sta_info *stainfo;
struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
struct security_priv *psecuritypriv = &padapter->securitypriv;
-/* struct recv_priv *precvpriv =&padapter->recvpriv; */
u32 res = _SUCCESS;
pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
@@ -1869,15 +1836,15 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
if (prxattrib->encrypt == _AES_) {
stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
if (stainfo != NULL) {
- RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_decrypt: stainfo!= NULL!!!\n"));
+ RT_TRACE(_module_rtl871x_security_c_,
+ _drv_err_,
+ ("%s: stainfo!= NULL!!!\n", __func__));
if (IS_MCAST(prxattrib->ra)) {
static unsigned long start;
static u32 no_gkey_bc_cnt;
static u32 no_gkey_mc_cnt;
- /* DBG_871X("rx bc/mc packets, to perform sw rtw_aes_decrypt\n"); */
- /* prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; */
if (psecuritypriv->binstallGrpkey == false) {
res = _FAIL;
@@ -1927,7 +1894,9 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
AES_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
} else {
- RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_decrypt: stainfo == NULL!!!\n"));
+ RT_TRACE(_module_rtl871x_security_c_,
+ _drv_err_,
+ ("%s: stainfo == NULL!!!\n", __func__));
res = _FAIL;
}
}
diff --git a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
index bdc52d8d5625..09d2ca30d653 100644
--- a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
+++ b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
@@ -187,7 +187,6 @@ u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
/* struct sta_info *rtw_alloc_stainfo(_queue *pfree_sta_queue, unsigned char *hwaddr) */
struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
{
- uint tmp_aid;
s32 index;
struct list_head *phash_list;
struct sta_info *psta;
@@ -211,8 +210,6 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
/* spin_unlock_bh(&(pfree_sta_queue->lock)); */
- tmp_aid = psta->aid;
-
_rtw_init_stainfo(psta);
psta->padapter = pstapriv->padapter;
diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
index ea3ea2a6b314..9590e6f351c1 100644
--- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
@@ -606,19 +606,6 @@ inline void clear_cam_entry(struct adapter *adapter, u8 id)
clear_cam_cache(adapter, id);
}
-inline void write_cam_from_cache(struct adapter *adapter, u8 id)
-{
- struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
- struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
- struct cam_entry_cache cache;
-
- spin_lock_bh(&cam_ctl->lock);
- memcpy(&cache, &dvobj->cam_cache[id], sizeof(struct cam_entry_cache));
- spin_unlock_bh(&cam_ctl->lock);
-
- _write_cam(adapter, id, cache.ctrl, cache.mac, cache.key);
-}
-
void write_cam_cache(struct adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
{
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
@@ -1170,8 +1157,6 @@ void HT_info_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
pmlmeinfo->HT_info_enable = 1;
memcpy(&(pmlmeinfo->HT_info), pIE->data, pIE->Length);
-
- return;
}
void HTOnAssocRsp(struct adapter *padapter)
@@ -1481,11 +1466,11 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
}
}
- kfree((u8 *)bssid);
+ kfree(bssid);
return _SUCCESS;
_mismatch:
- kfree((u8 *)bssid);
+ kfree(bssid);
if (pmlmepriv->NumOfBcnInfoChkFail == 0)
pmlmepriv->timeBcnInfoChkStart = jiffies;
diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c
index b5dcb78fb4f4..ab85abecfaaa 100644
--- a/drivers/staging/rtl8723bs/core/rtw_xmit.c
+++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c
@@ -89,7 +89,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;
for (i = 0; i < NR_XMITFRAME; i++) {
- INIT_LIST_HEAD(&(pxframe->list));
+ INIT_LIST_HEAD(&pxframe->list);
pxframe->padapter = padapter;
pxframe->frame_tag = NULL_FRAMETAG;
@@ -99,7 +99,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxframe->buf_addr = NULL;
pxframe->pxmitbuf = NULL;
- list_add_tail(&(pxframe->list), &(pxmitpriv->free_xmit_queue.queue));
+ list_add_tail(&pxframe->list,
+ &pxmitpriv->free_xmit_queue.queue);
pxframe++;
}
@@ -150,7 +151,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitbuf->flags = XMIT_VO_QUEUE;
- list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue));
+ list_add_tail(&pxmitbuf->list,
+ &pxmitpriv->free_xmitbuf_queue.queue);
#ifdef DBG_XMIT_BUF
pxmitbuf->no = i;
#endif
@@ -176,7 +178,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxframe = (struct xmit_frame *)pxmitpriv->xframe_ext;
for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
- INIT_LIST_HEAD(&(pxframe->list));
+ INIT_LIST_HEAD(&pxframe->list);
pxframe->padapter = padapter;
pxframe->frame_tag = NULL_FRAMETAG;
@@ -188,7 +190,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxframe->ext_tag = 1;
- list_add_tail(&(pxframe->list), &(pxmitpriv->free_xframe_ext_queue.queue));
+ list_add_tail(&pxframe->list,
+ &pxmitpriv->free_xframe_ext_queue.queue);
pxframe++;
}
@@ -227,7 +230,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitbuf->len = 0;
pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
- list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
+ list_add_tail(&pxmitbuf->list,
+ &pxmitpriv->free_xmit_extbuf_queue.queue);
#ifdef DBG_XMIT_BUF_EXT
pxmitbuf->no = i;
#endif
@@ -372,8 +376,8 @@ static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *
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);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
if (pattrib->nr_frags != 1)
sz = padapter->xmitpriv.frag_len;
@@ -675,7 +679,6 @@ static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
static s32 update_attrib(struct adapter *padapter, _pkt *pkt, struct pkt_attrib *pattrib)
{
- uint i;
struct pkt_file pktfile;
struct sta_info *psta = NULL;
struct ethhdr etherhdr;
@@ -689,7 +692,7 @@ static s32 update_attrib(struct adapter *padapter, _pkt *pkt, struct pkt_attrib
DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib);
_rtw_open_pktfile(pkt, &pktfile);
- i = _rtw_pktfile_read(&pktfile, (u8 *)&etherhdr, ETH_HLEN);
+ _rtw_pktfile_read(&pktfile, (u8 *)&etherhdr, ETH_HLEN);
pattrib->ether_type = ntohs(etherhdr.h_proto);
@@ -956,7 +959,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("curfragnum =%d length =%d pattrib->icv_len =%d", curfragnum, length, pattrib->icv_len));
}
}
- rtw_secgetmic(&micdata, &(mic[0]));
+ rtw_secgetmic(&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\n\
@@ -964,7 +967,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
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);
+ memcpy(payload, &mic[0], 8);
pattrib->last_txcmdsz += 8;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("\n ========last pkt ========\n"));
@@ -1030,7 +1033,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
SetFrameSubType(fctrl, pattrib->subtype);
if (pattrib->subtype & WIFI_DATA_TYPE) {
- if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)) {
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
/* to_ds = 1, fr_ds = 0; */
{
@@ -1045,7 +1048,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
if (pqospriv->qos_option)
qos_option = true;
- } else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)) {
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
/* to_ds = 0, fr_ds = 1; */
SetFrDs(fctrl);
memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
@@ -1410,7 +1413,8 @@ s32 rtw_mgmt_xmitframe_coalesce(struct adapter *padapter, _pkt *pkt, struct xmit
pmlmeext->mgnt_80211w_IPN++;
/* add MME IE with MIC all zero, MME string doesn't include element id and length */
- pframe = rtw_set_ie(pframe, _MME_IE_, 16, MME, &(pattrib->pktlen));
+ pframe = rtw_set_ie(pframe, _MME_IE_, 16,
+ MME, &pattrib->pktlen);
pattrib->last_txcmdsz = pattrib->pktlen;
/* total frame length - header length */
frame_body_len = pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr);
@@ -1688,7 +1692,7 @@ struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv)
pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
- list_del_init(&(pxmitbuf->list));
+ list_del_init(&pxmitbuf->list);
}
if (pxmitbuf) {
@@ -1728,7 +1732,7 @@ s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
list_del_init(&pxmitbuf->list);
- list_add_tail(&(pxmitbuf->list), get_list_head(pfree_queue));
+ list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue));
pxmitpriv->free_xmit_extbuf_cnt++;
#ifdef DBG_XMIT_BUF_EXT
DBG_871X("DBG_XMIT_BUF_EXT FREE no =%d, free_xmit_extbuf_cnt =%d\n", pxmitbuf->no, pxmitpriv->free_xmit_extbuf_cnt);
@@ -1760,7 +1764,7 @@ struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
- list_del_init(&(pxmitbuf->list));
+ list_del_init(&pxmitbuf->list);
}
if (pxmitbuf) {
@@ -1815,7 +1819,8 @@ s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
list_del_init(&pxmitbuf->list);
- list_add_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));
+ list_add_tail(&pxmitbuf->list,
+ get_list_head(pfree_xmitbuf_queue));
pxmitpriv->free_xmitbuf_cnt++;
/* DBG_871X("FREE, free_xmitbuf_cnt =%d\n", pxmitpriv->free_xmitbuf_cnt); */
@@ -1879,7 +1884,7 @@ struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pf
pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
- list_del_init(&(pxframe->list));
+ 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));
}
@@ -1906,7 +1911,7 @@ struct xmit_frame *rtw_alloc_xmitframe_ext(struct xmit_priv *pxmitpriv)
plist = get_next(phead);
pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
- list_del_init(&(pxframe->list));
+ list_del_init(&pxframe->list);
pxmitpriv->free_xframe_ext_cnt--;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe_ext():free_xmitframe_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
}
@@ -2006,7 +2011,7 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram
struct list_head *plist, *phead;
struct xmit_frame *pxmitframe;
- spin_lock_bh(&(pframequeue->lock));
+ spin_lock_bh(&pframequeue->lock);
phead = get_list_head(pframequeue);
plist = get_next(phead);
@@ -2020,7 +2025,7 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram
rtw_free_xmitframe(pxmitpriv, pxmitframe);
}
- spin_unlock_bh(&(pframequeue->lock));
+ spin_unlock_bh(&pframequeue->lock);
}
s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
@@ -2043,21 +2048,21 @@ struct tx_servq *rtw_get_sta_pending(struct adapter *padapter, struct sta_info *
switch (up) {
case 1:
case 2:
- ptxservq = &(psta->sta_xmitpriv.bk_q);
+ ptxservq = &psta->sta_xmitpriv.bk_q;
*(ac) = 3;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending : BK\n"));
break;
case 4:
case 5:
- ptxservq = &(psta->sta_xmitpriv.vi_q);
+ ptxservq = &psta->sta_xmitpriv.vi_q;
*(ac) = 1;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending : VI\n"));
break;
case 6:
case 7:
- ptxservq = &(psta->sta_xmitpriv.vo_q);
+ ptxservq = &psta->sta_xmitpriv.vo_q;
*(ac) = 0;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending : VO\n"));
break;
@@ -2065,7 +2070,7 @@ struct tx_servq *rtw_get_sta_pending(struct adapter *padapter, struct sta_info *
case 0:
case 3:
default:
- ptxservq = &(psta->sta_xmitpriv.be_q);
+ ptxservq = &psta->sta_xmitpriv.be_q;
*(ac) = 2;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending : BE\n"));
break;
@@ -2207,12 +2212,9 @@ s32 rtw_alloc_hwxmits(struct adapter *padapter)
void rtw_free_hwxmits(struct adapter *padapter)
{
- struct hw_xmit *hwxmits;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- hwxmits = pxmitpriv->hwxmits;
- if (hwxmits)
- kfree((u8 *)hwxmits);
+ kfree(pxmitpriv->hwxmits);
}
void rtw_init_hwxmits(struct hw_xmit *phwxmit, sint entry)
@@ -2310,7 +2312,7 @@ s32 rtw_xmit(struct adapter *padapter, _pkt **ppkt)
if (!pxmitframe) {
drop_cnt++;
- RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit: no more pxmitframe\n"));
+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("%s: no more pxmitframe\n", __func__));
DBG_COUNTER(padapter->tx_logs.core_tx_err_pxmitframe);
return -1;
}
@@ -2318,7 +2320,7 @@ s32 rtw_xmit(struct adapter *padapter, _pkt **ppkt)
res = update_attrib(padapter, *ppkt, &pxmitframe->attrib);
if (res == _FAIL) {
- RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit: update attrib fail\n"));
+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("%s: update attrib fail\n", __func__));
#ifdef DBG_TX_DROP_FRAME
DBG_871X("DBG_TX_DROP_FRAME %s update attrib fail\n", __func__);
#endif
@@ -2604,24 +2606,24 @@ void stop_sta_xmit(struct adapter *padapter, struct sta_info *psta)
dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
- list_del_init(&(pstaxmitpriv->vo_q.tx_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));
+ 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));
+ 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));
+ 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));
+ list_del_init(&pstaxmitpriv->be_q.tx_pending);
spin_unlock_bh(&pxmitpriv->lock);
}
@@ -2690,14 +2692,6 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
pxmitframe->attrib.triggered = 1;
-/*
- spin_unlock_bh(&psta->sleep_q.lock);
- if (rtw_hal_xmit(padapter, pxmitframe) == true)
- {
- rtw_os_xmit_complete(padapter, pxmitframe);
- }
- spin_lock_bh(&psta->sleep_q.lock);
-*/
rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
@@ -2875,7 +2869,7 @@ void enqueue_pending_xmitbuf(
list_add_tail(&pxmitbuf->list, get_list_head(pqueue));
spin_unlock_bh(&pqueue->lock);
- complete(&(pri_adapter->xmitpriv.xmit_comp));
+ complete(&pri_adapter->xmitpriv.xmit_comp);
}
void enqueue_pending_xmitbuf_to_head(
@@ -2992,7 +2986,7 @@ int rtw_xmit_thread(void *context)
do {
err = rtw_hal_xmit_thread_handler(padapter);
flush_signals_thread();
- } while (_SUCCESS == err);
+ } while (err == _SUCCESS);
complete(&padapter->xmitpriv.terminate_xmitthread_comp);
@@ -3022,9 +3016,8 @@ int rtw_sctx_wait(struct submit_ctx *sctx, const char *msg)
status = sctx->status;
}
- if (status == RTW_SCTX_DONE_SUCCESS) {
+ if (status == RTW_SCTX_DONE_SUCCESS)
ret = _SUCCESS;
- }
return ret;
}
@@ -3075,9 +3068,8 @@ void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status)
{
struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
- if (pxmitpriv->ack_tx) {
+ if (pxmitpriv->ack_tx)
rtw_sctx_done_err(&pack_tx_ops, status);
- } else {
+ else
DBG_871X("%s ack_tx not set\n", __func__);
- }
}
diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
index 3239d37087c8..1ca9063a269f 100644
--- a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
+++ b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
@@ -402,8 +402,6 @@ static void GetDeltaSwingTable_8723B(
*TemperatureUP_B = (u8 *)DeltaSwingTableIdx_2GA_P_8188E;
*TemperatureDOWN_B = (u8 *)DeltaSwingTableIdx_2GA_N_8188E;
}
-
- return;
}
diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c
index 6e4a1fcb8790..d5793e4614bf 100644
--- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c
+++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c
@@ -1315,7 +1315,7 @@ void EXhalbtcoutsrc_DisplayBtCoexInfo(PBTC_COEXIST pBtCoexist)
/*
* Description:
- *Run BT-Coexist mechansim or not
+ *Run BT-Coexist mechanism or not
*
*/
void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist)
diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c
index eddd56abbb2d..109bd85b0cd8 100644
--- a/drivers/staging/rtl8723bs/hal/hal_com.c
+++ b/drivers/staging/rtl8723bs/hal/hal_com.c
@@ -30,7 +30,6 @@ void rtw_hal_data_deinit(struct adapter *padapter)
{
if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */
if (padapter->HalData) {
- phy_free_filebuf(padapter);
vfree(padapter->HalData);
padapter->HalData = NULL;
padapter->hal_data_sz = 0;
diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
index 6539bee9b5ba..eb7de3617d83 100644
--- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
+++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
@@ -2202,1079 +2202,3 @@ void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan)
break;
}
}
-
-
-static char file_path_bs[PATH_MAX];
-
-#define GetLineFromBuffer(buffer) strsep(&buffer, "\n")
-
-int phy_ConfigMACWithParaFile(struct adapter *Adapter, char *pFileName)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- int rlen = 0, rtStatus = _FAIL;
- char *szLine, *ptmp;
- u32 u4bRegOffset, u4bRegValue, u4bMove;
-
- if (!(Adapter->registrypriv.load_phy_file & LOAD_MAC_PARA_FILE))
- return rtStatus;
-
- memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
-
- if ((pHalData->mac_reg_len == 0) && !pHalData->mac_reg) {
- rtw_merge_string(file_path_bs, PATH_MAX, rtw_phy_file_path, pFileName);
-
- if (rtw_is_file_readable(file_path_bs) == true) {
- rlen = rtw_retrive_from_file(file_path_bs, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
- if (rlen > 0) {
- rtStatus = _SUCCESS;
- pHalData->mac_reg = vzalloc(rlen);
- if (pHalData->mac_reg) {
- memcpy(pHalData->mac_reg, pHalData->para_file_buf, rlen);
- pHalData->mac_reg_len = rlen;
- } else
- DBG_871X("%s mac_reg alloc fail !\n", __func__);
- }
- }
- } else {
- if ((pHalData->mac_reg_len != 0) && (pHalData->mac_reg != NULL)) {
- memcpy(pHalData->para_file_buf, pHalData->mac_reg, pHalData->mac_reg_len);
- rtStatus = _SUCCESS;
- } else
- DBG_871X("%s(): Critical Error !!!\n", __func__);
- }
-
- if (rtStatus == _SUCCESS) {
- ptmp = pHalData->para_file_buf;
- for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
- if (!IsCommentString(szLine)) {
- /* Get 1st hex value as register offset */
- if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) {
- if (u4bRegOffset == 0xffff) /* Ending. */
- break;
-
- /* Get 2nd hex value as register value. */
- szLine += u4bMove;
- if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove))
- rtw_write8(Adapter, u4bRegOffset, (u8)u4bRegValue);
- }
- }
- }
- } else
- DBG_871X("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName);
-
- return rtStatus;
-}
-
-int phy_ConfigBBWithParaFile(
- struct adapter *Adapter, char *pFileName, u32 ConfigType
-)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- int rlen = 0, rtStatus = _FAIL;
- char *szLine, *ptmp;
- u32 u4bRegOffset, u4bRegValue, u4bMove;
- char *pBuf = NULL;
- u32 *pBufLen = NULL;
-
- if (!(Adapter->registrypriv.load_phy_file & LOAD_BB_PARA_FILE))
- return rtStatus;
-
- switch (ConfigType) {
- case CONFIG_BB_PHY_REG:
- pBuf = pHalData->bb_phy_reg;
- pBufLen = &pHalData->bb_phy_reg_len;
- break;
- case CONFIG_BB_AGC_TAB:
- pBuf = pHalData->bb_agc_tab;
- pBufLen = &pHalData->bb_agc_tab_len;
- break;
- default:
- DBG_871X("Unknown ConfigType!! %d\r\n", ConfigType);
- break;
- }
-
- memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
-
- if (pBufLen && (*pBufLen == 0) && !pBuf) {
- rtw_merge_string(file_path_bs, PATH_MAX, rtw_phy_file_path, pFileName);
-
- if (rtw_is_file_readable(file_path_bs) == true) {
- rlen = rtw_retrive_from_file(file_path_bs, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
- if (rlen > 0) {
- rtStatus = _SUCCESS;
- pBuf = vzalloc(rlen);
- if (pBuf) {
- memcpy(pBuf, pHalData->para_file_buf, rlen);
- *pBufLen = rlen;
-
- switch (ConfigType) {
- case CONFIG_BB_PHY_REG:
- pHalData->bb_phy_reg = pBuf;
- break;
- case CONFIG_BB_AGC_TAB:
- pHalData->bb_agc_tab = pBuf;
- break;
- }
- } else
- DBG_871X("%s(): ConfigType %d alloc fail !\n", __func__, ConfigType);
- }
- }
- } else {
- if (pBufLen && (*pBufLen == 0) && !pBuf) {
- memcpy(pHalData->para_file_buf, pBuf, *pBufLen);
- rtStatus = _SUCCESS;
- } else
- DBG_871X("%s(): Critical Error !!!\n", __func__);
- }
-
- if (rtStatus == _SUCCESS) {
- ptmp = pHalData->para_file_buf;
- for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
- if (!IsCommentString(szLine)) {
- /* Get 1st hex value as register offset. */
- if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) {
- if (u4bRegOffset == 0xffff) /* Ending. */
- break;
- else if (u4bRegOffset == 0xfe || u4bRegOffset == 0xffe)
- msleep(50);
- else if (u4bRegOffset == 0xfd)
- mdelay(5);
- else if (u4bRegOffset == 0xfc)
- mdelay(1);
- else if (u4bRegOffset == 0xfb)
- udelay(50);
- else if (u4bRegOffset == 0xfa)
- udelay(5);
- else if (u4bRegOffset == 0xf9)
- udelay(1);
-
- /* Get 2nd hex value as register value. */
- szLine += u4bMove;
- if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) {
- /* DBG_871X("[BB-ADDR]%03lX =%08lX\n", u4bRegOffset, u4bRegValue); */
- PHY_SetBBReg(Adapter, u4bRegOffset, bMaskDWord, u4bRegValue);
-
- if (u4bRegOffset == 0xa24)
- pHalData->odmpriv.RFCalibrateInfo.RegA24 = u4bRegValue;
-
- /* Add 1us delay between BB/RF register setting. */
- udelay(1);
- }
- }
- }
- }
- } else
- DBG_871X("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName);
-
- return rtStatus;
-}
-
-static void phy_DecryptBBPgParaFile(struct adapter *Adapter, char *buffer)
-{
- u32 i = 0, j = 0;
- u8 map[95] = {0};
- u8 currentChar;
- char *BufOfLines, *ptmp;
-
- /* DBG_871X("=====>phy_DecryptBBPgParaFile()\n"); */
- /* 32 the ascii code of the first visable char, 126 the last one */
- for (i = 0; i < 95; ++i)
- map[i] = (u8) (94 - i);
-
- ptmp = buffer;
- i = 0;
- for (BufOfLines = GetLineFromBuffer(ptmp); BufOfLines != NULL; BufOfLines = GetLineFromBuffer(ptmp)) {
- /* DBG_871X("Encrypted Line: %s\n", BufOfLines); */
-
- for (j = 0; j < strlen(BufOfLines); ++j) {
- currentChar = BufOfLines[j];
-
- if (currentChar == '\0')
- break;
-
- currentChar -= (u8) ((((i + j) * 3) % 128));
-
- BufOfLines[j] = map[currentChar - 32] + 32;
- }
- /* DBG_871X("Decrypted Line: %s\n", BufOfLines); */
- if (strlen(BufOfLines) != 0)
- i++;
- BufOfLines[strlen(BufOfLines)] = '\n';
- }
-}
-
-static int phy_ParseBBPgParaFile(struct adapter *Adapter, char *buffer)
-{
- int rtStatus = _SUCCESS;
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- char *szLine, *ptmp;
- u32 u4bRegOffset, u4bRegMask, u4bRegValue;
- u32 u4bMove;
- bool firstLine = true;
- u8 tx_num = 0;
- u8 band = 0, rf_path = 0;
-
- /* DBG_871X("=====>phy_ParseBBPgParaFile()\n"); */
-
- if (Adapter->registrypriv.RegDecryptCustomFile == 1)
- phy_DecryptBBPgParaFile(Adapter, buffer);
-
- ptmp = buffer;
- for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
- if (!IsCommentString(szLine)) {
- if (isAllSpaceOrTab(szLine, sizeof(*szLine)))
- continue;
-
- /* Get header info (relative value or exact value) */
- if (firstLine) {
- if (eqNByte(szLine, (u8 *)("#[v1]"), 5)) {
-
- pHalData->odmpriv.PhyRegPgVersion = szLine[3] - '0';
- /* DBG_871X("This is a new format PHY_REG_PG.txt\n"); */
- } else if (eqNByte(szLine, (u8 *)("#[v0]"), 5)) {
- pHalData->odmpriv.PhyRegPgVersion = szLine[3] - '0';
- /* DBG_871X("This is a old format PHY_REG_PG.txt ok\n"); */
- } else {
- DBG_871X("The format in PHY_REG_PG are invalid %s\n", szLine);
- return _FAIL;
- }
-
- if (eqNByte(szLine + 5, (u8 *)("[Exact]#"), 8)) {
- pHalData->odmpriv.PhyRegPgValueType = PHY_REG_PG_EXACT_VALUE;
- /* DBG_871X("The values in PHY_REG_PG are exact values ok\n"); */
- firstLine = false;
- continue;
- } else if (eqNByte(szLine + 5, (u8 *)("[Relative]#"), 11)) {
- pHalData->odmpriv.PhyRegPgValueType = PHY_REG_PG_RELATIVE_VALUE;
- /* DBG_871X("The values in PHY_REG_PG are relative values ok\n"); */
- firstLine = false;
- continue;
- } else {
- DBG_871X("The values in PHY_REG_PG are invalid %s\n", szLine);
- return _FAIL;
- }
- }
-
- if (pHalData->odmpriv.PhyRegPgVersion == 0) {
- /* Get 1st hex value as register offset. */
- if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) {
- szLine += u4bMove;
- if (u4bRegOffset == 0xffff) /* Ending. */
- break;
-
- /* Get 2nd hex value as register mask. */
- if (GetHexValueFromString(szLine, &u4bRegMask, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_RELATIVE_VALUE) {
- /* Get 3rd hex value as register value. */
- if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) {
- PHY_StoreTxPowerByRate(Adapter, 0, 0, 1, u4bRegOffset, u4bRegMask, u4bRegValue);
- /* DBG_871X("[ADDR] %03X =%08X Mask =%08x\n", u4bRegOffset, u4bRegValue, u4bRegMask); */
- } else
- return _FAIL;
- } else if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE) {
- u32 combineValue = 0;
- u8 integer = 0, fraction = 0;
-
- if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- integer *= 2;
- if (fraction == 5)
- integer += 1;
- combineValue |= (((integer / 10) << 4) + (integer % 10));
- /* DBG_871X(" %d", integer); */
-
- if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- integer *= 2;
- if (fraction == 5)
- integer += 1;
- combineValue <<= 8;
- combineValue |= (((integer / 10) << 4) + (integer % 10));
- /* DBG_871X(" %d", integer); */
-
- if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- integer *= 2;
- if (fraction == 5)
- integer += 1;
- combineValue <<= 8;
- combineValue |= (((integer / 10) << 4) + (integer % 10));
- /* DBG_871X(" %d", integer); */
-
- if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- integer *= 2;
- if (fraction == 5)
- integer += 1;
- combineValue <<= 8;
- combineValue |= (((integer / 10) << 4) + (integer % 10));
- /* DBG_871X(" %d", integer); */
- PHY_StoreTxPowerByRate(Adapter, 0, 0, 1, u4bRegOffset, u4bRegMask, combineValue);
-
- /* DBG_871X("[ADDR] 0x%3x = 0x%4x\n", u4bRegOffset, combineValue); */
- }
- }
- } else if (pHalData->odmpriv.PhyRegPgVersion > 0) {
- u32 index = 0;
-
- if (eqNByte(szLine, "0xffff", 6))
- break;
-
- if (!eqNByte("#[END]#", szLine, 7)) {
- /* load the table label info */
- if (szLine[0] == '#') {
- index = 0;
- if (eqNByte(szLine, "#[2.4G]", 7)) {
- band = BAND_ON_2_4G;
- index += 8;
- } else if (eqNByte(szLine, "#[5G]", 5)) {
- band = BAND_ON_5G;
- index += 6;
- } else {
- DBG_871X("Invalid band %s in PHY_REG_PG.txt\n", szLine);
- return _FAIL;
- }
-
- rf_path = szLine[index] - 'A';
- /* DBG_871X(" Table label Band %d, RfPath %d\n", band, rf_path); */
- } else { /* load rows of tables */
- if (szLine[1] == '1')
- tx_num = RF_1TX;
- else if (szLine[1] == '2')
- tx_num = RF_2TX;
- else if (szLine[1] == '3')
- tx_num = RF_3TX;
- else if (szLine[1] == '4')
- tx_num = RF_4TX;
- else {
- DBG_871X("Invalid row in PHY_REG_PG.txt %c\n", szLine[1]);
- return _FAIL;
- }
-
- while (szLine[index] != ']')
- ++index;
- ++index;/* skip ] */
-
- /* Get 2nd hex value as register offset. */
- szLine += index;
- if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- /* Get 2nd hex value as register mask. */
- if (GetHexValueFromString(szLine, &u4bRegMask, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_RELATIVE_VALUE) {
- /* Get 3rd hex value as register value. */
- if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) {
- PHY_StoreTxPowerByRate(Adapter, band, rf_path, tx_num, u4bRegOffset, u4bRegMask, u4bRegValue);
- /* DBG_871X("[ADDR] %03X (tx_num %d) =%08X Mask =%08x\n", u4bRegOffset, tx_num, u4bRegValue, u4bRegMask); */
- } else
- return _FAIL;
- } else if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE) {
- u32 combineValue = 0;
- u8 integer = 0, fraction = 0;
-
- if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- integer *= 2;
- if (fraction == 5)
- integer += 1;
- combineValue |= (((integer / 10) << 4) + (integer % 10));
- /* DBG_871X(" %d", integer); */
-
- if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- integer *= 2;
- if (fraction == 5)
- integer += 1;
- combineValue <<= 8;
- combineValue |= (((integer / 10) << 4) + (integer % 10));
- /* DBG_871X(" %d", integer); */
-
- if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- integer *= 2;
- if (fraction == 5)
- integer += 1;
- combineValue <<= 8;
- combineValue |= (((integer / 10) << 4) + (integer % 10));
- /* DBG_871X(" %d", integer); */
-
- if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
- szLine += u4bMove;
- else
- return _FAIL;
-
- integer *= 2;
- if (fraction == 5)
- integer += 1;
- combineValue <<= 8;
- combineValue |= (((integer / 10) << 4) + (integer % 10));
- /* DBG_871X(" %d", integer); */
- PHY_StoreTxPowerByRate(Adapter, band, rf_path, tx_num, u4bRegOffset, u4bRegMask, combineValue);
-
- /* DBG_871X("[ADDR] 0x%3x (tx_num %d) = 0x%4x\n", u4bRegOffset, tx_num, combineValue); */
- }
- }
- }
- }
- }
- }
- /* DBG_871X("<=====phy_ParseBBPgParaFile()\n"); */
- return rtStatus;
-}
-
-int phy_ConfigBBWithPgParaFile(struct adapter *Adapter, char *pFileName)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- int rlen = 0, rtStatus = _FAIL;
-
- if (!(Adapter->registrypriv.load_phy_file & LOAD_BB_PG_PARA_FILE))
- return rtStatus;
-
- memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
-
- if ((pHalData->bb_phy_reg_pg_len == 0) && !pHalData->bb_phy_reg_pg) {
- rtw_merge_string(file_path_bs, PATH_MAX, rtw_phy_file_path, pFileName);
-
- if (rtw_is_file_readable(file_path_bs) == true) {
- rlen = rtw_retrive_from_file(file_path_bs, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
- if (rlen > 0) {
- rtStatus = _SUCCESS;
- pHalData->bb_phy_reg_pg = vzalloc(rlen);
- if (pHalData->bb_phy_reg_pg) {
- memcpy(pHalData->bb_phy_reg_pg, pHalData->para_file_buf, rlen);
- pHalData->bb_phy_reg_pg_len = rlen;
- } else
- DBG_871X("%s bb_phy_reg_pg alloc fail !\n", __func__);
- }
- }
- } else {
- if ((pHalData->bb_phy_reg_pg_len != 0) && (pHalData->bb_phy_reg_pg != NULL)) {
- memcpy(pHalData->para_file_buf, pHalData->bb_phy_reg_pg, pHalData->bb_phy_reg_pg_len);
- rtStatus = _SUCCESS;
- } else
- DBG_871X("%s(): Critical Error !!!\n", __func__);
- }
-
- if (rtStatus == _SUCCESS) {
- /* DBG_871X("phy_ConfigBBWithPgParaFile(): read %s ok\n", pFileName); */
- phy_ParseBBPgParaFile(Adapter, pHalData->para_file_buf);
- } else
- DBG_871X("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName);
-
- return rtStatus;
-}
-
-int PHY_ConfigRFWithParaFile(
- struct adapter *Adapter, char *pFileName, u8 eRFPath
-)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- int rlen = 0, rtStatus = _FAIL;
- char *szLine, *ptmp;
- u32 u4bRegOffset, u4bRegValue, u4bMove;
- u16 i;
- char *pBuf = NULL;
- u32 *pBufLen = NULL;
-
- if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_PARA_FILE))
- return rtStatus;
-
- switch (eRFPath) {
- case ODM_RF_PATH_A:
- pBuf = pHalData->rf_radio_a;
- pBufLen = &pHalData->rf_radio_a_len;
- break;
- case ODM_RF_PATH_B:
- pBuf = pHalData->rf_radio_b;
- pBufLen = &pHalData->rf_radio_b_len;
- break;
- default:
- DBG_871X("Unknown RF path!! %d\r\n", eRFPath);
- break;
- }
-
- memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
-
- if (pBufLen && (*pBufLen == 0) && !pBuf) {
- rtw_merge_string(file_path_bs, PATH_MAX, rtw_phy_file_path, pFileName);
-
- if (rtw_is_file_readable(file_path_bs) == true) {
- rlen = rtw_retrive_from_file(file_path_bs, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
- if (rlen > 0) {
- rtStatus = _SUCCESS;
- pBuf = vzalloc(rlen);
- if (pBuf) {
- memcpy(pBuf, pHalData->para_file_buf, rlen);
- *pBufLen = rlen;
-
- switch (eRFPath) {
- case ODM_RF_PATH_A:
- pHalData->rf_radio_a = pBuf;
- break;
- case ODM_RF_PATH_B:
- pHalData->rf_radio_b = pBuf;
- break;
- }
- } else
- DBG_871X("%s(): eRFPath =%d alloc fail !\n", __func__, eRFPath);
- }
- }
- } else {
- if (pBufLen && (*pBufLen == 0) && !pBuf) {
- memcpy(pHalData->para_file_buf, pBuf, *pBufLen);
- rtStatus = _SUCCESS;
- } else
- DBG_871X("%s(): Critical Error !!!\n", __func__);
- }
-
- if (rtStatus == _SUCCESS) {
- /* DBG_871X("%s(): read %s successfully\n", __func__, pFileName); */
-
- ptmp = pHalData->para_file_buf;
- for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
- if (!IsCommentString(szLine)) {
- /* Get 1st hex value as register offset. */
- if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) {
- if (u4bRegOffset == 0xfe || u4bRegOffset == 0xffe) /* Deay specific ms. Only RF configuration require delay. */
- msleep(50);
- else if (u4bRegOffset == 0xfd) {
- /* mdelay(5); */
- for (i = 0; i < 100; i++)
- udelay(MAX_STALL_TIME);
- } else if (u4bRegOffset == 0xfc) {
- /* mdelay(1); */
- for (i = 0; i < 20; i++)
- udelay(MAX_STALL_TIME);
- } else if (u4bRegOffset == 0xfb)
- udelay(50);
- else if (u4bRegOffset == 0xfa)
- udelay(5);
- else if (u4bRegOffset == 0xf9)
- udelay(1);
- else if (u4bRegOffset == 0xffff)
- break;
-
- /* Get 2nd hex value as register value. */
- szLine += u4bMove;
- if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) {
- PHY_SetRFReg(Adapter, eRFPath, u4bRegOffset, bRFRegOffsetMask, u4bRegValue);
-
- /* Temp add, for frequency lock, if no delay, that may cause */
- /* frequency shift, ex: 2412MHz => 2417MHz */
- /* If frequency shift, the following action may works. */
- /* Fractional-N table in radio_a.txt */
- /* 0x2a 0x00001 channel 1 */
- /* 0x2b 0x00808 frequency divider. */
- /* 0x2b 0x53333 */
- /* 0x2c 0x0000c */
- udelay(1);
- }
- }
- }
- }
- } else
- DBG_871X("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName);
-
- return rtStatus;
-}
-
-static void initDeltaSwingIndexTables(
- struct adapter *Adapter,
- char *Band,
- char *Path,
- char *Sign,
- char *Channel,
- char *Rate,
- char *Data
-)
-{
- #define STR_EQUAL_5G(_band, _path, _sign, _rate, _chnl) \
- ((strcmp(Band, _band) == 0) && (strcmp(Path, _path) == 0) && (strcmp(Sign, _sign) == 0) &&\
- (strcmp(Rate, _rate) == 0) && (strcmp(Channel, _chnl) == 0)\
- )
- #define STR_EQUAL_2G(_band, _path, _sign, _rate) \
- ((strcmp(Band, _band) == 0) && (strcmp(Path, _path) == 0) && (strcmp(Sign, _sign) == 0) &&\
- (strcmp(Rate, _rate) == 0)\
- )
-
- #define STORE_SWING_TABLE(_array, _iteratedIdx) \
- for (token = strsep(&Data, delim); token != NULL; token = strsep(&Data, delim)) {\
- sscanf(token, "%d", &idx);\
- _array[_iteratedIdx++] = (u8)idx;\
- } \
-
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
- PODM_RF_CAL_T pRFCalibrateInfo = &(pDM_Odm->RFCalibrateInfo);
- u32 j = 0;
- char *token;
- char delim[] = ",";
- u32 idx = 0;
-
- /* DBG_871X("===>initDeltaSwingIndexTables(): Band: %s;\nPath: %s;\nSign: %s;\nChannel: %s;\nRate: %s;\n, Data: %s;\n", */
- /* Band, Path, Sign, Channel, Rate, Data); */
-
- if (STR_EQUAL_2G("2G", "A", "+", "CCK")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKA_P, j);
- } else if (STR_EQUAL_2G("2G", "A", "-", "CCK")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKA_N, j);
- } else if (STR_EQUAL_2G("2G", "B", "+", "CCK")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKB_P, j);
- } else if (STR_EQUAL_2G("2G", "B", "-", "CCK")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKB_N, j);
- } else if (STR_EQUAL_2G("2G", "A", "+", "ALL")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_2GA_P, j);
- } else if (STR_EQUAL_2G("2G", "A", "-", "ALL")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_2GA_N, j);
- } else if (STR_EQUAL_2G("2G", "B", "+", "ALL")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_2GB_P, j);
- } else if (STR_EQUAL_2G("2G", "B", "-", "ALL")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_2GB_N, j);
- } else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "0")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GA_P[0], j);
- } else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "0")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GA_N[0], j);
- } else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "0")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GB_P[0], j);
- } else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "0")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GB_N[0], j);
- } else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "1")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GA_P[1], j);
- } else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "1")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GA_N[1], j);
- } else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "1")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GB_P[1], j);
- } else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "1")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GB_N[1], j);
- } else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "2")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GA_P[2], j);
- } else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "2")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GA_N[2], j);
- } else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "2")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GB_P[2], j);
- } else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "2")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GB_N[2], j);
- } else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "3")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GA_P[3], j);
- } else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "3")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GA_N[3], j);
- } else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "3")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GB_P[3], j);
- } else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "3")) {
- STORE_SWING_TABLE(pRFCalibrateInfo->DeltaSwingTableIdx_5GB_N[3], j);
- } else
- DBG_871X("===>initDeltaSwingIndexTables(): The input is invalid!!\n");
-}
-
-int PHY_ConfigRFWithTxPwrTrackParaFile(struct adapter *Adapter, char *pFileName)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- int rlen = 0, rtStatus = _FAIL;
- char *szLine, *ptmp;
-
- if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_TXPWR_TRACK_PARA_FILE))
- return rtStatus;
-
- memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
-
- if ((pHalData->rf_tx_pwr_track_len == 0) && !pHalData->rf_tx_pwr_track) {
- rtw_merge_string(file_path_bs, PATH_MAX, rtw_phy_file_path, pFileName);
-
- if (rtw_is_file_readable(file_path_bs) == true) {
- rlen = rtw_retrive_from_file(file_path_bs, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
- if (rlen > 0) {
- rtStatus = _SUCCESS;
- pHalData->rf_tx_pwr_track = vzalloc(rlen);
- if (pHalData->rf_tx_pwr_track) {
- memcpy(pHalData->rf_tx_pwr_track, pHalData->para_file_buf, rlen);
- pHalData->rf_tx_pwr_track_len = rlen;
- } else
- DBG_871X("%s rf_tx_pwr_track alloc fail !\n", __func__);
- }
- }
- } else {
- if ((pHalData->rf_tx_pwr_track_len != 0) && (pHalData->rf_tx_pwr_track != NULL)) {
- memcpy(pHalData->para_file_buf, pHalData->rf_tx_pwr_track, pHalData->rf_tx_pwr_track_len);
- rtStatus = _SUCCESS;
- } else
- DBG_871X("%s(): Critical Error !!!\n", __func__);
- }
-
- if (rtStatus == _SUCCESS) {
- /* DBG_871X("%s(): read %s successfully\n", __func__, pFileName); */
-
- ptmp = pHalData->para_file_buf;
- for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
- if (!IsCommentString(szLine)) {
- char band[5] = "", path[5] = "", sign[5] = "";
- char chnl[5] = "", rate[10] = "";
- char data[300] = ""; /* 100 is too small */
- const int len = strlen(szLine);
- int i;
-
- if (len < 10 || szLine[0] != '[')
- continue;
-
- strncpy(band, szLine+1, 2);
- strncpy(path, szLine+5, 1);
- strncpy(sign, szLine+8, 1);
-
- i = 10; /* szLine+10 */
- if (!ParseQualifiedString(szLine, &i, rate, '[', ']')) {
- /* DBG_871X("Fail to parse rate!\n"); */
- }
- if (!ParseQualifiedString(szLine, &i, chnl, '[', ']')) {
- /* DBG_871X("Fail to parse channel group!\n"); */
- }
- while (i < len && szLine[i] != '{')
- i++;
- if (!ParseQualifiedString(szLine, &i, data, '{', '}')) {
- /* DBG_871X("Fail to parse data!\n"); */
- }
-
- initDeltaSwingIndexTables(Adapter, band, path, sign, chnl, rate, data);
- }
- }
- } else
- DBG_871X("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName);
-
- return rtStatus;
-}
-
-static int phy_ParsePowerLimitTableFile(struct adapter *Adapter, char *buffer)
-{
- u32 i = 0, forCnt = 0;
- u8 loadingStage = 0, limitValue = 0, fraction = 0;
- char *szLine, *ptmp;
- int rtStatus = _SUCCESS;
- char band[10], bandwidth[10], rateSection[10],
- regulation[TXPWR_LMT_MAX_REGULATION_NUM][10], rfPath[10], colNumBuf[10];
- u8 colNum = 0;
-
- DBG_871X("===>phy_ParsePowerLimitTableFile()\n");
-
- if (Adapter->registrypriv.RegDecryptCustomFile == 1)
- phy_DecryptBBPgParaFile(Adapter, buffer);
-
- ptmp = buffer;
- for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
- /* skip comment */
- if (IsCommentString(szLine)) {
- continue;
- }
-
- if (loadingStage == 0) {
- for (forCnt = 0; forCnt < TXPWR_LMT_MAX_REGULATION_NUM; ++forCnt)
- memset((void *) regulation[forCnt], 0, 10);
-
- memset((void *) band, 0, 10);
- memset((void *) bandwidth, 0, 10);
- memset((void *) rateSection, 0, 10);
- memset((void *) rfPath, 0, 10);
- memset((void *) colNumBuf, 0, 10);
-
- if (szLine[0] != '#' || szLine[1] != '#')
- continue;
-
- /* skip the space */
- i = 2;
- while (szLine[i] == ' ' || szLine[i] == '\t')
- ++i;
-
- szLine[--i] = ' '; /* return the space in front of the regulation info */
-
- /* Parse the label of the table */
- if (!ParseQualifiedString(szLine, &i, band, ' ', ',')) {
- DBG_871X("Fail to parse band!\n");
- return _FAIL;
- }
- if (!ParseQualifiedString(szLine, &i, bandwidth, ' ', ',')) {
- DBG_871X("Fail to parse bandwidth!\n");
- return _FAIL;
- }
- if (!ParseQualifiedString(szLine, &i, rfPath, ' ', ',')) {
- DBG_871X("Fail to parse rf path!\n");
- return _FAIL;
- }
- if (!ParseQualifiedString(szLine, &i, rateSection, ' ', ',')) {
- DBG_871X("Fail to parse rate!\n");
- return _FAIL;
- }
-
- loadingStage = 1;
- } else if (loadingStage == 1) {
- if (szLine[0] != '#' || szLine[1] != '#')
- continue;
-
- /* skip the space */
- i = 2;
- while (szLine[i] == ' ' || szLine[i] == '\t')
- ++i;
-
- if (!eqNByte((u8 *)(szLine + i), (u8 *)("START"), 5)) {
- DBG_871X("Lost \"## START\" label\n");
- return _FAIL;
- }
-
- loadingStage = 2;
- } else if (loadingStage == 2) {
- if (szLine[0] != '#' || szLine[1] != '#')
- continue;
-
- /* skip the space */
- i = 2;
- while (szLine[i] == ' ' || szLine[i] == '\t')
- ++i;
-
- if (!ParseQualifiedString(szLine, &i, colNumBuf, '#', '#')) {
- DBG_871X("Fail to parse column number!\n");
- return _FAIL;
- }
-
- if (!GetU1ByteIntegerFromStringInDecimal(colNumBuf, &colNum))
- return _FAIL;
-
- if (colNum > TXPWR_LMT_MAX_REGULATION_NUM) {
- DBG_871X(
- "invalid col number %d (greater than max %d)\n",
- colNum, TXPWR_LMT_MAX_REGULATION_NUM
- );
- return _FAIL;
- }
-
- for (forCnt = 0; forCnt < colNum; ++forCnt) {
- u8 regulation_name_cnt = 0;
-
- /* skip the space */
- while (szLine[i] == ' ' || szLine[i] == '\t')
- ++i;
-
- while (szLine[i] != ' ' && szLine[i] != '\t' && szLine[i] != '\0')
- regulation[forCnt][regulation_name_cnt++] = szLine[i++];
- /* DBG_871X("regulation %s!\n", regulation[forCnt]); */
-
- if (regulation_name_cnt == 0) {
- DBG_871X("invalid number of regulation!\n");
- return _FAIL;
- }
- }
-
- loadingStage = 3;
- } else if (loadingStage == 3) {
- char channel[10] = {0}, powerLimit[10] = {0};
- u8 cnt = 0;
-
- /* the table ends */
- if (szLine[0] == '#' && szLine[1] == '#') {
- i = 2;
- while (szLine[i] == ' ' || szLine[i] == '\t')
- ++i;
-
- if (eqNByte((u8 *)(szLine + i), (u8 *)("END"), 3)) {
- loadingStage = 0;
- continue;
- } else {
- DBG_871X("Wrong format\n");
- DBG_871X("<===== phy_ParsePowerLimitTableFile()\n");
- return _FAIL;
- }
- }
-
- if ((szLine[0] != 'c' && szLine[0] != 'C') ||
- (szLine[1] != 'h' && szLine[1] != 'H')) {
- DBG_871X("Meet wrong channel => power limt pair\n");
- continue;
- }
- i = 2;/* move to the location behind 'h' */
-
- /* load the channel number */
- cnt = 0;
- while (szLine[i] >= '0' && szLine[i] <= '9') {
- channel[cnt] = szLine[i];
- ++cnt;
- ++i;
- }
- /* DBG_871X("chnl %s!\n", channel); */
-
- for (forCnt = 0; forCnt < colNum; ++forCnt) {
- /* skip the space between channel number and the power limit value */
- while (szLine[i] == ' ' || szLine[i] == '\t')
- ++i;
-
- /* load the power limit value */
- cnt = 0;
- fraction = 0;
- memset((void *) powerLimit, 0, 10);
- while ((szLine[i] >= '0' && szLine[i] <= '9') || szLine[i] == '.') {
- if (szLine[i] == '.') {
- if ((szLine[i+1] >= '0' && szLine[i+1] <= '9')) {
- fraction = szLine[i+1];
- i += 2;
- } else {
- DBG_871X("Wrong fraction in TXPWR_LMT.txt\n");
- return _FAIL;
- }
-
- break;
- }
-
- powerLimit[cnt] = szLine[i];
- ++cnt;
- ++i;
- }
-
- if (powerLimit[0] == '\0') {
- powerLimit[0] = '6';
- powerLimit[1] = '3';
- i += 2;
- } else {
- if (!GetU1ByteIntegerFromStringInDecimal(powerLimit, &limitValue))
- return _FAIL;
-
- limitValue *= 2;
- cnt = 0;
- if (fraction == '5')
- ++limitValue;
-
- /* the value is greater or equal to 100 */
- if (limitValue >= 100) {
- powerLimit[cnt++] = limitValue/100 + '0';
- limitValue %= 100;
-
- if (limitValue >= 10) {
- powerLimit[cnt++] = limitValue/10 + '0';
- limitValue %= 10;
- } else
- powerLimit[cnt++] = '0';
-
- powerLimit[cnt++] = limitValue + '0';
- } else if (limitValue >= 10) { /* the value is greater or equal to 10 */
- powerLimit[cnt++] = limitValue/10 + '0';
- limitValue %= 10;
- powerLimit[cnt++] = limitValue + '0';
- }
- /* the value is less than 10 */
- else
- powerLimit[cnt++] = limitValue + '0';
-
- powerLimit[cnt] = '\0';
- }
-
- /* DBG_871X("ch%s => %s\n", channel, powerLimit); */
-
- /* store the power limit value */
- PHY_SetTxPowerLimit(Adapter, (u8 *)regulation[forCnt], (u8 *)band,
- (u8 *)bandwidth, (u8 *)rateSection, (u8 *)rfPath, (u8 *)channel, (u8 *)powerLimit);
-
- }
- } else {
- DBG_871X("Abnormal loading stage in phy_ParsePowerLimitTableFile()!\n");
- rtStatus = _FAIL;
- break;
- }
- }
-
- DBG_871X("<===phy_ParsePowerLimitTableFile()\n");
- return rtStatus;
-}
-
-int PHY_ConfigRFWithPowerLimitTableParaFile(
- struct adapter *Adapter, char *pFileName
-)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- int rlen = 0, rtStatus = _FAIL;
-
- if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_TXPWR_LMT_PARA_FILE))
- return rtStatus;
-
- memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
-
- if ((pHalData->rf_tx_pwr_lmt_len == 0) && !pHalData->rf_tx_pwr_lmt) {
- rtw_merge_string(file_path_bs, PATH_MAX, rtw_phy_file_path, pFileName);
-
- if (rtw_is_file_readable(file_path_bs) == true) {
- rlen = rtw_retrive_from_file(file_path_bs, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
- if (rlen > 0) {
- rtStatus = _SUCCESS;
- pHalData->rf_tx_pwr_lmt = vzalloc(rlen);
- if (pHalData->rf_tx_pwr_lmt) {
- memcpy(pHalData->rf_tx_pwr_lmt, pHalData->para_file_buf, rlen);
- pHalData->rf_tx_pwr_lmt_len = rlen;
- } else
- DBG_871X("%s rf_tx_pwr_lmt alloc fail !\n", __func__);
- }
- }
- } else {
- if ((pHalData->rf_tx_pwr_lmt_len != 0) && (pHalData->rf_tx_pwr_lmt != NULL)) {
- memcpy(pHalData->para_file_buf, pHalData->rf_tx_pwr_lmt, pHalData->rf_tx_pwr_lmt_len);
- rtStatus = _SUCCESS;
- } else
- DBG_871X("%s(): Critical Error !!!\n", __func__);
- }
-
- if (rtStatus == _SUCCESS) {
- /* DBG_871X("%s(): read %s ok\n", __func__, pFileName); */
- rtStatus = phy_ParsePowerLimitTableFile(Adapter, pHalData->para_file_buf);
- } else
- DBG_871X("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName);
-
- return rtStatus;
-}
-
-void phy_free_filebuf(struct adapter *padapter)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
-
- if (pHalData->mac_reg)
- vfree(pHalData->mac_reg);
- if (pHalData->bb_phy_reg)
- vfree(pHalData->bb_phy_reg);
- if (pHalData->bb_agc_tab)
- vfree(pHalData->bb_agc_tab);
- if (pHalData->bb_phy_reg_pg)
- vfree(pHalData->bb_phy_reg_pg);
- if (pHalData->bb_phy_reg_mp)
- vfree(pHalData->bb_phy_reg_mp);
- if (pHalData->rf_radio_a)
- vfree(pHalData->rf_radio_a);
- if (pHalData->rf_radio_b)
- vfree(pHalData->rf_radio_b);
- if (pHalData->rf_tx_pwr_track)
- vfree(pHalData->rf_tx_pwr_track);
- if (pHalData->rf_tx_pwr_lmt)
- vfree(pHalData->rf_tx_pwr_lmt);
-
-}
diff --git a/drivers/staging/rtl8723bs/hal/odm_DIG.c b/drivers/staging/rtl8723bs/hal/odm_DIG.c
index 70d98c58ca97..40fe43c62c45 100644
--- a/drivers/staging/rtl8723bs/hal/odm_DIG.c
+++ b/drivers/staging/rtl8723bs/hal/odm_DIG.c
@@ -1074,7 +1074,6 @@ void odm_FAThresholdCheck(
dm_FA_thres[1] = 4000;
dm_FA_thres[2] = 5000;
}
- return;
}
u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI)
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c b/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c
index c514cb735afd..650fbedd34e8 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c
@@ -188,7 +188,8 @@ void rtl8723b_HalDmWatchDog(struct adapter *Adapter)
bBtDisabled = hal_btcoex_IsBtDisabled(Adapter);
- ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_BT_ENABLED, ((bBtDisabled == true)?false:true));
+ ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_BT_ENABLED,
+ !bBtDisabled);
ODM_DMWatchdog(&pHalData->odmpriv);
}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
index faeaf24fa833..22931ab3a5fc 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
@@ -3773,7 +3773,6 @@ void C2HPacketHandler_8723B(struct adapter *padapter, u8 *pbuffer, u16 length)
process_c2h_event(padapter, &C2hEvent, tmpBuf);
/* c2h_handler_8723b(padapter,&C2hEvent); */
- return;
}
void SetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
@@ -4157,9 +4156,8 @@ void SetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
break;
}
- /* The value of ((usNavUpper + HAL_NAV_UPPER_UNIT_8723B - 1) / HAL_NAV_UPPER_UNIT_8723B) */
- /* is getting the upper integer. */
- usNavUpper = (usNavUpper + HAL_NAV_UPPER_UNIT_8723B - 1) / HAL_NAV_UPPER_UNIT_8723B;
+ usNavUpper = DIV_ROUND_UP(usNavUpper,
+ HAL_NAV_UPPER_UNIT_8723B);
rtw_write8(padapter, REG_NAV_UPPER, (u8)usNavUpper);
}
break;
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
index 6df2b58bdc67..cf23414d7224 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
@@ -362,24 +362,10 @@ void PHY_SetRFReg_8723B(
*/
s32 PHY_MACConfig8723B(struct adapter *Adapter)
{
- int rtStatus = _SUCCESS;
struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- s8 *pszMACRegFile;
- s8 sz8723MACRegFile[] = RTL8723B_PHY_MACREG;
-
-
- pszMACRegFile = sz8723MACRegFile;
-
- /* */
- /* Config MAC */
- /* */
- rtStatus = phy_ConfigMACWithParaFile(Adapter, pszMACRegFile);
- if (rtStatus == _FAIL) {
- ODM_ReadAndConfig_MP_8723B_MAC_REG(&pHalData->odmpriv);
- rtStatus = _SUCCESS;
- }
- return rtStatus;
+ ODM_ReadAndConfig_MP_8723B_MAC_REG(&pHalData->odmpriv);
+ return _SUCCESS;
}
/**
@@ -427,17 +413,6 @@ static void phy_InitBBRFRegisterDefinition(struct adapter *Adapter)
static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
{
struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- int rtStatus = _SUCCESS;
- u8 sz8723BBRegFile[] = RTL8723B_PHY_REG;
- u8 sz8723AGCTableFile[] = RTL8723B_AGC_TAB;
- u8 sz8723BBBRegPgFile[] = RTL8723B_PHY_REG_PG;
- u8 sz8723BRFTxPwrLmtFile[] = RTL8723B_TXPWR_LMT;
- u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL, *pszBBRegPgFile = NULL, *pszRFTxPwrLmtFile = NULL;
-
- pszBBRegFile = sz8723BBRegFile;
- pszAGCTableFile = sz8723AGCTableFile;
- pszBBRegPgFile = sz8723BBBRegPgFile;
- pszRFTxPwrLmtFile = sz8723BRFTxPwrLmtFile;
/* Read Tx Power Limit File */
PHY_InitTxPowerLimit(Adapter);
@@ -445,30 +420,14 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
Adapter->registrypriv.RegEnableTxPowerLimit == 1 ||
(Adapter->registrypriv.RegEnableTxPowerLimit == 2 && pHalData->EEPROMRegulatory == 1)
) {
- if (PHY_ConfigRFWithPowerLimitTableParaFile(Adapter, pszRFTxPwrLmtFile) == _FAIL) {
- if (HAL_STATUS_SUCCESS != ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, CONFIG_RF_TXPWR_LMT, (ODM_RF_RADIO_PATH_E)0))
- rtStatus = _FAIL;
- }
-
- if (rtStatus != _SUCCESS) {
- DBG_871X("%s():Read Tx power limit fail\n", __func__);
- goto phy_BB8190_Config_ParaFile_Fail;
- }
+ ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv,
+ CONFIG_RF_TXPWR_LMT, 0);
}
/* */
/* 1. Read PHY_REG.TXT BB INIT!! */
/* */
- if (phy_ConfigBBWithParaFile(Adapter, pszBBRegFile, CONFIG_BB_PHY_REG) ==
- _FAIL) {
- if (HAL_STATUS_SUCCESS != ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG))
- rtStatus = _FAIL;
- }
-
- if (rtStatus != _SUCCESS) {
- DBG_8192C("%s():Write BB Reg Fail!!", __func__);
- goto phy_BB8190_Config_ParaFile_Fail;
- }
+ ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG);
/* If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */
PHY_InitTxPowerByRate(Adapter);
@@ -476,11 +435,8 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
Adapter->registrypriv.RegEnableTxPowerByRate == 1 ||
(Adapter->registrypriv.RegEnableTxPowerByRate == 2 && pHalData->EEPROMRegulatory != 2)
) {
- if (phy_ConfigBBWithPgParaFile(Adapter, pszBBRegPgFile) ==
- _FAIL) {
- if (HAL_STATUS_SUCCESS != ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG_PG))
- rtStatus = _FAIL;
- }
+ ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv,
+ CONFIG_BB_PHY_REG_PG);
if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE)
PHY_TxPowerByRateConfiguration(Adapter);
@@ -490,29 +446,14 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
(Adapter->registrypriv.RegEnableTxPowerLimit == 2 && pHalData->EEPROMRegulatory == 1)
)
PHY_ConvertTxPowerLimitToPowerIndex(Adapter);
-
- if (rtStatus != _SUCCESS) {
- DBG_8192C("%s():BB_PG Reg Fail!!\n", __func__);
- }
}
/* */
/* 2. Read BB AGC table Initialization */
/* */
- if (phy_ConfigBBWithParaFile(Adapter, pszAGCTableFile,
- CONFIG_BB_AGC_TAB) == _FAIL) {
- if (HAL_STATUS_SUCCESS != ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_AGC_TAB))
- rtStatus = _FAIL;
- }
-
- if (rtStatus != _SUCCESS) {
- DBG_8192C("%s():AGC Table Fail\n", __func__);
- goto phy_BB8190_Config_ParaFile_Fail;
- }
-
-phy_BB8190_Config_ParaFile_Fail:
+ ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_AGC_TAB);
- return rtStatus;
+ return _SUCCESS;
}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c b/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
index d0ffe0af5339..aafceaf9b139 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
@@ -85,19 +85,8 @@ static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
u32 u4RegValue = 0;
u8 eRFPath;
struct bb_register_def *pPhyReg;
-
- int rtStatus = _SUCCESS;
struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- static char sz8723RadioAFile[] = RTL8723B_PHY_RADIO_A;
- static char sz8723RadioBFile[] = RTL8723B_PHY_RADIO_B;
- static s8 sz8723BTxPwrTrackFile[] = RTL8723B_TXPWR_TRACK;
- char *pszRadioAFile, *pszRadioBFile, *pszTxPwrTrackFile;
-
- pszRadioAFile = sz8723RadioAFile;
- pszRadioBFile = sz8723RadioBFile;
- pszTxPwrTrackFile = sz8723BTxPwrTrackFile;
-
/* 3----------------------------------------------------------------- */
/* 3 <2> Initialize RF */
/* 3----------------------------------------------------------------- */
@@ -136,21 +125,11 @@ static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
/*----Initialize RF fom connfiguration file----*/
switch (eRFPath) {
case RF_PATH_A:
- if (PHY_ConfigRFWithParaFile(Adapter, pszRadioAFile,
- eRFPath) == _FAIL) {
- if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, CONFIG_RF_RADIO, (ODM_RF_RADIO_PATH_E)eRFPath))
- rtStatus = _FAIL;
- }
- break;
case RF_PATH_B:
- if (PHY_ConfigRFWithParaFile(Adapter, pszRadioBFile,
- eRFPath) == _FAIL) {
- if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, CONFIG_RF_RADIO, (ODM_RF_RADIO_PATH_E)eRFPath))
- rtStatus = _FAIL;
- }
+ ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv,
+ CONFIG_RF_RADIO, eRFPath);
break;
case RF_PATH_C:
- break;
case RF_PATH_D:
break;
}
@@ -166,28 +145,16 @@ static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue);
break;
}
-
- if (rtStatus != _SUCCESS) {
- /* RT_TRACE(COMP_FPGA, DBG_LOUD, ("phy_RF6052_Config_ParaFile():Radio[%d] Fail!!", eRFPath)); */
- goto phy_RF6052_Config_ParaFile_Fail;
- }
-
}
/* 3 ----------------------------------------------------------------- */
/* 3 Configuration of Tx Power Tracking */
/* 3 ----------------------------------------------------------------- */
- if (PHY_ConfigRFWithTxPwrTrackParaFile(Adapter, pszTxPwrTrackFile) ==
- _FAIL) {
- ODM_ConfigRFWithTxPwrTrackHeaderFile(&pHalData->odmpriv);
- }
+ ODM_ConfigRFWithTxPwrTrackHeaderFile(&pHalData->odmpriv);
/* RT_TRACE(COMP_INIT, DBG_LOUD, ("<---phy_RF6052_Config_ParaFile()\n")); */
- return rtStatus;
-
-phy_RF6052_Config_ParaFile_Fail:
- return rtStatus;
+ return _SUCCESS;
}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
index 0f3301091258..e8577c084bbd 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
@@ -179,8 +179,6 @@ static void rtl8723bs_c2h_packet_handler(struct adapter *padapter,
kfree(tmp);
/* DBG_871X("-%s res(%d)\n", __func__, res); */
-
- return;
}
static inline union recv_frame *try_alloc_recvframe(struct recv_priv *precvpriv,
diff --git a/drivers/staging/rtl8723bs/hal/sdio_ops.c b/drivers/staging/rtl8723bs/hal/sdio_ops.c
index 301d327d0624..b6b4adb5a28a 100644
--- a/drivers/staging/rtl8723bs/hal/sdio_ops.c
+++ b/drivers/staging/rtl8723bs/hal/sdio_ops.c
@@ -15,7 +15,7 @@
/* */
/* Description: */
-/* The following mapping is for SDIO host local register space. */
+/* The following mapping is for SDIO host local register space. */
/* */
/* Creadted by Roger, 2011.01.31. */
/* */
@@ -61,7 +61,6 @@ static u8 get_deviceid(u32 addr)
u8 devide_id;
u16 pseudo_id;
-
pseudo_id = (u16)(addr >> 16);
switch (pseudo_id) {
case 0x1025:
@@ -72,10 +71,6 @@ static u8 get_deviceid(u32 addr)
devide_id = WLAN_IOREG_DEVICE_ID;
break;
-/* case 0x1027: */
-/* devide_id = SDIO_FIRMWARE_FIFO; */
-/* break; */
-
case 0x1031:
devide_id = WLAN_TX_HIQ_DEVICE_ID;
break;
@@ -93,7 +88,6 @@ static u8 get_deviceid(u32 addr)
break;
default:
-/* devide_id = (u8)((addr >> 13) & 0xF); */
devide_id = WLAN_IOREG_DEVICE_ID;
break;
}
@@ -111,7 +105,6 @@ static u32 _cvrt2ftaddr(const u32 addr, u8 *pdevice_id, u16 *poffset)
u16 offset;
u32 ftaddr;
-
device_id = get_deviceid(addr);
offset = 0;
@@ -427,20 +420,16 @@ static u32 sdio_read_port(
struct adapter *adapter;
struct sdio_data *psdio;
struct hal_com_data *hal;
- u32 oldcnt;
s32 err;
-
adapter = intfhdl->padapter;
psdio = &adapter_to_dvobj(adapter)->intf_data;
hal = GET_HAL_DATA(adapter);
HalSdioGetCmdAddr8723BSdio(adapter, addr, hal->SdioRxFIFOCnt++, &addr);
- oldcnt = cnt;
if (cnt > psdio->block_transfer_len)
cnt = _RND(cnt, psdio->block_transfer_len);
-/* cnt = sdio_align_size(cnt); */
err = _sd_read(intfhdl, addr, cnt, mem);
@@ -490,7 +479,6 @@ static u32 sdio_write_port(
if (cnt > psdio->block_transfer_len)
cnt = _RND(cnt, psdio->block_transfer_len);
-/* cnt = sdio_align_size(cnt); */
err = sd_write(intfhdl, addr, cnt, xmitbuf->pdata);
@@ -538,7 +526,6 @@ static s32 _sdio_local_read(
u8 *tmpbuf;
u32 n;
-
intfhdl = &adapter->iopriv.intf;
HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
@@ -711,7 +698,6 @@ static s32 ReadInterrupt8723BSdio(struct adapter *adapter, u32 *phisr)
u32 hisr, himr;
u8 val8, hisr_len;
-
if (!phisr)
return false;
@@ -737,73 +723,48 @@ static s32 ReadInterrupt8723BSdio(struct adapter *adapter, u32 *phisr)
}
/* */
-/* Description: */
-/* Initialize SDIO Host Interrupt Mask configuration variables for future use. */
+/* Description: */
+/* Initialize SDIO Host Interrupt Mask configuration variables for future use. */
/* */
-/* Assumption: */
-/* Using SDIO Local register ONLY for configuration. */
+/* Assumption: */
+/* Using SDIO Local register ONLY for configuration. */
/* */
-/* Created by Roger, 2011.02.11. */
+/* Created by Roger, 2011.02.11. */
/* */
void InitInterrupt8723BSdio(struct adapter *adapter)
{
struct hal_com_data *haldata;
-
haldata = GET_HAL_DATA(adapter);
- haldata->sdio_himr = (u32)( \
- SDIO_HIMR_RX_REQUEST_MSK |
- SDIO_HIMR_AVAL_MSK |
-/* SDIO_HIMR_TXERR_MSK | */
-/* SDIO_HIMR_RXERR_MSK | */
-/* SDIO_HIMR_TXFOVW_MSK | */
-/* SDIO_HIMR_RXFOVW_MSK | */
-/* SDIO_HIMR_TXBCNOK_MSK | */
-/* SDIO_HIMR_TXBCNERR_MSK | */
-/* SDIO_HIMR_BCNERLY_INT_MSK | */
-/* SDIO_HIMR_C2HCMD_MSK | */
-/* SDIO_HIMR_HSISR_IND_MSK | */
-/* SDIO_HIMR_GTINT3_IND_MSK | */
-/* SDIO_HIMR_GTINT4_IND_MSK | */
-/* SDIO_HIMR_PSTIMEOUT_MSK | */
-/* SDIO_HIMR_OCPINT_MSK | */
-/* SDIO_HIMR_ATIMEND_MSK | */
-/* SDIO_HIMR_ATIMEND_E_MSK | */
-/* SDIO_HIMR_CTWEND_MSK | */
- 0);
+ haldata->sdio_himr = (u32)(SDIO_HIMR_RX_REQUEST_MSK |
+ SDIO_HIMR_AVAL_MSK |
+ 0);
}
/* */
-/* Description: */
-/* Initialize System Host Interrupt Mask configuration variables for future use. */
+/* Description: */
+/* Initialize System Host Interrupt Mask configuration variables for future use. */
/* */
-/* Created by Roger, 2011.08.03. */
+/* Created by Roger, 2011.08.03. */
/* */
void InitSysInterrupt8723BSdio(struct adapter *adapter)
{
struct hal_com_data *haldata;
-
haldata = GET_HAL_DATA(adapter);
- haldata->SysIntrMask = ( \
-/* HSIMR_GPIO12_0_INT_EN | */
-/* HSIMR_SPS_OCP_INT_EN | */
-/* HSIMR_RON_INT_EN | */
-/* HSIMR_PDNINT_EN | */
-/* HSIMR_GPIO9_INT_EN | */
- 0);
+ haldata->SysIntrMask = (0);
}
/* */
-/* Description: */
-/* Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
+/* Description: */
+/* Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
/* */
-/* Assumption: */
-/* 1. Using SDIO Local register ONLY for configuration. */
-/* 2. PASSIVE LEVEL */
+/* Assumption: */
+/* 1. Using SDIO Local register ONLY for configuration. */
+/* 2. PASSIVE LEVEL */
/* */
-/* Created by Roger, 2011.02.11. */
+/* Created by Roger, 2011.02.11. */
/* */
void EnableInterrupt8723BSdio(struct adapter *adapter)
{
@@ -849,13 +810,13 @@ void EnableInterrupt8723BSdio(struct adapter *adapter)
}
/* */
-/* Description: */
-/* Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
+/* Description: */
+/* Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
/* */
-/* Assumption: */
-/* Using SDIO Local register ONLY for configuration. */
+/* Assumption: */
+/* Using SDIO Local register ONLY for configuration. */
/* */
-/* Created by Roger, 2011.02.11. */
+/* Created by Roger, 2011.02.11. */
/* */
void DisableInterrupt8723BSdio(struct adapter *adapter)
{
@@ -866,13 +827,13 @@ void DisableInterrupt8723BSdio(struct adapter *adapter)
}
/* */
-/* Description: */
-/* Using 0x100 to check the power status of FW. */
+/* Description: */
+/* Using 0x100 to check the power status of FW. */
/* */
-/* Assumption: */
-/* Using SDIO Local register ONLY for configuration. */
+/* Assumption: */
+/* Using SDIO Local register ONLY for configuration. */
/* */
-/* Created by Isaac, 2013.09.10. */
+/* Created by Isaac, 2013.09.10. */
/* */
u8 CheckIPSStatus(struct adapter *adapter)
{
@@ -896,7 +857,6 @@ static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size)
struct recv_priv *recv_priv;
struct recv_buf *recvbuf;
-
/* Patch for some SDIO Host 4 bytes issue */
/* ex. RK3188 */
readsize = RND4(size);
@@ -938,7 +898,6 @@ static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size)
return NULL;
}
-
/* 3 4. init recvbuf */
recvbuf->len = size;
recvbuf->phead = recvbuf->pskb->head;
@@ -972,7 +931,6 @@ void sd_int_dpc(struct adapter *adapter)
struct intf_hdl *intfhdl = &adapter->iopriv.intf;
struct pwrctrl_priv *pwrctl;
-
hal = GET_HAL_DATA(adapter);
dvobj = adapter_to_dvobj(adapter);
pwrctl = dvobj_to_pwrctl(dvobj);
@@ -992,7 +950,6 @@ void sd_int_dpc(struct adapter *adapter)
report.state = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HCPWM1_8723B);
- /* cpwm_int_hdl(adapter, &report); */
_set_workitem(&(pwrctl->cpwm_event));
}
@@ -1029,7 +986,7 @@ void sd_int_dpc(struct adapter *adapter)
if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
/* Handle CCX report here */
rtw_hal_c2h_handler(adapter, (u8 *)c2h_evt);
- kfree((u8 *)c2h_evt);
+ kfree(c2h_evt);
} else {
rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
}
@@ -1049,13 +1006,11 @@ void sd_int_dpc(struct adapter *adapter)
if (hal->sdio_hisr & SDIO_HISR_RXERR)
DBG_8192C("%s: Rx Error\n", __func__);
-
if (hal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
struct recv_buf *recvbuf;
int alloc_fail_time = 0;
u32 hisr;
-/* DBG_8192C("%s: RX Request, size =%d\n", __func__, hal->SdioRxFIFOSize); */
hal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
do {
hal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(adapter, SDIO_REG_RX0_REQ_LEN);
@@ -1090,7 +1045,6 @@ void sd_int_hdl(struct adapter *adapter)
{
struct hal_com_data *hal;
-
if (
(adapter->bDriverStopped) || (adapter->bSurpriseRemoved)
)
@@ -1120,27 +1074,24 @@ void sd_int_hdl(struct adapter *adapter)
}
/* */
-/* Description: */
-/* Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
+/* Description: */
+/* Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
/* */
-/* Assumption: */
-/* 1. Running at PASSIVE_LEVEL */
-/* 2. RT_TX_SPINLOCK is NOT acquired. */
+/* Assumption: */
+/* 1. Running at PASSIVE_LEVEL */
+/* 2. RT_TX_SPINLOCK is NOT acquired. */
/* */
-/* Created by Roger, 2011.01.28. */
+/* Created by Roger, 2011.01.28. */
/* */
u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter)
{
struct hal_com_data *hal;
u32 numof_free_page;
- /* _irql irql; */
-
hal = GET_HAL_DATA(adapter);
numof_free_page = SdioLocalCmd53Read4Byte(adapter, SDIO_REG_FREE_TXPG);
- /* spin_lock_bh(&phal->SdioTxFIFOFreePageLock); */
memcpy(hal->SdioTxFIFOFreePage, &numof_free_page, 4);
RT_TRACE(_module_hci_ops_c_, _drv_notice_,
("%s: Free page for HIQ(%#x), MIDQ(%#x), LOWQ(%#x), PUBQ(%#x)\n",
@@ -1149,14 +1100,13 @@ u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter)
hal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
hal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
hal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
- /* spin_unlock_bh(&hal->SdioTxFIFOFreePageLock); */
return true;
}
/* */
-/* Description: */
-/* Query SDIO Local register to get the current number of TX OQT Free Space. */
+/* Description: */
+/* Query SDIO Local register to get the current number of TX OQT Free Space. */
/* */
void HalQueryTxOQTBufferStatus8723BSdio(struct adapter *adapter)
{
@@ -1190,7 +1140,6 @@ u8 RecvOnePkt(struct adapter *adapter, u32 size)
recvbuf = sd_recv_rxfifo(adapter, size);
if (recvbuf) {
- /* printk("Completed Recv One Pkt.\n"); */
sd_rxhandler(adapter, recvbuf);
res = true;
} else {
diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h
index 8d7fce1e39b7..6ec9087f2eb1 100644
--- a/drivers/staging/rtl8723bs/include/drv_types.h
+++ b/drivers/staging/rtl8723bs/include/drv_types.h
@@ -197,9 +197,6 @@ struct registry_priv
u8 RFE_Type;
u8 check_fw_ps;
- u8 load_phy_file;
- u8 RegDecryptCustomFile;
-
#ifdef CONFIG_MULTI_VIR_IFACES
u8 ext_iface_num;/* primary/secondary iface is excluded */
#endif
@@ -693,7 +690,6 @@ void rtw_indicate_wx_disassoc_event(struct adapter *padapter);
void indicate_wx_scan_complete_event(struct adapter *padapter);
int rtw_change_ifname(struct adapter *padapter, const char *ifname);
-extern char *rtw_phy_file_path;
extern char *rtw_initmac;
extern int rtw_mc2u_disable;
extern int rtw_ht_enable;
diff --git a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h
index 9167f1e7827f..e9a3006a3e20 100644
--- a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h
+++ b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h
@@ -219,30 +219,4 @@ struct adapter * Adapter,
u16 ChannelPlan
);
-#define MAX_PARA_FILE_BUF_LEN 25600
-
-#define LOAD_MAC_PARA_FILE BIT0
-#define LOAD_BB_PARA_FILE BIT1
-#define LOAD_BB_PG_PARA_FILE BIT2
-#define LOAD_BB_MP_PARA_FILE BIT3
-#define LOAD_RF_PARA_FILE BIT4
-#define LOAD_RF_TXPWR_TRACK_PARA_FILE BIT5
-#define LOAD_RF_TXPWR_LMT_PARA_FILE BIT6
-
-int phy_ConfigMACWithParaFile(struct adapter *Adapter, char*pFileName);
-
-int phy_ConfigBBWithParaFile(struct adapter *Adapter, char*pFileName, u32 ConfigType);
-
-int phy_ConfigBBWithPgParaFile(struct adapter *Adapter, char*pFileName);
-
-int phy_ConfigBBWithMpParaFile(struct adapter *Adapter, char*pFileName);
-
-int PHY_ConfigRFWithParaFile(struct adapter *Adapter, char*pFileName, u8 eRFPath);
-
-int PHY_ConfigRFWithTxPwrTrackParaFile(struct adapter *Adapter, char*pFileName);
-
-int PHY_ConfigRFWithPowerLimitTableParaFile(struct adapter *Adapter, char*pFileName);
-
-void phy_free_filebuf(struct adapter *padapter);
-
#endif /* __HAL_COMMON_H__ */
diff --git a/drivers/staging/rtl8723bs/include/hal_data.h b/drivers/staging/rtl8723bs/include/hal_data.h
index 7d782659a84f..e5e667df6154 100644
--- a/drivers/staging/rtl8723bs/include/hal_data.h
+++ b/drivers/staging/rtl8723bs/include/hal_data.h
@@ -440,27 +440,6 @@ struct hal_com_data {
u32 SysIntrStatus;
u32 SysIntrMask;
-
- char para_file_buf[MAX_PARA_FILE_BUF_LEN];
- char *mac_reg;
- u32 mac_reg_len;
- char *bb_phy_reg;
- u32 bb_phy_reg_len;
- char *bb_agc_tab;
- u32 bb_agc_tab_len;
- char *bb_phy_reg_pg;
- u32 bb_phy_reg_pg_len;
- char *bb_phy_reg_mp;
- u32 bb_phy_reg_mp_len;
- char *rf_radio_a;
- u32 rf_radio_a_len;
- char *rf_radio_b;
- u32 rf_radio_b_len;
- char *rf_tx_pwr_track;
- u32 rf_tx_pwr_track_len;
- char *rf_tx_pwr_lmt;
- u32 rf_tx_pwr_lmt_len;
-
#ifdef CONFIG_BACKGROUND_NOISE_MONITOR
s16 noise[ODM_MAX_CHANNEL_NUM];
#endif
diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h
index 81a9c19ecc6a..a40cf7b60a69 100644
--- a/drivers/staging/rtl8723bs/include/osdep_service.h
+++ b/drivers/staging/rtl8723bs/include/osdep_service.h
@@ -171,10 +171,6 @@ extern void rtw_softap_lock_suspend(void);
extern void rtw_softap_unlock_suspend(void);
#endif
-/* File operation APIs, just for linux now */
-extern int rtw_is_file_readable(char *path);
-extern int rtw_retrive_from_file(char *path, u8 *buf, u32 sz);
-
extern void rtw_free_netdev(struct net_device * netdev);
diff --git a/drivers/staging/rtl8723bs/include/osdep_service_linux.h b/drivers/staging/rtl8723bs/include/osdep_service_linux.h
index c582ede1ac12..a2d9de866c4b 100644
--- a/drivers/staging/rtl8723bs/include/osdep_service_linux.h
+++ b/drivers/staging/rtl8723bs/include/osdep_service_linux.h
@@ -127,13 +127,6 @@ static inline void rtw_netif_stop_queue(struct net_device *pnetdev)
netif_tx_stop_all_queues(pnetdev);
}
-static inline void rtw_merge_string(char *dst, int dst_len, char *src1, char *src2)
-{
- int len = 0;
- len += snprintf(dst+len, dst_len - len, "%s", src1);
- len += snprintf(dst+len, dst_len - len, "%s", src2);
-}
-
#define rtw_signal_process(pid, sig) kill_pid(find_vpid((pid)), (sig), 1)
#define rtw_netdev_priv(netdev) (((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv)
diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_hal.h b/drivers/staging/rtl8723bs/include/rtl8723b_hal.h
index 8f00ced1c697..f36516fa84c7 100644
--- a/drivers/staging/rtl8723bs/include/rtl8723b_hal.h
+++ b/drivers/staging/rtl8723bs/include/rtl8723b_hal.h
@@ -21,21 +21,6 @@
#include "hal_phy_cfg.h"
/* */
-/* RTL8723B From file */
-/* */
-#define RTL8723B_FW_IMG "rtl8723b/FW_NIC.bin"
-#define RTL8723B_FW_WW_IMG "rtl8723b/FW_WoWLAN.bin"
-#define RTL8723B_PHY_REG "rtl8723b/PHY_REG.txt"
-#define RTL8723B_PHY_RADIO_A "rtl8723b/RadioA.txt"
-#define RTL8723B_PHY_RADIO_B "rtl8723b/RadioB.txt"
-#define RTL8723B_TXPWR_TRACK "rtl8723b/TxPowerTrack.txt"
-#define RTL8723B_AGC_TAB "rtl8723b/AGC_TAB.txt"
-#define RTL8723B_PHY_MACREG "rtl8723b/MAC_REG.txt"
-#define RTL8723B_PHY_REG_PG "rtl8723b/PHY_REG_PG.txt"
-#define RTL8723B_PHY_REG_MP "rtl8723b/PHY_REG_MP.txt"
-#define RTL8723B_TXPWR_LMT "rtl8723b/TXPWR_LMT.txt"
-
-/* */
/* RTL8723B From header */
/* */
diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
index fd3cf955c9f8..73e8ec09b6e1 100644
--- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
+++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
@@ -576,7 +576,6 @@ void read_cam(struct adapter *padapter , u8 entry, u8 *get_key);
/* modify HW only */
void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key);
void _clear_cam_entry(struct adapter *padapter, u8 entry);
-void write_cam_from_cache(struct adapter *adapter, u8 id);
/* modify both HW and cache */
void write_cam(struct adapter *padapter, u8 id, u16 ctrl, u8 *mac, u8 *key);
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
index f819abb756dc..52c1f6625038 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
@@ -165,7 +165,7 @@ static void rtw_spt_band_free(struct ieee80211_supported_band *spt_band)
+ sizeof(struct ieee80211_channel)*RTW_2G_CHANNELS_NUM
+ sizeof(struct ieee80211_rate)*RTW_G_RATES_NUM;
}
- kfree((u8 *)spt_band);
+ kfree(spt_band);
}
static const struct ieee80211_txrx_stypes
@@ -1156,7 +1156,7 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
}
addkey_end:
- kfree((u8 *)param);
+ kfree(param);
return ret;
@@ -1410,19 +1410,19 @@ void rtw_cfg80211_unlink_bss(struct adapter *padapter, struct wlan_network *pnet
struct wireless_dev *pwdev = padapter->rtw_wdev;
struct wiphy *wiphy = pwdev->wiphy;
struct cfg80211_bss *bss = NULL;
- struct wlan_bssid_ex select_network = pnetwork->network;
+ struct wlan_bssid_ex *select_network = &pnetwork->network;
bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/,
- select_network.MacAddress, select_network.Ssid.Ssid,
- select_network.Ssid.SsidLength, 0/*WLAN_CAPABILITY_ESS*/,
+ select_network->MacAddress, select_network->Ssid.Ssid,
+ select_network->Ssid.SsidLength, 0/*WLAN_CAPABILITY_ESS*/,
0/*WLAN_CAPABILITY_ESS*/);
if (bss) {
cfg80211_unlink_bss(wiphy, bss);
- DBG_8192C("%s(): cfg80211_unlink %s!! () ", __func__, select_network.Ssid.Ssid);
+ DBG_8192C("%s(): cfg80211_unlink %s!! () ", __func__,
+ select_network->Ssid.Ssid);
cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);
}
- return;
}
void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter)
@@ -1513,7 +1513,7 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
int i;
u8 _status = false;
int ret = 0;
- struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
+ struct ndis_802_11_ssid *ssid = NULL;
struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
u8 survey_times =3;
u8 survey_times_for_one_ch =6;
@@ -1604,7 +1604,13 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
goto check_need_indicate_scan_done;
}
- memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
+ ssid = kzalloc(RTW_SSID_SCAN_AMOUNT * sizeof(struct ndis_802_11_ssid),
+ GFP_KERNEL);
+ if (!ssid) {
+ ret = -ENOMEM;
+ goto check_need_indicate_scan_done;
+ }
+
/* parsing request ssids, n_ssids */
for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
#ifdef DEBUG_CFG80211
@@ -1648,6 +1654,7 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
}
check_need_indicate_scan_done:
+ kfree(ssid);
if (need_indicate_scan_done)
{
rtw_cfg80211_surveydone_event_callback(padapter);
@@ -2194,7 +2201,7 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
ret = -EOPNOTSUPP ;
}
- kfree((u8 *)pwep);
+ kfree(pwep);
if (ret < 0)
goto exit;
@@ -2433,7 +2440,6 @@ void rtw_cfg80211_indicate_sta_disassoc(struct adapter *padapter, unsigned char
static netdev_tx_t 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;
@@ -2499,9 +2505,7 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
DBG_8192C("should be eapol packet\n");
/* Use the real net device to transmit the packet */
- ret = _rtw_xmit_entry(skb, padapter->pnetdev);
-
- return ret;
+ return _rtw_xmit_entry(skb, padapter->pnetdev);
}
else if ((frame_control & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE))
@@ -2647,7 +2651,7 @@ static int rtw_cfg80211_add_monitor_if (struct adapter *padapter, char *name, st
out:
if (ret && mon_wdev) {
- kfree((u8 *)mon_wdev);
+ kfree(mon_wdev);
mon_wdev = NULL;
}
@@ -2808,14 +2812,11 @@ static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
static int cfg80211_rtw_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_beacon_data *info)
{
- int ret = 0;
struct adapter *adapter = (struct adapter *)rtw_netdev_priv(ndev);
DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
- ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);
-
- return ret;
+ return rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);
}
static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
@@ -3503,7 +3504,7 @@ void rtw_wdev_free(struct wireless_dev *wdev)
wiphy_free(wdev->wiphy);
- kfree((u8 *)wdev);
+ kfree(wdev);
}
void rtw_wdev_unregister(struct wireless_dev *wdev)
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
index d1b199e3e5bd..db6528a01229 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
@@ -2425,19 +2425,13 @@ static int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
return 0;
}
-static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- return ret;
-}
-
static int rtw_get_ap_info(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret = 0;
- u32 cnt = 0, wpa_ielen;
+ int wpa_ielen;
+ u32 cnt = 0;
struct list_head *plist, *phead;
unsigned char *pbuf;
u8 bssid[ETH_ALEN];
@@ -2793,7 +2787,7 @@ static int rtw_dbg_port(struct net_device *dev,
DBG_871X("oper_ch =%d\n", rtw_get_oper_ch(padapter));
DBG_871X("oper_bw =%d\n", rtw_get_oper_bw(padapter));
- DBG_871X("oper_ch_offet =%d\n", rtw_get_oper_choffset(padapter));
+ DBG_871X("oper_ch_offset =%d\n", rtw_get_oper_choffset(padapter));
break;
case 0x05:
@@ -4458,43 +4452,6 @@ static int rtw_pm_set(struct net_device *dev,
return ret;
}
-static int rtw_mp_efuse_get(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wdata, char *extra)
-{
- int err = 0;
- return err;
-}
-
-static int rtw_mp_efuse_set(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wdata, char *extra)
-{
- int err = 0;
- return err;
-}
-
-static int rtw_tdls(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- return ret;
-}
-
-
-static int rtw_tdls_get(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- return ret;
-}
-
-
-
-
-
static int rtw_test(
struct net_device *dev,
struct iw_request_info *info,
@@ -4744,7 +4701,7 @@ static iw_handler rtw_private_handler[] = {
rtw_wx_write32, /* 0x00 */
rtw_wx_read32, /* 0x01 */
rtw_drvext_hdl, /* 0x02 */
- rtw_mp_ioctl_hdl, /* 0x03 */
+ NULL, /* 0x03 */
/* for MM DTV platform */
rtw_get_ap_info, /* 0x04 */
@@ -4771,15 +4728,15 @@ static iw_handler rtw_private_handler[] = {
NULL, /* 0x12 */
rtw_p2p_get2, /* 0x13 */
- rtw_tdls, /* 0x14 */
- rtw_tdls_get, /* 0x15 */
+ NULL, /* 0x14 */
+ NULL, /* 0x15 */
rtw_pm_set, /* 0x16 */
rtw_wx_priv_null, /* 0x17 */
rtw_rereg_nd_name, /* 0x18 */
rtw_wx_priv_null, /* 0x19 */
- rtw_mp_efuse_set, /* 0x1A */
- rtw_mp_efuse_get, /* 0x1B */
+ NULL, /* 0x1A */
+ NULL, /* 0x1B */
NULL, /* 0x1C is reserved for hostapd */
rtw_test, /* 0x1D */
};
diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
index ec3a75485233..47e984d5b7cb 100644
--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
@@ -201,24 +201,6 @@ MODULE_PARM_DESC(rtw_tx_pwr_lmt_enable, "0:Disable, 1:Enable, 2: Depend on efuse
module_param(rtw_tx_pwr_by_rate, int, 0644);
MODULE_PARM_DESC(rtw_tx_pwr_by_rate, "0:Disable, 1:Enable, 2: Depend on efuse");
-char *rtw_phy_file_path = "";
-module_param(rtw_phy_file_path, charp, 0644);
-MODULE_PARM_DESC(rtw_phy_file_path, "The path of phy parameter");
-/* PHY FILE Bit Map */
-/* BIT0 - MAC, 0: non-support, 1: support */
-/* BIT1 - BB, 0: non-support, 1: support */
-/* BIT2 - BB_PG, 0: non-support, 1: support */
-/* BIT3 - BB_MP, 0: non-support, 1: support */
-/* BIT4 - RF, 0: non-support, 1: support */
-/* BIT5 - RF_TXPWR_TRACK, 0: non-support, 1: support */
-/* BIT6 - RF_TXPWR_LMT, 0: non-support, 1: support */
-static int rtw_load_phy_file = (BIT2 | BIT6);
-module_param(rtw_load_phy_file, int, 0644);
-MODULE_PARM_DESC(rtw_load_phy_file, "PHY File Bit Map");
-static int rtw_decrypt_phy_file;
-module_param(rtw_decrypt_phy_file, int, 0644);
-MODULE_PARM_DESC(rtw_decrypt_phy_file, "Enable Decrypt PHY File");
-
int _netdev_open(struct net_device *pnetdev);
int netdev_open (struct net_device *pnetdev);
static int netdev_close (struct net_device *pnetdev);
@@ -321,8 +303,6 @@ static void loadparam(struct adapter *padapter, _nic_hdl pnetdev)
registry_par->bEn_RFE = 1;
registry_par->RFE_Type = 64;
- registry_par->load_phy_file = (u8)rtw_load_phy_file;
- registry_par->RegDecryptCustomFile = (u8)rtw_decrypt_phy_file;
registry_par->qos_opt_enable = (u8)rtw_qos_opt_enable;
registry_par->hiq_filter = (u8)rtw_hiq_filter;
@@ -1141,8 +1121,7 @@ void rtw_ndev_destructor(struct net_device *ndev)
{
DBG_871X(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
- if (ndev->ieee80211_ptr)
- kfree((u8 *)ndev->ieee80211_ptr);
+ kfree(ndev->ieee80211_ptr);
}
void rtw_dev_unload(struct adapter *padapter)
diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c
index 25a80041ce87..f5614e56371e 100644
--- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c
+++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c
@@ -65,142 +65,6 @@ void _rtw_init_queue(struct __queue *pqueue)
spin_lock_init(&(pqueue->lock));
}
-/*
-* Open a file with the specific @param path, @param flag, @param mode
-* @param fpp the pointer of struct file pointer to get struct file pointer while file opening is success
-* @param path the path of the file to open
-* @param flag file operation flags, please refer to linux document
-* @param mode please refer to linux document
-* @return Linux specific error code
-*/
-static int openFile(struct file **fpp, char *path, int flag, int mode)
-{
- struct file *fp;
-
- fp = filp_open(path, flag, mode);
- if (IS_ERR(fp)) {
- *fpp = NULL;
- return PTR_ERR(fp);
- }
- else {
- *fpp = fp;
- return 0;
- }
-}
-
-/*
-* Close the file with the specific @param fp
-* @param fp the pointer of struct file to close
-* @return always 0
-*/
-static int closeFile(struct file *fp)
-{
- filp_close(fp, NULL);
- return 0;
-}
-
-static int readFile(struct file *fp, char *buf, int len)
-{
- int rlen = 0, sum = 0;
-
- if (!fp->f_op || !fp->f_op->read)
- return -EPERM;
-
- while (sum < len) {
- rlen = kernel_read(fp, buf + sum, len - sum, &fp->f_pos);
- if (rlen > 0)
- sum += rlen;
- else if (0 != rlen)
- return rlen;
- else
- break;
- }
-
- return sum;
-
-}
-
-/*
-* Test if the specifi @param path is a file and readable
-* @param path the path of the file to test
-* @return Linux specific error code
-*/
-static int isFileReadable(char *path)
-{
- struct file *fp;
- int ret = 0;
- char buf;
-
- fp = filp_open(path, O_RDONLY, 0);
- if (IS_ERR(fp))
- return PTR_ERR(fp);
-
- if (readFile(fp, &buf, 1) != 1)
- ret = -EINVAL;
-
- filp_close(fp, NULL);
- return ret;
-}
-
-/*
-* Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most
-* @param path the path of the file to open and read
-* @param buf the starting address of the buffer to store file content
-* @param sz how many bytes to read at most
-* @return the byte we've read, or Linux specific error code
-*/
-static int retriveFromFile(char *path, u8 *buf, u32 sz)
-{
- int ret = -1;
- struct file *fp;
-
- if (path && buf) {
- ret = openFile(&fp, path, O_RDONLY, 0);
-
- if (ret == 0) {
- DBG_871X("%s openFile path:%s fp =%p\n", __func__, path , fp);
-
- ret = readFile(fp, buf, sz);
- closeFile(fp);
-
- DBG_871X("%s readFile, ret:%d\n", __func__, ret);
-
- } else {
- DBG_871X("%s openFile path:%s Fail, ret:%d\n", __func__, path, ret);
- }
- } else {
- DBG_871X("%s NULL pointer\n", __func__);
- ret = -EINVAL;
- }
- return ret;
-}
-
-/*
-* Test if the specifi @param path is a file and readable
-* @param path the path of the file to test
-* @return true or false
-*/
-int rtw_is_file_readable(char *path)
-{
- if (isFileReadable(path) == 0)
- return true;
- else
- return false;
-}
-
-/*
-* Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most
-* @param path the path of the file to open and read
-* @param buf the starting address of the buffer to store file content
-* @param sz how many bytes to read at most
-* @return the byte we've read
-*/
-int rtw_retrive_from_file(char *path, u8 *buf, u32 sz)
-{
- int ret = retriveFromFile(path, buf, sz);
- return ret >= 0 ? ret : 0;
-}
-
struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
{
struct net_device *pnetdev;
diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
index d3784c44f6d0..12f683e2e0e2 100644
--- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
+++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
@@ -281,7 +281,6 @@ static void sdio_dvobj_deinit(struct sdio_func *func)
sdio_deinit(dvobj);
devobj_deinit(dvobj);
}
- return;
}
void rtw_set_hal_ops(struct adapter *padapter)
diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
index e853fa9cc950..d53dd138a356 100644
--- a/drivers/staging/rts5208/ms.c
+++ b/drivers/staging/rts5208/ms.c
@@ -590,7 +590,7 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
int retval, i;
u8 val;
- retval = ms_set_rw_reg_addr(chip, Pro_StatusReg, 6, SystemParm, 1);
+ retval = ms_set_rw_reg_addr(chip, PRO_STATUS_REG, 6, SYSTEM_PARAM, 1);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -840,7 +840,7 @@ static int msxc_change_power(struct rtsx_chip *chip, u8 mode)
ms_cleanup_work(chip);
- retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
+ retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_DATA_COUNT1, 6);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -885,7 +885,7 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
int found_sys_info = 0, found_model_name = 0;
#endif
- retval = ms_set_rw_reg_addr(chip, Pro_IntReg, 2, Pro_SystemParm, 7);
+ retval = ms_set_rw_reg_addr(chip, PRO_INT_REG, 2, PRO_SYSTEM_PARAM, 7);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1232,7 +1232,7 @@ static int ms_read_status_reg(struct rtsx_chip *chip)
int retval;
u8 val[2];
- retval = ms_set_rw_reg_addr(chip, StatusReg0, 2, 0, 0);
+ retval = ms_set_rw_reg_addr(chip, STATUS_REG0, 2, 0, 0);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1255,8 +1255,8 @@ static int ms_read_extra_data(struct rtsx_chip *chip,
int retval, i;
u8 val, data[10];
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, 6);
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, 6);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1307,8 +1307,8 @@ static int ms_read_extra_data(struct rtsx_chip *chip,
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
- MS_EXTRA_SIZE, SystemParm,
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
+ MS_EXTRA_SIZE, SYSTEM_PARAM,
6);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1339,8 +1339,8 @@ static int ms_write_extra_data(struct rtsx_chip *chip, u16 block_addr,
if (!buf || (buf_len < MS_EXTRA_SIZE))
return STATUS_FAIL;
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, 6 + MS_EXTRA_SIZE);
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, 6 + MS_EXTRA_SIZE);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1392,8 +1392,8 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num)
int retval;
u8 val, data[6];
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, 6);
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, 6);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1465,8 +1465,8 @@ static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk)
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, 7);
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, 7);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1519,8 +1519,8 @@ static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk)
int retval, i = 0;
u8 val, data[6];
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, 6);
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, 6);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1579,7 +1579,7 @@ static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len)
memset(extra, 0xFF, MS_EXTRA_SIZE);
- if (type == setPS_NG) {
+ if (type == set_PS_NG) {
/* set page status as 1:NG,and block status keep 1:OK */
extra[0] = 0xB8;
} else {
@@ -1670,8 +1670,8 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
- MS_EXTRA_SIZE, SystemParm, 6);
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
+ MS_EXTRA_SIZE, SYSTEM_PARAM, 6);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1725,7 +1725,7 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
return STATUS_FAIL;
if (uncorrect_flag) {
- ms_set_page_status(log_blk, setPS_NG,
+ ms_set_page_status(log_blk, set_PS_NG,
extra,
MS_EXTRA_SIZE);
if (i == 0)
@@ -1738,8 +1738,8 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
i, extra[0]);
MS_SET_BAD_BLOCK_FLG(ms_card);
- ms_set_page_status(log_blk, setPS_Error,
- extra,
+ ms_set_page_status(log_blk,
+ set_PS_error, extra,
MS_EXTRA_SIZE);
ms_write_extra_data(chip, new_blk, i,
extra,
@@ -1767,8 +1767,8 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
}
}
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, (6 + MS_EXTRA_SIZE));
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, (6 + MS_EXTRA_SIZE));
ms_set_err_code(chip, MS_NO_ERROR);
@@ -1822,8 +1822,8 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
}
if (i == 0) {
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
- MS_EXTRA_SIZE, SystemParm,
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
+ MS_EXTRA_SIZE, SYSTEM_PARAM,
7);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -1980,8 +1980,8 @@ RE_SEARCH:
for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++)
rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, MS_Device_Type, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_Support, 0, 0);
+ rtsx_add_cmd(chip, READ_REG_CMD, MS_device_type, 0, 0);
+ rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_support, 0, 0);
retval = rtsx_send_cmd(chip, MS_CARD, 100);
if (retval < 0)
@@ -2057,7 +2057,7 @@ RE_SEARCH:
/* Switch I/F Mode */
if (ptr[15]) {
- retval = ms_set_rw_reg_addr(chip, 0, 0, SystemParm, 1);
+ retval = ms_set_rw_reg_addr(chip, 0, 0, SYSTEM_PARAM, 1);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -2887,7 +2887,7 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
- retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, Pro_TPCParm, 0x01);
+ retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, PRO_TPC_PARM, 0x01);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -2970,8 +2970,8 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
}
}
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, 6);
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, 6);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -3026,7 +3026,7 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
if (!(chip->card_wp & MS_CARD)) {
reset_ms(chip);
ms_set_page_status
- (log_blk, setPS_NG,
+ (log_blk, set_PS_NG,
extra,
MS_EXTRA_SIZE);
ms_write_extra_data
@@ -3131,8 +3131,8 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
u8 *ptr;
if (!start_page) {
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, 7);
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, 7);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -3165,8 +3165,8 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
return STATUS_FAIL;
}
- retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
- SystemParm, (6 + MS_EXTRA_SIZE));
+ retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
+ SYSTEM_PARAM, (6 + MS_EXTRA_SIZE));
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -3773,9 +3773,9 @@ static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type,
u8 buf[6];
if (type == 0)
- retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_TPCParm, 1);
+ retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_TPC_PARM, 1);
else
- retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
+ retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_DATA_COUNT1, 6);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
@@ -4154,7 +4154,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
} else {
set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
}
- goto SetICVFinish;
+ goto set_ICV_finish;
}
#ifdef MG_SET_ICV_SLOW
@@ -4195,7 +4195,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
SENSE_TYPE_MG_WRITE_ERR);
}
retval = STATUS_FAIL;
- goto SetICVFinish;
+ goto set_ICV_finish;
}
}
#else
@@ -4214,11 +4214,11 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
} else {
set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
}
- goto SetICVFinish;
+ goto set_ICV_finish;
}
#endif
-SetICVFinish:
+set_ICV_finish:
kfree(buf);
return retval;
}
diff --git a/drivers/staging/rts5208/ms.h b/drivers/staging/rts5208/ms.h
index 952cc14dd079..33bda9ce36b6 100644
--- a/drivers/staging/rts5208/ms.h
+++ b/drivers/staging/rts5208/ms.h
@@ -92,37 +92,37 @@
#define PRO_FORMAT 0x10
#define PRO_SLEEP 0x11
-#define IntReg 0x01
-#define StatusReg0 0x02
-#define StatusReg1 0x03
-
-#define SystemParm 0x10
-#define BlockAdrs 0x11
-#define CMDParm 0x14
-#define PageAdrs 0x15
-
-#define OverwriteFlag 0x16
-#define ManagemenFlag 0x17
-#define LogicalAdrs 0x18
-#define ReserveArea 0x1A
-
-#define Pro_IntReg 0x01
-#define Pro_StatusReg 0x02
-#define Pro_TypeReg 0x04
-#define Pro_IFModeReg 0x05
-#define Pro_CatagoryReg 0x06
-#define Pro_ClassReg 0x07
-
-#define Pro_SystemParm 0x10
-#define Pro_DataCount1 0x11
-#define Pro_DataCount0 0x12
-#define Pro_DataAddr3 0x13
-#define Pro_DataAddr2 0x14
-#define Pro_DataAddr1 0x15
-#define Pro_DataAddr0 0x16
-
-#define Pro_TPCParm 0x17
-#define Pro_CMDParm 0x18
+#define INT_REG 0x01
+#define STATUS_REG0 0x02
+#define STATUS_REG1 0x03
+
+#define SYSTEM_PARAM 0x10
+#define BLOCK_ADRS 0x11
+#define CMD_PARM 0x14
+#define PAGE_ADRS 0x15
+
+#define OVERWRITE_FLAG 0x16
+#define MANAGEMEN_FLAG 0x17
+#define LOGICAL_ADRS 0x18
+#define RESERVE_AREA 0x1A
+
+#define PRO_INT_REG 0x01
+#define PRO_STATUS_REG 0x02
+#define PRO_TYPE_REG 0x04
+#define PRO_IF_mode_REG 0x05
+#define PRO_CATEGORY_REG 0x06
+#define PRO_CLASS_REG 0x07
+
+#define PRO_SYSTEM_PARAM 0x10
+#define PRO_DATA_COUNT1 0x11
+#define PRO_DATA_COUNT0 0x12
+#define PRO_DATA_ADDR3 0x13
+#define PRO_DATA_ADDR2 0x14
+#define PRO_DATA_ADDR1 0x15
+#define PRO_DATA_ADDR0 0x16
+
+#define PRO_TPC_PARM 0x17
+#define PRO_CMD_PARM 0x18
#define INT_REG_CED 0x80
#define INT_REG_ERR 0x40
@@ -152,12 +152,12 @@
#define PAGE_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 8)
#define PAGE_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 9)
-#define MS_Device_Type (PPBUF_BASE2 + 0x1D8)
+#define MS_device_type (PPBUF_BASE2 + 0x1D8)
-#define MS_4bit_Support (PPBUF_BASE2 + 0x1D3)
+#define MS_4bit_support (PPBUF_BASE2 + 0x1D3)
-#define setPS_NG 1
-#define setPS_Error 0
+#define set_PS_NG 1
+#define set_PS_error 0
#define PARALLEL_8BIT_IF 0x40
#define PARALLEL_4BIT_IF 0x00
diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c
index fa597953e9a0..cb95ad6fa4f9 100644
--- a/drivers/staging/rts5208/rtsx.c
+++ b/drivers/staging/rts5208/rtsx.c
@@ -873,7 +873,8 @@ static int rtsx_probe(struct pci_dev *pci,
(unsigned long)(dev->addr), (unsigned long)(dev->remap_addr));
dev->rtsx_resv_buf = dmam_alloc_coherent(&pci->dev, RTSX_RESV_BUF_LEN,
- &dev->rtsx_resv_buf_addr, GFP_KERNEL);
+ &dev->rtsx_resv_buf_addr,
+ GFP_KERNEL);
if (!dev->rtsx_resv_buf) {
dev_err(&pci->dev, "alloc dma buffer fail\n");
err = -ENXIO;
diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c
index 561851cc8780..5f1eefe80f1e 100644
--- a/drivers/staging/rts5208/rtsx_transport.c
+++ b/drivers/staging/rts5208/rtsx_transport.c
@@ -677,8 +677,8 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf,
spin_unlock_irq(&rtsx->reg_lock);
/* Wait for TRANS_OK_INT */
- timeleft = wait_for_completion_interruptible_timeout(
- &trans_done, msecs_to_jiffies(timeout));
+ timeleft = wait_for_completion_interruptible_timeout(&trans_done,
+ msecs_to_jiffies(timeout));
if (timeleft <= 0) {
dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
__func__, __LINE__);
diff --git a/drivers/staging/rts5208/sd.h b/drivers/staging/rts5208/sd.h
index dc9e8cad7a74..f4ff62653b56 100644
--- a/drivers/staging/rts5208/sd.h
+++ b/drivers/staging/rts5208/sd.h
@@ -232,7 +232,7 @@
#define DCM_LOW_FREQUENCY_MODE 0x01
#define DCM_HIGH_FREQUENCY_MODE_SET 0x0C
-#define DCM_Low_FREQUENCY_MODE_SET 0x00
+#define DCM_LOW_FREQUENCY_MODE_SET 0x00
#define MULTIPLY_BY_1 0x00
#define MULTIPLY_BY_2 0x01
diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c
index f3dc96a4c59d..0f369935fb6c 100644
--- a/drivers/staging/rts5208/xd.c
+++ b/drivers/staging/rts5208/xd.c
@@ -630,13 +630,13 @@ static int reset_xd(struct rtsx_chip *chip)
xd_card->zone_cnt = 32;
xd_card->capacity = 1024000;
break;
- case xD_1G_X8_512:
+ case XD_1G_X8_512:
XD_PAGE_512(xd_card);
xd_card->addr_cycle = 4;
xd_card->zone_cnt = 64;
xd_card->capacity = 2048000;
break;
- case xD_2G_X8_512:
+ case XD_2G_X8_512:
XD_PAGE_512(xd_card);
xd_card->addr_cycle = 4;
xd_card->zone_cnt = 128;
@@ -669,10 +669,10 @@ static int reset_xd(struct rtsx_chip *chip)
return STATUS_FAIL;
}
- retval = xd_read_id(chip, READ_xD_ID, id_buf, 4);
+ retval = xd_read_id(chip, READ_XD_ID, id_buf, 4);
if (retval != STATUS_SUCCESS)
return STATUS_FAIL;
- dev_dbg(rtsx_dev(chip), "READ_xD_ID: 0x%x 0x%x 0x%x 0x%x\n",
+ dev_dbg(rtsx_dev(chip), "READ_XD_ID: 0x%x 0x%x 0x%x 0x%x\n",
id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
if (id_buf[2] != XD_ID_CODE)
return STATUS_FAIL;
diff --git a/drivers/staging/rts5208/xd.h b/drivers/staging/rts5208/xd.h
index 57b94129b26f..98c00f268e56 100644
--- a/drivers/staging/rts5208/xd.h
+++ b/drivers/staging/rts5208/xd.h
@@ -36,7 +36,7 @@
#define BLK_ERASE_1 0x60
#define BLK_ERASE_2 0xD0
#define READ_STS 0x70
-#define READ_xD_ID 0x9A
+#define READ_XD_ID 0x9A
#define COPY_BACK_512 0x8A
#define COPY_BACK_2K 0x85
#define READ1_1_2 0x30
@@ -72,8 +72,8 @@
#define XD_128M_X16_2048 0xC1
#define XD_4M_X8_512_1 0xE3
#define XD_4M_X8_512_2 0xE5
-#define xD_1G_X8_512 0xD3
-#define xD_2G_X8_512 0xD5
+#define XD_1G_X8_512 0xD3
+#define XD_2G_X8_512 0xD5
#define XD_ID_CODE 0xB5
diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c
index 5a317cc98a4b..02860d3ec365 100644
--- a/drivers/staging/sm750fb/ddk750_chip.c
+++ b/drivers/staging/sm750fb/ddk750_chip.c
@@ -56,7 +56,6 @@ static unsigned int get_mxclk_freq(void)
static void set_chip_clock(unsigned int frequency)
{
struct pll_value pll;
- unsigned int actual_mx_clk;
/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
if (sm750_get_chip_type() == SM750LE)
@@ -66,8 +65,8 @@ static void set_chip_clock(unsigned int frequency)
/*
* Set up PLL structure to hold the value to be set in clocks.
*/
- pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
- pll.clockType = MXCLK_PLL;
+ pll.input_freq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
+ pll.clock_type = MXCLK_PLL;
/*
* Call sm750_calc_pll_value() to fill the other fields
@@ -76,7 +75,7 @@ static void set_chip_clock(unsigned int frequency)
* Return value of sm750_calc_pll_value gives the actual
* possible clock.
*/
- actual_mx_clk = sm750_calc_pll_value(frequency, &pll);
+ sm750_calc_pll_value(frequency, &pll);
/* Master Clock Control: MXCLK_PLL */
poke32(MXCLK_PLL_CTRL, sm750_format_pll_reg(&pll));
@@ -211,13 +210,13 @@ unsigned int ddk750_get_vm_size(void)
return data;
}
-int ddk750_init_hw(struct initchip_param *pInitParam)
+int ddk750_init_hw(struct initchip_param *p_init_param)
{
unsigned int reg;
- if (pInitParam->powerMode != 0)
- pInitParam->powerMode = 0;
- sm750_set_power_mode(pInitParam->powerMode);
+ if (p_init_param->power_mode != 0)
+ p_init_param->power_mode = 0;
+ sm750_set_power_mode(p_init_param->power_mode);
/* Enable display power gate & LOCALMEM power gate*/
reg = peek32(CURRENT_GATE);
@@ -238,13 +237,13 @@ int ddk750_init_hw(struct initchip_param *pInitParam)
}
/* Set the Main Chip Clock */
- set_chip_clock(MHz((unsigned int)pInitParam->chipClock));
+ set_chip_clock(MHz((unsigned int)p_init_param->chip_clock));
/* Set up memory clock. */
- set_memory_clock(MHz(pInitParam->memClock));
+ set_memory_clock(MHz(p_init_param->mem_clock));
/* Set up master clock */
- set_master_clock(MHz(pInitParam->masterClock));
+ set_master_clock(MHz(p_init_param->master_clock));
/*
* Reset the memory controller.
@@ -252,7 +251,7 @@ int ddk750_init_hw(struct initchip_param *pInitParam)
* the system might hang when sw accesses the memory.
* The memory should be resetted after changing the MXCLK.
*/
- if (pInitParam->resetMemory == 1) {
+ if (p_init_param->reset_memory == 1) {
reg = peek32(MISC_CTRL);
reg &= ~MISC_CTRL_LOCALMEM_RESET;
poke32(MISC_CTRL, reg);
@@ -261,7 +260,7 @@ int ddk750_init_hw(struct initchip_param *pInitParam)
poke32(MISC_CTRL, reg);
}
- if (pInitParam->setAllEngOff == 1) {
+ if (p_init_param->set_all_eng_off == 1) {
sm750_enable_2d_engine(0);
/* Disable Overlay, if a former application left it on */
@@ -337,13 +336,13 @@ unsigned int sm750_calc_pll_value(unsigned int request_orig,
ret = 0;
mini_diff = ~0;
request = request_orig / 1000;
- input = pll->inputFreq / 1000;
+ input = pll->input_freq / 1000;
/*
* for MXCLK register,
* no POD provided, so need be treated differently
*/
- if (pll->clockType == MXCLK_PLL)
+ if (pll->clock_type == MXCLK_PLL)
max_d = 3;
for (N = 15; N > 1; N--) {
@@ -365,7 +364,7 @@ unsigned int sm750_calc_pll_value(unsigned int request_orig,
if (M < 256 && M > 0) {
unsigned int diff;
- tmp_clock = pll->inputFreq * M / N / X;
+ tmp_clock = pll->input_freq * M / N / X;
diff = abs(tmp_clock - request_orig);
if (diff < mini_diff) {
pll->M = M;
@@ -383,14 +382,14 @@ unsigned int sm750_calc_pll_value(unsigned int request_orig,
return ret;
}
-unsigned int sm750_format_pll_reg(struct pll_value *pPLL)
+unsigned int sm750_format_pll_reg(struct pll_value *p_PLL)
{
#ifndef VALIDATION_CHIP
- unsigned int POD = pPLL->POD;
+ unsigned int POD = p_PLL->POD;
#endif
- unsigned int OD = pPLL->OD;
- unsigned int M = pPLL->M;
- unsigned int N = pPLL->N;
+ unsigned int OD = p_PLL->OD;
+ unsigned int M = p_PLL->M;
+ unsigned int N = p_PLL->N;
/*
* Note that all PLL's have the same format. Here, we just use
diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h
index 3e92b3297160..ee2e9d90f7dd 100644
--- a/drivers/staging/sm750fb/ddk750_chip.h
+++ b/drivers/staging/sm750fb/ddk750_chip.h
@@ -40,8 +40,8 @@ enum clock_type {
};
struct pll_value {
- enum clock_type clockType;
- unsigned long inputFreq; /* Input clock frequency to the PLL */
+ enum clock_type clock_type;
+ unsigned long input_freq; /* Input clock frequency to the PLL */
/* Use this when clockType = PANEL_PLL */
unsigned long M;
@@ -53,41 +53,41 @@ struct pll_value {
/* input struct to initChipParam() function */
struct initchip_param {
/* Use power mode 0 or 1 */
- unsigned short powerMode;
+ unsigned short power_mode;
/*
* Speed of main chip clock in MHz unit
* 0 = keep the current clock setting
* Others = the new main chip clock
*/
- unsigned short chipClock;
+ unsigned short chip_clock;
/*
* Speed of memory clock in MHz unit
* 0 = keep the current clock setting
* Others = the new memory clock
*/
- unsigned short memClock;
+ unsigned short mem_clock;
/*
* Speed of master clock in MHz unit
* 0 = keep the current clock setting
* Others = the new master clock
*/
- unsigned short masterClock;
+ unsigned short master_clock;
/*
* 0 = leave all engine state untouched.
* 1 = make sure they are off: 2D, Overlay,
* video alpha, alpha, hardware cursors
*/
- unsigned short setAllEngOff;
+ unsigned short set_all_eng_off;
/*
* 0 = Do not reset the memory controller
* 1 = Reset the memory controller
*/
- unsigned char resetMemory;
+ unsigned char reset_memory;
/* More initialization parameter can be added if needed */
};
@@ -95,7 +95,7 @@ struct initchip_param {
enum logical_chip_type sm750_get_chip_type(void);
void sm750_set_chip_type(unsigned short dev_id, u8 rev_id);
unsigned int sm750_calc_pll_value(unsigned int request, struct pll_value *pll);
-unsigned int sm750_format_pll_reg(struct pll_value *pPLL);
+unsigned int sm750_format_pll_reg(struct pll_value *p_PLL);
unsigned int ddk750_get_vm_size(void);
int ddk750_init_hw(struct initchip_param *pinit_param);
diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c
index 887ea8aef43f..172624ff98b0 100644
--- a/drivers/staging/sm750fb/ddk750_display.c
+++ b/drivers/staging/sm750fb/ddk750_display.c
@@ -147,8 +147,8 @@ void ddk750_set_logical_disp_out(enum disp_output output)
if (output & PNL_SEQ_USAGE) {
/* set panel sequence */
- sw_panel_power_sequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET,
- 4);
+ sw_panel_power_sequence((output & PNL_SEQ_MASK) >>
+ PNL_SEQ_OFFSET, 4);
}
if (output & DAC_USAGE)
diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c
index 4dac691ad1b1..e00a6cb31947 100644
--- a/drivers/staging/sm750fb/ddk750_mode.c
+++ b/drivers/staging/sm750fb/ddk750_mode.c
@@ -13,8 +13,9 @@
* HW only supports 7 predefined pixel clocks, and clock select is
* in bit 29:27 of Display Control register.
*/
-static unsigned long displayControlAdjust_SM750LE(struct mode_parameter *pModeParam,
- unsigned long dispControl)
+static unsigned long
+displayControlAdjust_SM750LE(struct mode_parameter *pModeParam,
+ unsigned long dispControl)
{
unsigned long x, y;
@@ -81,7 +82,7 @@ static int programModeRegisters(struct mode_parameter *pModeParam,
int cnt = 0;
unsigned int tmp, reg;
- if (pll->clockType == SECONDARY_PLL) {
+ if (pll->clock_type == SECONDARY_PLL) {
/* programe secondary pixel clock */
poke32(CRT_PLL_CTRL, sm750_format_pll_reg(pll));
@@ -134,7 +135,7 @@ static int programModeRegisters(struct mode_parameter *pModeParam,
poke32(CRT_DISPLAY_CTRL, tmp | reg);
}
- } else if (pll->clockType == PRIMARY_PLL) {
+ } else if (pll->clock_type == PRIMARY_PLL) {
unsigned int reserved;
poke32(PANEL_PLL_CTRL, sm750_format_pll_reg(pll));
@@ -209,12 +210,11 @@ static int programModeRegisters(struct mode_parameter *pModeParam,
int ddk750_setModeTiming(struct mode_parameter *parm, enum clock_type clock)
{
struct pll_value pll;
- unsigned int uiActualPixelClk;
- pll.inputFreq = DEFAULT_INPUT_CLOCK;
- pll.clockType = clock;
+ pll.input_freq = DEFAULT_INPUT_CLOCK;
+ pll.clock_type = clock;
- uiActualPixelClk = sm750_calc_pll_value(parm->pixel_clock, &pll);
+ sm750_calc_pll_value(parm->pixel_clock, &pll);
if (sm750_get_chip_type() == SM750LE) {
/* set graphic mode via IO method */
outb_p(0x88, 0x3d4);
diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c
index c8e856c13912..73e0e9f41ec5 100644
--- a/drivers/staging/sm750fb/ddk750_sii164.c
+++ b/drivers/staging/sm750fb/ddk750_sii164.c
@@ -39,8 +39,10 @@ unsigned short sii164GetVendorID(void)
{
unsigned short vendorID;
- vendorID = ((unsigned short)i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
- (unsigned short)i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
+ vendorID = ((unsigned short)i2cReadReg(SII164_I2C_ADDRESS,
+ SII164_VENDOR_ID_HIGH) << 8) |
+ (unsigned short)i2cReadReg(SII164_I2C_ADDRESS,
+ SII164_VENDOR_ID_LOW);
return vendorID;
}
@@ -56,13 +58,18 @@ unsigned short sii164GetDeviceID(void)
{
unsigned short deviceID;
- deviceID = ((unsigned short)i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
- (unsigned short)i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
+ deviceID = ((unsigned short)i2cReadReg(SII164_I2C_ADDRESS,
+ SII164_DEVICE_ID_HIGH) << 8) |
+ (unsigned short)i2cReadReg(SII164_I2C_ADDRESS,
+ SII164_DEVICE_ID_LOW);
return deviceID;
}
-/* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
+/*
+ * DVI.C will handle all SiI164 chip stuffs and try its best to make code
+ * minimal and useful
+ */
/*
* sii164InitChip
@@ -133,7 +140,8 @@ long sii164InitChip(unsigned char edge_select,
#endif
/* Check if SII164 Chip exists */
- if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
+ if ((sii164GetVendorID() == SII164_VENDOR_ID) &&
+ (sii164GetDeviceID() == SII164_DEVICE_ID)) {
/*
* Initialize SII164 controller chip.
*/
@@ -254,7 +262,9 @@ void sii164ResetChip(void)
/*
* sii164GetChipString
- * This function returns a char string name of the current DVI Controller chip.
+ * This function returns a char string name of the current DVI Controller
+ * chip.
+ *
* It's convenient for application need to display the chip name.
*/
char *sii164GetChipString(void)
@@ -330,8 +340,8 @@ void sii164EnableHotPlugDetection(unsigned char enableHotPlug)
detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
- /* Depending on each DVI controller, need to enable the hot plug based on each
- * individual chip design.
+ /* Depending on each DVI controller, need to enable the hot plug based
+ * on each individual chip design.
*/
if (enableHotPlug != 0)
sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
diff --git a/drivers/staging/sm750fb/ddk750_sii164.h b/drivers/staging/sm750fb/ddk750_sii164.h
index 862e7bf27353..d940cb729066 100644
--- a/drivers/staging/sm750fb/ddk750_sii164.h
+++ b/drivers/staging/sm750fb/ddk750_sii164.h
@@ -6,10 +6,13 @@
/* Hot Plug detection mode structure */
enum sii164_hot_plug_mode {
- SII164_HOTPLUG_DISABLE = 0, /* Disable Hot Plug output bit (always high). */
- SII164_HOTPLUG_USE_MDI, /* Use Monitor Detect Interrupt bit. */
- SII164_HOTPLUG_USE_RSEN, /* Use Receiver Sense detect bit. */
- SII164_HOTPLUG_USE_HTPLG /* Use Hot Plug detect bit. */
+ SII164_HOTPLUG_DISABLE = 0, /* Disable Hot Plug output bit
+ * (always high).
+ */
+
+ SII164_HOTPLUG_USE_MDI, /* Use Monitor Detect Interrupt bit. */
+ SII164_HOTPLUG_USE_RSEN, /* Use Receiver Sense detect bit. */
+ SII164_HOTPLUG_USE_HTPLG /* Use Hot Plug detect bit. */
};
/* Silicon Image SiI164 chip prototype */
diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c
index dbcbbd1055da..8faa601c700b 100644
--- a/drivers/staging/sm750fb/sm750_accel.c
+++ b/drivers/staging/sm750fb/sm750_accel.c
@@ -130,20 +130,28 @@ int sm750_hw_fillrect(struct lynx_accel *accel,
return 0;
}
-int sm750_hw_copyarea(
-struct lynx_accel *accel,
-unsigned int sBase, /* Address of source: offset in frame buffer */
-unsigned int sPitch, /* Pitch value of source surface in BYTE */
-unsigned int sx,
-unsigned int sy, /* Starting coordinate of source surface */
-unsigned int dBase, /* Address of destination: offset in frame buffer */
-unsigned int dPitch, /* Pitch value of destination surface in BYTE */
-unsigned int Bpp, /* Color depth of destination surface */
-unsigned int dx,
-unsigned int dy, /* Starting coordinate of destination surface */
-unsigned int width,
-unsigned int height, /* width and height of rectangle in pixel value */
-unsigned int rop2) /* ROP value */
+/**
+ * sm750_hm_copyarea
+ * @sBase: Address of source: offset in frame buffer
+ * @sPitch: Pitch value of source surface in BYTE
+ * @sx: Starting x coordinate of source surface
+ * @sy: Starting y coordinate of source surface
+ * @dBase: Address of destination: offset in frame buffer
+ * @dPitch: Pitch value of destination surface in BYTE
+ * @Bpp: Color depth of destination surface
+ * @dx: Starting x coordinate of destination surface
+ * @dy: Starting y coordinate of destination surface
+ * @width: width of rectangle in pixel value
+ * @height: height of rectangle in pixel value
+ * @rop2: ROP value
+ */
+int sm750_hw_copyarea(struct lynx_accel *accel,
+ unsigned int sBase, unsigned int sPitch,
+ unsigned int sx, unsigned int sy,
+ unsigned int dBase, unsigned int dPitch,
+ unsigned int Bpp, unsigned int dx, unsigned int dy,
+ unsigned int width, unsigned int height,
+ unsigned int rop2)
{
unsigned int nDirection, de_ctrl;
@@ -216,7 +224,7 @@ unsigned int rop2) /* ROP value */
/*
* Note:
- * DE_FOREGROUND are DE_BACKGROUND are don't care.
+ * DE_FOREGROUND and DE_BACKGROUND are don't care.
* DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS
* are set by set deSetTransparency().
*/
@@ -235,21 +243,21 @@ unsigned int rop2) /* ROP value */
*/
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.
- */
+ /*
+ * 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.
+ */
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.
- */
+ /*
+ * Screen Window width in Pixels.
+ * 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) |
@@ -288,20 +296,28 @@ static unsigned int deGetTransparency(struct lynx_accel *accel)
return de_ctrl;
}
-int sm750_hw_imageblit(struct lynx_accel *accel,
- const char *pSrcbuf, /* pointer to start of source buffer in system memory */
- u32 srcDelta, /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
- u32 startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
- u32 dBase, /* Address of destination: offset in frame buffer */
- u32 dPitch, /* Pitch value of destination surface in BYTE */
- u32 bytePerPixel, /* Color depth of destination surface */
- u32 dx,
- u32 dy, /* Starting coordinate of destination surface */
- u32 width,
- u32 height, /* width and height of rectangle in pixel value */
- u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */
- u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */
- u32 rop2) /* ROP value */
+/**
+ * sm750_hw_imageblit
+ * @pSrcbuf: pointer to start of source buffer in system memory
+ * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top down
+ * and -ive mean button up
+ * @startBit: Mono data can start at any bit in a byte, this value should be
+ * 0 to 7
+ * @dBase: Address of destination: offset in frame buffer
+ * @dPitch: Pitch value of destination surface in BYTE
+ * @bytePerPixel: Color depth of destination surface
+ * @dx: Starting x coordinate of destination surface
+ * @dy: Starting y coordinate of destination surface
+ * @width: width of rectangle in pixel value
+ * @height: height of rectangle in pixel value
+ * @fColor: Foreground color (corresponding to a 1 in the monochrome data
+ * @bColor: Background color (corresponding to a 0 in the monochrome data
+ * @rop2: ROP value
+ */
+int sm750_hw_imageblit(struct lynx_accel *accel, const char *pSrcbuf,
+ u32 srcDelta, u32 startBit, u32 dBase, u32 dPitch,
+ u32 bytePerPixel, u32 dx, u32 dy, u32 width,
+ u32 height, u32 fColor, u32 bColor, u32 rop2)
{
unsigned int ulBytesPerScan;
unsigned int ul4BytesPerScan;
diff --git a/drivers/staging/sm750fb/sm750_accel.h b/drivers/staging/sm750fb/sm750_accel.h
index c4f42002a50f..2c79cb730a0a 100644
--- a/drivers/staging/sm750fb/sm750_accel.h
+++ b/drivers/staging/sm750fb/sm750_accel.h
@@ -190,37 +190,54 @@ void sm750_hw_set2dformat(struct lynx_accel *accel, int fmt);
void sm750_hw_de_init(struct lynx_accel *accel);
int sm750_hw_fillrect(struct lynx_accel *accel,
- u32 base, u32 pitch, u32 Bpp,
- u32 x, u32 y, u32 width, u32 height,
- u32 color, u32 rop);
-
-int sm750_hw_copyarea(
-struct lynx_accel *accel,
-unsigned int sBase, /* Address of source: offset in frame buffer */
-unsigned int sPitch, /* Pitch value of source surface in BYTE */
-unsigned int sx,
-unsigned int sy, /* Starting coordinate of source surface */
-unsigned int dBase, /* Address of destination: offset in frame buffer */
-unsigned int dPitch, /* Pitch value of destination surface in BYTE */
-unsigned int bpp, /* Color depth of destination surface */
-unsigned int dx,
-unsigned int dy, /* Starting coordinate of destination surface */
-unsigned int width,
-unsigned int height, /* width and height of rectangle in pixel value */
-unsigned int rop2);
-
-int sm750_hw_imageblit(struct lynx_accel *accel,
- const char *pSrcbuf, /* pointer to start of source buffer in system memory */
- u32 srcDelta, /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
- u32 startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
- u32 dBase, /* Address of destination: offset in frame buffer */
- u32 dPitch, /* Pitch value of destination surface in BYTE */
- u32 bytePerPixel, /* Color depth of destination surface */
- u32 dx,
- u32 dy, /* Starting coordinate of destination surface */
- u32 width,
- u32 height, /* width and height of rectangle in pixel value */
- u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */
- u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */
- u32 rop2);
+ u32 base, u32 pitch, u32 Bpp,
+ u32 x, u32 y, u32 width, u32 height,
+ u32 color, u32 rop);
+
+/**
+ * sm750_hm_copyarea
+ * @sBase: Address of source: offset in frame buffer
+ * @sPitch: Pitch value of source surface in BYTE
+ * @sx: Starting x coordinate of source surface
+ * @sy: Starting y coordinate of source surface
+ * @dBase: Address of destination: offset in frame buffer
+ * @dPitch: Pitch value of destination surface in BYTE
+ * @Bpp: Color depth of destination surface
+ * @dx: Starting x coordinate of destination surface
+ * @dy: Starting y coordinate of destination surface
+ * @width: width of rectangle in pixel value
+ * @height: height of rectangle in pixel value
+ * @rop2: ROP value
+ */
+int sm750_hw_copyarea(struct lynx_accel *accel,
+ unsigned int sBase, unsigned int sPitch,
+ unsigned int sx, unsigned int sy,
+ unsigned int dBase, unsigned int dPitch,
+ unsigned int Bpp, unsigned int dx, unsigned int dy,
+ unsigned int width, unsigned int height,
+ unsigned int rop2);
+
+/**
+ * sm750_hw_imageblit
+ * @pSrcbuf: pointer to start of source buffer in system memory
+ * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top down
+ *>----- and -ive mean button up
+ * @startBit: Mono data can start at any bit in a byte, this value should be
+ *>----- 0 to 7
+ * @dBase: Address of destination: offset in frame buffer
+ * @dPitch: Pitch value of destination surface in BYTE
+ * @bytePerPixel: Color depth of destination surface
+ * @dx: Starting x coordinate of destination surface
+ * @dy: Starting y coordinate of destination surface
+ * @width: width of rectangle in pixel value
+ * @height: height of rectangle in pixel value
+ * @fColor: Foreground color (corresponding to a 1 in the monochrome data
+ * @bColor: Background color (corresponding to a 0 in the monochrome data
+ * @rop2: ROP value
+ */
+int sm750_hw_imageblit(struct lynx_accel *accel, const char *pSrcbuf,
+ u32 srcDelta, u32 startBit, u32 dBase, u32 dPitch,
+ u32 bytePerPixel, u32 dx, u32 dy, u32 width,
+ u32 height, u32 fColor, u32 bColor, u32 rop2);
+
#endif
diff --git a/drivers/staging/sm750fb/sm750_cursor.h b/drivers/staging/sm750fb/sm750_cursor.h
index 16ac07eb58d6..b59643dd61ed 100644
--- a/drivers/staging/sm750fb/sm750_cursor.h
+++ b/drivers/staging/sm750fb/sm750_cursor.h
@@ -5,14 +5,11 @@
/* hw_cursor_xxx works for voyager,718 and 750 */
void sm750_hw_cursor_enable(struct lynx_cursor *cursor);
void sm750_hw_cursor_disable(struct lynx_cursor *cursor);
-void sm750_hw_cursor_setSize(struct lynx_cursor *cursor,
- int w, int h);
-void sm750_hw_cursor_setPos(struct lynx_cursor *cursor,
- int x, int y);
-void sm750_hw_cursor_setColor(struct lynx_cursor *cursor,
- u32 fg, u32 bg);
-void sm750_hw_cursor_setData(struct lynx_cursor *cursor,
- u16 rop, const u8 *data, const u8 *mask);
-void sm750_hw_cursor_setData2(struct lynx_cursor *cursor,
- u16 rop, const u8 *data, const u8 *mask);
+void sm750_hw_cursor_setSize(struct lynx_cursor *cursor, int w, int h);
+void sm750_hw_cursor_setPos(struct lynx_cursor *cursor, int x, int y);
+void sm750_hw_cursor_setColor(struct lynx_cursor *cursor, u32 fg, u32 bg);
+void sm750_hw_cursor_setData(struct lynx_cursor *cursor, u16 rop,
+ const u8 *data, const u8 *mask);
+void sm750_hw_cursor_setData2(struct lynx_cursor *cursor, u16 rop,
+ const u8 *data, const u8 *mask);
#endif
diff --git a/drivers/staging/uwb/rsv.c b/drivers/staging/uwb/rsv.c
index f45a04ff7275..d593a41c3d8d 100644
--- a/drivers/staging/uwb/rsv.c
+++ b/drivers/staging/uwb/rsv.c
@@ -614,7 +614,7 @@ int uwb_rsv_try_move(struct uwb_rsv *rsv, struct uwb_mas_bm *available)
struct uwb_rsv_move *mv;
int ret = 0;
- if (bow->can_reserve_extra_mases == false)
+ if (!bow->can_reserve_extra_mases)
return -EBUSY;
mv = &rsv->mv;
@@ -643,7 +643,7 @@ void uwb_rsv_handle_drp_avail_change(struct uwb_rc *rc)
struct uwb_rsv *rsv;
struct uwb_mas_bm mas;
- if (bow->can_reserve_extra_mases == false)
+ if (!bow->can_reserve_extra_mases)
return;
list_for_each_entry(rsv, &rc->reservations, rc_node) {
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
index c6f9cf1913d2..73144f1ce45e 100644
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
@@ -9,7 +9,7 @@
struct bcm2835_audio_instance {
struct device *dev;
- VCHI_SERVICE_HANDLE_T vchi_handle;
+ struct vchi_service_handle *vchi_handle;
struct completion msg_avail_comp;
struct mutex vchi_mutex;
struct bcm2835_alsa_stream *alsa_stream;
@@ -90,7 +90,7 @@ static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
}
static void audio_vchi_callback(void *param,
- const VCHI_CALLBACK_REASON_T reason,
+ const enum vchi_callback_reason reason,
void *msg_handle)
{
struct bcm2835_audio_instance *instance = param;
@@ -103,6 +103,9 @@ static void audio_vchi_callback(void *param,
status = vchi_msg_dequeue(instance->vchi_handle,
&m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
+ if (status)
+ return;
+
if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
instance->result = m.result.success;
complete(&instance->msg_avail_comp);
@@ -119,7 +122,7 @@ static void audio_vchi_callback(void *param,
}
static int
-vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
+vc_vchi_audio_init(struct vchi_instance_handle *vchi_instance,
struct bcm2835_audio_instance *instance)
{
struct service_creation params = {
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
index ed0feb34b6c8..d2fe8d36ab7d 100644
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
@@ -44,7 +44,7 @@ enum snd_bcm2835_ctrl {
};
struct bcm2835_vchi_ctx {
- VCHI_INSTANCE_T vchi_instance;
+ struct vchi_instance_handle *vchi_instance;
};
/* definition of the chip-specific record */
diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
index d4d1e44b16b2..beb6a0063bb8 100644
--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
@@ -1090,8 +1090,8 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
- if (!ret
- && camera_port ==
+ if (!ret &&
+ camera_port ==
&dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO]) {
bool overlay_enabled =
!!dev->component[COMP_PREVIEW]->enabled;
diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
index 1c180ead4a20..de03b90021a8 100644
--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
@@ -155,7 +155,7 @@ struct mmal_msg_context {
};
struct vchiq_mmal_instance {
- VCHI_SERVICE_HANDLE_T handle;
+ struct vchi_service_handle *handle;
/* ensure serialised access to service */
struct mutex vchiq_mutex;
@@ -535,7 +535,7 @@ static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
/* incoming event service callback */
static void service_callback(void *param,
- const VCHI_CALLBACK_REASON_T reason,
+ const enum vchi_callback_reason reason,
void *bulk_ctx)
{
struct vchiq_mmal_instance *instance = param;
@@ -1814,7 +1814,7 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
{
int status;
struct vchiq_mmal_instance *instance;
- static VCHI_INSTANCE_T vchi_instance;
+ static struct vchi_instance_handle *vchi_instance;
struct service_creation params = {
.version = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
.service_id = VC_MMAL_SERVER_NAME,
diff --git a/drivers/staging/vc04_services/interface/vchi/vchi.h b/drivers/staging/vc04_services/interface/vchi/vchi.h
index f85562b9ba9e..56b1037d8e25 100644
--- a/drivers/staging/vc04_services/interface/vchi/vchi.h
+++ b/drivers/staging/vc04_services/interface/vchi/vchi.h
@@ -8,17 +8,17 @@
#include "interface/vchi/vchi_common.h"
/******************************************************************************
- Global defs
+ * 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))))
+#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)
+#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN - 1)) == 0)
#endif
struct vchi_version {
@@ -45,18 +45,19 @@ struct vchi_held_msg {
struct service_creation {
struct vchi_version version;
int32_t service_id;
- VCHI_CALLBACK_T callback;
+ vchi_callback callback;
void *callback_param;
};
// Opaque handle for a VCHI instance
-typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T;
+struct vchi_instance_handle;
// Opaque handle for a server or client
-typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T;
+struct vchi_service_handle;
/******************************************************************************
- Global funcs - implementation is specific to which side you are on (local / remote)
+ * Global funcs - implementation is specific to which side you are on
+ * (local / remote)
*****************************************************************************/
#ifdef __cplusplus
@@ -64,98 +65,99 @@ extern "C" {
#endif
// 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_initialise(struct vchi_instance_handle **instance_handle);
extern int32_t vchi_exit(void);
-extern int32_t vchi_connect(VCHI_INSTANCE_T instance_handle);
+extern int32_t vchi_connect(struct vchi_instance_handle *instance_handle);
//When this is called, ensure that all services have no data pending.
//Bulk transfers can remain 'queued'
-extern int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle);
+extern int32_t vchi_disconnect(struct vchi_instance_handle *instance_handle);
// 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);
+extern void *vchi_allocate_buffer(struct vchi_service_handle *handle, uint32_t *length);
+extern void vchi_free_buffer(struct vchi_service_handle *handle, void *address);
+extern uint32_t vchi_current_time(struct vchi_instance_handle *instance_handle);
/******************************************************************************
- Global service API
+ * Global service API
*****************************************************************************/
// Routine to destroy a service
-extern int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle);
+extern int32_t vchi_service_destroy(const struct vchi_service_handle *handle);
// Routine to open a named service
-extern int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
+extern int32_t vchi_service_open(struct vchi_instance_handle *instance_handle,
struct service_creation *setup,
- VCHI_SERVICE_HANDLE_T *handle);
+ struct vchi_service_handle **handle);
-extern int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T handle,
+extern int32_t vchi_get_peer_version(const struct vchi_service_handle *handle,
short *peer_version);
// Routine to close a named service
-extern int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle);
+extern int32_t vchi_service_close(const struct vchi_service_handle *handle);
// Routine to increment ref count on a named service
-extern int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle);
+extern int32_t vchi_service_use(const struct vchi_service_handle *handle);
// Routine to decrement ref count on a named service
-extern int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle);
+extern int32_t vchi_service_release(const struct vchi_service_handle *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);
+extern int32_t vchi_service_set_option(const struct vchi_service_handle *handle,
+ enum vchi_service_option option,
+ int value);
/* Routine to send a message from kernel memory across a service */
extern int
-vchi_queue_kernel_message(VCHI_SERVICE_HANDLE_T handle,
+vchi_queue_kernel_message(struct vchi_service_handle *handle,
void *data,
unsigned int size);
/* Routine to send a message from user memory across a service */
extern int
-vchi_queue_user_message(VCHI_SERVICE_HANDLE_T handle,
+vchi_queue_user_message(struct vchi_service_handle *handle,
void __user *data,
unsigned int size);
// Routine to receive a msg from a service
// Dequeue is equivalent to hold, copy into client buffer, release
-extern int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle,
+extern int32_t vchi_msg_dequeue(struct vchi_service_handle *handle,
void *data,
uint32_t max_data_size_to_read,
uint32_t *actual_msg_size,
- VCHI_FLAGS_T flags);
+ enum vchi_flags flags);
// Routine to look at a message in place.
// The message is not dequeued, so a subsequent call to peek or dequeue
// will return the same message.
-extern int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle,
+extern int32_t vchi_msg_peek(struct vchi_service_handle *handle,
void **data,
uint32_t *msg_size,
- VCHI_FLAGS_T flags);
+ enum vchi_flags flags);
// Routine to remove a message after it has been read in place with peek
// The first message on the queue is dequeued.
-extern int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle);
+extern int32_t vchi_msg_remove(struct vchi_service_handle *handle);
// Routine to look at a message in place.
// The message is dequeued, so the caller is left holding it; the descriptor is
// filled in and must be released when the user has finished with the message.
-extern int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,
+extern int32_t vchi_msg_hold(struct vchi_service_handle *handle,
void **data, // } may be NULL, as info can be
uint32_t *msg_size, // } obtained from HELD_MSG_T
- VCHI_FLAGS_T flags,
+ enum vchi_flags flags,
struct vchi_held_msg *message_descriptor);
// Initialise an iterator to look through messages in place
-extern int32_t vchi_msg_look_ahead(VCHI_SERVICE_HANDLE_T handle,
+extern int32_t vchi_msg_look_ahead(struct vchi_service_handle *handle,
struct vchi_msg_iter *iter,
- VCHI_FLAGS_T flags);
+ enum vchi_flags flags);
-/******************************************************************************
- Global service support API - operations on held messages and message iterators
- *****************************************************************************/
+/*******************************************************************************
+ * 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 struct vchi_held_msg *message);
@@ -196,42 +198,42 @@ extern int32_t vchi_msg_iter_hold_next(struct vchi_msg_iter *iter,
struct vchi_held_msg *message);
/******************************************************************************
- Global bulk API
+ * 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,
+extern int32_t vchi_bulk_queue_receive(struct vchi_service_handle *handle,
void *data_dst,
uint32_t data_size,
- VCHI_FLAGS_T flags,
+ enum vchi_flags 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,
+int32_t vchi_bulk_queue_receive_reloc(const struct vchi_service_handle *handle,
uint32_t offset,
uint32_t data_size,
- const VCHI_FLAGS_T flags,
+ const enum vchi_flags 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,
+extern int32_t vchi_bulk_queue_transmit(struct vchi_service_handle *handle,
const void *data_src,
uint32_t data_size,
- VCHI_FLAGS_T flags,
+ enum vchi_flags flags,
void *transfer_handle);
/******************************************************************************
- Configuration plumbing
+ * Configuration plumbing
*****************************************************************************/
#ifdef __cplusplus
}
#endif
-extern int32_t vchi_bulk_queue_transmit_reloc(VCHI_SERVICE_HANDLE_T handle,
+extern int32_t vchi_bulk_queue_transmit_reloc(struct vchi_service_handle *handle,
uint32_t offset,
uint32_t data_size,
- VCHI_FLAGS_T flags,
+ enum vchi_flags flags,
void *transfer_handle);
#endif /* VCHI_H_ */
diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h b/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h
index 89aa4e6122cd..138c36151a22 100644
--- a/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h
+++ b/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h
@@ -4,13 +4,17 @@
#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. */
+/*******************************************************************************
+ * 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
@@ -19,9 +23,13 @@
# 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. */
+/*
+ * 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
@@ -39,19 +47,24 @@
# endif
#endif
-/******************************************************************************************
- * Defines below are system configuration options, and should not be used by VCHI services.
- *****************************************************************************************/
+/******************************************************************************
+ * 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. */
+/*
+ * 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. */
+/*
+ * 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
@@ -66,8 +79,10 @@
# 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. */
+/*
+ * 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
@@ -76,112 +91,141 @@
# endif
#endif
-/* Do we utilise overrun facility for receive message slots? Can aid peer transmit
- * performance. Only define on VideoCore end, talking to host.
+/*
+ * 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. */
+/*
+ * 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. */
+/*
+ * 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. */
+/*
+ * 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. */
+/*
+ * 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.
+/*
+ * 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. */
+/*
+ * 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. */
+/*
+ * 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. */
+/*
+ * 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
+/*
+ * 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)
+# 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. */
+/*
+ * 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. */
+/*
+ * 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. */
+/*
+ * 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
+/*
+ * 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.
+/*
+ * 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.
+/*
+ * 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
diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_common.h b/drivers/staging/vc04_services/interface/vchi/vchi_common.h
index e7955cbaf26a..141af16ce031 100644
--- a/drivers/staging/vc04_services/interface/vchi/vchi_common.h
+++ b/drivers/staging/vc04_services/interface/vchi/vchi_common.h
@@ -5,7 +5,7 @@
#define VCHI_COMMON_H_
//flags used when sending messages (must be bitmapped)
-typedef enum {
+enum vchi_flags {
VCHI_FLAGS_NONE = 0x0,
VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side)
VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent
@@ -20,17 +20,17 @@ typedef enum {
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 {
+enum vchi_crc_control {
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 {
+enum vchi_callback_reason {
VCHI_CALLBACK_REASON_MIN,
//This indicates that there is data available
@@ -73,22 +73,22 @@ typedef enum {
VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
VCHI_CALLBACK_REASON_MAX
-} VCHI_CALLBACK_REASON_T;
+};
// service control options
-typedef enum {
+enum vchi_service_option {
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
+typedef void (*vchi_callback)(void *callback_param, //my service local param
+ enum vchi_callback_reason reason,
+ void *handle); //for transmitting msg's only
/*
* Define vector struct for scatter-gather (vector) operations
@@ -112,12 +112,6 @@ struct vchi_msg_vector {
int32_t vec_len;
};
-// 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 -
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
index 8dc730cfe7a6..e568e9e6eb95 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
@@ -81,7 +81,6 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev);
struct rpi_firmware *fw = drvdata->fw;
struct vchiq_slot_zero *vchiq_slot_zero;
- struct resource *res;
void *slot_mem;
dma_addr_t slot_phys;
u32 channelbase;
@@ -135,8 +134,7 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
if (vchiq_init_state(state, vchiq_slot_zero) != VCHIQ_SUCCESS)
return -EINVAL;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- g_regs = devm_ioremap_resource(&pdev->dev, res);
+ g_regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(g_regs))
return PTR_ERR(g_regs);
@@ -170,10 +168,10 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
return 0;
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_platform_init_state(struct vchiq_state *state)
{
- VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
+ enum vchiq_status status = VCHIQ_SUCCESS;
struct vchiq_2835_state *platform_state;
state->platform_state = kzalloc(sizeof(*platform_state), GFP_KERNEL);
@@ -216,7 +214,7 @@ remote_event_signal(struct remote_event *event)
writel(0, g_regs + BELL2); /* trigger vc interrupt */
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, int size,
int dir)
{
@@ -260,13 +258,13 @@ vchiq_dump_platform_state(void *dump_context)
vchiq_dump(dump_context, buf, len + 1);
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_platform_suspend(struct vchiq_state *state)
{
return VCHIQ_ERROR;
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_platform_resume(struct vchiq_state *state)
{
return VCHIQ_SUCCESS;
@@ -526,11 +524,11 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
return NULL;
}
- WARN_ON(g_free_fragments == NULL);
+ WARN_ON(!g_free_fragments);
down(&g_free_fragments_mutex);
fragments = g_free_fragments;
- WARN_ON(fragments == NULL);
+ WARN_ON(!fragments);
g_free_fragments = *(char **) g_free_fragments;
up(&g_free_fragments_mutex);
pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index b1595b13dea8..be8b2a71da2d 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -84,7 +84,7 @@ static void suspend_timer_callback(struct timer_list *t);
struct user_service {
struct vchiq_service *service;
void *userdata;
- VCHIQ_INSTANCE_T instance;
+ struct vchiq_instance *instance;
char is_vchi;
char dequeue_pending;
char close_pending;
@@ -103,7 +103,7 @@ struct bulk_waiter_node {
struct list_head list;
};
-struct vchiq_instance_struct {
+struct vchiq_instance {
struct vchiq_state *state;
struct vchiq_completion_data completions[MAX_COMPLETIONS];
int completion_insert;
@@ -172,16 +172,16 @@ static const char *const ioctl_names[] = {
vchiq_static_assert(ARRAY_SIZE(ioctl_names) ==
(VCHIQ_IOC_MAX + 1));
-static VCHIQ_STATUS_T
-vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
- unsigned int size, VCHIQ_BULK_DIR_T dir);
+static enum vchiq_status
+vchiq_blocking_bulk_transfer(unsigned int handle, void *data,
+ unsigned int size, enum vchiq_bulk_dir dir);
#define VCHIQ_INIT_RETRIES 10
-VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out)
+enum vchiq_status vchiq_initialise(struct vchiq_instance **instance_out)
{
- VCHIQ_STATUS_T status = VCHIQ_ERROR;
+ enum vchiq_status status = VCHIQ_ERROR;
struct vchiq_state *state;
- VCHIQ_INSTANCE_T instance = NULL;
+ struct vchiq_instance *instance = NULL;
int i;
vchiq_log_trace(vchiq_core_log_level, "%s called", __func__);
@@ -230,9 +230,9 @@ failed:
}
EXPORT_SYMBOL(vchiq_initialise);
-VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
+enum vchiq_status vchiq_shutdown(struct vchiq_instance *instance)
{
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
struct vchiq_state *state = instance->state;
vchiq_log_trace(vchiq_core_log_level,
@@ -267,14 +267,14 @@ VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
}
EXPORT_SYMBOL(vchiq_shutdown);
-static int vchiq_is_connected(VCHIQ_INSTANCE_T instance)
+static int vchiq_is_connected(struct vchiq_instance *instance)
{
return instance->connected;
}
-VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance)
+enum vchiq_status vchiq_connect(struct vchiq_instance *instance)
{
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
struct vchiq_state *state = instance->state;
vchiq_log_trace(vchiq_core_log_level,
@@ -301,12 +301,12 @@ failed:
}
EXPORT_SYMBOL(vchiq_connect);
-VCHIQ_STATUS_T vchiq_add_service(
- VCHIQ_INSTANCE_T instance,
+enum vchiq_status vchiq_add_service(
+ struct vchiq_instance *instance,
const struct vchiq_service_params *params,
- VCHIQ_SERVICE_HANDLE_T *phandle)
+ unsigned int *phandle)
{
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
struct vchiq_state *state = instance->state;
struct vchiq_service *service = NULL;
int srvstate;
@@ -340,12 +340,12 @@ VCHIQ_STATUS_T vchiq_add_service(
}
EXPORT_SYMBOL(vchiq_add_service);
-VCHIQ_STATUS_T vchiq_open_service(
- VCHIQ_INSTANCE_T instance,
+enum vchiq_status vchiq_open_service(
+ struct vchiq_instance *instance,
const struct vchiq_service_params *params,
- VCHIQ_SERVICE_HANDLE_T *phandle)
+ unsigned int *phandle)
{
- VCHIQ_STATUS_T status = VCHIQ_ERROR;
+ enum vchiq_status status = VCHIQ_ERROR;
struct vchiq_state *state = instance->state;
struct vchiq_service *service = NULL;
@@ -380,11 +380,11 @@ failed:
}
EXPORT_SYMBOL(vchiq_open_service);
-VCHIQ_STATUS_T
-vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data,
- unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
+enum vchiq_status
+vchiq_bulk_transmit(unsigned int handle, const void *data,
+ unsigned int size, void *userdata, enum vchiq_bulk_mode mode)
{
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
switch (mode) {
case VCHIQ_BULK_MODE_NOCALLBACK:
@@ -405,11 +405,11 @@ vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data,
}
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)
+enum vchiq_status
+vchiq_bulk_receive(unsigned int handle, void *data,
+ unsigned int size, void *userdata, enum vchiq_bulk_mode mode)
{
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
switch (mode) {
case VCHIQ_BULK_MODE_NOCALLBACK:
@@ -429,13 +429,13 @@ vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
}
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)
+static enum vchiq_status
+vchiq_blocking_bulk_transfer(unsigned int handle, void *data,
+ unsigned int size, enum vchiq_bulk_dir dir)
{
- VCHIQ_INSTANCE_T instance;
+ struct vchiq_instance *instance;
struct vchiq_service *service;
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
struct bulk_waiter_node *waiter = NULL;
service = find_service_by_handle(handle);
@@ -515,8 +515,8 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
*
***************************************************************************/
-static VCHIQ_STATUS_T
-add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
+static enum vchiq_status
+add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
struct vchiq_header *header, struct user_service *user_service,
void *bulk_userdata)
{
@@ -582,9 +582,9 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
*
***************************************************************************/
-static VCHIQ_STATUS_T
-service_callback(VCHIQ_REASON_T reason, struct vchiq_header *header,
- VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata)
+static enum vchiq_status
+service_callback(enum vchiq_reason reason, struct vchiq_header *header,
+ unsigned int handle, void *bulk_userdata)
{
/* How do we ensure the callback goes to the right client?
** The service_user data points to a user_service record
@@ -593,7 +593,7 @@ service_callback(VCHIQ_REASON_T reason, struct vchiq_header *header,
*/
struct user_service *user_service;
struct vchiq_service *service;
- VCHIQ_INSTANCE_T instance;
+ struct vchiq_instance *instance;
bool skip_completion = false;
DEBUG_INITIALISE(g_state.local)
@@ -630,7 +630,7 @@ service_callback(VCHIQ_REASON_T reason, struct vchiq_header *header,
*/
if ((user_service->message_available_pos -
instance->completion_remove) < 0) {
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
vchiq_log_info(vchiq_arm_log_level,
"Inserting extra MESSAGE_AVAILABLE");
@@ -772,8 +772,8 @@ static ssize_t vchiq_ioc_copy_element_data(void *context, void *dest,
* vchiq_ioc_queue_message
*
**************************************************************************/
-static VCHIQ_STATUS_T
-vchiq_ioc_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
+static enum vchiq_status
+vchiq_ioc_queue_message(unsigned int handle,
struct vchiq_element *elements,
unsigned long count)
{
@@ -804,8 +804,8 @@ vchiq_ioc_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
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;
+ struct vchiq_instance *instance = file->private_data;
+ enum vchiq_status status = VCHIQ_SUCCESS;
struct vchiq_service *service = NULL;
long ret = 0;
int i, rc;
@@ -827,7 +827,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* Remove all services */
i = 0;
while ((service = next_service_by_instance(instance->state,
- instance, &i)) != NULL) {
+ instance, &i))) {
status = vchiq_remove_service(service->handle);
unlock_service(service);
if (status != VCHIQ_SUCCESS)
@@ -907,7 +907,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
&args.params, srvstate,
instance, user_service_free);
- if (service != NULL) {
+ if (service) {
user_service->service = service;
user_service->userdata = userdata;
user_service->instance = instance;
@@ -952,7 +952,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case VCHIQ_IOC_CLOSE_SERVICE:
case VCHIQ_IOC_REMOVE_SERVICE: {
- VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
+ unsigned int handle = (unsigned int)arg;
struct user_service *user_service;
service = find_service_for_instance(instance, handle);
@@ -985,10 +985,10 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case VCHIQ_IOC_USE_SERVICE:
case VCHIQ_IOC_RELEASE_SERVICE: {
- VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
+ unsigned int handle = (unsigned int)arg;
service = find_service_for_instance(instance, handle);
- if (service != NULL) {
+ if (service) {
status = (cmd == VCHIQ_IOC_USE_SERVICE) ?
vchiq_use_service_internal(service) :
vchiq_release_service_internal(service);
@@ -1021,7 +1021,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
service = find_service_for_instance(instance, args.handle);
- if ((service != NULL) && (args.count <= MAX_ELEMENTS)) {
+ if (service && (args.count <= MAX_ELEMENTS)) {
/* Copy elements into kernel space */
struct vchiq_element elements[MAX_ELEMENTS];
@@ -1042,7 +1042,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct vchiq_queue_bulk_transfer args;
struct bulk_waiter_node *waiter = NULL;
- VCHIQ_BULK_DIR_T dir =
+ enum vchiq_bulk_dir dir =
(cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
@@ -1107,7 +1107,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
kfree(waiter);
} else {
- const VCHIQ_BULK_MODE_T mode_waiting =
+ const enum vchiq_bulk_mode mode_waiting =
VCHIQ_BULK_MODE_WAITING;
waiter->pid = current->pid;
mutex_lock(&instance->bulk_waiter_list_mutex);
@@ -1343,11 +1343,11 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
spin_unlock(&msg_queue_spinlock);
complete(&user_service->remove_event);
- if (header == NULL)
+ if (!header)
ret = -ENOTCONN;
else if (header->size <= args.bufsize) {
/* Copy to user space if msgbuf is not NULL */
- if ((args.buf == NULL) ||
+ if (!args.buf ||
(copy_to_user((void __user *)args.buf,
header->data,
header->size) == 0)) {
@@ -1368,7 +1368,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} break;
case VCHIQ_IOC_GET_CLIENT_ID: {
- VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
+ unsigned int handle = (unsigned int)arg;
ret = vchiq_get_client_id(handle);
} break;
@@ -1423,10 +1423,10 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} break;
case VCHIQ_IOC_CLOSE_DELIVERED: {
- VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
+ unsigned int handle = (unsigned int)arg;
service = find_closed_service_for_instance(instance, handle);
- if (service != NULL) {
+ if (service) {
struct user_service *user_service =
(struct user_service *)service->base.userdata;
close_delivered(user_service);
@@ -1611,7 +1611,7 @@ struct vchiq_queue_bulk_transfer32 {
compat_uptr_t data;
unsigned int size;
compat_uptr_t userdata;
- VCHIQ_BULK_MODE_T mode;
+ enum vchiq_bulk_mode mode;
};
#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 \
@@ -1666,7 +1666,7 @@ vchiq_compat_ioctl_queue_bulk(struct file *file,
}
struct vchiq_completion_data32 {
- VCHIQ_REASON_T reason;
+ enum vchiq_reason reason;
compat_uptr_t header;
compat_uptr_t service_userdata;
compat_uptr_t bulk_userdata;
@@ -1919,7 +1919,7 @@ vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static int vchiq_open(struct inode *inode, struct file *file)
{
struct vchiq_state *state = vchiq_get_state();
- VCHIQ_INSTANCE_T instance;
+ struct vchiq_instance *instance;
vchiq_log_info(vchiq_arm_log_level, "vchiq_open");
@@ -1951,7 +1951,7 @@ static int vchiq_open(struct inode *inode, struct file *file)
static int vchiq_release(struct inode *inode, struct file *file)
{
- VCHIQ_INSTANCE_T instance = file->private_data;
+ struct vchiq_instance *instance = file->private_data;
struct vchiq_state *state = vchiq_get_state();
struct vchiq_service *service;
int ret = 0;
@@ -2130,7 +2130,7 @@ vchiq_dump_platform_instances(void *dump_context)
for (i = 0; i < state->unused_service; i++) {
struct vchiq_service *service = state->services[i];
- VCHIQ_INSTANCE_T instance;
+ struct vchiq_instance *instance;
if (service && (service->base.callback == service_callback)) {
instance = service->instance;
@@ -2141,7 +2141,7 @@ vchiq_dump_platform_instances(void *dump_context)
for (i = 0; i < state->unused_service; i++) {
struct vchiq_service *service = state->services[i];
- VCHIQ_INSTANCE_T instance;
+ struct vchiq_instance *instance;
if (service && (service->base.callback == service_callback)) {
instance = service->instance;
@@ -2223,13 +2223,13 @@ struct vchiq_state *
vchiq_get_state(void)
{
- if (g_state.remote == NULL)
+ if (!g_state.remote)
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) &&
+ return (g_state.remote &&
(g_state.remote->initialised == 1)) ? &g_state : NULL;
}
@@ -2270,10 +2270,10 @@ vchiq_videocore_wanted(struct vchiq_state *state)
return 1;
}
-static VCHIQ_STATUS_T
-vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason,
+static enum vchiq_status
+vchiq_keepalive_vchiq_callback(enum vchiq_reason reason,
struct vchiq_header *header,
- VCHIQ_SERVICE_HANDLE_T service_user,
+ unsigned int service_user,
void *bulk_user)
{
vchiq_log_error(vchiq_susp_log_level,
@@ -2287,9 +2287,9 @@ vchiq_keepalive_thread_func(void *v)
struct vchiq_state *state = (struct vchiq_state *)v;
struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
- VCHIQ_STATUS_T status;
- VCHIQ_INSTANCE_T instance;
- VCHIQ_SERVICE_HANDLE_T ka_handle;
+ enum vchiq_status status;
+ struct vchiq_instance *instance;
+ unsigned int ka_handle;
struct vchiq_service_params params = {
.fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'),
@@ -2361,7 +2361,7 @@ exit:
return 0;
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_arm_init_state(struct vchiq_state *state,
struct vchiq_arm_state *arm_state)
{
@@ -2563,10 +2563,10 @@ unblock_resume(struct vchiq_arm_state *arm_state)
/* Initiate suspend via slot handler. Should be called with the write lock
* held */
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_arm_vcsuspend(struct vchiq_state *state)
{
- VCHIQ_STATUS_T status = VCHIQ_ERROR;
+ enum vchiq_status status = VCHIQ_ERROR;
struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
if (!arm_state)
@@ -2684,12 +2684,12 @@ out:
return resume;
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service,
enum USE_TYPE_E use_type)
{
struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
- VCHIQ_STATUS_T ret = VCHIQ_SUCCESS;
+ enum vchiq_status ret = VCHIQ_SUCCESS;
char entity[16];
int *entity_uc;
int local_uc, local_entity_uc;
@@ -2798,7 +2798,7 @@ vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service,
}
if (ret == VCHIQ_SUCCESS) {
- VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
+ enum vchiq_status status = VCHIQ_SUCCESS;
long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0);
while (ack_cnt && (status == VCHIQ_SUCCESS)) {
@@ -2817,11 +2817,11 @@ out:
return ret;
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service)
{
struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
- VCHIQ_STATUS_T ret = VCHIQ_SUCCESS;
+ enum vchiq_status ret = VCHIQ_SUCCESS;
char entity[16];
int *entity_uc;
@@ -2898,33 +2898,33 @@ vchiq_on_remote_release(struct vchiq_state *state)
complete(&arm_state->ka_evt);
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_use_service_internal(struct vchiq_service *service)
{
return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE);
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_release_service_internal(struct vchiq_service *service)
{
return vchiq_release_internal(service->state, service);
}
struct vchiq_debugfs_node *
-vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance)
+vchiq_instance_get_debugfs_node(struct vchiq_instance *instance)
{
return &instance->debugfs_node;
}
int
-vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance)
+vchiq_instance_get_use_count(struct vchiq_instance *instance)
{
struct vchiq_service *service;
int use_count = 0, i;
i = 0;
while ((service = next_service_by_instance(instance->state,
- instance, &i)) != NULL) {
+ instance, &i))) {
use_count += service->service_use_count;
unlock_service(service);
}
@@ -2932,26 +2932,26 @@ vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance)
}
int
-vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance)
+vchiq_instance_get_pid(struct vchiq_instance *instance)
{
return instance->pid;
}
int
-vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance)
+vchiq_instance_get_trace(struct vchiq_instance *instance)
{
return instance->trace;
}
void
-vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace)
+vchiq_instance_set_trace(struct vchiq_instance *instance, int trace)
{
struct vchiq_service *service;
int i;
i = 0;
while ((service = next_service_by_instance(instance->state,
- instance, &i)) != NULL) {
+ instance, &i))) {
service->trace = trace;
unlock_service(service);
}
@@ -2969,10 +2969,10 @@ static void suspend_timer_callback(struct timer_list *t)
vchiq_check_suspend(state);
}
-VCHIQ_STATUS_T
-vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle)
+enum vchiq_status
+vchiq_use_service(unsigned int handle)
{
- VCHIQ_STATUS_T ret = VCHIQ_ERROR;
+ enum vchiq_status ret = VCHIQ_ERROR;
struct vchiq_service *service = find_service_by_handle(handle);
if (service) {
@@ -2983,10 +2983,10 @@ vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle)
return ret;
}
-VCHIQ_STATUS_T
-vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle)
+enum vchiq_status
+vchiq_release_service(unsigned int handle)
{
- VCHIQ_STATUS_T ret = VCHIQ_ERROR;
+ enum vchiq_status ret = VCHIQ_ERROR;
struct vchiq_service *service = find_service_by_handle(handle);
if (service) {
@@ -3088,11 +3088,11 @@ vchiq_dump_service_use_state(struct vchiq_state *state)
vchiq_dump_platform_use_state(state);
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_check_service(struct vchiq_service *service)
{
struct vchiq_arm_state *arm_state;
- VCHIQ_STATUS_T ret = VCHIQ_ERROR;
+ enum vchiq_status ret = VCHIQ_ERROR;
if (!service || !service->state)
goto out;
@@ -3128,8 +3128,8 @@ void vchiq_on_remote_use_active(struct vchiq_state *state)
}
void vchiq_platform_conn_state_changed(struct vchiq_state *state,
- VCHIQ_CONNSTATE_T oldstate,
- VCHIQ_CONNSTATE_T newstate)
+ enum vchiq_connstate oldstate,
+ enum vchiq_connstate newstate)
{
struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
index b424323e9613..19d2a2eefb6a 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
@@ -109,13 +109,13 @@ int vchiq_platform_init(struct platform_device *pdev,
extern struct vchiq_state *
vchiq_get_state(void);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_arm_vcsuspend(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_arm_vcresume(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_arm_init_state(struct vchiq_state *state,
struct vchiq_arm_state *arm_state);
@@ -124,16 +124,16 @@ vchiq_check_resume(struct vchiq_state *state);
extern void
vchiq_check_suspend(struct vchiq_state *state);
-VCHIQ_STATUS_T
-vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle);
+enum vchiq_status
+vchiq_use_service(unsigned int handle);
-extern VCHIQ_STATUS_T
-vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle);
+extern enum vchiq_status
+vchiq_release_service(unsigned int handle);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_check_service(struct vchiq_service *service);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_platform_suspend(struct vchiq_state *state);
extern int
@@ -154,27 +154,27 @@ vchiq_platform_get_arm_state(struct vchiq_state *state);
extern int
vchiq_videocore_wanted(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service,
enum USE_TYPE_E use_type);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_release_internal(struct vchiq_state *state,
struct vchiq_service *service);
extern struct vchiq_debugfs_node *
-vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance);
+vchiq_instance_get_debugfs_node(struct vchiq_instance *instance);
extern int
-vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance);
+vchiq_instance_get_use_count(struct vchiq_instance *instance);
extern int
-vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance);
+vchiq_instance_get_pid(struct vchiq_instance *instance);
extern int
-vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance);
+vchiq_instance_get_trace(struct vchiq_instance *instance);
extern void
-vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace);
+vchiq_instance_set_trace(struct vchiq_instance *instance, int trace);
extern void
set_suspend_state(struct vchiq_arm_state *arm_state,
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 56a23a297fa4..b9d94f6b9bef 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -132,7 +132,7 @@ vchiq_set_service_state(struct vchiq_service *service, int newstate)
}
struct vchiq_service *
-find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle)
+find_service_by_handle(unsigned int handle)
{
struct vchiq_service *service;
@@ -177,8 +177,8 @@ find_service_by_port(struct vchiq_state *state, int localport)
}
struct vchiq_service *
-find_service_for_instance(VCHIQ_INSTANCE_T instance,
- VCHIQ_SERVICE_HANDLE_T handle)
+find_service_for_instance(struct vchiq_instance *instance,
+ unsigned int handle)
{
struct vchiq_service *service;
@@ -201,8 +201,8 @@ find_service_for_instance(VCHIQ_INSTANCE_T instance,
}
struct vchiq_service *
-find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
- VCHIQ_SERVICE_HANDLE_T handle)
+find_closed_service_for_instance(struct vchiq_instance *instance,
+ unsigned int handle)
{
struct vchiq_service *service;
@@ -227,7 +227,7 @@ find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
}
struct vchiq_service *
-next_service_by_instance(struct vchiq_state *state, VCHIQ_INSTANCE_T instance,
+next_service_by_instance(struct vchiq_state *state, struct vchiq_instance *instance,
int *pidx)
{
struct vchiq_service *service = NULL;
@@ -295,7 +295,7 @@ unlock:
}
int
-vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle)
+vchiq_get_client_id(unsigned int handle)
{
struct vchiq_service *service = find_service_by_handle(handle);
int id;
@@ -308,7 +308,7 @@ vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle)
}
void *
-vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle)
+vchiq_get_service_userdata(unsigned int handle)
{
struct vchiq_service *service = handle_to_service(handle);
@@ -316,7 +316,7 @@ vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle)
}
int
-vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T handle)
+vchiq_get_service_fourcc(unsigned int handle)
{
struct vchiq_service *service = handle_to_service(handle);
@@ -354,11 +354,11 @@ mark_service_closing(struct vchiq_service *service)
mark_service_closing_internal(service, 0);
}
-static inline VCHIQ_STATUS_T
-make_service_callback(struct vchiq_service *service, VCHIQ_REASON_T reason,
+static inline enum vchiq_status
+make_service_callback(struct vchiq_service *service, enum vchiq_reason reason,
struct vchiq_header *header, void *bulk_userdata)
{
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %pK, %pK)",
service->state->id, service->localport, reason_names[reason],
@@ -375,9 +375,9 @@ make_service_callback(struct vchiq_service *service, VCHIQ_REASON_T reason,
}
inline void
-vchiq_set_conn_state(struct vchiq_state *state, VCHIQ_CONNSTATE_T newstate)
+vchiq_set_conn_state(struct vchiq_state *state, enum vchiq_connstate newstate)
{
- VCHIQ_CONNSTATE_T oldstate = state->conn_state;
+ enum vchiq_connstate oldstate = state->conn_state;
vchiq_log_info(vchiq_core_log_level, "%d: %s->%s", state->id,
conn_state_names[oldstate],
@@ -542,7 +542,7 @@ reserve_space(struct vchiq_state *state, size_t space, int is_blocking)
if (space > slot_space) {
struct vchiq_header *header;
/* Fill the remaining space with padding */
- WARN_ON(state->tx_data == NULL);
+ WARN_ON(!state->tx_data);
header = (struct vchiq_header *)
(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK));
header->msgid = VCHIQ_MSGID_PADDING;
@@ -779,7 +779,7 @@ copy_message_data(
}
/* Called by the slot handler and application threads */
-static VCHIQ_STATUS_T
+static enum vchiq_status
queue_message(struct vchiq_state *state, struct vchiq_service *service,
int msgid,
ssize_t (*copy_callback)(void *context, void *dest,
@@ -1027,7 +1027,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
}
/* Called by the slot handler and application threads */
-static VCHIQ_STATUS_T
+static enum vchiq_status
queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
int msgid,
ssize_t (*copy_callback)(void *context, void *dest,
@@ -1178,11 +1178,11 @@ release_slot(struct vchiq_state *state, struct vchiq_slot_info *slot_info,
}
/* Called by the slot handler - don't hold the bulk mutex */
-static VCHIQ_STATUS_T
+static enum vchiq_status
notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue,
int retry_poll)
{
- VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
+ enum vchiq_status status = VCHIQ_SUCCESS;
vchiq_log_trace(vchiq_core_log_level,
"%d: nb:%d %cx - p=%x rn=%x r=%x",
@@ -1230,7 +1230,7 @@ notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue,
spin_unlock(&bulk_waiter_spinlock);
} else if (bulk->mode ==
VCHIQ_BULK_MODE_CALLBACK) {
- VCHIQ_REASON_T reason = (bulk->dir ==
+ enum vchiq_reason reason = (bulk->dir ==
VCHIQ_BULK_TRANSMIT) ?
((bulk->actual ==
VCHIQ_BULK_ACTUAL_ABORTED) ?
@@ -2078,7 +2078,7 @@ init_bulk_queue(struct vchiq_bulk_queue *queue)
}
inline const char *
-get_conn_state_name(VCHIQ_CONNSTATE_T conn_state)
+get_conn_state_name(enum vchiq_connstate conn_state)
{
return conn_state_names[conn_state];
}
@@ -2123,18 +2123,15 @@ vchiq_init_slots(void *mem_base, int mem_size)
return slot_zero;
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero)
{
struct vchiq_shared_state *local;
struct vchiq_shared_state *remote;
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
char threadname[16];
int i;
- vchiq_log_warning(vchiq_core_log_level,
- "%s: slot_zero = %pK", __func__, slot_zero);
-
if (vchiq_states[0]) {
pr_err("%s: VCHIQ state already initialized\n", __func__);
return VCHIQ_ERROR;
@@ -2283,8 +2280,8 @@ fail_free_handler_thread:
struct vchiq_service *
vchiq_add_service_internal(struct vchiq_state *state,
const struct vchiq_service_params *params,
- int srvstate, VCHIQ_INSTANCE_T instance,
- VCHIQ_USERDATA_TERM_T userdata_term)
+ int srvstate, struct vchiq_instance *instance,
+ vchiq_userdata_term userdata_term)
{
struct vchiq_service *service;
struct vchiq_service **pservice = NULL;
@@ -2412,7 +2409,7 @@ vchiq_add_service_internal(struct vchiq_state *state,
return service;
}
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_open_service_internal(struct vchiq_service *service, int client_id)
{
struct vchiq_open_payload payload = {
@@ -2421,7 +2418,7 @@ vchiq_open_service_internal(struct vchiq_service *service, int client_id)
service->version,
service->version_min
};
- VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
+ enum vchiq_status status = VCHIQ_SUCCESS;
service->client_id = client_id;
vchiq_use_service_internal(service);
@@ -2519,7 +2516,7 @@ release_service_messages(struct vchiq_service *service)
static int
do_abort_bulks(struct vchiq_service *service)
{
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
/* Abort any outstanding bulk transfers */
if (mutex_lock_killable(&service->bulk_mutex))
@@ -2535,10 +2532,10 @@ do_abort_bulks(struct vchiq_service *service)
return (status == VCHIQ_SUCCESS);
}
-static VCHIQ_STATUS_T
+static enum vchiq_status
close_service_complete(struct vchiq_service *service, int failstate)
{
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID);
int newstate;
@@ -2597,11 +2594,11 @@ close_service_complete(struct vchiq_service *service, int failstate)
}
/* Called by the slot handler */
-VCHIQ_STATUS_T
+enum vchiq_status
vchiq_close_service_internal(struct vchiq_service *service, int close_recvd)
{
struct vchiq_state *state = service->state;
- VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
+ enum vchiq_status status = VCHIQ_SUCCESS;
int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID);
vchiq_log_info(vchiq_core_log_level, "%d: csi:%d,%d (%s)",
@@ -2777,8 +2774,8 @@ vchiq_free_service_internal(struct vchiq_service *service)
unlock_service(service);
}
-VCHIQ_STATUS_T
-vchiq_connect_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance)
+enum vchiq_status
+vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance)
{
struct vchiq_service *service;
int i;
@@ -2813,8 +2810,8 @@ vchiq_connect_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance)
return VCHIQ_SUCCESS;
}
-VCHIQ_STATUS_T
-vchiq_shutdown_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance)
+enum vchiq_status
+vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instance)
{
struct vchiq_service *service;
int i;
@@ -2830,12 +2827,12 @@ vchiq_shutdown_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance)
return VCHIQ_SUCCESS;
}
-VCHIQ_STATUS_T
-vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle)
+enum vchiq_status
+vchiq_close_service(unsigned int handle)
{
/* Unregister the service */
struct vchiq_service *service = find_service_by_handle(handle);
- VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
+ enum vchiq_status status = VCHIQ_SUCCESS;
if (!service)
return VCHIQ_ERROR;
@@ -2889,12 +2886,12 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle)
return status;
}
-VCHIQ_STATUS_T
-vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle)
+enum vchiq_status
+vchiq_remove_service(unsigned int handle)
{
/* Unregister the service */
struct vchiq_service *service = find_service_by_handle(handle);
- VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
+ enum vchiq_status status = VCHIQ_SUCCESS;
if (!service)
return VCHIQ_ERROR;
@@ -2955,10 +2952,10 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle)
* 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,
+enum vchiq_status vchiq_bulk_transfer(unsigned int handle,
void *offset, int size, void *userdata,
- VCHIQ_BULK_MODE_T mode,
- VCHIQ_BULK_DIR_T dir)
+ enum vchiq_bulk_mode mode,
+ enum vchiq_bulk_dir dir)
{
struct vchiq_service *service = find_service_by_handle(handle);
struct vchiq_bulk_queue *queue;
@@ -2968,7 +2965,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
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;
+ enum vchiq_status status = VCHIQ_ERROR;
int payload[2];
if (!service || service->srvstate != VCHIQ_SRVSTATE_OPEN ||
@@ -3103,15 +3100,15 @@ error_exit:
return status;
}
-VCHIQ_STATUS_T
-vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
+enum vchiq_status
+vchiq_queue_message(unsigned int handle,
ssize_t (*copy_callback)(void *context, void *dest,
size_t offset, size_t maxsize),
void *context,
size_t size)
{
struct vchiq_service *service = find_service_by_handle(handle);
- VCHIQ_STATUS_T status = VCHIQ_ERROR;
+ enum vchiq_status status = VCHIQ_ERROR;
if (!service ||
(vchiq_check_service(service) != VCHIQ_SUCCESS))
@@ -3156,7 +3153,7 @@ error_exit:
}
void
-vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle,
+vchiq_release_message(unsigned int handle,
struct vchiq_header *header)
{
struct vchiq_service *service = find_service_by_handle(handle);
@@ -3195,10 +3192,10 @@ release_message_sync(struct vchiq_state *state, struct vchiq_header *header)
remote_event_signal(&state->remote->sync_release);
}
-VCHIQ_STATUS_T
-vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, short *peer_version)
+enum vchiq_status
+vchiq_get_peer_version(unsigned int handle, short *peer_version)
{
- VCHIQ_STATUS_T status = VCHIQ_ERROR;
+ enum vchiq_status status = VCHIQ_ERROR;
struct vchiq_service *service = find_service_by_handle(handle);
if (!service ||
@@ -3224,12 +3221,12 @@ void vchiq_get_config(struct vchiq_config *config)
config->version_min = VCHIQ_VERSION_MIN;
}
-VCHIQ_STATUS_T
-vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle,
- VCHIQ_SERVICE_OPTION_T option, int value)
+enum vchiq_status
+vchiq_set_service_option(unsigned int handle,
+ enum vchiq_service_option option, int value)
{
struct vchiq_service *service = find_service_by_handle(handle);
- VCHIQ_STATUS_T status = VCHIQ_ERROR;
+ enum vchiq_status status = VCHIQ_ERROR;
if (service) {
switch (option) {
@@ -3527,9 +3524,9 @@ vchiq_loud_error_footer(void)
"================");
}
-VCHIQ_STATUS_T vchiq_send_remote_use(struct vchiq_state *state)
+enum vchiq_status vchiq_send_remote_use(struct vchiq_state *state)
{
- VCHIQ_STATUS_T status = VCHIQ_RETRY;
+ enum vchiq_status status = VCHIQ_RETRY;
if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED)
status = queue_message(state, NULL,
@@ -3538,9 +3535,9 @@ VCHIQ_STATUS_T vchiq_send_remote_use(struct vchiq_state *state)
return status;
}
-VCHIQ_STATUS_T vchiq_send_remote_use_active(struct vchiq_state *state)
+enum vchiq_status vchiq_send_remote_use_active(struct vchiq_state *state)
{
- VCHIQ_STATUS_T status = VCHIQ_RETRY;
+ enum vchiq_status status = VCHIQ_RETRY;
if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED)
status = queue_message(state, NULL,
@@ -3578,7 +3575,7 @@ void vchiq_log_dump_mem(const char *label, u32 addr, const void *void_mem,
}
*s++ = '\0';
- if ((label != NULL) && (*label != '\0'))
+ if (label && (*label != '\0'))
vchiq_log_trace(VCHIQ_LOG_TRACE,
"%s: %08x: %s", label, addr, line_buf);
else
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
index 63f71b2a492f..419bcdd165b4 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
@@ -60,8 +60,8 @@ 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(struct vchiq_slot_zero) + \
- VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE)
+#define VCHIQ_SLOT_ZERO_SLOTS DIV_ROUND_UP(sizeof(struct vchiq_slot_zero), \
+ VCHIQ_SLOT_SIZE)
#define VCHIQ_MSG_PADDING 0 /* - */
#define VCHIQ_MSG_CONNECT 1 /* - */
@@ -169,7 +169,7 @@ enum {
#endif /* VCHIQ_ENABLE_DEBUG */
-typedef enum {
+enum vchiq_connstate {
VCHIQ_CONNSTATE_DISCONNECTED,
VCHIQ_CONNSTATE_CONNECTING,
VCHIQ_CONNSTATE_CONNECTED,
@@ -179,7 +179,7 @@ typedef enum {
VCHIQ_CONNSTATE_RESUMING,
VCHIQ_CONNSTATE_PAUSE_TIMEOUT,
VCHIQ_CONNSTATE_RESUME_TIMEOUT
-} VCHIQ_CONNSTATE_T;
+};
enum {
VCHIQ_SRVSTATE_FREE,
@@ -202,12 +202,12 @@ enum {
VCHIQ_POLL_COUNT
};
-typedef enum {
+enum vchiq_bulk_dir {
VCHIQ_BULK_TRANSMIT,
VCHIQ_BULK_RECEIVE
-} VCHIQ_BULK_DIR_T;
+};
-typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata);
+typedef void (*vchiq_userdata_term)(void *userdata);
struct vchiq_bulk {
short mode;
@@ -236,7 +236,7 @@ struct remote_event {
u32 __unused;
};
-typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T;
+struct opaque_platform_state;
struct vchiq_slot {
char data[VCHIQ_SLOT_SIZE];
@@ -250,10 +250,10 @@ struct vchiq_slot_info {
struct vchiq_service {
struct vchiq_service_base base;
- VCHIQ_SERVICE_HANDLE_T handle;
+ unsigned int handle;
unsigned int ref_count;
int srvstate;
- VCHIQ_USERDATA_TERM_T userdata_term;
+ vchiq_userdata_term userdata_term;
unsigned int localport;
unsigned int remoteport;
int public_fourcc;
@@ -268,7 +268,7 @@ struct vchiq_service {
short peer_version;
struct vchiq_state *state;
- VCHIQ_INSTANCE_T instance;
+ struct vchiq_instance *instance;
int service_use_count;
@@ -367,7 +367,7 @@ struct vchiq_slot_zero {
struct vchiq_state {
int id;
int initialised;
- VCHIQ_CONNSTATE_T conn_state;
+ enum vchiq_connstate conn_state;
short version_common;
struct vchiq_shared_state *local;
@@ -382,7 +382,7 @@ struct vchiq_state {
/* Mutex protecting services */
struct mutex mutex;
- VCHIQ_INSTANCE_T *instance;
+ struct vchiq_instance **instance;
/* Processes incoming messages */
struct task_struct *slot_handler_thread;
@@ -468,7 +468,7 @@ struct vchiq_state {
struct vchiq_service_quota service_quotas[VCHIQ_MAX_SERVICES];
struct vchiq_slot_info slot_info[VCHIQ_MAX_SLOTS];
- VCHIQ_PLATFORM_STATE_T platform_state;
+ struct opaque_platform_state *platform_state;
};
struct bulk_waiter {
@@ -486,27 +486,27 @@ extern int vchiq_sync_log_level;
extern struct vchiq_state *vchiq_states[VCHIQ_MAX_STATES];
extern const char *
-get_conn_state_name(VCHIQ_CONNSTATE_T conn_state);
+get_conn_state_name(enum vchiq_connstate conn_state);
extern struct vchiq_slot_zero *
vchiq_init_slots(void *mem_base, int mem_size);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero);
-extern VCHIQ_STATUS_T
-vchiq_connect_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance);
+extern enum vchiq_status
+vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance);
extern struct vchiq_service *
vchiq_add_service_internal(struct vchiq_state *state,
const struct vchiq_service_params *params,
- int srvstate, VCHIQ_INSTANCE_T instance,
- VCHIQ_USERDATA_TERM_T userdata_term);
+ int srvstate, struct vchiq_instance *instance,
+ vchiq_userdata_term userdata_term);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_open_service_internal(struct vchiq_service *service, int client_id);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_close_service_internal(struct vchiq_service *service, int close_recvd);
extern void
@@ -515,16 +515,16 @@ vchiq_terminate_service_internal(struct vchiq_service *service);
extern void
vchiq_free_service_internal(struct vchiq_service *service);
-extern VCHIQ_STATUS_T
-vchiq_shutdown_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance);
+extern enum vchiq_status
+vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instance);
extern void
remote_event_pollall(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
-vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *offset, int size,
- void *userdata, VCHIQ_BULK_MODE_T mode,
- VCHIQ_BULK_DIR_T dir);
+extern enum vchiq_status
+vchiq_bulk_transfer(unsigned int handle, void *offset, int size,
+ void *userdata, enum vchiq_bulk_mode mode,
+ enum vchiq_bulk_dir dir);
extern void
vchiq_dump_state(void *dump_context, struct vchiq_state *state);
@@ -543,7 +543,7 @@ request_poll(struct vchiq_state *state, struct vchiq_service *service,
int poll_type);
static inline struct vchiq_service *
-handle_to_service(VCHIQ_SERVICE_HANDLE_T handle)
+handle_to_service(unsigned int handle)
{
struct vchiq_state *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) &
(VCHIQ_MAX_STATES - 1)];
@@ -554,21 +554,21 @@ handle_to_service(VCHIQ_SERVICE_HANDLE_T handle)
}
extern struct vchiq_service *
-find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle);
+find_service_by_handle(unsigned int handle);
extern struct vchiq_service *
find_service_by_port(struct vchiq_state *state, int localport);
extern struct vchiq_service *
-find_service_for_instance(VCHIQ_INSTANCE_T instance,
- VCHIQ_SERVICE_HANDLE_T handle);
+find_service_for_instance(struct vchiq_instance *instance,
+ unsigned int handle);
extern struct vchiq_service *
-find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
- VCHIQ_SERVICE_HANDLE_T handle);
+find_closed_service_for_instance(struct vchiq_instance *instance,
+ unsigned int handle);
extern struct vchiq_service *
-next_service_by_instance(struct vchiq_state *state, VCHIQ_INSTANCE_T instance,
+next_service_by_instance(struct vchiq_state *state, struct vchiq_instance *instance,
int *pidx);
extern void
@@ -580,7 +580,7 @@ unlock_service(struct vchiq_service *service);
/* The following functions are called from vchiq_core, and external
** implementations must be provided. */
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, int size,
int dir);
@@ -596,7 +596,7 @@ vchiq_platform_check_suspend(struct vchiq_state *state);
extern void
vchiq_platform_paused(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_platform_resume(struct vchiq_state *state);
extern void
@@ -615,10 +615,10 @@ extern void
vchiq_dump_platform_service_state(void *dump_context,
struct vchiq_service *service);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_use_service_internal(struct vchiq_service *service);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_release_service_internal(struct vchiq_service *service);
extern void
@@ -627,31 +627,31 @@ vchiq_on_remote_use(struct vchiq_state *state);
extern void
vchiq_on_remote_release(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_platform_init_state(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_check_service(struct vchiq_service *service);
extern void
vchiq_on_remote_use_active(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_send_remote_use(struct vchiq_state *state);
-extern VCHIQ_STATUS_T
+extern enum vchiq_status
vchiq_send_remote_use_active(struct vchiq_state *state);
extern void
vchiq_platform_conn_state_changed(struct vchiq_state *state,
- VCHIQ_CONNSTATE_T oldstate,
- VCHIQ_CONNSTATE_T newstate);
+ enum vchiq_connstate oldstate,
+ enum vchiq_connstate newstate);
extern void
vchiq_platform_handle_timeout(struct vchiq_state *state);
extern void
-vchiq_set_conn_state(struct vchiq_state *state, VCHIQ_CONNSTATE_T newstate);
+vchiq_set_conn_state(struct vchiq_state *state, enum vchiq_connstate newstate);
extern void
vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem,
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c
index f217b78d95a0..89cc52211de4 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c
@@ -117,7 +117,7 @@ static const struct file_operations debugfs_log_fops = {
static int debugfs_usecount_show(struct seq_file *f, void *offset)
{
- VCHIQ_INSTANCE_T instance = f->private;
+ struct vchiq_instance *instance = f->private;
int use_count;
use_count = vchiq_instance_get_use_count(instance);
@@ -129,7 +129,7 @@ DEFINE_SHOW_ATTRIBUTE(debugfs_usecount);
static int debugfs_trace_show(struct seq_file *f, void *offset)
{
- VCHIQ_INSTANCE_T instance = f->private;
+ struct vchiq_instance *instance = f->private;
int trace;
trace = vchiq_instance_get_trace(instance);
@@ -148,7 +148,7 @@ static ssize_t debugfs_trace_write(struct file *file,
size_t count, loff_t *ppos)
{
struct seq_file *f = (struct seq_file *)file->private_data;
- VCHIQ_INSTANCE_T instance = f->private;
+ struct vchiq_instance *instance = f->private;
char firstchar;
if (copy_from_user(&firstchar, buffer, 1))
@@ -184,7 +184,7 @@ static const struct file_operations debugfs_trace_fops = {
};
/* add an instance (process) to the debugfs entries */
-void vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance)
+void vchiq_debugfs_add_instance(struct vchiq_instance *instance)
{
char pidstr[16];
struct dentry *top;
@@ -201,7 +201,7 @@ void vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance)
vchiq_instance_get_debugfs_node(instance)->dentry = top;
}
-void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance)
+void vchiq_debugfs_remove_instance(struct vchiq_instance *instance)
{
struct vchiq_debugfs_node *node =
vchiq_instance_get_debugfs_node(instance);
@@ -242,11 +242,11 @@ void vchiq_debugfs_deinit(void)
{
}
-void vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance)
+void vchiq_debugfs_add_instance(struct vchiq_instance *instance)
{
}
-void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance)
+void vchiq_debugfs_remove_instance(struct vchiq_instance *instance)
{
}
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
index 9b563d105fdb..ec2f033cdf32 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
@@ -14,8 +14,8 @@ void vchiq_debugfs_init(void);
void vchiq_debugfs_deinit(void);
-void vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance);
+void vchiq_debugfs_add_instance(struct vchiq_instance *instance);
-void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance);
+void vchiq_debugfs_remove_instance(struct vchiq_instance *instance);
#endif /* VCHIQ_DEBUGFS_H */
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h
index c23bd105c40f..07c6a3db5ab6 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h
@@ -15,7 +15,7 @@
#define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service)
#define VCHIQ_GET_SERVICE_FOURCC(service) vchiq_get_service_fourcc(service)
-typedef enum {
+enum vchiq_reason {
VCHIQ_SERVICE_OPENED, /* service, -, - */
VCHIQ_SERVICE_CLOSED, /* service, -, - */
VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */
@@ -23,28 +23,28 @@ typedef enum {
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 {
+enum vchiq_status {
VCHIQ_ERROR = -1,
VCHIQ_SUCCESS = 0,
VCHIQ_RETRY = 1
-} VCHIQ_STATUS_T;
+};
-typedef enum {
+enum vchiq_bulk_mode {
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 {
+enum vchiq_service_option {
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;
+};
struct vchiq_header {
/* The message identifier - opaque to applications. */
@@ -61,21 +61,19 @@ struct vchiq_element {
unsigned int size;
};
-typedef unsigned int VCHIQ_SERVICE_HANDLE_T;
-
-typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T,
- struct vchiq_header *,
- VCHIQ_SERVICE_HANDLE_T, void *);
+typedef enum vchiq_status (*vchiq_callback)(enum vchiq_reason,
+ struct vchiq_header *,
+ unsigned int, void *);
struct vchiq_service_base {
int fourcc;
- VCHIQ_CALLBACK_T callback;
+ vchiq_callback callback;
void *userdata;
};
struct vchiq_service_params {
int fourcc;
- VCHIQ_CALLBACK_T callback;
+ vchiq_callback callback;
void *userdata;
short version; /* Increment for non-trivial changes */
short version_min; /* Update for incompatible changes */
@@ -92,57 +90,57 @@ struct vchiq_config {
short version_min; /* The minimum compatible version of VCHIQ */
};
-typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T;
-typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg);
+struct vchiq_instance;
+typedef void (*vchiq_remote_callback)(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,
+extern enum vchiq_status vchiq_initialise(struct vchiq_instance **pinstance);
+extern enum vchiq_status vchiq_shutdown(struct vchiq_instance *instance);
+extern enum vchiq_status vchiq_connect(struct vchiq_instance *instance);
+extern enum vchiq_status vchiq_add_service(struct vchiq_instance *instance,
const struct vchiq_service_params *params,
- VCHIQ_SERVICE_HANDLE_T *pservice);
-extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance,
+ unsigned int *pservice);
+extern enum vchiq_status vchiq_open_service(struct vchiq_instance *instance,
const struct vchiq_service_params *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_release_service(VCHIQ_SERVICE_HANDLE_T service);
-extern VCHIQ_STATUS_T
-vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
+ unsigned int *pservice);
+extern enum vchiq_status vchiq_close_service(unsigned int service);
+extern enum vchiq_status vchiq_remove_service(unsigned int service);
+extern enum vchiq_status vchiq_use_service(unsigned int service);
+extern enum vchiq_status vchiq_release_service(unsigned int service);
+extern enum vchiq_status
+vchiq_queue_message(unsigned int handle,
ssize_t (*copy_callback)(void *context, void *dest,
size_t offset, size_t maxsize),
void *context,
size_t size);
-extern void vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service,
+extern void vchiq_release_message(unsigned int service,
struct vchiq_header *header);
-extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service,
+extern enum vchiq_status vchiq_bulk_transmit(unsigned int 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,
+ enum vchiq_bulk_mode mode);
+extern enum vchiq_status vchiq_bulk_receive(unsigned int 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,
+ enum vchiq_bulk_mode mode);
+extern enum vchiq_status vchiq_bulk_transmit_handle(unsigned int service,
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,
+ void *userdata, enum vchiq_bulk_mode mode);
+extern enum vchiq_status vchiq_bulk_receive_handle(unsigned int service,
void *offset, unsigned int size, void *userdata,
- 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);
+ enum vchiq_bulk_mode mode);
+extern int vchiq_get_client_id(unsigned int service);
+extern void *vchiq_get_service_userdata(unsigned int service);
+extern int vchiq_get_service_fourcc(unsigned int service);
extern void vchiq_get_config(struct vchiq_config *config);
-extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service,
- VCHIQ_SERVICE_OPTION_T option, int value);
+extern enum vchiq_status vchiq_set_service_option(unsigned int service,
+ enum vchiq_service_option 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 enum vchiq_status vchiq_remote_use(struct vchiq_instance *instance,
+ vchiq_remote_callback callback, void *cb_arg);
+extern enum vchiq_status vchiq_remote_release(struct vchiq_instance *instance);
-extern VCHIQ_STATUS_T vchiq_dump_phys_mem(VCHIQ_SERVICE_HANDLE_T service,
+extern enum vchiq_status vchiq_dump_phys_mem(unsigned int service,
void *ptr, size_t num_bytes);
-extern VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle,
+extern enum vchiq_status vchiq_get_peer_version(unsigned int 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
index 460ccea088bf..202889b3774f 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
@@ -28,11 +28,11 @@ struct vchiq_queue_bulk_transfer {
void *data;
unsigned int size;
void *userdata;
- VCHIQ_BULK_MODE_T mode;
+ enum vchiq_bulk_mode mode;
};
struct vchiq_completion_data {
- VCHIQ_REASON_T reason;
+ enum vchiq_reason reason;
struct vchiq_header *header;
void *service_userdata;
void *bulk_userdata;
@@ -60,7 +60,7 @@ struct vchiq_get_config {
struct vchiq_set_service_option {
unsigned int handle;
- VCHIQ_SERVICE_OPTION_T option;
+ enum vchiq_service_option option;
int value;
};
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
index 17a4f2c8d8b1..0ce3b08b3441 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
@@ -12,22 +12,22 @@
#define vchiq_status_to_vchi(status) ((int32_t)status)
struct shim_service {
- VCHIQ_SERVICE_HANDLE_T handle;
+ unsigned int handle;
struct vchiu_queue queue;
- VCHI_CALLBACK_T callback;
+ vchi_callback callback;
void *callback_param;
};
/***********************************************************
* Name: vchi_msg_peek
*
- * Arguments: const VCHI_SERVICE_HANDLE_T handle,
+ * Arguments: struct vchi_service_handle *handle,
* void **data,
* uint32_t *msg_size,
- * VCHI_FLAGS_T flags
+ * enum vchi_flags flags
*
* Description: Routine to return a pointer to the current message (to allow in
* place processing). The message can be removed using
@@ -36,10 +36,10 @@ struct shim_service {
* 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)
+int32_t vchi_msg_peek(struct vchi_service_handle *handle,
+ void **data,
+ uint32_t *msg_size,
+ enum vchi_flags flags)
{
struct shim_service *service = (struct shim_service *)handle;
struct vchiq_header *header;
@@ -63,7 +63,7 @@ EXPORT_SYMBOL(vchi_msg_peek);
/***********************************************************
* Name: vchi_msg_remove
*
- * Arguments: const VCHI_SERVICE_HANDLE_T handle,
+ * Arguments: struct vchi_service_handle *handle,
*
* Description: Routine to remove a message (after it has been read with
* vchi_msg_peek)
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(vchi_msg_peek);
* Returns: int32_t - success == 0
*
***********************************************************/
-int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle)
+int32_t vchi_msg_remove(struct vchi_service_handle *handle)
{
struct shim_service *service = (struct shim_service *)handle;
struct vchiq_header *header;
@@ -87,7 +87,7 @@ EXPORT_SYMBOL(vchi_msg_remove);
/***********************************************************
* Name: vchi_msg_queue
*
- * Arguments: VCHI_SERVICE_HANDLE_T handle,
+ * Arguments: struct vchi_service_handle *handle,
* ssize_t (*copy_callback)(void *context, void *dest,
* size_t offset, size_t maxsize),
* void *context,
@@ -99,14 +99,14 @@ EXPORT_SYMBOL(vchi_msg_remove);
*
***********************************************************/
static
-int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
+int32_t vchi_msg_queue(struct vchi_service_handle *handle,
ssize_t (*copy_callback)(void *context, void *dest,
size_t offset, size_t maxsize),
void *context,
uint32_t data_size)
{
struct shim_service *service = (struct shim_service *)handle;
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
while (1) {
status = vchiq_queue_message(service->handle,
@@ -139,7 +139,7 @@ vchi_queue_kernel_message_callback(void *context,
}
int
-vchi_queue_kernel_message(VCHI_SERVICE_HANDLE_T handle,
+vchi_queue_kernel_message(struct vchi_service_handle *handle,
void *data,
unsigned int size)
{
@@ -169,7 +169,7 @@ vchi_queue_user_message_callback(void *context,
}
int
-vchi_queue_user_message(VCHI_SERVICE_HANDLE_T handle,
+vchi_queue_user_message(struct vchi_service_handle *handle,
void __user *data,
unsigned int size)
{
@@ -190,7 +190,7 @@ EXPORT_SYMBOL(vchi_queue_user_message);
* Arguments: VCHI_BULK_HANDLE_T handle,
* void *data_dst,
* const uint32_t data_size,
- * VCHI_FLAGS_T flags
+ * enum vchi_flags flags
* void *bulk_handle
*
* Description: Routine to setup a rcv buffer
@@ -198,15 +198,13 @@ EXPORT_SYMBOL(vchi_queue_user_message);
* 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)
+int32_t vchi_bulk_queue_receive(struct vchi_service_handle *handle, void *data_dst,
+ uint32_t data_size, enum vchi_flags flags,
+ void *bulk_handle)
{
struct shim_service *service = (struct shim_service *)handle;
- VCHIQ_BULK_MODE_T mode;
- VCHIQ_STATUS_T status;
+ enum vchiq_bulk_mode mode;
+ enum vchiq_status status;
switch ((int)flags) {
case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
@@ -250,7 +248,7 @@ EXPORT_SYMBOL(vchi_bulk_queue_receive);
* Arguments: VCHI_BULK_HANDLE_T handle,
* const void *data_src,
* uint32_t data_size,
- * VCHI_FLAGS_T flags,
+ * enum vchi_flags flags,
* void *bulk_handle
*
* Description: Routine to transmit some data
@@ -258,15 +256,15 @@ EXPORT_SYMBOL(vchi_bulk_queue_receive);
* 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)
+int32_t vchi_bulk_queue_transmit(struct vchi_service_handle *handle,
+ const void *data_src,
+ uint32_t data_size,
+ enum vchi_flags flags,
+ void *bulk_handle)
{
struct shim_service *service = (struct shim_service *)handle;
- VCHIQ_BULK_MODE_T mode;
- VCHIQ_STATUS_T status;
+ enum vchiq_bulk_mode mode;
+ enum vchiq_status status;
switch ((int)flags) {
case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
@@ -309,22 +307,20 @@ EXPORT_SYMBOL(vchi_bulk_queue_transmit);
/***********************************************************
* Name: vchi_msg_dequeue
*
- * Arguments: VCHI_SERVICE_HANDLE_T handle,
+ * Arguments: struct vchi_service_handle *handle,
* void *data,
* uint32_t max_data_size_to_read,
* uint32_t *actual_msg_size
- * VCHI_FLAGS_T flags
+ * enum vchi_flags 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)
+int32_t vchi_msg_dequeue(struct vchi_service_handle *handle, void *data,
+ uint32_t max_data_size_to_read,
+ uint32_t *actual_msg_size, enum vchi_flags flags)
{
struct shim_service *service = (struct shim_service *)handle;
struct vchiq_header *header;
@@ -364,13 +360,13 @@ int32_t vchi_held_msg_release(struct vchi_held_msg *message)
{
/*
* Convert the service field pointer back to an
- * VCHIQ_SERVICE_HANDLE_T which is an int.
+ * unsigned int which is an int.
* This pointer is opaque to everything except
* vchi_msg_hold which simply upcasted the int
* to a pointer.
*/
- vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)(long)message->service,
+ vchiq_release_message((unsigned int)(long)message->service,
(struct vchiq_header *)message->message);
return 0;
@@ -380,10 +376,10 @@ EXPORT_SYMBOL(vchi_held_msg_release);
/***********************************************************
* Name: vchi_msg_hold
*
- * Arguments: VCHI_SERVICE_HANDLE_T handle,
+ * Arguments: struct vchi_service_handle *handle,
* void **data,
* uint32_t *msg_size,
- * VCHI_FLAGS_T flags,
+ * enum vchi_flags flags,
* struct vchi_held_msg *message_handle
*
* Description: Routine to return a pointer to the current message (to allow
@@ -394,11 +390,9 @@ EXPORT_SYMBOL(vchi_held_msg_release);
* 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,
- struct vchi_held_msg *message_handle)
+int32_t vchi_msg_hold(struct vchi_service_handle *handle, void **data,
+ uint32_t *msg_size, enum vchi_flags flags,
+ struct vchi_held_msg *message_handle)
{
struct shim_service *service = (struct shim_service *)handle;
struct vchiq_header *header;
@@ -416,7 +410,7 @@ int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,
*msg_size = header->size;
/*
- * upcast the VCHIQ_SERVICE_HANDLE_T which is an int
+ * upcast the unsigned int which is an int
* to a pointer and stuff it in the held message.
* This pointer is opaque to everything except
* vchi_held_msg_release which simply downcasts it back
@@ -434,7 +428,7 @@ EXPORT_SYMBOL(vchi_msg_hold);
/***********************************************************
* Name: vchi_initialise
*
- * Arguments: VCHI_INSTANCE_T *instance_handle
+ * Arguments: struct vchi_instance_handle **instance_handle
*
* Description: Initialises the hardware but does not transmit anything
* When run as a Host App this will be called twice hence the need
@@ -444,14 +438,14 @@ EXPORT_SYMBOL(vchi_msg_hold);
*
***********************************************************/
-int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle)
+int32_t vchi_initialise(struct vchi_instance_handle **instance_handle)
{
- VCHIQ_INSTANCE_T instance;
- VCHIQ_STATUS_T status;
+ struct vchiq_instance *instance;
+ enum vchiq_status status;
status = vchiq_initialise(&instance);
- *instance_handle = (VCHI_INSTANCE_T)instance;
+ *instance_handle = (struct vchi_instance_handle *)instance;
return vchiq_status_to_vchi(status);
}
@@ -460,7 +454,7 @@ EXPORT_SYMBOL(vchi_initialise);
/***********************************************************
* Name: vchi_connect
*
- * Arguments: VCHI_INSTANCE_T instance_handle
+ * Arguments: struct vchi_instance_handle *instance_handle
*
* Description: Starts the command service on each connection,
* causing INIT messages to be pinged back and forth
@@ -468,9 +462,9 @@ EXPORT_SYMBOL(vchi_initialise);
* Returns: 0 if successful, failure otherwise
*
***********************************************************/
-int32_t vchi_connect(VCHI_INSTANCE_T instance_handle)
+int32_t vchi_connect(struct vchi_instance_handle *instance_handle)
{
- VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
+ struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle;
return vchiq_connect(instance);
}
@@ -479,7 +473,7 @@ EXPORT_SYMBOL(vchi_connect);
/***********************************************************
* Name: vchi_disconnect
*
- * Arguments: VCHI_INSTANCE_T instance_handle
+ * Arguments: struct vchi_instance_handle *instance_handle
*
* Description: Stops the command service on each connection,
* causing DE-INIT messages to be pinged back and forth
@@ -487,9 +481,9 @@ EXPORT_SYMBOL(vchi_connect);
* Returns: 0 if successful, failure otherwise
*
***********************************************************/
-int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle)
+int32_t vchi_disconnect(struct vchi_instance_handle *instance_handle)
{
- VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
+ struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle;
return vchiq_status_to_vchi(vchiq_shutdown(instance));
}
@@ -499,9 +493,9 @@ EXPORT_SYMBOL(vchi_disconnect);
* Name: vchi_service_open
* Name: vchi_service_create
*
- * Arguments: VCHI_INSTANCE_T *instance_handle
+ * Arguments: struct vchi_instance_handle *instance_handle
* struct service_creation *setup,
- * VCHI_SERVICE_HANDLE_T *handle
+ * struct vchi_service_handle **handle
*
* Description: Routine to open a service
*
@@ -509,9 +503,9 @@ EXPORT_SYMBOL(vchi_disconnect);
*
***********************************************************/
-static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason,
+static enum vchiq_status shim_callback(enum vchiq_reason reason,
struct vchiq_header *header,
- VCHIQ_SERVICE_HANDLE_T handle,
+ unsigned int handle,
void *bulk_user)
{
struct shim_service *service =
@@ -571,7 +565,7 @@ done:
return VCHIQ_SUCCESS;
}
-static struct shim_service *service_alloc(VCHIQ_INSTANCE_T instance,
+static struct shim_service *service_alloc(struct vchiq_instance *instance,
struct service_creation *setup)
{
struct shim_service *service = kzalloc(sizeof(struct shim_service), GFP_KERNEL);
@@ -579,7 +573,7 @@ static struct shim_service *service_alloc(VCHIQ_INSTANCE_T instance,
(void)instance;
if (service) {
- if (vchiu_queue_init(&service->queue, 64)) {
+ if (!vchiu_queue_init(&service->queue, 64)) {
service->callback = setup->callback;
service->callback_param = setup->callback_param;
} else {
@@ -599,18 +593,18 @@ static void service_free(struct shim_service *service)
}
}
-int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
+int32_t vchi_service_open(struct vchi_instance_handle *instance_handle,
struct service_creation *setup,
- VCHI_SERVICE_HANDLE_T *handle)
+ struct vchi_service_handle **handle)
{
- VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
+ struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle;
struct shim_service *service = service_alloc(instance, setup);
- *handle = (VCHI_SERVICE_HANDLE_T)service;
+ *handle = (struct vchi_service_handle *)service;
if (service) {
struct vchiq_service_params params;
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
memset(&params, 0, sizeof(params));
params.fourcc = setup->service_id;
@@ -628,17 +622,17 @@ int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
}
}
- return (service != NULL) ? 0 : -1;
+ return service ? 0 : -1;
}
EXPORT_SYMBOL(vchi_service_open);
-int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
+int32_t vchi_service_close(const struct vchi_service_handle *handle)
{
int32_t ret = -1;
struct shim_service *service = (struct shim_service *)handle;
if (service) {
- VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
+ enum vchiq_status status = vchiq_close_service(service->handle);
if (status == VCHIQ_SUCCESS)
service_free(service);
@@ -648,13 +642,13 @@ int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
}
EXPORT_SYMBOL(vchi_service_close);
-int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)
+int32_t vchi_service_destroy(const struct vchi_service_handle *handle)
{
int32_t ret = -1;
struct shim_service *service = (struct shim_service *)handle;
if (service) {
- VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
+ enum vchiq_status status = vchiq_remove_service(service->handle);
if (status == VCHIQ_SUCCESS) {
service_free(service);
@@ -667,13 +661,13 @@ int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)
}
EXPORT_SYMBOL(vchi_service_destroy);
-int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
- VCHI_SERVICE_OPTION_T option,
+int32_t vchi_service_set_option(const struct vchi_service_handle *handle,
+ enum vchi_service_option option,
int value)
{
int32_t ret = -1;
struct shim_service *service = (struct shim_service *)handle;
- VCHIQ_SERVICE_OPTION_T vchiq_option;
+ enum vchiq_service_option vchiq_option;
switch (option) {
case VCHI_SERVICE_OPTION_TRACE:
@@ -687,7 +681,7 @@ int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
break;
}
if (service) {
- VCHIQ_STATUS_T status =
+ enum vchiq_status status =
vchiq_set_service_option(service->handle,
vchiq_option,
value);
@@ -698,13 +692,13 @@ int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
}
EXPORT_SYMBOL(vchi_service_set_option);
-int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T handle, short *peer_version)
+int32_t vchi_get_peer_version(const struct vchi_service_handle *handle, short *peer_version)
{
int32_t ret = -1;
struct shim_service *service = (struct shim_service *)handle;
if (service) {
- VCHIQ_STATUS_T status;
+ enum vchiq_status status;
status = vchiq_get_peer_version(service->handle, peer_version);
ret = vchiq_status_to_vchi(status);
@@ -716,14 +710,14 @@ EXPORT_SYMBOL(vchi_get_peer_version);
/***********************************************************
* Name: vchi_service_use
*
- * Arguments: const VCHI_SERVICE_HANDLE_T handle
+ * Arguments: const struct vchi_service_handle *handle
*
* Description: Routine to increment refcount on a service
*
* Returns: void
*
***********************************************************/
-int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle)
+int32_t vchi_service_use(const struct vchi_service_handle *handle)
{
int32_t ret = -1;
@@ -737,14 +731,14 @@ EXPORT_SYMBOL(vchi_service_use);
/***********************************************************
* Name: vchi_service_release
*
- * Arguments: const VCHI_SERVICE_HANDLE_T handle
+ * Arguments: const struct vchi_service_handle *handle
*
* Description: Routine to decrement refcount on a service
*
* Returns: void
*
***********************************************************/
-int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle)
+int32_t vchi_service_release(const struct vchi_service_handle *handle)
{
int32_t ret = -1;
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
index 5e6d3035dc05..644844d88fed 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
@@ -24,9 +24,9 @@ int vchiu_queue_init(struct vchiu_queue *queue, int size)
GFP_KERNEL);
if (!queue->storage) {
vchiu_queue_delete(queue);
- return 0;
+ return -ENOMEM;
}
- return 1;
+ return 0;
}
void vchiu_queue_delete(struct vchiu_queue *queue)
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index eba4ee0750dc..e65c9825ea5a 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -79,14 +79,10 @@ static void s_vCalculateOFDMRParameter(unsigned char byRate, u8 bb_type,
*
* Return Value: none
*/
-static
-void
-s_vCalculateOFDMRParameter(
- unsigned char byRate,
- u8 bb_type,
- unsigned char *pbyTxRate,
- unsigned char *pbyRsvTime
-)
+static void s_vCalculateOFDMRParameter(unsigned char byRate,
+ u8 bb_type,
+ unsigned char *pbyTxRate,
+ unsigned char *pbyRsvTime)
{
switch (byRate) {
case RATE_6M:
@@ -736,8 +732,7 @@ void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type)
VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_24,
MAKEWORD(byTxRate, byRsvTime));
/* RSPINF_a_36 */
- s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate(
- (void *)priv,
+ s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv,
RATE_36M),
bb_type,
&byTxRate,
@@ -745,8 +740,7 @@ void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type)
VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_36,
MAKEWORD(byTxRate, byRsvTime));
/* RSPINF_a_48 */
- s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate(
- (void *)priv,
+ s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv,
RATE_48M),
bb_type,
&byTxRate,
@@ -754,8 +748,7 @@ void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type)
VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_48,
MAKEWORD(byTxRate, byRsvTime));
/* RSPINF_a_54 */
- s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate(
- (void *)priv,
+ s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv,
RATE_54M),
bb_type,
&byTxRate,
@@ -763,8 +756,7 @@ void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type)
VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_54,
MAKEWORD(byTxRate, byRsvTime));
/* RSPINF_a_72 */
- s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate(
- (void *)priv,
+ s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv,
RATE_54M),
bb_type,
&byTxRate,
diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
index 887c1692e05b..25867cb9d13d 100644
--- a/drivers/staging/vt6655/card.h
+++ b/drivers/staging/vt6655/card.h
@@ -45,7 +45,7 @@ void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type);
void CARDvUpdateBasicTopRate(struct vnt_private *priv);
bool CARDbIsOFDMinBasicRate(struct vnt_private *priv);
void CARDvSetLoopbackMode(struct vnt_private *priv,
- unsigned short wLoopbackMode);
+ unsigned short wLoopbackMode);
bool CARDbSoftwareReset(struct vnt_private *priv);
void CARDvSetFirstNextTBTT(struct vnt_private *priv,
unsigned short wBeaconInterval);
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 082302944c37..f69fc687d4c3 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -295,7 +295,8 @@ static void device_init_registers(struct vnt_private *priv)
/* Get Desire Power Value */
priv->byCurPwr = 0xFF;
priv->byCCKPwr = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_PWR_CCK);
- priv->byOFDMPwrG = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_PWR_OFDMG);
+ priv->byOFDMPwrG = SROMbyReadEmbedded(priv->PortOffset,
+ EEP_OFS_PWR_OFDMG);
/* Load power Table */
for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) {
@@ -373,7 +374,7 @@ static void device_init_registers(struct vnt_private *priv)
priv->bRadioOff = false;
priv->byRadioCtl = SROMbyReadEmbedded(priv->PortOffset,
- EEP_OFS_RADIOCTL);
+ EEP_OFS_RADIOCTL);
priv->bHWRadioOff = false;
if (priv->byRadioCtl & EEP_RADIOCTL_ENABLE) {
@@ -659,12 +660,13 @@ static int device_init_td0_ring(struct vnt_private *priv)
desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ;
desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ;
- desc->next = &(priv->apTD0Rings[(i+1) % priv->opts.tx_descs[0]]);
- desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
+ desc->next = &(priv->apTD0Rings[(i + 1) % priv->opts.tx_descs[0]]);
+ desc->next_desc = cpu_to_le32(curr +
+ sizeof(struct vnt_tx_desc));
}
if (i > 0)
- priv->apTD0Rings[i-1].next_desc = cpu_to_le32(priv->td0_pool_dma);
+ priv->apTD0Rings[i - 1].next_desc = cpu_to_le32(priv->td0_pool_dma);
priv->apTailTD[0] = priv->apCurrTD[0] = &priv->apTD0Rings[0];
return 0;
@@ -704,7 +706,7 @@ static int device_init_td1_ring(struct vnt_private *priv)
}
if (i > 0)
- priv->apTD1Rings[i-1].next_desc = cpu_to_le32(priv->td1_pool_dma);
+ priv->apTD1Rings[i - 1].next_desc = cpu_to_le32(priv->td1_pool_dma);
priv->apTailTD[1] = priv->apCurrTD[1] = &priv->apTD1Rings[0];
return 0;
diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c
index 9725de3bca6a..bfd598a93b04 100644
--- a/drivers/staging/vt6655/power.c
+++ b/drivers/staging/vt6655/power.c
@@ -97,10 +97,7 @@ void PSvEnablePowerSaving(struct vnt_private *priv,
*
*/
-void
-PSvDisablePowerSaving(
- struct vnt_private *priv
-)
+void PSvDisablePowerSaving(struct vnt_private *priv)
{
/* disable power saving hw function */
MACbPSWakeup(priv);
@@ -126,10 +123,7 @@ PSvDisablePowerSaving(
*
*/
-bool
-PSbIsNextTBTTWakeUp(
- struct vnt_private *priv
-)
+bool PSbIsNextTBTTWakeUp(struct vnt_private *priv)
{
struct ieee80211_hw *hw = priv->hw;
struct ieee80211_conf *conf = &hw->conf;
diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c
index e80fed69bafe..fb2855e686a7 100644
--- a/drivers/staging/vt6655/rf.c
+++ b/drivers/staging/vt6655/rf.c
@@ -436,7 +436,7 @@ static bool s_bAL7230Init(struct vnt_private *priv)
ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW));
MACvTimer0MicroSDelay(priv, 30);/* 30us */
/* TXDCOC:disable, RCK:disable */
- ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ - 1]);
MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 |
SOFTPWRCTL_SWPE2 |
@@ -558,7 +558,8 @@ static bool RFbAL2230Init(struct vnt_private *priv)
MACvTimer0MicroSDelay(priv, 30);/* 30us */
ret &= IFRFbWriteEmbedded(priv, (0x00780f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW));
MACvTimer0MicroSDelay(priv, 30);/* 30us */
- ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]);
+ ret &= IFRFbWriteEmbedded(priv,
+ dwAL2230InitTable[CB_AL2230_INIT_SEQ - 1]);
MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 |
SOFTPWRCTL_SWPE2 |
diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h
index 042ac67a9709..affb70eba10f 100644
--- a/drivers/staging/vt6655/rf.h
+++ b/drivers/staging/vt6655/rf.h
@@ -61,23 +61,14 @@
bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData);
bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, u16 byChannel);
-bool RFbInit(
- struct vnt_private *priv
-);
+bool RFbInit(struct vnt_private *priv);
bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, u16 uChannel);
bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH);
-bool RFbRawSetPower(
- struct vnt_private *priv,
- unsigned char byPwr,
- unsigned int rate
-);
+bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr,
+ unsigned int rate);
-void
-RFvRSSITodBm(
- struct vnt_private *priv,
- unsigned char byCurrRSSI,
- long *pldBm
-);
+void RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI,
+ long *pldBm);
/* {{ RobertYu: 20050104 */
bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, u16 byOldChannel, u16 byNewChannel);
diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c
index a14908895b9e..37fcc42ed000 100644
--- a/drivers/staging/vt6655/rxtx.c
+++ b/drivers/staging/vt6655/rxtx.c
@@ -1289,7 +1289,7 @@ int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
current_rate = rate->hw_value;
if (priv->wCurrentRate != current_rate &&
- !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
+ !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
priv->wCurrentRate = current_rate;
RFbSetPower(priv, priv->wCurrentRate,
@@ -1396,7 +1396,8 @@ int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
tx_key = info->control.hw_key;
if (tx_key->keylen > 0)
vnt_fill_txkey(hdr, tx_buffer_head->tx_key,
- tx_key, skb, tx_body_size, td_info->mic_hdr);
+ tx_key, skb, tx_body_size,
+ td_info->mic_hdr);
}
return 0;
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 856ba97aec4f..4ac85ecb0921 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -249,10 +249,10 @@ static int vnt_init_registers(struct vnt_private *priv)
} else {
priv->tx_antenna_mode = ANT_B;
- if (priv->tx_rx_ant_inv)
- priv->rx_antenna_mode = ANT_A;
- else
- priv->rx_antenna_mode = ANT_B;
+ if (priv->tx_rx_ant_inv)
+ priv->rx_antenna_mode = ANT_A;
+ else
+ priv->rx_antenna_mode = ANT_B;
}
}
@@ -362,7 +362,6 @@ static int vnt_init_registers(struct vnt_private *priv)
goto end;
}
-
ret = vnt_mac_set_led(priv, LEDSTS_TMLEN, 0x38);
if (ret)
goto end;
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 4e9cfacf75f2..f9020a4f7bbf 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -112,11 +112,11 @@ static u32 vnt_get_rsvtime(struct vnt_private *priv, u8 pkt_type,
frame_length, rate);
if (pkt_type == PK_TYPE_11B)
- ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
- 14, (u16)priv->top_cck_basic_rate);
+ ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type, 14,
+ (u16)priv->top_cck_basic_rate);
else
- ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
- 14, (u16)priv->top_ofdm_basic_rate);
+ ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type, 14,
+ (u16)priv->top_ofdm_basic_rate);
if (need_ack)
return data_time + priv->sifs + ack_time;
diff --git a/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt b/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt
new file mode 100644
index 000000000000..26de6762b942
--- /dev/null
+++ b/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt
@@ -0,0 +1,97 @@
+The WFxxx chip series can be connected via SPI or via SDIO.
+
+SPI
+---
+
+You have to declare the WFxxx chip in your device tree.
+
+Required properties:
+ - compatible: Should be "silabs,wfx-spi"
+ - reg: Chip select address of device
+ - spi-max-frequency: Maximum SPI clocking speed of device in Hz
+ - interrupts-extended: Should contain interrupt line (interrupt-parent +
+ interrupt can also been used). Trigger should be `IRQ_TYPE_EDGE_RISING`.
+
+Optional properties:
+ - reset-gpios: phandle of gpio that will be used to reset chip during probe.
+ Without this property, you may encounter issues with warm boot.
+
+Please consult Documentation/devicetree/bindings/spi/spi-bus.txt for optional
+SPI connection related properties,
+
+Example:
+
+&spi1 {
+ wfx {
+ compatible = "silabs,wfx-spi";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wfx_irq &wfx_gpios>;
+ interrupts-extended = <&gpio 16 IRQ_TYPE_EDGE_RISING>;
+ wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio 13 GPIO_ACTIVE_HIGH>;
+ reg = <0>;
+ spi-max-frequency = <42000000>;
+ };
+};
+
+
+SDIO
+----
+
+The driver is able to detect a WFxxx chip on SDIO bus by matching its Vendor ID
+and Product ID. However, driver will only provide limited features in this
+case. Thus declaring WFxxx chip in device tree is strongly recommended (and may
+become mandatory in the future).
+
+Required properties:
+ - compatible: Should be "silabs,wfx-sdio"
+ - reg: Should be 1
+
+In addition, it is recommended to declare a mmc-pwrseq on SDIO host above WFx.
+Without it, you may encounter issues with warm boot. mmc-pwrseq should be
+compatible with mmc-pwrseq-simple. Please consult
+Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt for more
+information.
+
+Example:
+
+/ {
+ wfx_pwrseq: wfx_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wfx_reset>;
+ reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&mmc1 {
+ mmc-pwrseq = <&wfx_pwrseq>;
+ #address-size = <1>;
+ #size = <0>;
+
+ mmc@1 {
+ compatible = "silabs,wfx-sdio";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wfx_wakeup>;
+ wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+Note that #address-size and #size shoud already be defined in node mmc1, but it
+is rarely the case.
+
+Common properties
+-----------------
+
+Some properties are recognized either by SPI and SDIO versions:
+ - wakeup-gpios: phandle of gpio that will be used to wake-up chip. Without
+ this property, driver will disable most of power saving features.
+ - config-file: Use an alternative file as PDS. Default is `wf200.pds`. Only
+ necessary for development/debug purpose.
+ - slk_key: String representing hexadecimal value of secure link key to use.
+ Must contains 64 hexadecimal digits. Not supported in current version.
+
+WFx driver also supports `mac-address` and `local-mac-address` as described in
+Documentation/devicetree/binding/net/ethernet.txt
+
diff --git a/drivers/staging/wfx/Kconfig b/drivers/staging/wfx/Kconfig
new file mode 100644
index 000000000000..83ee4d0ca8c6
--- /dev/null
+++ b/drivers/staging/wfx/Kconfig
@@ -0,0 +1,8 @@
+config WFX
+ tristate "Silicon Labs wireless chips WF200 and further"
+ depends on MAC80211
+ depends on MMC || !MMC # do not allow WFX=y if MMC=m
+ depends on (SPI || MMC)
+ help
+ This is a driver for Silicons Labs WFxxx series (WF200 and further)
+ chipsets. This chip can be found on SPI or SDIO buses.
diff --git a/drivers/staging/wfx/Makefile b/drivers/staging/wfx/Makefile
new file mode 100644
index 000000000000..0d9c1ed092f6
--- /dev/null
+++ b/drivers/staging/wfx/Makefile
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Necessary for CREATE_TRACE_POINTS
+CFLAGS_debug.o = -I$(src)
+
+wfx-y := \
+ bh.o \
+ hwio.o \
+ fwio.o \
+ hif_tx.o \
+ hif_rx.o \
+ queue.o \
+ data_tx.o \
+ data_rx.o \
+ scan.o \
+ sta.o \
+ key.o \
+ main.o \
+ sta.o \
+ debug.o
+wfx-$(CONFIG_SPI) += bus_spi.o
+wfx-$(subst m,y,$(CONFIG_MMC)) += bus_sdio.o
+
+obj-$(CONFIG_WFX) += wfx.o
diff --git a/drivers/staging/wfx/TODO b/drivers/staging/wfx/TODO
new file mode 100644
index 000000000000..e44772289af8
--- /dev/null
+++ b/drivers/staging/wfx/TODO
@@ -0,0 +1,17 @@
+This is a list of things that need to be done to get this driver out of the
+staging directory.
+
+ - I have to take a decision about secure link support. I can:
+ - drop completely
+ - keep it in an external patch (my preferred option)
+ - replace call to mbedtls with kernel crypto API (necessitate a
+ bunch of work)
+ - pull mbedtls in kernel (non-realistic)
+
+ - mac80211 interface does not (yet) have expected quality to be placed
+ outside of staging:
+ - Some processings are redundant with mac80211 ones
+ - Many members from wfx_dev/wfx_vif can be retrieved from mac80211
+ structures
+ - Some functions are too complex
+ - ...
diff --git a/drivers/staging/wfx/bh.c b/drivers/staging/wfx/bh.c
new file mode 100644
index 000000000000..955ed3a1dd73
--- /dev/null
+++ b/drivers/staging/wfx/bh.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Interrupt bottom half (BH).
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/gpio/consumer.h>
+#include <net/mac80211.h>
+
+#include "bh.h"
+#include "wfx.h"
+#include "hwio.h"
+#include "traces.h"
+#include "secure_link.h"
+#include "hif_rx.h"
+#include "hif_api_cmd.h"
+
+static void device_wakeup(struct wfx_dev *wdev)
+{
+ if (!wdev->pdata.gpio_wakeup)
+ return;
+ if (gpiod_get_value(wdev->pdata.gpio_wakeup))
+ return;
+
+ gpiod_set_value(wdev->pdata.gpio_wakeup, 1);
+ if (wfx_api_older_than(wdev, 1, 4)) {
+ if (!completion_done(&wdev->hif.ctrl_ready))
+ udelay(2000);
+ } else {
+ // completion.h does not provide any function to wait
+ // completion without consume it (a kind of
+ // wait_for_completion_done_timeout()). So we have to emulate
+ // it.
+ if (wait_for_completion_timeout(&wdev->hif.ctrl_ready,
+ msecs_to_jiffies(2) + 1))
+ complete(&wdev->hif.ctrl_ready);
+ else
+ dev_err(wdev->dev, "timeout while wake up chip\n");
+ }
+}
+
+static void device_release(struct wfx_dev *wdev)
+{
+ if (!wdev->pdata.gpio_wakeup)
+ return;
+
+ gpiod_set_value(wdev->pdata.gpio_wakeup, 0);
+}
+
+static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf)
+{
+ struct sk_buff *skb;
+ struct hif_msg *hif;
+ size_t alloc_len;
+ size_t computed_len;
+ int release_count;
+ int piggyback = 0;
+
+ WARN(read_len < 4, "corrupted read");
+ WARN(read_len > round_down(0xFFF, 2) * sizeof(u16),
+ "%s: request exceed WFx capability", __func__);
+
+ // Add 2 to take into account piggyback size
+ alloc_len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, read_len + 2);
+ skb = dev_alloc_skb(alloc_len);
+ if (!skb)
+ return -ENOMEM;
+
+ if (wfx_data_read(wdev, skb->data, alloc_len))
+ goto err;
+
+ piggyback = le16_to_cpup((u16 *)(skb->data + alloc_len - 2));
+ _trace_piggyback(piggyback, false);
+
+ hif = (struct hif_msg *)skb->data;
+ WARN(hif->encrypted & 0x1, "unsupported encryption type");
+ if (hif->encrypted == 0x2) {
+ if (wfx_sl_decode(wdev, (void *)hif)) {
+ dev_kfree_skb(skb);
+ // If frame was a confirmation, expect trouble in next
+ // exchange. However, it is harmless to fail to decode
+ // an indication frame, so try to continue. Anyway,
+ // piggyback is probably correct.
+ return piggyback;
+ }
+ le16_to_cpus(&hif->len);
+ computed_len = round_up(hif->len - sizeof(hif->len), 16)
+ + sizeof(struct hif_sl_msg)
+ + sizeof(struct hif_sl_tag);
+ } else {
+ le16_to_cpus(&hif->len);
+ computed_len = round_up(hif->len, 2);
+ }
+ if (computed_len != read_len) {
+ dev_err(wdev->dev, "inconsistent message length: %zu != %zu\n",
+ computed_len, read_len);
+ print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, 16, 1,
+ hif, read_len, true);
+ goto err;
+ }
+
+ if (!(hif->id & HIF_ID_IS_INDICATION)) {
+ (*is_cnf)++;
+ if (hif->id == HIF_CNF_ID_MULTI_TRANSMIT)
+ release_count = le32_to_cpu(((struct hif_cnf_multi_transmit *)hif->body)->num_tx_confs);
+ else
+ release_count = 1;
+ WARN(wdev->hif.tx_buffers_used < release_count, "corrupted buffer counter");
+ wdev->hif.tx_buffers_used -= release_count;
+ if (!wdev->hif.tx_buffers_used)
+ wake_up(&wdev->hif.tx_buffers_empty);
+ }
+ _trace_hif_recv(hif, wdev->hif.tx_buffers_used);
+
+ if (hif->id != HIF_IND_ID_EXCEPTION && hif->id != HIF_IND_ID_ERROR) {
+ if (hif->seqnum != wdev->hif.rx_seqnum)
+ dev_warn(wdev->dev, "wrong message sequence: %d != %d\n",
+ hif->seqnum, wdev->hif.rx_seqnum);
+ wdev->hif.rx_seqnum = (hif->seqnum + 1) % (HIF_COUNTER_MAX + 1);
+ }
+
+ skb_put(skb, hif->len);
+ // wfx_handle_rx takes care on SKB livetime
+ wfx_handle_rx(wdev, skb);
+
+ return piggyback;
+
+err:
+ if (skb)
+ dev_kfree_skb(skb);
+ return -EIO;
+}
+
+static int bh_work_rx(struct wfx_dev *wdev, int max_msg, int *num_cnf)
+{
+ size_t len;
+ int i;
+ int ctrl_reg, piggyback;
+
+ piggyback = 0;
+ for (i = 0; i < max_msg; i++) {
+ if (piggyback & CTRL_NEXT_LEN_MASK)
+ ctrl_reg = piggyback;
+ else if (try_wait_for_completion(&wdev->hif.ctrl_ready))
+ ctrl_reg = atomic_xchg(&wdev->hif.ctrl_reg, 0);
+ else
+ ctrl_reg = 0;
+ if (!(ctrl_reg & CTRL_NEXT_LEN_MASK))
+ return i;
+ // ctrl_reg units are 16bits words
+ len = (ctrl_reg & CTRL_NEXT_LEN_MASK) * 2;
+ piggyback = rx_helper(wdev, len, num_cnf);
+ if (piggyback < 0)
+ return i;
+ if (!(piggyback & CTRL_WLAN_READY))
+ dev_err(wdev->dev, "unexpected piggyback value: ready bit not set: %04x\n",
+ piggyback);
+ }
+ if (piggyback & CTRL_NEXT_LEN_MASK) {
+ ctrl_reg = atomic_xchg(&wdev->hif.ctrl_reg, piggyback);
+ complete(&wdev->hif.ctrl_ready);
+ if (ctrl_reg)
+ dev_err(wdev->dev, "unexpected IRQ happened: %04x/%04x\n",
+ ctrl_reg, piggyback);
+ }
+ return i;
+}
+
+static void tx_helper(struct wfx_dev *wdev, struct hif_msg *hif)
+{
+ int ret;
+ void *data;
+ bool is_encrypted = false;
+ size_t len = le16_to_cpu(hif->len);
+
+ WARN(len < sizeof(*hif), "try to send corrupted data");
+
+ hif->seqnum = wdev->hif.tx_seqnum;
+ wdev->hif.tx_seqnum = (wdev->hif.tx_seqnum + 1) % (HIF_COUNTER_MAX + 1);
+
+ if (wfx_is_secure_command(wdev, hif->id)) {
+ len = round_up(len - sizeof(hif->len), 16) + sizeof(hif->len) +
+ sizeof(struct hif_sl_msg_hdr) +
+ sizeof(struct hif_sl_tag);
+ // AES support encryption in-place. However, mac80211 access to
+ // 802.11 header after frame was sent (to get MAC addresses).
+ // So, keep origin buffer clear.
+ data = kmalloc(len, GFP_KERNEL);
+ if (!data)
+ goto end;
+ is_encrypted = true;
+ ret = wfx_sl_encode(wdev, hif, data);
+ if (ret)
+ goto end;
+ } else {
+ data = hif;
+ }
+ WARN(len > wdev->hw_caps.size_inp_ch_buf,
+ "%s: request exceed WFx capability: %zu > %d\n", __func__,
+ len, wdev->hw_caps.size_inp_ch_buf);
+ len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, len);
+ ret = wfx_data_write(wdev, data, len);
+ if (ret)
+ goto end;
+
+ wdev->hif.tx_buffers_used++;
+ _trace_hif_send(hif, wdev->hif.tx_buffers_used);
+end:
+ if (is_encrypted)
+ kfree(data);
+}
+
+static int bh_work_tx(struct wfx_dev *wdev, int max_msg)
+{
+ struct hif_msg *hif;
+ int i;
+
+ for (i = 0; i < max_msg; i++) {
+ hif = NULL;
+ if (wdev->hif.tx_buffers_used < wdev->hw_caps.num_inp_ch_bufs) {
+ if (try_wait_for_completion(&wdev->hif_cmd.ready)) {
+ WARN(!mutex_is_locked(&wdev->hif_cmd.lock), "data locking error");
+ hif = wdev->hif_cmd.buf_send;
+ } else {
+ hif = wfx_tx_queues_get(wdev);
+ }
+ }
+ if (!hif)
+ return i;
+ tx_helper(wdev, hif);
+ }
+ return i;
+}
+
+/* In SDIO mode, it is necessary to make an access to a register to acknowledge
+ * last received message. It could be possible to restrict this acknowledge to
+ * SDIO mode and only if last operation was rx.
+ */
+static void ack_sdio_data(struct wfx_dev *wdev)
+{
+ uint32_t cfg_reg;
+
+ config_reg_read(wdev, &cfg_reg);
+ if (cfg_reg & 0xFF) {
+ dev_warn(wdev->dev, "chip reports errors: %02x\n",
+ cfg_reg & 0xFF);
+ config_reg_write_bits(wdev, 0xFF, 0x00);
+ }
+}
+
+static void bh_work(struct work_struct *work)
+{
+ struct wfx_dev *wdev = container_of(work, struct wfx_dev, hif.bh);
+ int stats_req = 0, stats_cnf = 0, stats_ind = 0;
+ bool release_chip = false, last_op_is_rx = false;
+ int num_tx, num_rx;
+
+ device_wakeup(wdev);
+ do {
+ num_tx = bh_work_tx(wdev, 32);
+ stats_req += num_tx;
+ if (num_tx)
+ last_op_is_rx = false;
+ num_rx = bh_work_rx(wdev, 32, &stats_cnf);
+ stats_ind += num_rx;
+ if (num_rx)
+ last_op_is_rx = true;
+ } while (num_rx || num_tx);
+ stats_ind -= stats_cnf;
+
+ if (last_op_is_rx)
+ ack_sdio_data(wdev);
+ if (!wdev->hif.tx_buffers_used && !work_pending(work) &&
+ !atomic_read(&wdev->scan_in_progress)) {
+ device_release(wdev);
+ release_chip = true;
+ }
+ _trace_bh_stats(stats_ind, stats_req, stats_cnf,
+ wdev->hif.tx_buffers_used, release_chip);
+}
+
+/*
+ * An IRQ from chip did occur
+ */
+void wfx_bh_request_rx(struct wfx_dev *wdev)
+{
+ u32 cur, prev;
+
+ control_reg_read(wdev, &cur);
+ prev = atomic_xchg(&wdev->hif.ctrl_reg, cur);
+ complete(&wdev->hif.ctrl_ready);
+ queue_work(system_highpri_wq, &wdev->hif.bh);
+
+ if (!(cur & CTRL_NEXT_LEN_MASK))
+ dev_err(wdev->dev, "unexpected control register value: length field is 0: %04x\n",
+ cur);
+ if (prev != 0)
+ dev_err(wdev->dev, "received IRQ but previous data was not (yet) read: %04x/%04x\n",
+ prev, cur);
+}
+
+/*
+ * Driver want to send data
+ */
+void wfx_bh_request_tx(struct wfx_dev *wdev)
+{
+ queue_work(system_highpri_wq, &wdev->hif.bh);
+}
+
+void wfx_bh_register(struct wfx_dev *wdev)
+{
+ INIT_WORK(&wdev->hif.bh, bh_work);
+ init_completion(&wdev->hif.ctrl_ready);
+ init_waitqueue_head(&wdev->hif.tx_buffers_empty);
+}
+
+void wfx_bh_unregister(struct wfx_dev *wdev)
+{
+ flush_work(&wdev->hif.bh);
+}
diff --git a/drivers/staging/wfx/bh.h b/drivers/staging/wfx/bh.h
new file mode 100644
index 000000000000..93ca98424e0b
--- /dev/null
+++ b/drivers/staging/wfx/bh.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Interrupt bottom half.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_BH_H
+#define WFX_BH_H
+
+#include <linux/atomic.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+struct wfx_dev;
+
+struct wfx_hif {
+ struct work_struct bh;
+ struct completion ctrl_ready;
+ wait_queue_head_t tx_buffers_empty;
+ atomic_t ctrl_reg;
+ int rx_seqnum;
+ int tx_seqnum;
+ int tx_buffers_used;
+};
+
+void wfx_bh_register(struct wfx_dev *wdev);
+void wfx_bh_unregister(struct wfx_dev *wdev);
+void wfx_bh_request_rx(struct wfx_dev *wdev);
+void wfx_bh_request_tx(struct wfx_dev *wdev);
+
+#endif /* WFX_BH_H */
diff --git a/drivers/staging/wfx/bus.h b/drivers/staging/wfx/bus.h
new file mode 100644
index 000000000000..62d6ecabe4cb
--- /dev/null
+++ b/drivers/staging/wfx/bus.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Common bus abstraction layer.
+ *
+ * Copyright (c) 2017-2018, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_BUS_H
+#define WFX_BUS_H
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/spi/spi.h>
+
+#define WFX_REG_CONFIG 0x0
+#define WFX_REG_CONTROL 0x1
+#define WFX_REG_IN_OUT_QUEUE 0x2
+#define WFX_REG_AHB_DPORT 0x3
+#define WFX_REG_BASE_ADDR 0x4
+#define WFX_REG_SRAM_DPORT 0x5
+#define WFX_REG_SET_GEN_R_W 0x6
+#define WFX_REG_FRAME_OUT 0x7
+
+struct hwbus_ops {
+ int (*copy_from_io)(void *bus_priv, unsigned int addr,
+ void *dst, size_t count);
+ int (*copy_to_io)(void *bus_priv, unsigned int addr,
+ const void *src, size_t count);
+ void (*lock)(void *bus_priv);
+ void (*unlock)(void *bus_priv);
+ size_t (*align_size)(void *bus_priv, size_t size);
+};
+
+extern struct sdio_driver wfx_sdio_driver;
+extern struct spi_driver wfx_spi_driver;
+
+#endif
diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c
new file mode 100644
index 000000000000..375e07d6d9ae
--- /dev/null
+++ b/drivers/staging/wfx/bus_sdio.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SDIO interface.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/module.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+
+#include "bus.h"
+#include "wfx.h"
+#include "hwio.h"
+#include "main.h"
+#include "bh.h"
+
+static const struct wfx_platform_data wfx_sdio_pdata = {
+ .file_fw = "wfm_wf200",
+ .file_pds = "wf200.pds",
+};
+
+struct wfx_sdio_priv {
+ struct sdio_func *func;
+ struct wfx_dev *core;
+ u8 buf_id_tx;
+ u8 buf_id_rx;
+ int of_irq;
+};
+
+static int wfx_sdio_copy_from_io(void *priv, unsigned int reg_id,
+ void *dst, size_t count)
+{
+ struct wfx_sdio_priv *bus = priv;
+ unsigned int sdio_addr = reg_id << 2;
+ int ret;
+
+ WARN(reg_id > 7, "chip only has 7 registers");
+ WARN(((uintptr_t)dst) & 3, "unaligned buffer size");
+ WARN(count & 3, "unaligned buffer address");
+
+ /* Use queue mode buffers */
+ if (reg_id == WFX_REG_IN_OUT_QUEUE)
+ sdio_addr |= (bus->buf_id_rx + 1) << 7;
+ ret = sdio_memcpy_fromio(bus->func, dst, sdio_addr, count);
+ if (!ret && reg_id == WFX_REG_IN_OUT_QUEUE)
+ bus->buf_id_rx = (bus->buf_id_rx + 1) % 4;
+
+ return ret;
+}
+
+static int wfx_sdio_copy_to_io(void *priv, unsigned int reg_id,
+ const void *src, size_t count)
+{
+ struct wfx_sdio_priv *bus = priv;
+ unsigned int sdio_addr = reg_id << 2;
+ int ret;
+
+ WARN(reg_id > 7, "chip only has 7 registers");
+ WARN(((uintptr_t)src) & 3, "unaligned buffer size");
+ WARN(count & 3, "unaligned buffer address");
+
+ /* Use queue mode buffers */
+ if (reg_id == WFX_REG_IN_OUT_QUEUE)
+ sdio_addr |= bus->buf_id_tx << 7;
+ // FIXME: discards 'const' qualifier for src
+ ret = sdio_memcpy_toio(bus->func, sdio_addr, (void *)src, count);
+ if (!ret && reg_id == WFX_REG_IN_OUT_QUEUE)
+ bus->buf_id_tx = (bus->buf_id_tx + 1) % 32;
+
+ return ret;
+}
+
+static void wfx_sdio_lock(void *priv)
+{
+ struct wfx_sdio_priv *bus = priv;
+
+ sdio_claim_host(bus->func);
+}
+
+static void wfx_sdio_unlock(void *priv)
+{
+ struct wfx_sdio_priv *bus = priv;
+
+ sdio_release_host(bus->func);
+}
+
+static void wfx_sdio_irq_handler(struct sdio_func *func)
+{
+ struct wfx_sdio_priv *bus = sdio_get_drvdata(func);
+
+ if (bus->core)
+ wfx_bh_request_rx(bus->core);
+ else
+ WARN(!bus->core, "race condition in driver init/deinit");
+}
+
+static irqreturn_t wfx_sdio_irq_handler_ext(int irq, void *priv)
+{
+ struct wfx_sdio_priv *bus = priv;
+
+ if (!bus->core) {
+ WARN(!bus->core, "race condition in driver init/deinit");
+ return IRQ_NONE;
+ }
+ sdio_claim_host(bus->func);
+ wfx_bh_request_rx(bus->core);
+ sdio_release_host(bus->func);
+ return IRQ_HANDLED;
+}
+
+static int wfx_sdio_irq_subscribe(struct wfx_sdio_priv *bus)
+{
+ int ret;
+
+ if (bus->of_irq) {
+ ret = request_irq(bus->of_irq, wfx_sdio_irq_handler_ext,
+ IRQF_TRIGGER_RISING, "wfx", bus);
+ } else {
+ sdio_claim_host(bus->func);
+ ret = sdio_claim_irq(bus->func, wfx_sdio_irq_handler);
+ sdio_release_host(bus->func);
+ }
+ return ret;
+}
+
+static int wfx_sdio_irq_unsubscribe(struct wfx_sdio_priv *bus)
+{
+ int ret;
+
+ if (bus->of_irq) {
+ free_irq(bus->of_irq, bus);
+ ret = 0;
+ } else {
+ sdio_claim_host(bus->func);
+ ret = sdio_release_irq(bus->func);
+ sdio_release_host(bus->func);
+ }
+ return ret;
+}
+
+static size_t wfx_sdio_align_size(void *priv, size_t size)
+{
+ struct wfx_sdio_priv *bus = priv;
+
+ return sdio_align_size(bus->func, size);
+}
+
+static const struct hwbus_ops wfx_sdio_hwbus_ops = {
+ .copy_from_io = wfx_sdio_copy_from_io,
+ .copy_to_io = wfx_sdio_copy_to_io,
+ .lock = wfx_sdio_lock,
+ .unlock = wfx_sdio_unlock,
+ .align_size = wfx_sdio_align_size,
+};
+
+static const struct of_device_id wfx_sdio_of_match[];
+static int wfx_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ struct device_node *np = func->dev.of_node;
+ struct wfx_sdio_priv *bus;
+ int ret;
+
+ if (func->num != 1) {
+ dev_err(&func->dev, "SDIO function number is %d while it should always be 1 (unsupported chip?)\n", func->num);
+ return -ENODEV;
+ }
+
+ bus = devm_kzalloc(&func->dev, sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+
+ if (np) {
+ if (!of_match_node(wfx_sdio_of_match, np)) {
+ dev_warn(&func->dev, "no compatible device found in DT\n");
+ return -ENODEV;
+ }
+ bus->of_irq = irq_of_parse_and_map(np, 0);
+ } else {
+ dev_warn(&func->dev,
+ "device is not declared in DT, features will be limited\n");
+ // FIXME: ignore VID/PID and only rely on device tree
+ // return -ENODEV;
+ }
+
+ bus->func = func;
+ sdio_set_drvdata(func, bus);
+ func->card->quirks |= MMC_QUIRK_LENIENT_FN0 | MMC_QUIRK_BLKSZ_FOR_BYTE_MODE | MMC_QUIRK_BROKEN_BYTE_MODE_512;
+
+ sdio_claim_host(func);
+ ret = sdio_enable_func(func);
+ // Block of 64 bytes is more efficient than 512B for frame sizes < 4k
+ sdio_set_block_size(func, 64);
+ sdio_release_host(func);
+ if (ret)
+ goto err0;
+
+ ret = wfx_sdio_irq_subscribe(bus);
+ if (ret)
+ goto err1;
+
+ bus->core = wfx_init_common(&func->dev, &wfx_sdio_pdata,
+ &wfx_sdio_hwbus_ops, bus);
+ if (!bus->core) {
+ ret = -EIO;
+ goto err2;
+ }
+
+ ret = wfx_probe(bus->core);
+ if (ret)
+ goto err3;
+
+ return 0;
+
+err3:
+ wfx_free_common(bus->core);
+err2:
+ wfx_sdio_irq_unsubscribe(bus);
+err1:
+ sdio_claim_host(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+err0:
+ return ret;
+}
+
+static void wfx_sdio_remove(struct sdio_func *func)
+{
+ struct wfx_sdio_priv *bus = sdio_get_drvdata(func);
+
+ wfx_release(bus->core);
+ wfx_free_common(bus->core);
+ wfx_sdio_irq_unsubscribe(bus);
+ sdio_claim_host(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+}
+
+#define SDIO_VENDOR_ID_SILABS 0x0000
+#define SDIO_DEVICE_ID_SILABS_WF200 0x1000
+static const struct sdio_device_id wfx_sdio_ids[] = {
+ { SDIO_DEVICE(SDIO_VENDOR_ID_SILABS, SDIO_DEVICE_ID_SILABS_WF200) },
+ // FIXME: ignore VID/PID and only rely on device tree
+ // { SDIO_DEVICE(SDIO_ANY_ID, SDIO_ANY_ID) },
+ { },
+};
+MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id wfx_sdio_of_match[] = {
+ { .compatible = "silabs,wfx-sdio" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, wfx_sdio_of_match);
+#endif
+
+struct sdio_driver wfx_sdio_driver = {
+ .name = "wfx-sdio",
+ .id_table = wfx_sdio_ids,
+ .probe = wfx_sdio_probe,
+ .remove = wfx_sdio_remove,
+ .drv = {
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(wfx_sdio_of_match),
+ }
+};
diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c
new file mode 100644
index 000000000000..ab0cda1e124f
--- /dev/null
+++ b/drivers/staging/wfx/bus_spi.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SPI interface.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2011, Sagrad Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+
+#include "bus.h"
+#include "wfx.h"
+#include "hwio.h"
+#include "main.h"
+#include "bh.h"
+
+static int gpio_reset = -2;
+module_param(gpio_reset, int, 0644);
+MODULE_PARM_DESC(gpio_reset, "gpio number for reset. -1 for none.");
+
+#define SET_WRITE 0x7FFF /* usage: and operation */
+#define SET_READ 0x8000 /* usage: or operation */
+
+static const struct wfx_platform_data wfx_spi_pdata = {
+ .file_fw = "wfm_wf200",
+ .file_pds = "wf200.pds",
+ .use_rising_clk = true,
+};
+
+struct wfx_spi_priv {
+ struct spi_device *func;
+ struct wfx_dev *core;
+ struct gpio_desc *gpio_reset;
+ struct work_struct request_rx;
+ bool need_swab;
+};
+
+/*
+ * WFx chip read data 16bits at time and place them directly into (little
+ * endian) CPU register. So, chip expect byte order like "B1 B0 B3 B2" (while
+ * LE is "B0 B1 B2 B3" and BE is "B3 B2 B1 B0")
+ *
+ * A little endian host with bits_per_word == 16 should do the right job
+ * natively. The code below to support big endian host and commonly used SPI
+ * 8bits.
+ */
+static int wfx_spi_copy_from_io(void *priv, unsigned int addr,
+ void *dst, size_t count)
+{
+ struct wfx_spi_priv *bus = priv;
+ u16 regaddr = (addr << 12) | (count / 2) | SET_READ;
+ struct spi_message m;
+ struct spi_transfer t_addr = {
+ .tx_buf = &regaddr,
+ .len = sizeof(regaddr),
+ };
+ struct spi_transfer t_msg = {
+ .rx_buf = dst,
+ .len = count,
+ };
+ u16 *dst16 = dst;
+ int ret, i;
+
+ WARN(count % 2, "buffer size must be a multiple of 2");
+
+ cpu_to_le16s(&regaddr);
+ if (bus->need_swab)
+ swab16s(&regaddr);
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t_addr, &m);
+ spi_message_add_tail(&t_msg, &m);
+ ret = spi_sync(bus->func, &m);
+
+ if (bus->need_swab && addr == WFX_REG_CONFIG)
+ for (i = 0; i < count / 2; i++)
+ swab16s(&dst16[i]);
+ return ret;
+}
+
+static int wfx_spi_copy_to_io(void *priv, unsigned int addr,
+ const void *src, size_t count)
+{
+ struct wfx_spi_priv *bus = priv;
+ u16 regaddr = (addr << 12) | (count / 2);
+ // FIXME: use a bounce buffer
+ u16 *src16 = (void *)src;
+ int ret, i;
+ struct spi_message m;
+ struct spi_transfer t_addr = {
+ .tx_buf = &regaddr,
+ .len = sizeof(regaddr),
+ };
+ struct spi_transfer t_msg = {
+ .tx_buf = src,
+ .len = count,
+ };
+
+ WARN(count % 2, "buffer size must be a multiple of 2");
+ WARN(regaddr & SET_READ, "bad addr or size overflow");
+
+ cpu_to_le16s(&regaddr);
+
+ if (bus->need_swab)
+ swab16s(&regaddr);
+ if (bus->need_swab && addr == WFX_REG_CONFIG)
+ for (i = 0; i < count / 2; i++)
+ swab16s(&src16[i]);
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t_addr, &m);
+ spi_message_add_tail(&t_msg, &m);
+ ret = spi_sync(bus->func, &m);
+
+ if (bus->need_swab && addr == WFX_REG_CONFIG)
+ for (i = 0; i < count / 2; i++)
+ swab16s(&src16[i]);
+ return ret;
+}
+
+static void wfx_spi_lock(void *priv)
+{
+}
+
+static void wfx_spi_unlock(void *priv)
+{
+}
+
+static irqreturn_t wfx_spi_irq_handler(int irq, void *priv)
+{
+ struct wfx_spi_priv *bus = priv;
+
+ if (!bus->core) {
+ WARN(!bus->core, "race condition in driver init/deinit");
+ return IRQ_NONE;
+ }
+ queue_work(system_highpri_wq, &bus->request_rx);
+ return IRQ_HANDLED;
+}
+
+static void wfx_spi_request_rx(struct work_struct *work)
+{
+ struct wfx_spi_priv *bus =
+ container_of(work, struct wfx_spi_priv, request_rx);
+
+ wfx_bh_request_rx(bus->core);
+}
+
+static size_t wfx_spi_align_size(void *priv, size_t size)
+{
+ // Most of SPI controllers avoid DMA if buffer size is not 32bit aligned
+ return ALIGN(size, 4);
+}
+
+static const struct hwbus_ops wfx_spi_hwbus_ops = {
+ .copy_from_io = wfx_spi_copy_from_io,
+ .copy_to_io = wfx_spi_copy_to_io,
+ .lock = wfx_spi_lock,
+ .unlock = wfx_spi_unlock,
+ .align_size = wfx_spi_align_size,
+};
+
+static int wfx_spi_probe(struct spi_device *func)
+{
+ struct wfx_spi_priv *bus;
+ int ret;
+
+ if (!func->bits_per_word)
+ func->bits_per_word = 16;
+ ret = spi_setup(func);
+ if (ret)
+ return ret;
+ // Trace below is also displayed by spi_setup() if compiled with DEBUG
+ dev_dbg(&func->dev, "SPI params: CS=%d, mode=%d bits/word=%d speed=%d\n",
+ func->chip_select, func->mode, func->bits_per_word,
+ func->max_speed_hz);
+ if (func->bits_per_word != 16 && func->bits_per_word != 8)
+ dev_warn(&func->dev, "unusual bits/word value: %d\n",
+ func->bits_per_word);
+ if (func->max_speed_hz > 49000000)
+ dev_warn(&func->dev, "%dHz is a very high speed\n",
+ func->max_speed_hz);
+
+ bus = devm_kzalloc(&func->dev, sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+ bus->func = func;
+ if (func->bits_per_word == 8 || IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+ bus->need_swab = true;
+ spi_set_drvdata(func, bus);
+
+ bus->gpio_reset = wfx_get_gpio(&func->dev, gpio_reset, "reset");
+ if (!bus->gpio_reset) {
+ dev_warn(&func->dev, "try to load firmware anyway\n");
+ } else {
+ gpiod_set_value(bus->gpio_reset, 0);
+ udelay(100);
+ gpiod_set_value(bus->gpio_reset, 1);
+ udelay(2000);
+ }
+
+ ret = devm_request_irq(&func->dev, func->irq, wfx_spi_irq_handler,
+ IRQF_TRIGGER_RISING, "wfx", bus);
+ if (ret)
+ return ret;
+
+ INIT_WORK(&bus->request_rx, wfx_spi_request_rx);
+ bus->core = wfx_init_common(&func->dev, &wfx_spi_pdata,
+ &wfx_spi_hwbus_ops, bus);
+ if (!bus->core)
+ return -EIO;
+
+ ret = wfx_probe(bus->core);
+ if (ret)
+ wfx_free_common(bus->core);
+
+ return ret;
+}
+
+/* Disconnect Function to be called by SPI stack when device is disconnected */
+static int wfx_spi_disconnect(struct spi_device *func)
+{
+ struct wfx_spi_priv *bus = spi_get_drvdata(func);
+
+ wfx_release(bus->core);
+ wfx_free_common(bus->core);
+ // A few IRQ will be sent during device release. Hopefully, no IRQ
+ // should happen after wdev/wvif are released.
+ devm_free_irq(&func->dev, func->irq, bus);
+ flush_work(&bus->request_rx);
+ return 0;
+}
+
+/*
+ * For dynamic driver binding, kernel does not use OF to match driver. It only
+ * use modalias and modalias is a copy of 'compatible' DT node with vendor
+ * stripped.
+ */
+static const struct spi_device_id wfx_spi_id[] = {
+ { "wfx-spi", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, wfx_spi_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id wfx_spi_of_match[] = {
+ { .compatible = "silabs,wfx-spi" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, wfx_spi_of_match);
+#endif
+
+struct spi_driver wfx_spi_driver = {
+ .driver = {
+ .name = "wfx-spi",
+ .of_match_table = of_match_ptr(wfx_spi_of_match),
+ },
+ .id_table = wfx_spi_id,
+ .probe = wfx_spi_probe,
+ .remove = wfx_spi_disconnect,
+};
diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c
new file mode 100644
index 000000000000..e7fcce8d0cc4
--- /dev/null
+++ b/drivers/staging/wfx/data_rx.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Datapath implementation.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+
+#include "data_rx.h"
+#include "wfx.h"
+#include "bh.h"
+#include "sta.h"
+
+static int wfx_handle_pspoll(struct wfx_vif *wvif, struct sk_buff *skb)
+{
+ struct ieee80211_sta *sta;
+ struct ieee80211_pspoll *pspoll = (struct ieee80211_pspoll *)skb->data;
+ int link_id = 0;
+ u32 pspoll_mask = 0;
+ int i;
+
+ if (wvif->state != WFX_STATE_AP)
+ return 1;
+ if (!ether_addr_equal(wvif->vif->addr, pspoll->bssid))
+ return 1;
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(wvif->vif, pspoll->ta);
+ if (sta)
+ link_id = ((struct wfx_sta_priv *)&sta->drv_priv)->link_id;
+ rcu_read_unlock();
+ if (link_id)
+ pspoll_mask = BIT(link_id);
+ else
+ return 1;
+
+ wvif->pspoll_mask |= pspoll_mask;
+ /* Do not report pspols if data for given link id is queued already. */
+ for (i = 0; i < IEEE80211_NUM_ACS; ++i) {
+ if (wfx_tx_queue_get_num_queued(&wvif->wdev->tx_queue[i],
+ pspoll_mask)) {
+ wfx_bh_request_tx(wvif->wdev);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int wfx_drop_encrypt_data(struct wfx_dev *wdev, struct hif_ind_rx *arg, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *) skb->data;
+ size_t hdrlen = ieee80211_hdrlen(frame->frame_control);
+ size_t iv_len, icv_len;
+
+ /* Oops... There is no fast way to ask mac80211 about
+ * IV/ICV lengths. Even defineas are not exposed.
+ */
+ switch (arg->rx_flags.encryp) {
+ case HIF_RI_FLAGS_WEP_ENCRYPTED:
+ iv_len = 4 /* WEP_IV_LEN */;
+ icv_len = 4 /* WEP_ICV_LEN */;
+ break;
+ case HIF_RI_FLAGS_TKIP_ENCRYPTED:
+ iv_len = 8 /* TKIP_IV_LEN */;
+ icv_len = 4 /* TKIP_ICV_LEN */
+ + 8 /*MICHAEL_MIC_LEN*/;
+ break;
+ case HIF_RI_FLAGS_AES_ENCRYPTED:
+ iv_len = 8 /* CCMP_HDR_LEN */;
+ icv_len = 8 /* CCMP_MIC_LEN */;
+ break;
+ case HIF_RI_FLAGS_WAPI_ENCRYPTED:
+ iv_len = 18 /* WAPI_HDR_LEN */;
+ icv_len = 16 /* WAPI_MIC_LEN */;
+ break;
+ default:
+ dev_err(wdev->dev, "unknown encryption type %d\n",
+ arg->rx_flags.encryp);
+ return -EIO;
+ }
+
+ /* Firmware strips ICV in case of MIC failure. */
+ if (arg->status == HIF_STATUS_MICFAILURE)
+ icv_len = 0;
+
+ if (skb->len < hdrlen + iv_len + icv_len) {
+ dev_warn(wdev->dev, "malformed SDU received\n");
+ return -EIO;
+ }
+
+ /* Remove IV, ICV and MIC */
+ skb_trim(skb, skb->len - icv_len);
+ memmove(skb->data + iv_len, skb->data, hdrlen);
+ skb_pull(skb, iv_len);
+ return 0;
+
+}
+
+void wfx_rx_cb(struct wfx_vif *wvif, struct hif_ind_rx *arg,
+ struct sk_buff *skb)
+{
+ int link_id = arg->rx_flags.peer_sta_id;
+ struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ struct wfx_link_entry *entry = NULL;
+ bool early_data = false;
+
+ memset(hdr, 0, sizeof(*hdr));
+
+ // FIXME: Why do we drop these frames?
+ if (!arg->rcpi_rssi &&
+ (ieee80211_is_probe_resp(frame->frame_control) ||
+ ieee80211_is_beacon(frame->frame_control)))
+ goto drop;
+
+ if (link_id && link_id <= WFX_MAX_STA_IN_AP_MODE) {
+ entry = &wvif->link_id_db[link_id - 1];
+ entry->timestamp = jiffies;
+ if (entry->status == WFX_LINK_SOFT &&
+ ieee80211_is_data(frame->frame_control))
+ early_data = true;
+ }
+
+ if (arg->status == HIF_STATUS_MICFAILURE)
+ hdr->flag |= RX_FLAG_MMIC_ERROR;
+ else if (arg->status)
+ goto drop;
+
+ if (skb->len < sizeof(struct ieee80211_pspoll)) {
+ dev_warn(wvif->wdev->dev, "malformed SDU received\n");
+ goto drop;
+ }
+
+ if (ieee80211_is_pspoll(frame->frame_control))
+ if (wfx_handle_pspoll(wvif, skb))
+ goto drop;
+
+ hdr->band = NL80211_BAND_2GHZ;
+ hdr->freq = ieee80211_channel_to_frequency(arg->channel_number,
+ hdr->band);
+
+ if (arg->rxed_rate >= 14) {
+ hdr->encoding = RX_ENC_HT;
+ hdr->rate_idx = arg->rxed_rate - 14;
+ } else if (arg->rxed_rate >= 4) {
+ hdr->rate_idx = arg->rxed_rate - 2;
+ } else {
+ hdr->rate_idx = arg->rxed_rate;
+ }
+
+ hdr->signal = arg->rcpi_rssi / 2 - 110;
+ hdr->antenna = 0;
+
+ if (arg->rx_flags.encryp) {
+ if (wfx_drop_encrypt_data(wvif->wdev, arg, skb))
+ goto drop;
+ hdr->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED;
+ if (arg->rx_flags.encryp == HIF_RI_FLAGS_TKIP_ENCRYPTED)
+ hdr->flag |= RX_FLAG_MMIC_STRIPPED;
+ }
+
+ /* Filter block ACK negotiation: fully controlled by firmware */
+ if (ieee80211_is_action(frame->frame_control) &&
+ arg->rx_flags.match_uc_addr &&
+ mgmt->u.action.category == WLAN_CATEGORY_BACK)
+ goto drop;
+ if (ieee80211_is_beacon(frame->frame_control) &&
+ !arg->status && wvif->vif &&
+ ether_addr_equal(ieee80211_get_SA(frame),
+ wvif->vif->bss_conf.bssid)) {
+ const u8 *tim_ie;
+ u8 *ies = mgmt->u.beacon.variable;
+ size_t ies_len = skb->len - (ies - skb->data);
+
+ tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len);
+ if (tim_ie) {
+ struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *)&tim_ie[2];
+
+ if (wvif->dtim_period != tim->dtim_period) {
+ wvif->dtim_period = tim->dtim_period;
+ schedule_work(&wvif->set_beacon_wakeup_period_work);
+ }
+ }
+
+ /* Disable beacon filter once we're associated... */
+ if (wvif->disable_beacon_filter &&
+ (wvif->vif->bss_conf.assoc ||
+ wvif->vif->bss_conf.ibss_joined)) {
+ wvif->disable_beacon_filter = false;
+ schedule_work(&wvif->update_filtering_work);
+ }
+ }
+
+ if (early_data) {
+ spin_lock_bh(&wvif->ps_state_lock);
+ /* Double-check status with lock held */
+ if (entry->status == WFX_LINK_SOFT)
+ skb_queue_tail(&entry->rx_queue, skb);
+ else
+ ieee80211_rx_irqsafe(wvif->wdev->hw, skb);
+ spin_unlock_bh(&wvif->ps_state_lock);
+ } else {
+ ieee80211_rx_irqsafe(wvif->wdev->hw, skb);
+ }
+
+ return;
+
+drop:
+ dev_kfree_skb(skb);
+}
diff --git a/drivers/staging/wfx/data_rx.h b/drivers/staging/wfx/data_rx.h
new file mode 100644
index 000000000000..b44d15268f83
--- /dev/null
+++ b/drivers/staging/wfx/data_rx.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Datapath implementation.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_DATA_RX_H
+#define WFX_DATA_RX_H
+
+#include "hif_api_cmd.h"
+
+struct wfx_vif;
+struct sk_buff;
+
+void wfx_rx_cb(struct wfx_vif *wvif, struct hif_ind_rx *arg, struct sk_buff *skb);
+
+#endif /* WFX_DATA_RX_H */
diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c
new file mode 100644
index 000000000000..ea4205ac2149
--- /dev/null
+++ b/drivers/staging/wfx/data_tx.c
@@ -0,0 +1,837 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Datapath implementation.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <net/mac80211.h>
+
+#include "data_tx.h"
+#include "wfx.h"
+#include "bh.h"
+#include "sta.h"
+#include "queue.h"
+#include "debug.h"
+#include "traces.h"
+#include "hif_tx_mib.h"
+
+#define WFX_INVALID_RATE_ID (0xFF)
+#define WFX_LINK_ID_NO_ASSOC 15
+#define WFX_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ))
+
+static int wfx_get_hw_rate(struct wfx_dev *wdev,
+ const struct ieee80211_tx_rate *rate)
+{
+ if (rate->idx < 0)
+ return -1;
+ if (rate->flags & IEEE80211_TX_RC_MCS) {
+ if (rate->idx > 7) {
+ WARN(1, "wrong rate->idx value: %d", rate->idx);
+ return -1;
+ }
+ return rate->idx + 14;
+ }
+ // WFx only support 2GHz, else band information should be retrieved
+ // from ieee80211_tx_info
+ return wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->bitrates[rate->idx].hw_value;
+}
+
+/* TX policy cache implementation */
+
+static void wfx_tx_policy_build(struct wfx_vif *wvif, struct tx_policy *policy,
+ struct ieee80211_tx_rate *rates)
+{
+ int i;
+ size_t count;
+ struct wfx_dev *wdev = wvif->wdev;
+
+ WARN(rates[0].idx < 0, "invalid rate policy");
+ memset(policy, 0, sizeof(*policy));
+ for (i = 1; i < IEEE80211_TX_MAX_RATES; i++)
+ if (rates[i].idx < 0)
+ break;
+ count = i;
+
+ /* HACK!!! Device has problems (at least) switching from
+ * 54Mbps CTS to 1Mbps. This switch takes enormous amount
+ * of time (100-200 ms), leading to valuable throughput drop.
+ * As a workaround, additional g-rates are injected to the
+ * policy.
+ */
+ if (count == 2 && !(rates[0].flags & IEEE80211_TX_RC_MCS) &&
+ rates[0].idx > 4 && rates[0].count > 2 &&
+ rates[1].idx < 2) {
+ int mid_rate = (rates[0].idx + 4) >> 1;
+
+ /* Decrease number of retries for the initial rate */
+ rates[0].count -= 2;
+
+ if (mid_rate != 4) {
+ /* Keep fallback rate at 1Mbps. */
+ rates[3] = rates[1];
+
+ /* Inject 1 transmission on lowest g-rate */
+ rates[2].idx = 4;
+ rates[2].count = 1;
+ rates[2].flags = rates[1].flags;
+
+ /* Inject 1 transmission on mid-rate */
+ rates[1].idx = mid_rate;
+ rates[1].count = 1;
+
+ /* Fallback to 1 Mbps is a really bad thing,
+ * so let's try to increase probability of
+ * successful transmission on the lowest g rate
+ * even more
+ */
+ if (rates[0].count >= 3) {
+ --rates[0].count;
+ ++rates[2].count;
+ }
+
+ /* Adjust amount of rates defined */
+ count += 2;
+ } else {
+ /* Keep fallback rate at 1Mbps. */
+ rates[2] = rates[1];
+
+ /* Inject 2 transmissions on lowest g-rate */
+ rates[1].idx = 4;
+ rates[1].count = 2;
+
+ /* Adjust amount of rates defined */
+ count += 1;
+ }
+ }
+
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; ++i) {
+ int rateid;
+ uint8_t count;
+
+ if (rates[i].idx < 0)
+ break;
+ WARN_ON(rates[i].count > 15);
+ rateid = wfx_get_hw_rate(wdev, &rates[i]);
+ // Pack two values in each byte of policy->rates
+ count = rates[i].count;
+ if (rateid % 2)
+ count <<= 4;
+ policy->rates[rateid / 2] |= count;
+ }
+}
+
+static bool tx_policy_is_equal(const struct tx_policy *a,
+ const struct tx_policy *b)
+{
+ return !memcmp(a->rates, b->rates, sizeof(a->rates));
+}
+
+static int wfx_tx_policy_find(struct tx_policy_cache *cache,
+ struct tx_policy *wanted)
+{
+ struct tx_policy *it;
+
+ list_for_each_entry(it, &cache->used, link)
+ if (tx_policy_is_equal(wanted, it))
+ return it - cache->cache;
+ list_for_each_entry(it, &cache->free, link)
+ if (tx_policy_is_equal(wanted, it))
+ return it - cache->cache;
+ return -1;
+}
+
+static void wfx_tx_policy_use(struct tx_policy_cache *cache,
+ struct tx_policy *entry)
+{
+ ++entry->usage_count;
+ list_move(&entry->link, &cache->used);
+}
+
+static int wfx_tx_policy_release(struct tx_policy_cache *cache,
+ struct tx_policy *entry)
+{
+ int ret = --entry->usage_count;
+
+ if (!ret)
+ list_move(&entry->link, &cache->free);
+ return ret;
+}
+
+static int wfx_tx_policy_get(struct wfx_vif *wvif,
+ struct ieee80211_tx_rate *rates,
+ bool *renew)
+{
+ int idx;
+ struct tx_policy_cache *cache = &wvif->tx_policy_cache;
+ struct tx_policy wanted;
+
+ wfx_tx_policy_build(wvif, &wanted, rates);
+
+ spin_lock_bh(&cache->lock);
+ if (WARN_ON(list_empty(&cache->free))) {
+ spin_unlock_bh(&cache->lock);
+ return WFX_INVALID_RATE_ID;
+ }
+ idx = wfx_tx_policy_find(cache, &wanted);
+ if (idx >= 0) {
+ *renew = false;
+ } else {
+ struct tx_policy *entry;
+ *renew = true;
+ /* If policy is not found create a new one
+ * using the oldest entry in "free" list
+ */
+ entry = list_entry(cache->free.prev, struct tx_policy, link);
+ memcpy(entry->rates, wanted.rates, sizeof(entry->rates));
+ entry->uploaded = 0;
+ entry->usage_count = 0;
+ idx = entry - cache->cache;
+ }
+ wfx_tx_policy_use(cache, &cache->cache[idx]);
+ if (list_empty(&cache->free)) {
+ /* Lock TX queues. */
+ wfx_tx_queues_lock(wvif->wdev);
+ }
+ spin_unlock_bh(&cache->lock);
+ return idx;
+}
+
+static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx)
+{
+ int usage, locked;
+ struct tx_policy_cache *cache = &wvif->tx_policy_cache;
+
+ spin_lock_bh(&cache->lock);
+ locked = list_empty(&cache->free);
+ usage = wfx_tx_policy_release(cache, &cache->cache[idx]);
+ if (locked && !usage) {
+ /* Unlock TX queues. */
+ wfx_tx_queues_unlock(wvif->wdev);
+ }
+ spin_unlock_bh(&cache->lock);
+}
+
+static int wfx_tx_policy_upload(struct wfx_vif *wvif)
+{
+ int i;
+ struct tx_policy_cache *cache = &wvif->tx_policy_cache;
+ struct hif_mib_set_tx_rate_retry_policy *arg =
+ kzalloc(struct_size(arg,
+ tx_rate_retry_policy,
+ HIF_MIB_NUM_TX_RATE_RETRY_POLICIES),
+ GFP_KERNEL);
+ struct hif_mib_tx_rate_retry_policy *dst;
+
+ spin_lock_bh(&cache->lock);
+ /* Upload only modified entries. */
+ for (i = 0; i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES; ++i) {
+ struct tx_policy *src = &cache->cache[i];
+
+ if (!src->uploaded && memzcmp(src->rates, sizeof(src->rates))) {
+ dst = arg->tx_rate_retry_policy +
+ arg->num_tx_rate_policies;
+
+ dst->policy_index = i;
+ dst->short_retry_count = 255;
+ dst->long_retry_count = 255;
+ dst->first_rate_sel = 1;
+ dst->terminate = 1;
+ dst->count_init = 1;
+ memcpy(&dst->rates, src->rates, sizeof(src->rates));
+ src->uploaded = 1;
+ arg->num_tx_rate_policies++;
+ }
+ }
+ spin_unlock_bh(&cache->lock);
+ hif_set_tx_rate_retry_policy(wvif, arg);
+ kfree(arg);
+ return 0;
+}
+
+static void wfx_tx_policy_upload_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif =
+ container_of(work, struct wfx_vif, tx_policy_upload_work);
+
+ wfx_tx_policy_upload(wvif);
+
+ wfx_tx_unlock(wvif->wdev);
+ wfx_tx_queues_unlock(wvif->wdev);
+}
+
+void wfx_tx_policy_init(struct wfx_vif *wvif)
+{
+ struct tx_policy_cache *cache = &wvif->tx_policy_cache;
+ int i;
+
+ memset(cache, 0, sizeof(*cache));
+
+ spin_lock_init(&cache->lock);
+ INIT_LIST_HEAD(&cache->used);
+ INIT_LIST_HEAD(&cache->free);
+ INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
+
+ for (i = 0; i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES; ++i)
+ list_add(&cache->cache[i].link, &cache->free);
+}
+
+/* Link ID related functions */
+
+static int wfx_alloc_link_id(struct wfx_vif *wvif, const u8 *mac)
+{
+ int i, ret = 0;
+ unsigned long max_inactivity = 0;
+ unsigned long now = jiffies;
+
+ spin_lock_bh(&wvif->ps_state_lock);
+ for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) {
+ if (!wvif->link_id_db[i].status) {
+ ret = i + 1;
+ break;
+ } else if (wvif->link_id_db[i].status != WFX_LINK_HARD &&
+ !wvif->wdev->tx_queue_stats.link_map_cache[i + 1]) {
+ unsigned long inactivity =
+ now - wvif->link_id_db[i].timestamp;
+
+ if (inactivity < max_inactivity)
+ continue;
+ max_inactivity = inactivity;
+ ret = i + 1;
+ }
+ }
+
+ if (ret) {
+ struct wfx_link_entry *entry = &wvif->link_id_db[ret - 1];
+
+ entry->status = WFX_LINK_RESERVE;
+ ether_addr_copy(entry->mac, mac);
+ memset(&entry->buffered, 0, WFX_MAX_TID);
+ skb_queue_head_init(&entry->rx_queue);
+ wfx_tx_lock(wvif->wdev);
+
+ if (!schedule_work(&wvif->link_id_work))
+ wfx_tx_unlock(wvif->wdev);
+ } else {
+ dev_info(wvif->wdev->dev, "no more link-id available\n");
+ }
+ spin_unlock_bh(&wvif->ps_state_lock);
+ return ret;
+}
+
+int wfx_find_link_id(struct wfx_vif *wvif, const u8 *mac)
+{
+ int i, ret = 0;
+
+ spin_lock_bh(&wvif->ps_state_lock);
+ for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) {
+ if (ether_addr_equal(mac, wvif->link_id_db[i].mac) &&
+ wvif->link_id_db[i].status) {
+ wvif->link_id_db[i].timestamp = jiffies;
+ ret = i + 1;
+ break;
+ }
+ }
+ spin_unlock_bh(&wvif->ps_state_lock);
+ return ret;
+}
+
+static int wfx_map_link(struct wfx_vif *wvif,
+ struct wfx_link_entry *link_entry, int sta_id)
+{
+ int ret;
+
+ ret = hif_map_link(wvif, link_entry->mac, 0, sta_id);
+
+ if (ret == 0)
+ /* Save the MAC address currently associated with the peer
+ * for future unmap request
+ */
+ ether_addr_copy(link_entry->old_mac, link_entry->mac);
+
+ return ret;
+}
+
+int wfx_unmap_link(struct wfx_vif *wvif, int sta_id)
+{
+ u8 *mac_addr = NULL;
+
+ if (sta_id)
+ mac_addr = wvif->link_id_db[sta_id - 1].old_mac;
+
+ return hif_map_link(wvif, mac_addr, 1, sta_id);
+}
+
+void wfx_link_id_gc_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif =
+ container_of(work, struct wfx_vif, link_id_gc_work.work);
+ unsigned long now = jiffies;
+ unsigned long next_gc = -1;
+ long ttl;
+ u32 mask;
+ int i;
+
+ if (wvif->state != WFX_STATE_AP)
+ return;
+
+ wfx_tx_lock_flush(wvif->wdev);
+ spin_lock_bh(&wvif->ps_state_lock);
+ for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) {
+ bool need_reset = false;
+
+ mask = BIT(i + 1);
+ if (wvif->link_id_db[i].status == WFX_LINK_RESERVE ||
+ (wvif->link_id_db[i].status == WFX_LINK_HARD &&
+ !(wvif->link_id_map & mask))) {
+ if (wvif->link_id_map & mask) {
+ wvif->sta_asleep_mask &= ~mask;
+ wvif->pspoll_mask &= ~mask;
+ need_reset = true;
+ }
+ wvif->link_id_map |= mask;
+ if (wvif->link_id_db[i].status != WFX_LINK_HARD)
+ wvif->link_id_db[i].status = WFX_LINK_SOFT;
+
+ spin_unlock_bh(&wvif->ps_state_lock);
+ if (need_reset)
+ wfx_unmap_link(wvif, i + 1);
+ wfx_map_link(wvif, &wvif->link_id_db[i], i + 1);
+ next_gc = min(next_gc, WFX_LINK_ID_GC_TIMEOUT);
+ spin_lock_bh(&wvif->ps_state_lock);
+ } else if (wvif->link_id_db[i].status == WFX_LINK_SOFT) {
+ ttl = wvif->link_id_db[i].timestamp - now +
+ WFX_LINK_ID_GC_TIMEOUT;
+ if (ttl <= 0) {
+ need_reset = true;
+ wvif->link_id_db[i].status = WFX_LINK_OFF;
+ wvif->link_id_map &= ~mask;
+ wvif->sta_asleep_mask &= ~mask;
+ wvif->pspoll_mask &= ~mask;
+ spin_unlock_bh(&wvif->ps_state_lock);
+ wfx_unmap_link(wvif, i + 1);
+ spin_lock_bh(&wvif->ps_state_lock);
+ } else {
+ next_gc = min_t(unsigned long, next_gc, ttl);
+ }
+ }
+ if (need_reset)
+ skb_queue_purge(&wvif->link_id_db[i].rx_queue);
+ }
+ spin_unlock_bh(&wvif->ps_state_lock);
+ if (next_gc != -1)
+ schedule_delayed_work(&wvif->link_id_gc_work, next_gc);
+ wfx_tx_unlock(wvif->wdev);
+}
+
+void wfx_link_id_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif =
+ container_of(work, struct wfx_vif, link_id_work);
+
+ wfx_tx_flush(wvif->wdev);
+ wfx_link_id_gc_work(&wvif->link_id_gc_work.work);
+ wfx_tx_unlock(wvif->wdev);
+}
+
+/* Tx implementation */
+
+static bool ieee80211_is_action_back(struct ieee80211_hdr *hdr)
+{
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr;
+
+ if (!ieee80211_is_action(mgmt->frame_control))
+ return false;
+ if (mgmt->u.action.category != WLAN_CATEGORY_BACK)
+ return false;
+ return true;
+}
+
+static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr,
+ struct wfx_tx_priv *tx_priv,
+ struct ieee80211_sta *sta)
+{
+ u32 mask = ~BIT(tx_priv->raw_link_id);
+
+ spin_lock_bh(&wvif->ps_state_lock);
+ if (ieee80211_is_auth(hdr->frame_control)) {
+ wvif->sta_asleep_mask &= mask;
+ wvif->pspoll_mask &= mask;
+ }
+
+ if (tx_priv->link_id == WFX_LINK_ID_AFTER_DTIM &&
+ !wvif->mcast_buffered) {
+ wvif->mcast_buffered = true;
+ if (wvif->sta_asleep_mask)
+ schedule_work(&wvif->mcast_start_work);
+ }
+
+ if (tx_priv->raw_link_id) {
+ wvif->link_id_db[tx_priv->raw_link_id - 1].timestamp = jiffies;
+ if (tx_priv->tid < WFX_MAX_TID)
+ wvif->link_id_db[tx_priv->raw_link_id - 1].buffered[tx_priv->tid]++;
+ }
+ spin_unlock_bh(&wvif->ps_state_lock);
+
+ if (sta)
+ ieee80211_sta_set_buffered(sta, tx_priv->tid, true);
+}
+
+static uint8_t wfx_tx_get_raw_link_id(struct wfx_vif *wvif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_hdr *hdr)
+{
+ struct wfx_sta_priv *sta_priv =
+ sta ? (struct wfx_sta_priv *) &sta->drv_priv : NULL;
+ const u8 *da = ieee80211_get_DA(hdr);
+ int ret;
+
+ if (sta_priv && sta_priv->link_id)
+ return sta_priv->link_id;
+ if (wvif->vif->type != NL80211_IFTYPE_AP)
+ return 0;
+ if (is_multicast_ether_addr(da))
+ return 0;
+ ret = wfx_find_link_id(wvif, da);
+ if (!ret)
+ ret = wfx_alloc_link_id(wvif, da);
+ if (!ret) {
+ dev_err(wvif->wdev->dev, "no more link-id available\n");
+ return WFX_LINK_ID_NO_ASSOC;
+ }
+ return ret;
+}
+
+static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates)
+{
+ int i;
+ bool finished;
+
+ // Firmware is not able to mix rates with differents flags
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ if (rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
+ rates[i].flags |= IEEE80211_TX_RC_SHORT_GI;
+ if (!(rates[0].flags & IEEE80211_TX_RC_SHORT_GI))
+ rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI;
+ if (!(rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS))
+ rates[i].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS;
+ }
+
+ // Sort rates and remove duplicates
+ do {
+ finished = true;
+ for (i = 0; i < IEEE80211_TX_MAX_RATES - 1; i++) {
+ if (rates[i + 1].idx == rates[i].idx &&
+ rates[i].idx != -1) {
+ rates[i].count =
+ max_t(int, rates[i].count,
+ rates[i + 1].count);
+ rates[i + 1].idx = -1;
+ rates[i + 1].count = 0;
+
+ finished = false;
+ }
+ if (rates[i + 1].idx > rates[i].idx) {
+ swap(rates[i + 1], rates[i]);
+ finished = false;
+ }
+ }
+ } while (!finished);
+ // All retries use long GI
+ for (i = 1; i < IEEE80211_TX_MAX_RATES; i++)
+ rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI;
+}
+
+static uint8_t wfx_tx_get_rate_id(struct wfx_vif *wvif,
+ struct ieee80211_tx_info *tx_info)
+{
+ bool tx_policy_renew = false;
+ uint8_t rate_id;
+
+ rate_id = wfx_tx_policy_get(wvif,
+ tx_info->driver_rates, &tx_policy_renew);
+ WARN(rate_id == WFX_INVALID_RATE_ID, "unable to get a valid Tx policy");
+
+ if (tx_policy_renew) {
+ /* FIXME: It's not so optimal to stop TX queues every now and
+ * then. Better to reimplement task scheduling with a counter.
+ */
+ wfx_tx_lock(wvif->wdev);
+ wfx_tx_queues_lock(wvif->wdev);
+ if (!schedule_work(&wvif->tx_policy_upload_work)) {
+ wfx_tx_queues_unlock(wvif->wdev);
+ wfx_tx_unlock(wvif->wdev);
+ }
+ }
+ return rate_id;
+}
+
+static struct hif_ht_tx_parameters wfx_tx_get_tx_parms(struct wfx_dev *wdev, struct ieee80211_tx_info *tx_info)
+{
+ struct ieee80211_tx_rate *rate = &tx_info->driver_rates[0];
+ struct hif_ht_tx_parameters ret = { };
+
+ if (!(rate->flags & IEEE80211_TX_RC_MCS))
+ ret.frame_format = HIF_FRAME_FORMAT_NON_HT;
+ else if (!(rate->flags & IEEE80211_TX_RC_GREEN_FIELD))
+ ret.frame_format = HIF_FRAME_FORMAT_MIXED_FORMAT_HT;
+ else
+ ret.frame_format = HIF_FRAME_FORMAT_GF_HT_11N;
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ ret.short_gi = 1;
+ if (tx_info->flags & IEEE80211_TX_CTL_STBC)
+ ret.stbc = 0; // FIXME: Not yet supported by firmware?
+ return ret;
+}
+
+static uint8_t wfx_tx_get_tid(struct ieee80211_hdr *hdr)
+{
+ // FIXME: ieee80211_get_tid(hdr) should be sufficient for all cases.
+ if (!ieee80211_is_data(hdr->frame_control))
+ return WFX_MAX_TID;
+ if (ieee80211_is_data_qos(hdr->frame_control))
+ return ieee80211_get_tid(hdr);
+ else
+ return 0;
+}
+
+static int wfx_tx_get_icv_len(struct ieee80211_key_conf *hw_key)
+{
+ int mic_space;
+
+ if (!hw_key)
+ return 0;
+ mic_space = (hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) ? 8 : 0;
+ return hw_key->icv_len + mic_space;
+}
+
+static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta,
+ struct sk_buff *skb)
+{
+ struct hif_msg *hif_msg;
+ struct hif_req_tx *req;
+ struct wfx_tx_priv *tx_priv;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ int queue_id = tx_info->hw_queue;
+ size_t offset = (size_t) skb->data & 3;
+ int wmsg_len = sizeof(struct hif_msg) +
+ sizeof(struct hif_req_tx) + offset;
+
+ WARN(queue_id >= IEEE80211_NUM_ACS, "unsupported queue_id");
+ wfx_tx_fixup_rates(tx_info->driver_rates);
+
+ // From now tx_info->control is unusable
+ memset(tx_info->rate_driver_data, 0, sizeof(struct wfx_tx_priv));
+ // Fill tx_priv
+ tx_priv = (struct wfx_tx_priv *)tx_info->rate_driver_data;
+ tx_priv->tid = wfx_tx_get_tid(hdr);
+ tx_priv->raw_link_id = wfx_tx_get_raw_link_id(wvif, sta, hdr);
+ tx_priv->link_id = tx_priv->raw_link_id;
+ if (ieee80211_has_protected(hdr->frame_control))
+ tx_priv->hw_key = hw_key;
+ if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)
+ tx_priv->link_id = WFX_LINK_ID_AFTER_DTIM;
+ if (sta && (sta->uapsd_queues & BIT(queue_id)))
+ tx_priv->link_id = WFX_LINK_ID_UAPSD;
+
+ // Fill hif_msg
+ WARN(skb_headroom(skb) < wmsg_len, "not enough space in skb");
+ WARN(offset & 1, "attempt to transmit an unaligned frame");
+ skb_put(skb, wfx_tx_get_icv_len(tx_priv->hw_key));
+ skb_push(skb, wmsg_len);
+ memset(skb->data, 0, wmsg_len);
+ hif_msg = (struct hif_msg *)skb->data;
+ hif_msg->len = cpu_to_le16(skb->len);
+ hif_msg->id = HIF_REQ_ID_TX;
+ hif_msg->interface = wvif->id;
+ if (skb->len > wvif->wdev->hw_caps.size_inp_ch_buf) {
+ dev_warn(wvif->wdev->dev, "requested frame size (%d) is larger than maximum supported (%d)\n",
+ skb->len, wvif->wdev->hw_caps.size_inp_ch_buf);
+ skb_pull(skb, wmsg_len);
+ return -EIO;
+ }
+
+ // Fill tx request
+ req = (struct hif_req_tx *)hif_msg->body;
+ req->packet_id = queue_id << 16 |
+ IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
+ req->data_flags.fc_offset = offset;
+ req->queue_id.peer_sta_id = tx_priv->raw_link_id;
+ // Queue index are inverted between firmware and Linux
+ req->queue_id.queue_id = 3 - queue_id;
+ req->ht_tx_parameters = wfx_tx_get_tx_parms(wvif->wdev, tx_info);
+ req->tx_flags.retry_policy_index = wfx_tx_get_rate_id(wvif, tx_info);
+
+ // Auxiliary operations
+ wfx_tx_manage_pm(wvif, hdr, tx_priv, sta);
+ wfx_tx_queue_put(wvif->wdev, &wvif->wdev->tx_queue[queue_id], skb);
+ wfx_bh_request_tx(wvif->wdev);
+ return 0;
+}
+
+void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+ struct sk_buff *skb)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif;
+ struct ieee80211_sta *sta = control ? control->sta : NULL;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ size_t driver_data_room = FIELD_SIZEOF(struct ieee80211_tx_info,
+ rate_driver_data);
+
+ compiletime_assert(sizeof(struct wfx_tx_priv) <= driver_data_room,
+ "struct tx_priv is too large");
+ WARN(skb->next || skb->prev, "skb is already member of a list");
+ // control.vif can be NULL for injected frames
+ if (tx_info->control.vif)
+ wvif = (struct wfx_vif *)tx_info->control.vif->drv_priv;
+ else
+ wvif = wvif_iterate(wdev, NULL);
+ if (WARN_ON(!wvif))
+ goto drop;
+ // FIXME: why?
+ if (ieee80211_is_action_back(hdr)) {
+ dev_info(wdev->dev, "drop BA action\n");
+ goto drop;
+ }
+ if (wfx_tx_inner(wvif, sta, skb))
+ goto drop;
+
+ return;
+
+drop:
+ ieee80211_tx_status_irqsafe(wdev->hw, skb);
+}
+
+void wfx_tx_confirm_cb(struct wfx_vif *wvif, struct hif_cnf_tx *arg)
+{
+ int i;
+ int tx_count;
+ struct sk_buff *skb;
+ struct ieee80211_tx_rate *rate;
+ struct ieee80211_tx_info *tx_info;
+ const struct wfx_tx_priv *tx_priv;
+
+ skb = wfx_pending_get(wvif->wdev, arg->packet_id);
+ if (!skb) {
+ dev_warn(wvif->wdev->dev,
+ "received unknown packet_id (%#.8x) from chip\n",
+ arg->packet_id);
+ return;
+ }
+ tx_info = IEEE80211_SKB_CB(skb);
+ tx_priv = wfx_skb_tx_priv(skb);
+ _trace_tx_stats(arg, skb,
+ wfx_pending_get_pkt_us_delay(wvif->wdev, skb));
+
+ // You can touch to tx_priv, but don't touch to tx_info->status.
+ tx_count = arg->ack_failures;
+ if (!arg->status || arg->ack_failures)
+ tx_count += 1; // Also report success
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ rate = &tx_info->status.rates[i];
+ if (rate->idx < 0)
+ break;
+ if (tx_count < rate->count && arg->status && arg->ack_failures)
+ dev_dbg(wvif->wdev->dev, "all retries were not consumed: %d != %d\n",
+ rate->count, tx_count);
+ if (tx_count <= rate->count && tx_count &&
+ arg->txed_rate != wfx_get_hw_rate(wvif->wdev, rate))
+ dev_dbg(wvif->wdev->dev,
+ "inconsistent tx_info rates: %d != %d\n",
+ arg->txed_rate,
+ wfx_get_hw_rate(wvif->wdev, rate));
+ if (tx_count > rate->count) {
+ tx_count -= rate->count;
+ } else if (!tx_count) {
+ rate->count = 0;
+ rate->idx = -1;
+ } else {
+ rate->count = tx_count;
+ tx_count = 0;
+ }
+ }
+ if (tx_count)
+ dev_dbg(wvif->wdev->dev,
+ "%d more retries than expected\n", tx_count);
+ skb_trim(skb, skb->len - wfx_tx_get_icv_len(tx_priv->hw_key));
+
+ // From now, you can touch to tx_info->status, but do not touch to
+ // tx_priv anymore
+ // FIXME: use ieee80211_tx_info_clear_status()
+ memset(tx_info->rate_driver_data, 0, sizeof(tx_info->rate_driver_data));
+ memset(tx_info->pad, 0, sizeof(tx_info->pad));
+
+ if (!arg->status) {
+ if (wvif->bss_loss_state &&
+ arg->packet_id == wvif->bss_loss_confirm_id)
+ wfx_cqm_bssloss_sm(wvif, 0, 1, 0);
+ tx_info->status.tx_time =
+ arg->media_delay - arg->tx_queue_delay;
+ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+ tx_info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+ else
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+ } else if (arg->status == HIF_REQUEUE) {
+ /* "REQUEUE" means "implicit suspend" */
+ struct hif_ind_suspend_resume_tx suspend = {
+ .suspend_resume_flags.resume = 0,
+ .suspend_resume_flags.bc_mc_only = 1,
+ };
+
+ WARN(!arg->tx_result_flags.requeue, "incoherent status and result_flags");
+ wfx_suspend_resume(wvif, &suspend);
+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+ } else {
+ if (wvif->bss_loss_state &&
+ arg->packet_id == wvif->bss_loss_confirm_id)
+ wfx_cqm_bssloss_sm(wvif, 0, 0, 1);
+ }
+ wfx_pending_remove(wvif->wdev, skb);
+}
+
+static void wfx_notify_buffered_tx(struct wfx_vif *wvif, struct sk_buff *skb,
+ struct hif_req_tx *req)
+{
+ struct ieee80211_sta *sta;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ int tid = wfx_tx_get_tid(hdr);
+ int raw_link_id = req->queue_id.peer_sta_id;
+ u8 *buffered;
+
+ if (raw_link_id && tid < WFX_MAX_TID) {
+ buffered = wvif->link_id_db[raw_link_id - 1].buffered;
+
+ spin_lock_bh(&wvif->ps_state_lock);
+ WARN(!buffered[tid], "inconsistent notification");
+ buffered[tid]--;
+ spin_unlock_bh(&wvif->ps_state_lock);
+
+ if (!buffered[tid]) {
+ rcu_read_lock();
+ sta = ieee80211_find_sta(wvif->vif, hdr->addr1);
+ if (sta)
+ ieee80211_sta_set_buffered(sta, tid, false);
+ rcu_read_unlock();
+ }
+ }
+}
+
+void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb)
+{
+ struct hif_msg *hif = (struct hif_msg *)skb->data;
+ struct hif_req_tx *req = (struct hif_req_tx *)hif->body;
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+ unsigned int offset = sizeof(struct hif_req_tx) +
+ sizeof(struct hif_msg) +
+ req->data_flags.fc_offset;
+
+ WARN_ON(!wvif);
+ skb_pull(skb, offset);
+ wfx_notify_buffered_tx(wvif, skb, req);
+ wfx_tx_policy_put(wvif, req->tx_flags.retry_policy_index);
+ ieee80211_tx_status_irqsafe(wdev->hw, skb);
+}
diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h
new file mode 100644
index 000000000000..f74d1988925d
--- /dev/null
+++ b/drivers/staging/wfx/data_tx.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Datapath implementation.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_DATA_TX_H
+#define WFX_DATA_TX_H
+
+#include <linux/list.h>
+#include <net/mac80211.h>
+
+#include "hif_api_cmd.h"
+#include "hif_api_mib.h"
+
+// FIXME: use IEEE80211_NUM_TIDS
+#define WFX_MAX_TID 8
+
+struct wfx_tx_priv;
+struct wfx_dev;
+struct wfx_vif;
+
+enum wfx_link_status {
+ WFX_LINK_OFF,
+ WFX_LINK_RESERVE,
+ WFX_LINK_SOFT,
+ WFX_LINK_HARD,
+};
+
+struct wfx_link_entry {
+ unsigned long timestamp;
+ enum wfx_link_status status;
+ uint8_t mac[ETH_ALEN];
+ uint8_t old_mac[ETH_ALEN];
+ uint8_t buffered[WFX_MAX_TID];
+ struct sk_buff_head rx_queue;
+};
+
+struct tx_policy {
+ struct list_head link;
+ uint8_t rates[12];
+ uint8_t usage_count;
+ uint8_t uploaded;
+};
+
+struct tx_policy_cache {
+ struct tx_policy cache[HIF_MIB_NUM_TX_RATE_RETRY_POLICIES];
+ // FIXME: use a trees and drop hash from tx_policy
+ struct list_head used;
+ struct list_head free;
+ spinlock_t lock;
+};
+
+struct wfx_tx_priv {
+ ktime_t xmit_timestamp;
+ struct ieee80211_key_conf *hw_key;
+ uint8_t link_id;
+ uint8_t raw_link_id;
+ uint8_t tid;
+} __packed;
+
+void wfx_tx_policy_init(struct wfx_vif *wvif);
+
+void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+ struct sk_buff *skb);
+void wfx_tx_confirm_cb(struct wfx_vif *wvif, struct hif_cnf_tx *arg);
+void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb);
+
+int wfx_unmap_link(struct wfx_vif *wvif, int link_id);
+void wfx_link_id_work(struct work_struct *work);
+void wfx_link_id_gc_work(struct work_struct *work);
+int wfx_find_link_id(struct wfx_vif *wvif, const u8 *mac);
+
+static inline struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *tx_info;
+
+ if (!skb)
+ return NULL;
+ tx_info = IEEE80211_SKB_CB(skb);
+ return (struct wfx_tx_priv *)tx_info->rate_driver_data;
+}
+
+static inline struct hif_req_tx *wfx_skb_txreq(struct sk_buff *skb)
+{
+ struct hif_msg *hif = (struct hif_msg *)skb->data;
+ struct hif_req_tx *req = (struct hif_req_tx *) hif->body;
+
+ return req;
+}
+
+#endif /* WFX_DATA_TX_H */
diff --git a/drivers/staging/wfx/debug.c b/drivers/staging/wfx/debug.c
new file mode 100644
index 000000000000..0a9ca109039c
--- /dev/null
+++ b/drivers/staging/wfx/debug.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Debugfs interface.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/crc32.h>
+
+#include "debug.h"
+#include "wfx.h"
+#include "sta.h"
+#include "main.h"
+#include "hif_tx.h"
+#include "hif_tx_mib.h"
+
+#define CREATE_TRACE_POINTS
+#include "traces.h"
+
+static const struct trace_print_flags hif_msg_print_map[] = {
+ hif_msg_list,
+};
+
+static const struct trace_print_flags hif_mib_print_map[] = {
+ hif_mib_list,
+};
+
+static const struct trace_print_flags wfx_reg_print_map[] = {
+ wfx_reg_list,
+};
+
+static const char *get_symbol(unsigned long val,
+ const struct trace_print_flags *symbol_array)
+{
+ int i;
+
+ for (i = 0; symbol_array[i].mask != -1; i++) {
+ if (val == symbol_array[i].mask)
+ return symbol_array[i].name;
+ }
+
+ return "unknown";
+}
+
+const char *get_hif_name(unsigned long id)
+{
+ return get_symbol(id, hif_msg_print_map);
+}
+
+const char *get_mib_name(unsigned long id)
+{
+ return get_symbol(id, hif_mib_print_map);
+}
+
+const char *get_reg_name(unsigned long id)
+{
+ return get_symbol(id, wfx_reg_print_map);
+}
+
+static int wfx_counters_show(struct seq_file *seq, void *v)
+{
+ int ret;
+ struct wfx_dev *wdev = seq->private;
+ struct hif_mib_extended_count_table counters;
+
+ ret = hif_get_counters_table(wdev, &counters);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ return -EIO;
+
+#define PUT_COUNTER(name) \
+ seq_printf(seq, "%24s %d\n", #name ":", le32_to_cpu(counters.count_##name))
+
+ PUT_COUNTER(tx_packets);
+ PUT_COUNTER(tx_multicast_frames);
+ PUT_COUNTER(tx_frames_success);
+ PUT_COUNTER(tx_frame_failures);
+ PUT_COUNTER(tx_frames_retried);
+ PUT_COUNTER(tx_frames_multi_retried);
+
+ PUT_COUNTER(rts_success);
+ PUT_COUNTER(rts_failures);
+ PUT_COUNTER(ack_failures);
+
+ PUT_COUNTER(rx_packets);
+ PUT_COUNTER(rx_frames_success);
+ PUT_COUNTER(rx_packet_errors);
+ PUT_COUNTER(plcp_errors);
+ PUT_COUNTER(fcs_errors);
+ PUT_COUNTER(rx_decryption_failures);
+ PUT_COUNTER(rx_mic_failures);
+ PUT_COUNTER(rx_no_key_failures);
+ PUT_COUNTER(rx_frame_duplicates);
+ PUT_COUNTER(rx_multicast_frames);
+ PUT_COUNTER(rx_cmacicv_errors);
+ PUT_COUNTER(rx_cmac_replays);
+ PUT_COUNTER(rx_mgmt_ccmp_replays);
+
+ PUT_COUNTER(rx_beacon);
+ PUT_COUNTER(miss_beacon);
+
+#undef PUT_COUNTER
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(wfx_counters);
+
+static const char * const channel_names[] = {
+ [0] = "1M",
+ [1] = "2M",
+ [2] = "5.5M",
+ [3] = "11M",
+ /* Entries 4 and 5 does not exist */
+ [6] = "6M",
+ [7] = "9M",
+ [8] = "12M",
+ [9] = "18M",
+ [10] = "24M",
+ [11] = "36M",
+ [12] = "48M",
+ [13] = "54M",
+ [14] = "MCS0",
+ [15] = "MCS1",
+ [16] = "MCS2",
+ [17] = "MCS3",
+ [18] = "MCS4",
+ [19] = "MCS5",
+ [20] = "MCS6",
+ [21] = "MCS7",
+};
+
+static int wfx_rx_stats_show(struct seq_file *seq, void *v)
+{
+ struct wfx_dev *wdev = seq->private;
+ struct hif_rx_stats *st = &wdev->rx_stats;
+ int i;
+
+ mutex_lock(&wdev->rx_stats_lock);
+ seq_printf(seq, "Timestamp: %dus\n", st->date);
+ seq_printf(seq, "Low power clock: frequency %uHz, external %s\n",
+ st->pwr_clk_freq,
+ st->is_ext_pwr_clk ? "yes" : "no");
+ seq_printf(seq,
+ "N. of frames: %d, PER (x10e4): %d, Throughput: %dKbps/s\n",
+ st->nb_rx_frame, st->per_total, st->throughput);
+ seq_puts(seq, " Num. of PER RSSI SNR CFO\n");
+ seq_puts(seq, " frames (x10e4) (dBm) (dB) (kHz)\n");
+ for (i = 0; i < ARRAY_SIZE(channel_names); i++) {
+ if (channel_names[i])
+ seq_printf(seq, "%5s %8d %8d %8d %8d %8d\n",
+ channel_names[i], st->nb_rx_by_rate[i],
+ st->per[i], st->rssi[i] / 100,
+ st->snr[i] / 100, st->cfo[i]);
+ }
+ mutex_unlock(&wdev->rx_stats_lock);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(wfx_rx_stats);
+
+static ssize_t wfx_send_pds_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wfx_dev *wdev = file->private_data;
+ char *buf;
+ int ret;
+
+ if (*ppos != 0) {
+ dev_dbg(wdev->dev, "PDS data must be written in one transaction");
+ return -EBUSY;
+ }
+ buf = memdup_user(user_buf, count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+ *ppos = *ppos + count;
+ ret = wfx_send_pds(wdev, buf, count);
+ kfree(buf);
+ if (ret < 0)
+ return ret;
+ return count;
+}
+
+static const struct file_operations wfx_send_pds_fops = {
+ .open = simple_open,
+ .write = wfx_send_pds_write,
+};
+
+static ssize_t wfx_burn_slk_key_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wfx_dev *wdev = file->private_data;
+
+ dev_info(wdev->dev, "this driver does not support secure link\n");
+ return -EINVAL;
+}
+
+static const struct file_operations wfx_burn_slk_key_fops = {
+ .open = simple_open,
+ .write = wfx_burn_slk_key_write,
+};
+
+struct dbgfs_hif_msg {
+ struct wfx_dev *wdev;
+ struct completion complete;
+ u8 reply[1024];
+ int ret;
+};
+
+static ssize_t wfx_send_hif_msg_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct dbgfs_hif_msg *context = file->private_data;
+ struct wfx_dev *wdev = context->wdev;
+ struct hif_msg *request;
+
+ if (completion_done(&context->complete)) {
+ dev_dbg(wdev->dev, "read previous result before start a new one\n");
+ return -EBUSY;
+ }
+ if (count < sizeof(struct hif_msg))
+ return -EINVAL;
+
+ // wfx_cmd_send() chekc that reply buffer is wide enough, but do not
+ // return precise length read. User have to know how many bytes should
+ // be read. Filling reply buffer with a memory pattern may help user.
+ memset(context->reply, 0xFF, sizeof(context->reply));
+ request = memdup_user(user_buf, count);
+ if (IS_ERR(request))
+ return PTR_ERR(request);
+ if (request->len != count) {
+ kfree(request);
+ return -EINVAL;
+ }
+ context->ret = wfx_cmd_send(wdev, request, context->reply, sizeof(context->reply), false);
+
+ kfree(request);
+ complete(&context->complete);
+ return count;
+}
+
+static ssize_t wfx_send_hif_msg_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct dbgfs_hif_msg *context = file->private_data;
+ int ret;
+
+ if (count > sizeof(context->reply))
+ return -EINVAL;
+ ret = wait_for_completion_interruptible(&context->complete);
+ if (ret)
+ return ret;
+ if (context->ret < 0)
+ return context->ret;
+ // Be carefull, write() is waiting for a full message while read()
+ // only return a payload
+ if (copy_to_user(user_buf, context->reply, count))
+ return -EFAULT;
+
+ return count;
+}
+
+static int wfx_send_hif_msg_open(struct inode *inode, struct file *file)
+{
+ struct dbgfs_hif_msg *context = kzalloc(sizeof(*context), GFP_KERNEL);
+
+ if (!context)
+ return -ENOMEM;
+ context->wdev = inode->i_private;
+ init_completion(&context->complete);
+ file->private_data = context;
+ return 0;
+}
+
+static int wfx_send_hif_msg_release(struct inode *inode, struct file *file)
+{
+ struct dbgfs_hif_msg *context = file->private_data;
+
+ kfree(context);
+ return 0;
+}
+
+static const struct file_operations wfx_send_hif_msg_fops = {
+ .open = wfx_send_hif_msg_open,
+ .release = wfx_send_hif_msg_release,
+ .write = wfx_send_hif_msg_write,
+ .read = wfx_send_hif_msg_read,
+};
+
+int wfx_debug_init(struct wfx_dev *wdev)
+{
+ struct dentry *d;
+
+ d = debugfs_create_dir("wfx", wdev->hw->wiphy->debugfsdir);
+ debugfs_create_file("counters", 0444, d, wdev, &wfx_counters_fops);
+ debugfs_create_file("rx_stats", 0444, d, wdev, &wfx_rx_stats_fops);
+ debugfs_create_file("send_pds", 0200, d, wdev, &wfx_send_pds_fops);
+ debugfs_create_file("burn_slk_key", 0200, d, wdev, &wfx_burn_slk_key_fops);
+ debugfs_create_file("send_hif_msg", 0600, d, wdev, &wfx_send_hif_msg_fops);
+
+ return 0;
+}
diff --git a/drivers/staging/wfx/debug.h b/drivers/staging/wfx/debug.h
new file mode 100644
index 000000000000..6f2f84d64c9e
--- /dev/null
+++ b/drivers/staging/wfx/debug.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Debugfs interface.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2011, ST-Ericsson
+ */
+#ifndef WFX_DEBUG_H
+#define WFX_DEBUG_H
+
+struct wfx_dev;
+
+int wfx_debug_init(struct wfx_dev *wdev);
+
+const char *get_hif_name(unsigned long id);
+const char *get_mib_name(unsigned long id);
+const char *get_reg_name(unsigned long id);
+
+#endif /* WFX_DEBUG_H */
diff --git a/drivers/staging/wfx/fwio.c b/drivers/staging/wfx/fwio.c
new file mode 100644
index 000000000000..6d82c6244c7f
--- /dev/null
+++ b/drivers/staging/wfx/fwio.c
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Firmware loading.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/bitfield.h>
+
+#include "fwio.h"
+#include "wfx.h"
+#include "hwio.h"
+
+// Addresses below are in SRAM area
+#define WFX_DNLD_FIFO 0x09004000
+#define DNLD_BLOCK_SIZE 0x0400
+#define DNLD_FIFO_SIZE 0x8000 // (32 * DNLD_BLOCK_SIZE)
+// Download Control Area (DCA)
+#define WFX_DCA_IMAGE_SIZE 0x0900C000
+#define WFX_DCA_PUT 0x0900C004
+#define WFX_DCA_GET 0x0900C008
+#define WFX_DCA_HOST_STATUS 0x0900C00C
+#define HOST_READY 0x87654321
+#define HOST_INFO_READ 0xA753BD99
+#define HOST_UPLOAD_PENDING 0xABCDDCBA
+#define HOST_UPLOAD_COMPLETE 0xD4C64A99
+#define HOST_OK_TO_JUMP 0x174FC882
+#define WFX_DCA_NCP_STATUS 0x0900C010
+#define NCP_NOT_READY 0x12345678
+#define NCP_READY 0x87654321
+#define NCP_INFO_READY 0xBD53EF99
+#define NCP_DOWNLOAD_PENDING 0xABCDDCBA
+#define NCP_DOWNLOAD_COMPLETE 0xCAFEFECA
+#define NCP_AUTH_OK 0xD4C64A99
+#define NCP_AUTH_FAIL 0x174FC882
+#define NCP_PUB_KEY_RDY 0x7AB41D19
+#define WFX_DCA_FW_SIGNATURE 0x0900C014
+#define FW_SIGNATURE_SIZE 0x40
+#define WFX_DCA_FW_HASH 0x0900C054
+#define FW_HASH_SIZE 0x08
+#define WFX_DCA_FW_VERSION 0x0900C05C
+#define FW_VERSION_SIZE 0x04
+#define WFX_DCA_RESERVED 0x0900C060
+#define DCA_RESERVED_SIZE 0x20
+#define WFX_STATUS_INFO 0x0900C080
+#define WFX_BOOTLOADER_LABEL 0x0900C084
+#define BOOTLOADER_LABEL_SIZE 0x3C
+#define WFX_PTE_INFO 0x0900C0C0
+#define PTE_INFO_KEYSET_IDX 0x0D
+#define PTE_INFO_SIZE 0x10
+#define WFX_ERR_INFO 0x0900C0D0
+#define ERR_INVALID_SEC_TYPE 0x05
+#define ERR_SIG_VERIF_FAILED 0x0F
+#define ERR_AES_CTRL_KEY 0x10
+#define ERR_ECC_PUB_KEY 0x11
+#define ERR_MAC_KEY 0x18
+
+#define DCA_TIMEOUT 50 // milliseconds
+#define WAKEUP_TIMEOUT 200 // milliseconds
+
+static const char * const fwio_error_strings[] = {
+ [ERR_INVALID_SEC_TYPE] = "Invalid section type or wrong encryption",
+ [ERR_SIG_VERIF_FAILED] = "Signature verification failed",
+ [ERR_AES_CTRL_KEY] = "AES control key not initialized",
+ [ERR_ECC_PUB_KEY] = "ECC public key not initialized",
+ [ERR_MAC_KEY] = "MAC key not initialized",
+};
+
+/*
+ * request_firmware() allocate data using vmalloc(). It is not compatible with
+ * underlying hardware that use DMA. Function below detect this case and
+ * allocate a bounce buffer if necessary.
+ *
+ * Notice that, in doubt, you can enable CONFIG_DEBUG_SG to ask kernel to
+ * detect this problem at runtime (else, kernel silently fail).
+ *
+ * NOTE: it may also be possible to use 'pages' from struct firmware and avoid
+ * bounce buffer
+ */
+static int sram_write_dma_safe(struct wfx_dev *wdev, u32 addr, const u8 *buf,
+ size_t len)
+{
+ int ret;
+ const u8 *tmp;
+
+ if (!virt_addr_valid(buf)) {
+ tmp = kmemdup(buf, len, GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+ } else {
+ tmp = buf;
+ }
+ ret = sram_buf_write(wdev, addr, tmp, len);
+ if (!virt_addr_valid(buf))
+ kfree(tmp);
+ return ret;
+}
+
+int get_firmware(struct wfx_dev *wdev, u32 keyset_chip,
+ const struct firmware **fw, int *file_offset)
+{
+ int keyset_file;
+ char filename[256];
+ const char *data;
+ int ret;
+
+ snprintf(filename, sizeof(filename), "%s_%02X.sec", wdev->pdata.file_fw, keyset_chip);
+ ret = firmware_request_nowarn(fw, filename, wdev->dev);
+ if (ret) {
+ dev_info(wdev->dev, "can't load %s, falling back to %s.sec\n", filename, wdev->pdata.file_fw);
+ snprintf(filename, sizeof(filename), "%s.sec", wdev->pdata.file_fw);
+ ret = request_firmware(fw, filename, wdev->dev);
+ if (ret) {
+ dev_err(wdev->dev, "can't load %s\n", filename);
+ *fw = NULL;
+ return ret;
+ }
+ }
+
+ data = (*fw)->data;
+ if (memcmp(data, "KEYSET", 6) != 0) {
+ // Legacy firmware format
+ *file_offset = 0;
+ keyset_file = 0x90;
+ } else {
+ *file_offset = 8;
+ keyset_file = (hex_to_bin(data[6]) * 16) | hex_to_bin(data[7]);
+ if (keyset_file < 0) {
+ dev_err(wdev->dev, "%s corrupted\n", filename);
+ release_firmware(*fw);
+ *fw = NULL;
+ return -EINVAL;
+ }
+ }
+ if (keyset_file != keyset_chip) {
+ dev_err(wdev->dev, "firmware keyset is incompatible with chip (file: 0x%02X, chip: 0x%02X)\n",
+ keyset_file, keyset_chip);
+ release_firmware(*fw);
+ *fw = NULL;
+ return -ENODEV;
+ }
+ wdev->keyset = keyset_file;
+ return 0;
+}
+
+static int wait_ncp_status(struct wfx_dev *wdev, u32 status)
+{
+ ktime_t now, start;
+ u32 reg;
+ int ret;
+
+ start = ktime_get();
+ for (;;) {
+ ret = sram_reg_read(wdev, WFX_DCA_NCP_STATUS, &reg);
+ if (ret < 0)
+ return -EIO;
+ now = ktime_get();
+ if (reg == status)
+ break;
+ if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT)))
+ return -ETIMEDOUT;
+ }
+ if (ktime_compare(now, start))
+ dev_dbg(wdev->dev, "chip answer after %lldus\n", ktime_us_delta(now, start));
+ else
+ dev_dbg(wdev->dev, "chip answer immediately\n");
+ return 0;
+}
+
+static int upload_firmware(struct wfx_dev *wdev, const u8 *data, size_t len)
+{
+ int ret;
+ u32 offs, bytes_done;
+ ktime_t now, start;
+
+ if (len % DNLD_BLOCK_SIZE) {
+ dev_err(wdev->dev, "firmware size is not aligned. Buffer overrun will occur\n");
+ return -EIO;
+ }
+ offs = 0;
+ while (offs < len) {
+ start = ktime_get();
+ for (;;) {
+ ret = sram_reg_read(wdev, WFX_DCA_GET, &bytes_done);
+ if (ret < 0)
+ return ret;
+ now = ktime_get();
+ if (offs + DNLD_BLOCK_SIZE - bytes_done < DNLD_FIFO_SIZE)
+ break;
+ if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT)))
+ return -ETIMEDOUT;
+ }
+ if (ktime_compare(now, start))
+ dev_dbg(wdev->dev, "answer after %lldus\n", ktime_us_delta(now, start));
+
+ ret = sram_write_dma_safe(wdev, WFX_DNLD_FIFO + (offs % DNLD_FIFO_SIZE),
+ data + offs, DNLD_BLOCK_SIZE);
+ if (ret < 0)
+ return ret;
+
+ // WFx seems to not support writing 0 in this register during
+ // first loop
+ offs += DNLD_BLOCK_SIZE;
+ ret = sram_reg_write(wdev, WFX_DCA_PUT, offs);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
+static void print_boot_status(struct wfx_dev *wdev)
+{
+ u32 val32;
+
+ sram_reg_read(wdev, WFX_STATUS_INFO, &val32);
+ if (val32 == 0x12345678) {
+ dev_info(wdev->dev, "no error reported by secure boot\n");
+ } else {
+ sram_reg_read(wdev, WFX_ERR_INFO, &val32);
+ if (val32 < ARRAY_SIZE(fwio_error_strings) && fwio_error_strings[val32])
+ dev_info(wdev->dev, "secure boot error: %s\n", fwio_error_strings[val32]);
+ else
+ dev_info(wdev->dev, "secure boot error: Unknown (0x%02x)\n", val32);
+ }
+}
+
+static int load_firmware_secure(struct wfx_dev *wdev)
+{
+ const struct firmware *fw = NULL;
+ int header_size;
+ int fw_offset;
+ ktime_t start;
+ u8 *buf;
+ int ret;
+
+ BUILD_BUG_ON(PTE_INFO_SIZE > BOOTLOADER_LABEL_SIZE);
+ buf = kmalloc(BOOTLOADER_LABEL_SIZE + 1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_READY);
+ ret = wait_ncp_status(wdev, NCP_INFO_READY);
+ if (ret)
+ goto error;
+
+ sram_buf_read(wdev, WFX_BOOTLOADER_LABEL, buf, BOOTLOADER_LABEL_SIZE);
+ buf[BOOTLOADER_LABEL_SIZE] = 0;
+ dev_dbg(wdev->dev, "bootloader: \"%s\"\n", buf);
+
+ sram_buf_read(wdev, WFX_PTE_INFO, buf, PTE_INFO_SIZE);
+ ret = get_firmware(wdev, buf[PTE_INFO_KEYSET_IDX], &fw, &fw_offset);
+ if (ret)
+ goto error;
+ header_size = fw_offset + FW_SIGNATURE_SIZE + FW_HASH_SIZE;
+
+ sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_INFO_READ);
+ ret = wait_ncp_status(wdev, NCP_READY);
+ if (ret)
+ goto error;
+
+ sram_reg_write(wdev, WFX_DNLD_FIFO, 0xFFFFFFFF); // Fifo init
+ sram_write_dma_safe(wdev, WFX_DCA_FW_VERSION, "\x01\x00\x00\x00", FW_VERSION_SIZE);
+ sram_write_dma_safe(wdev, WFX_DCA_FW_SIGNATURE, fw->data + fw_offset, FW_SIGNATURE_SIZE);
+ sram_write_dma_safe(wdev, WFX_DCA_FW_HASH, fw->data + fw_offset + FW_SIGNATURE_SIZE, FW_HASH_SIZE);
+ sram_reg_write(wdev, WFX_DCA_IMAGE_SIZE, fw->size - header_size);
+ sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_PENDING);
+ ret = wait_ncp_status(wdev, NCP_DOWNLOAD_PENDING);
+ if (ret)
+ goto error;
+
+ start = ktime_get();
+ ret = upload_firmware(wdev, fw->data + header_size, fw->size - header_size);
+ if (ret)
+ goto error;
+ dev_dbg(wdev->dev, "firmware load after %lldus\n", ktime_us_delta(ktime_get(), start));
+
+ sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_COMPLETE);
+ ret = wait_ncp_status(wdev, NCP_AUTH_OK);
+ // Legacy ROM support
+ if (ret < 0)
+ ret = wait_ncp_status(wdev, NCP_PUB_KEY_RDY);
+ if (ret < 0)
+ goto error;
+ sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_OK_TO_JUMP);
+
+error:
+ kfree(buf);
+ if (fw)
+ release_firmware(fw);
+ if (ret)
+ print_boot_status(wdev);
+ return ret;
+}
+
+static int init_gpr(struct wfx_dev *wdev)
+{
+ int ret, i;
+ static const struct {
+ int index;
+ u32 value;
+ } gpr_init[] = {
+ { 0x07, 0x208775 },
+ { 0x08, 0x2EC020 },
+ { 0x09, 0x3C3C3C },
+ { 0x0B, 0x322C44 },
+ { 0x0C, 0xA06497 },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(gpr_init); i++) {
+ ret = igpr_reg_write(wdev, gpr_init[i].index, gpr_init[i].value);
+ if (ret < 0)
+ return ret;
+ dev_dbg(wdev->dev, " index %02x: %08x\n", gpr_init[i].index, gpr_init[i].value);
+ }
+ return 0;
+}
+
+int wfx_init_device(struct wfx_dev *wdev)
+{
+ int ret;
+ int hw_revision, hw_type;
+ int wakeup_timeout = 50; // ms
+ ktime_t now, start;
+ u32 reg;
+
+ reg = CFG_DIRECT_ACCESS_MODE | CFG_CPU_RESET | CFG_WORD_MODE2;
+ if (wdev->pdata.use_rising_clk)
+ reg |= CFG_CLK_RISE_EDGE;
+ ret = config_reg_write(wdev, reg);
+ if (ret < 0) {
+ dev_err(wdev->dev, "bus returned an error during first write access. Host configuration error?\n");
+ return -EIO;
+ }
+
+ ret = config_reg_read(wdev, &reg);
+ if (ret < 0) {
+ dev_err(wdev->dev, "bus returned an error during first read access. Bus configuration error?\n");
+ return -EIO;
+ }
+ if (reg == 0 || reg == ~0) {
+ dev_err(wdev->dev, "chip mute. Bus configuration error or chip wasn't reset?\n");
+ return -EIO;
+ }
+ dev_dbg(wdev->dev, "initial config register value: %08x\n", reg);
+
+ hw_revision = FIELD_GET(CFG_DEVICE_ID_MAJOR, reg);
+ if (hw_revision == 0 || hw_revision > 2) {
+ dev_err(wdev->dev, "bad hardware revision number: %d\n", hw_revision);
+ return -ENODEV;
+ }
+ hw_type = FIELD_GET(CFG_DEVICE_ID_TYPE, reg);
+ if (hw_type == 1) {
+ dev_notice(wdev->dev, "development hardware detected\n");
+ wakeup_timeout = 2000;
+ }
+
+ ret = init_gpr(wdev);
+ if (ret < 0)
+ return ret;
+
+ ret = control_reg_write(wdev, CTRL_WLAN_WAKEUP);
+ if (ret < 0)
+ return -EIO;
+ start = ktime_get();
+ for (;;) {
+ ret = control_reg_read(wdev, &reg);
+ now = ktime_get();
+ if (reg & CTRL_WLAN_READY)
+ break;
+ if (ktime_after(now, ktime_add_ms(start, wakeup_timeout))) {
+ dev_err(wdev->dev, "chip didn't wake up. Chip wasn't reset?\n");
+ return -ETIMEDOUT;
+ }
+ }
+ dev_dbg(wdev->dev, "chip wake up after %lldus\n", ktime_us_delta(now, start));
+
+ ret = config_reg_write_bits(wdev, CFG_CPU_RESET, 0);
+ if (ret < 0)
+ return ret;
+ ret = load_firmware_secure(wdev);
+ if (ret < 0)
+ return ret;
+ ret = config_reg_write_bits(wdev, CFG_DIRECT_ACCESS_MODE | CFG_IRQ_ENABLE_DATA | CFG_IRQ_ENABLE_WRDY, CFG_IRQ_ENABLE_DATA);
+ return ret;
+}
diff --git a/drivers/staging/wfx/fwio.h b/drivers/staging/wfx/fwio.h
new file mode 100644
index 000000000000..6028f92503fe
--- /dev/null
+++ b/drivers/staging/wfx/fwio.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Firmware loading.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_FWIO_H
+#define WFX_FWIO_H
+
+struct wfx_dev;
+
+int wfx_init_device(struct wfx_dev *wdev);
+
+#endif /* WFX_FWIO_H */
diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h
new file mode 100644
index 000000000000..7c5d1ea6098d
--- /dev/null
+++ b/drivers/staging/wfx/hif_api_cmd.h
@@ -0,0 +1,681 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/*
+ * WFx hardware interface definitions
+ *
+ * Copyright (c) 2018-2019, Silicon Laboratories Inc.
+ */
+
+#ifndef WFX_HIF_API_CMD_H
+#define WFX_HIF_API_CMD_H
+
+#include "hif_api_general.h"
+
+#define HIF_NUM_AC 4
+
+#define HIF_API_SSID_SIZE API_SSID_SIZE
+
+enum hif_requests_ids {
+ HIF_REQ_ID_RESET = 0x0a,
+ HIF_REQ_ID_READ_MIB = 0x05,
+ HIF_REQ_ID_WRITE_MIB = 0x06,
+ HIF_REQ_ID_START_SCAN = 0x07,
+ HIF_REQ_ID_STOP_SCAN = 0x08,
+ HIF_REQ_ID_TX = 0x04,
+ HIF_REQ_ID_JOIN = 0x0b,
+ HIF_REQ_ID_SET_PM_MODE = 0x10,
+ HIF_REQ_ID_SET_BSS_PARAMS = 0x11,
+ HIF_REQ_ID_ADD_KEY = 0x0c,
+ HIF_REQ_ID_REMOVE_KEY = 0x0d,
+ HIF_REQ_ID_EDCA_QUEUE_PARAMS = 0x13,
+ HIF_REQ_ID_START = 0x17,
+ HIF_REQ_ID_BEACON_TRANSMIT = 0x18,
+ HIF_REQ_ID_UPDATE_IE = 0x1b,
+ HIF_REQ_ID_MAP_LINK = 0x1c,
+};
+
+enum hif_confirmations_ids {
+ HIF_CNF_ID_RESET = 0x0a,
+ HIF_CNF_ID_READ_MIB = 0x05,
+ HIF_CNF_ID_WRITE_MIB = 0x06,
+ HIF_CNF_ID_START_SCAN = 0x07,
+ HIF_CNF_ID_STOP_SCAN = 0x08,
+ HIF_CNF_ID_TX = 0x04,
+ HIF_CNF_ID_MULTI_TRANSMIT = 0x1e,
+ HIF_CNF_ID_JOIN = 0x0b,
+ HIF_CNF_ID_SET_PM_MODE = 0x10,
+ HIF_CNF_ID_SET_BSS_PARAMS = 0x11,
+ HIF_CNF_ID_ADD_KEY = 0x0c,
+ HIF_CNF_ID_REMOVE_KEY = 0x0d,
+ HIF_CNF_ID_EDCA_QUEUE_PARAMS = 0x13,
+ HIF_CNF_ID_START = 0x17,
+ HIF_CNF_ID_BEACON_TRANSMIT = 0x18,
+ HIF_CNF_ID_UPDATE_IE = 0x1b,
+ HIF_CNF_ID_MAP_LINK = 0x1c,
+};
+
+enum hif_indications_ids {
+ HIF_IND_ID_RX = 0x84,
+ HIF_IND_ID_SCAN_CMPL = 0x86,
+ HIF_IND_ID_JOIN_COMPLETE = 0x8f,
+ HIF_IND_ID_SET_PM_MODE_CMPL = 0x89,
+ HIF_IND_ID_SUSPEND_RESUME_TX = 0x8c,
+ HIF_IND_ID_EVENT = 0x85
+};
+
+union hif_commands_ids {
+ enum hif_requests_ids request;
+ enum hif_confirmations_ids confirmation;
+ enum hif_indications_ids indication;
+};
+
+enum hif_status {
+ HIF_STATUS_SUCCESS = 0x0,
+ HIF_STATUS_FAILURE = 0x1,
+ HIF_INVALID_PARAMETER = 0x2,
+ HIF_STATUS_WARNING = 0x3,
+ HIF_ERROR_UNSUPPORTED_MSG_ID = 0x4,
+ HIF_STATUS_DECRYPTFAILURE = 0x10,
+ HIF_STATUS_MICFAILURE = 0x11,
+ HIF_STATUS_NO_KEY_FOUND = 0x12,
+ HIF_STATUS_RETRY_EXCEEDED = 0x13,
+ HIF_STATUS_TX_LIFETIME_EXCEEDED = 0x14,
+ HIF_REQUEUE = 0x15,
+ HIF_STATUS_REFUSED = 0x16,
+ HIF_STATUS_BUSY = 0x17
+};
+
+struct hif_reset_flags {
+ uint8_t reset_stat:1;
+ uint8_t reset_all_int:1;
+ uint8_t reserved1:6;
+ uint8_t reserved2[3];
+} __packed;
+
+struct hif_req_reset {
+ struct hif_reset_flags reset_flags;
+} __packed;
+
+struct hif_cnf_reset {
+ uint32_t status;
+} __packed;
+
+struct hif_req_read_mib {
+ uint16_t mib_id;
+ uint16_t reserved;
+} __packed;
+
+struct hif_cnf_read_mib {
+ uint32_t status;
+ uint16_t mib_id;
+ uint16_t length;
+ uint8_t mib_data[];
+} __packed;
+
+struct hif_req_write_mib {
+ uint16_t mib_id;
+ uint16_t length;
+ uint8_t mib_data[];
+} __packed;
+
+struct hif_cnf_write_mib {
+ uint32_t status;
+} __packed;
+
+struct hif_ie_flags {
+ uint8_t beacon:1;
+ uint8_t probe_resp:1;
+ uint8_t probe_req:1;
+ uint8_t reserved1:5;
+ uint8_t reserved2;
+} __packed;
+
+struct hif_ie_tlv {
+ uint8_t type;
+ uint8_t length;
+ uint8_t data[];
+} __packed;
+
+struct hif_req_update_ie {
+ struct hif_ie_flags ie_flags;
+ uint16_t num_i_es;
+ struct hif_ie_tlv ie[];
+} __packed;
+
+struct hif_cnf_update_ie {
+ uint32_t status;
+} __packed;
+
+struct hif_scan_type {
+ uint8_t type:1;
+ uint8_t mode:1;
+ uint8_t reserved:6;
+} __packed;
+
+struct hif_scan_flags {
+ uint8_t fbg:1;
+ uint8_t reserved1:1;
+ uint8_t pre:1;
+ uint8_t reserved2:5;
+} __packed;
+
+struct hif_auto_scan_param {
+ uint16_t interval;
+ uint8_t reserved;
+ int8_t rssi_thr;
+} __packed;
+
+struct hif_ssid_def {
+ uint32_t ssid_length;
+ uint8_t ssid[HIF_API_SSID_SIZE];
+} __packed;
+
+#define HIF_API_MAX_NB_SSIDS 2
+#define HIF_API_MAX_NB_CHANNELS 14
+
+struct hif_req_start_scan {
+ uint8_t band;
+ struct hif_scan_type scan_type;
+ struct hif_scan_flags scan_flags;
+ uint8_t max_transmit_rate;
+ struct hif_auto_scan_param auto_scan_param;
+ uint8_t num_of_probe_requests;
+ uint8_t probe_delay;
+ uint8_t num_of_ssi_ds;
+ uint8_t num_of_channels;
+ uint32_t min_channel_time;
+ uint32_t max_channel_time;
+ int32_t tx_power_level;
+ uint8_t ssid_and_channel_lists[];
+} __packed;
+
+struct hif_start_scan_req_cstnbssid_body {
+ uint8_t band;
+ struct hif_scan_type scan_type;
+ struct hif_scan_flags scan_flags;
+ uint8_t max_transmit_rate;
+ struct hif_auto_scan_param auto_scan_param;
+ uint8_t num_of_probe_requests;
+ uint8_t probe_delay;
+ uint8_t num_of_ssi_ds;
+ uint8_t num_of_channels;
+ uint32_t min_channel_time;
+ uint32_t max_channel_time;
+ int32_t tx_power_level;
+ struct hif_ssid_def ssid_def[HIF_API_MAX_NB_SSIDS];
+ uint8_t channel_list[];
+} __packed;
+
+struct hif_cnf_start_scan {
+ uint32_t status;
+} __packed;
+
+struct hif_cnf_stop_scan {
+ uint32_t status;
+} __packed;
+
+enum hif_pm_mode_status {
+ HIF_PM_MODE_ACTIVE = 0x0,
+ HIF_PM_MODE_PS = 0x1,
+ HIF_PM_MODE_UNDETERMINED = 0x2
+};
+
+struct hif_ind_scan_cmpl {
+ uint32_t status;
+ uint8_t pm_mode;
+ uint8_t num_channels_completed;
+ uint16_t reserved;
+} __packed;
+
+enum hif_queue_id {
+ HIF_QUEUE_ID_BACKGROUND = 0x0,
+ HIF_QUEUE_ID_BESTEFFORT = 0x1,
+ HIF_QUEUE_ID_VIDEO = 0x2,
+ HIF_QUEUE_ID_VOICE = 0x3
+};
+
+enum hif_frame_format {
+ HIF_FRAME_FORMAT_NON_HT = 0x0,
+ HIF_FRAME_FORMAT_MIXED_FORMAT_HT = 0x1,
+ HIF_FRAME_FORMAT_GF_HT_11N = 0x2
+};
+
+enum hif_stbc {
+ HIF_STBC_NOT_ALLOWED = 0x0,
+ HIF_STBC_ALLOWED = 0x1
+};
+
+struct hif_queue {
+ uint8_t queue_id:2;
+ uint8_t peer_sta_id:4;
+ uint8_t reserved:2;
+} __packed;
+
+struct hif_data_flags {
+ uint8_t more:1;
+ uint8_t fc_offset:3;
+ uint8_t reserved:4;
+} __packed;
+
+struct hif_tx_flags {
+ uint8_t start_exp:1;
+ uint8_t reserved:3;
+ uint8_t retry_policy_index:4;
+} __packed;
+
+struct hif_ht_tx_parameters {
+ uint8_t frame_format:4;
+ uint8_t fec_coding:1;
+ uint8_t short_gi:1;
+ uint8_t reserved1:1;
+ uint8_t stbc:1;
+ uint8_t reserved2;
+ uint8_t aggregation:1;
+ uint8_t reserved3:7;
+ uint8_t reserved4;
+} __packed;
+
+struct hif_req_tx {
+ uint32_t packet_id;
+ uint8_t max_tx_rate;
+ struct hif_queue queue_id;
+ struct hif_data_flags data_flags;
+ struct hif_tx_flags tx_flags;
+ uint32_t reserved;
+ uint32_t expire_time;
+ struct hif_ht_tx_parameters ht_tx_parameters;
+ uint8_t frame[];
+} __packed;
+
+enum hif_qos_ackplcy {
+ HIF_QOS_ACKPLCY_NORMAL = 0x0,
+ HIF_QOS_ACKPLCY_TXNOACK = 0x1,
+ HIF_QOS_ACKPLCY_NOEXPACK = 0x2,
+ HIF_QOS_ACKPLCY_BLCKACK = 0x3
+};
+
+struct hif_tx_result_flags {
+ uint8_t aggr:1;
+ uint8_t requeue:1;
+ uint8_t ack_policy:2;
+ uint8_t txop_limit:1;
+ uint8_t reserved1:3;
+ uint8_t reserved2;
+} __packed;
+
+struct hif_cnf_tx {
+ uint32_t status;
+ uint32_t packet_id;
+ uint8_t txed_rate;
+ uint8_t ack_failures;
+ struct hif_tx_result_flags tx_result_flags;
+ uint32_t media_delay;
+ uint32_t tx_queue_delay;
+} __packed;
+
+struct hif_cnf_multi_transmit {
+ uint32_t num_tx_confs;
+ struct hif_cnf_tx tx_conf_payload[];
+} __packed;
+
+enum hif_ri_flags_encrypt {
+ HIF_RI_FLAGS_UNENCRYPTED = 0x0,
+ HIF_RI_FLAGS_WEP_ENCRYPTED = 0x1,
+ HIF_RI_FLAGS_TKIP_ENCRYPTED = 0x2,
+ HIF_RI_FLAGS_AES_ENCRYPTED = 0x3,
+ HIF_RI_FLAGS_WAPI_ENCRYPTED = 0x4
+};
+
+struct hif_rx_flags {
+ uint8_t encryp:3;
+ uint8_t in_aggr:1;
+ uint8_t first_aggr:1;
+ uint8_t last_aggr:1;
+ uint8_t defrag:1;
+ uint8_t beacon:1;
+ uint8_t tim:1;
+ uint8_t bitmap:1;
+ uint8_t match_ssid:1;
+ uint8_t match_bssid:1;
+ uint8_t more:1;
+ uint8_t reserved1:1;
+ uint8_t ht:1;
+ uint8_t stbc:1;
+ uint8_t match_uc_addr:1;
+ uint8_t match_mc_addr:1;
+ uint8_t match_bc_addr:1;
+ uint8_t key_type:1;
+ uint8_t key_index:4;
+ uint8_t reserved2:1;
+ uint8_t peer_sta_id:4;
+ uint8_t reserved3:2;
+ uint8_t reserved4:1;
+} __packed;
+
+struct hif_ind_rx {
+ uint32_t status;
+ uint16_t channel_number;
+ uint8_t rxed_rate;
+ uint8_t rcpi_rssi;
+ struct hif_rx_flags rx_flags;
+ uint8_t frame[];
+} __packed;
+
+
+struct hif_req_edca_queue_params {
+ uint8_t queue_id;
+ uint8_t reserved1;
+ uint8_t aifsn;
+ uint8_t reserved2;
+ uint16_t cw_min;
+ uint16_t cw_max;
+ uint16_t tx_op_limit;
+ uint16_t allowed_medium_time;
+ uint32_t reserved3;
+} __packed;
+
+struct hif_cnf_edca_queue_params {
+ uint32_t status;
+} __packed;
+
+enum hif_ap_mode {
+ HIF_MODE_IBSS = 0x0,
+ HIF_MODE_BSS = 0x1
+};
+
+enum hif_preamble {
+ HIF_PREAMBLE_LONG = 0x0,
+ HIF_PREAMBLE_SHORT = 0x1,
+ HIF_PREAMBLE_SHORT_LONG12 = 0x2
+};
+
+struct hif_join_flags {
+ uint8_t reserved1:2;
+ uint8_t force_no_beacon:1;
+ uint8_t force_with_ind:1;
+ uint8_t reserved2:4;
+} __packed;
+
+struct hif_req_join {
+ uint8_t mode;
+ uint8_t band;
+ uint16_t channel_number;
+ uint8_t bssid[ETH_ALEN];
+ uint16_t atim_window;
+ uint8_t preamble_type;
+ uint8_t probe_for_join;
+ uint8_t reserved;
+ struct hif_join_flags join_flags;
+ uint32_t ssid_length;
+ uint8_t ssid[HIF_API_SSID_SIZE];
+ uint32_t beacon_interval;
+ uint32_t basic_rate_set;
+} __packed;
+
+struct hif_cnf_join {
+ uint32_t status;
+} __packed;
+
+struct hif_ind_join_complete {
+ uint32_t status;
+} __packed;
+
+struct hif_bss_flags {
+ uint8_t lost_count_only:1;
+ uint8_t reserved:7;
+} __packed;
+
+struct hif_req_set_bss_params {
+ struct hif_bss_flags bss_flags;
+ uint8_t beacon_lost_count;
+ uint16_t aid;
+ uint32_t operational_rate_set;
+} __packed;
+
+struct hif_cnf_set_bss_params {
+ uint32_t status;
+} __packed;
+
+struct hif_pm_mode {
+ uint8_t enter_psm:1;
+ uint8_t reserved:6;
+ uint8_t fast_psm:1;
+} __packed;
+
+struct hif_req_set_pm_mode {
+ struct hif_pm_mode pm_mode;
+ uint8_t fast_psm_idle_period;
+ uint8_t ap_psm_change_period;
+ uint8_t min_auto_ps_poll_period;
+} __packed;
+
+struct hif_cnf_set_pm_mode {
+ uint32_t status;
+} __packed;
+
+struct hif_ind_set_pm_mode_cmpl {
+ uint32_t status;
+ uint8_t pm_mode;
+ uint8_t reserved[3];
+} __packed;
+
+
+struct hif_req_start {
+ uint8_t mode;
+ uint8_t band;
+ uint16_t channel_number;
+ uint32_t reserved1;
+ uint32_t beacon_interval;
+ uint8_t dtim_period;
+ uint8_t preamble_type;
+ uint8_t reserved2;
+ uint8_t ssid_length;
+ uint8_t ssid[HIF_API_SSID_SIZE];
+ uint32_t basic_rate_set;
+} __packed;
+
+struct hif_cnf_start {
+ uint32_t status;
+} __packed;
+
+enum hif_beacon {
+ HIF_BEACON_STOP = 0x0,
+ HIF_BEACON_START = 0x1
+};
+
+struct hif_req_beacon_transmit {
+ uint8_t enable_beaconing;
+ uint8_t reserved[3];
+} __packed;
+
+struct hif_cnf_beacon_transmit {
+ uint32_t status;
+} __packed;
+
+enum hif_sta_map_direction {
+ HIF_STA_MAP = 0x0,
+ HIF_STA_UNMAP = 0x1
+};
+
+struct hif_map_link_flags {
+ uint8_t map_direction:1;
+ uint8_t mfpc:1;
+ uint8_t reserved:6;
+} __packed;
+
+struct hif_req_map_link {
+ uint8_t mac_addr[ETH_ALEN];
+ struct hif_map_link_flags map_link_flags;
+ uint8_t peer_sta_id;
+} __packed;
+
+struct hif_cnf_map_link {
+ uint32_t status;
+} __packed;
+
+struct hif_suspend_resume_flags {
+ uint8_t resume:1;
+ uint8_t reserved1:2;
+ uint8_t bc_mc_only:1;
+ uint8_t reserved2:4;
+ uint8_t reserved3;
+} __packed;
+
+struct hif_ind_suspend_resume_tx {
+ struct hif_suspend_resume_flags suspend_resume_flags;
+ uint16_t peer_sta_set;
+} __packed;
+
+
+#define MAX_KEY_ENTRIES 24
+#define HIF_API_WEP_KEY_DATA_SIZE 16
+#define HIF_API_TKIP_KEY_DATA_SIZE 16
+#define HIF_API_RX_MIC_KEY_SIZE 8
+#define HIF_API_TX_MIC_KEY_SIZE 8
+#define HIF_API_AES_KEY_DATA_SIZE 16
+#define HIF_API_WAPI_KEY_DATA_SIZE 16
+#define HIF_API_MIC_KEY_DATA_SIZE 16
+#define HIF_API_IGTK_KEY_DATA_SIZE 16
+#define HIF_API_RX_SEQUENCE_COUNTER_SIZE 8
+#define HIF_API_IPN_SIZE 8
+
+enum hif_key_type {
+ HIF_KEY_TYPE_WEP_DEFAULT = 0x0,
+ HIF_KEY_TYPE_WEP_PAIRWISE = 0x1,
+ HIF_KEY_TYPE_TKIP_GROUP = 0x2,
+ HIF_KEY_TYPE_TKIP_PAIRWISE = 0x3,
+ HIF_KEY_TYPE_AES_GROUP = 0x4,
+ HIF_KEY_TYPE_AES_PAIRWISE = 0x5,
+ HIF_KEY_TYPE_WAPI_GROUP = 0x6,
+ HIF_KEY_TYPE_WAPI_PAIRWISE = 0x7,
+ HIF_KEY_TYPE_IGTK_GROUP = 0x8,
+ HIF_KEY_TYPE_NONE = 0x9
+};
+
+struct hif_wep_pairwise_key {
+ uint8_t peer_address[ETH_ALEN];
+ uint8_t reserved;
+ uint8_t key_length;
+ uint8_t key_data[HIF_API_WEP_KEY_DATA_SIZE];
+} __packed;
+
+struct hif_wep_group_key {
+ uint8_t key_id;
+ uint8_t key_length;
+ uint8_t reserved[2];
+ uint8_t key_data[HIF_API_WEP_KEY_DATA_SIZE];
+} __packed;
+
+struct hif_tkip_pairwise_key {
+ uint8_t peer_address[ETH_ALEN];
+ uint8_t reserved[2];
+ uint8_t tkip_key_data[HIF_API_TKIP_KEY_DATA_SIZE];
+ uint8_t rx_mic_key[HIF_API_RX_MIC_KEY_SIZE];
+ uint8_t tx_mic_key[HIF_API_TX_MIC_KEY_SIZE];
+} __packed;
+
+struct hif_tkip_group_key {
+ uint8_t tkip_key_data[HIF_API_TKIP_KEY_DATA_SIZE];
+ uint8_t rx_mic_key[HIF_API_RX_MIC_KEY_SIZE];
+ uint8_t key_id;
+ uint8_t reserved[3];
+ uint8_t rx_sequence_counter[HIF_API_RX_SEQUENCE_COUNTER_SIZE];
+} __packed;
+
+struct hif_aes_pairwise_key {
+ uint8_t peer_address[ETH_ALEN];
+ uint8_t reserved[2];
+ uint8_t aes_key_data[HIF_API_AES_KEY_DATA_SIZE];
+} __packed;
+
+struct hif_aes_group_key {
+ uint8_t aes_key_data[HIF_API_AES_KEY_DATA_SIZE];
+ uint8_t key_id;
+ uint8_t reserved[3];
+ uint8_t rx_sequence_counter[HIF_API_RX_SEQUENCE_COUNTER_SIZE];
+} __packed;
+
+struct hif_wapi_pairwise_key {
+ uint8_t peer_address[ETH_ALEN];
+ uint8_t key_id;
+ uint8_t reserved;
+ uint8_t wapi_key_data[HIF_API_WAPI_KEY_DATA_SIZE];
+ uint8_t mic_key_data[HIF_API_MIC_KEY_DATA_SIZE];
+} __packed;
+
+struct hif_wapi_group_key {
+ uint8_t wapi_key_data[HIF_API_WAPI_KEY_DATA_SIZE];
+ uint8_t mic_key_data[HIF_API_MIC_KEY_DATA_SIZE];
+ uint8_t key_id;
+ uint8_t reserved[3];
+} __packed;
+
+struct hif_igtk_group_key {
+ uint8_t igtk_key_data[HIF_API_IGTK_KEY_DATA_SIZE];
+ uint8_t key_id;
+ uint8_t reserved[3];
+ uint8_t ipn[HIF_API_IPN_SIZE];
+} __packed;
+
+union hif_privacy_key_data {
+ struct hif_wep_pairwise_key wep_pairwise_key;
+ struct hif_wep_group_key wep_group_key;
+ struct hif_tkip_pairwise_key tkip_pairwise_key;
+ struct hif_tkip_group_key tkip_group_key;
+ struct hif_aes_pairwise_key aes_pairwise_key;
+ struct hif_aes_group_key aes_group_key;
+ struct hif_wapi_pairwise_key wapi_pairwise_key;
+ struct hif_wapi_group_key wapi_group_key;
+ struct hif_igtk_group_key igtk_group_key;
+};
+
+struct hif_req_add_key {
+ uint8_t type;
+ uint8_t entry_index;
+ uint8_t int_id:2;
+ uint8_t reserved1:6;
+ uint8_t reserved2;
+ union hif_privacy_key_data key;
+} __packed;
+
+struct hif_cnf_add_key {
+ uint32_t status;
+} __packed;
+
+struct hif_req_remove_key {
+ uint8_t entry_index;
+ uint8_t reserved[3];
+} __packed;
+
+struct hif_cnf_remove_key {
+ uint32_t status;
+} __packed;
+
+enum hif_event_ind {
+ HIF_EVENT_IND_BSSLOST = 0x1,
+ HIF_EVENT_IND_BSSREGAINED = 0x2,
+ HIF_EVENT_IND_RCPI_RSSI = 0x3,
+ HIF_EVENT_IND_PS_MODE_ERROR = 0x4,
+ HIF_EVENT_IND_INACTIVITY = 0x5
+};
+
+enum hif_ps_mode_error {
+ HIF_PS_ERROR_NO_ERROR = 0,
+ HIF_PS_ERROR_AP_NOT_RESP_TO_POLL = 1,
+ HIF_PS_ERROR_AP_NOT_RESP_TO_UAPSD_TRIGGER = 2,
+ HIF_PS_ERROR_AP_SENT_UNICAST_IN_DOZE = 3,
+ HIF_PS_ERROR_AP_NO_DATA_AFTER_TIM = 4
+};
+
+union hif_event_data {
+ uint8_t rcpi_rssi;
+ uint32_t ps_mode_error;
+ uint32_t peer_sta_set;
+};
+
+struct hif_ind_event {
+ uint32_t event_id;
+ union hif_event_data event_data;
+} __packed;
+
+
+#endif
diff --git a/drivers/staging/wfx/hif_api_general.h b/drivers/staging/wfx/hif_api_general.h
new file mode 100644
index 000000000000..d885b55d2882
--- /dev/null
+++ b/drivers/staging/wfx/hif_api_general.h
@@ -0,0 +1,437 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/*
+ * WFx hardware interface definitions
+ *
+ * Copyright (c) 2018-2019, Silicon Laboratories Inc.
+ */
+
+#ifndef WFX_HIF_API_GENERAL_H
+#define WFX_HIF_API_GENERAL_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#else
+#include <net/ethernet.h>
+#include <stdint.h>
+#define __packed __attribute__((__packed__))
+#endif
+
+#define API_SSID_SIZE 32
+
+#define HIF_ID_IS_INDICATION 0x80
+#define HIF_COUNTER_MAX 7
+
+struct hif_msg {
+ uint16_t len;
+ uint8_t id;
+ uint8_t reserved:1;
+ uint8_t interface:2;
+ uint8_t seqnum:3;
+ uint8_t encrypted:2;
+ uint8_t body[];
+} __packed;
+
+enum hif_general_requests_ids {
+ HIF_REQ_ID_CONFIGURATION = 0x09,
+ HIF_REQ_ID_CONTROL_GPIO = 0x26,
+ HIF_REQ_ID_SET_SL_MAC_KEY = 0x27,
+ HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS = 0x28,
+ HIF_REQ_ID_SL_CONFIGURE = 0x29,
+ HIF_REQ_ID_PREVENT_ROLLBACK = 0x2a,
+ HIF_REQ_ID_PTA_SETTINGS = 0x2b,
+ HIF_REQ_ID_PTA_PRIORITY = 0x2c,
+ HIF_REQ_ID_PTA_STATE = 0x2d,
+ HIF_REQ_ID_SHUT_DOWN = 0x32,
+};
+
+enum hif_general_confirmations_ids {
+ HIF_CNF_ID_CONFIGURATION = 0x09,
+ HIF_CNF_ID_CONTROL_GPIO = 0x26,
+ HIF_CNF_ID_SET_SL_MAC_KEY = 0x27,
+ HIF_CNF_ID_SL_EXCHANGE_PUB_KEYS = 0x28,
+ HIF_CNF_ID_SL_CONFIGURE = 0x29,
+ HIF_CNF_ID_PREVENT_ROLLBACK = 0x2a,
+ HIF_CNF_ID_PTA_SETTINGS = 0x2b,
+ HIF_CNF_ID_PTA_PRIORITY = 0x2c,
+ HIF_CNF_ID_PTA_STATE = 0x2d,
+ HIF_CNF_ID_SHUT_DOWN = 0x32,
+};
+
+enum hif_general_indications_ids {
+ HIF_IND_ID_EXCEPTION = 0xe0,
+ HIF_IND_ID_STARTUP = 0xe1,
+ HIF_IND_ID_WAKEUP = 0xe2,
+ HIF_IND_ID_GENERIC = 0xe3,
+ HIF_IND_ID_ERROR = 0xe4,
+ HIF_IND_ID_SL_EXCHANGE_PUB_KEYS = 0xe5
+};
+
+enum hif_hi_status {
+ HI_STATUS_SUCCESS = 0x0000,
+ HI_STATUS_FAILURE = 0x0001,
+ HI_INVALID_PARAMETER = 0x0002,
+ HI_STATUS_GPIO_WARNING = 0x0003,
+ HI_ERROR_UNSUPPORTED_MSG_ID = 0x0004,
+ SL_MAC_KEY_STATUS_SUCCESS = 0x005A,
+ SL_MAC_KEY_STATUS_FAILED_KEY_ALREADY_BURNED = 0x006B,
+ SL_MAC_KEY_STATUS_FAILED_RAM_MODE_NOT_ALLOWED = 0x007C,
+ SL_MAC_KEY_STATUS_FAILED_UNKNOWN_MODE = 0x008D,
+ SL_PUB_KEY_EXCHANGE_STATUS_SUCCESS = 0x009E,
+ SL_PUB_KEY_EXCHANGE_STATUS_FAILED = 0x00AF,
+ PREVENT_ROLLBACK_CNF_SUCCESS = 0x1234,
+ PREVENT_ROLLBACK_CNF_WRONG_MAGIC_WORD = 0x1256
+};
+
+enum hif_api_rate_index {
+ API_RATE_INDEX_B_1MBPS = 0,
+ API_RATE_INDEX_B_2MBPS = 1,
+ API_RATE_INDEX_B_5P5MBPS = 2,
+ API_RATE_INDEX_B_11MBPS = 3,
+ API_RATE_INDEX_PBCC_22MBPS = 4,
+ API_RATE_INDEX_PBCC_33MBPS = 5,
+ API_RATE_INDEX_G_6MBPS = 6,
+ API_RATE_INDEX_G_9MBPS = 7,
+ API_RATE_INDEX_G_12MBPS = 8,
+ API_RATE_INDEX_G_18MBPS = 9,
+ API_RATE_INDEX_G_24MBPS = 10,
+ API_RATE_INDEX_G_36MBPS = 11,
+ API_RATE_INDEX_G_48MBPS = 12,
+ API_RATE_INDEX_G_54MBPS = 13,
+ API_RATE_INDEX_N_6P5MBPS = 14,
+ API_RATE_INDEX_N_13MBPS = 15,
+ API_RATE_INDEX_N_19P5MBPS = 16,
+ API_RATE_INDEX_N_26MBPS = 17,
+ API_RATE_INDEX_N_39MBPS = 18,
+ API_RATE_INDEX_N_52MBPS = 19,
+ API_RATE_INDEX_N_58P5MBPS = 20,
+ API_RATE_INDEX_N_65MBPS = 21,
+ API_RATE_NUM_ENTRIES = 22
+};
+
+
+enum hif_fw_type {
+ HIF_FW_TYPE_ETF = 0x0,
+ HIF_FW_TYPE_WFM = 0x1,
+ HIF_FW_TYPE_WSM = 0x2
+};
+
+struct hif_capabilities {
+ uint8_t link_mode:2;
+ uint8_t reserved1:6;
+ uint8_t reserved2;
+ uint8_t reserved3;
+ uint8_t reserved4;
+} __packed;
+
+struct hif_otp_regul_sel_mode_info {
+ uint8_t region_sel_mode:4;
+ uint8_t reserved:4;
+} __packed;
+
+struct hif_otp_phy_info {
+ uint8_t phy1_region:3;
+ uint8_t phy0_region:3;
+ uint8_t otp_phy_ver:2;
+} __packed;
+
+#define API_OPN_SIZE 14
+#define API_UID_SIZE 8
+#define API_DISABLED_CHANNEL_LIST_SIZE 2
+#define API_FIRMWARE_LABEL_SIZE 128
+
+struct hif_ind_startup {
+ uint32_t status;
+ uint16_t hardware_id;
+ uint8_t opn[API_OPN_SIZE];
+ uint8_t uid[API_UID_SIZE];
+ uint16_t num_inp_ch_bufs;
+ uint16_t size_inp_ch_buf;
+ uint8_t num_links_ap;
+ uint8_t num_interfaces;
+ uint8_t mac_addr[2][ETH_ALEN];
+ uint8_t api_version_minor;
+ uint8_t api_version_major;
+ struct hif_capabilities capabilities;
+ uint8_t firmware_build;
+ uint8_t firmware_minor;
+ uint8_t firmware_major;
+ uint8_t firmware_type;
+ uint8_t disabled_channel_list[API_DISABLED_CHANNEL_LIST_SIZE];
+ struct hif_otp_regul_sel_mode_info regul_sel_mode_info;
+ struct hif_otp_phy_info otp_phy_info;
+ uint32_t supported_rate_mask;
+ uint8_t firmware_label[API_FIRMWARE_LABEL_SIZE];
+} __packed;
+
+struct hif_ind_wakeup {
+} __packed;
+
+struct hif_req_configuration {
+ uint16_t length;
+ uint8_t pds_data[];
+} __packed;
+
+struct hif_cnf_configuration {
+ uint32_t status;
+} __packed;
+
+enum hif_gpio_mode {
+ HIF_GPIO_MODE_D0 = 0x0,
+ HIF_GPIO_MODE_D1 = 0x1,
+ HIF_GPIO_MODE_OD0 = 0x2,
+ HIF_GPIO_MODE_OD1 = 0x3,
+ HIF_GPIO_MODE_TRISTATE = 0x4,
+ HIF_GPIO_MODE_TOGGLE = 0x5,
+ HIF_GPIO_MODE_READ = 0x6
+};
+
+struct hif_req_control_gpio {
+ uint8_t gpio_label;
+ uint8_t gpio_mode;
+} __packed;
+
+enum hif_gpio_error {
+ HIF_GPIO_ERROR_0 = 0x0,
+ HIF_GPIO_ERROR_1 = 0x1,
+ HIF_GPIO_ERROR_2 = 0x2
+};
+
+struct hif_cnf_control_gpio {
+ uint32_t status;
+ uint32_t value;
+} __packed;
+
+enum hif_generic_indication_type {
+ HIF_GENERIC_INDICATION_TYPE_RAW = 0x0,
+ HIF_GENERIC_INDICATION_TYPE_STRING = 0x1,
+ HIF_GENERIC_INDICATION_TYPE_RX_STATS = 0x2
+};
+
+struct hif_rx_stats {
+ uint32_t nb_rx_frame;
+ uint32_t nb_crc_frame;
+ uint32_t per_total;
+ uint32_t throughput;
+ uint32_t nb_rx_by_rate[API_RATE_NUM_ENTRIES];
+ uint16_t per[API_RATE_NUM_ENTRIES];
+ int16_t snr[API_RATE_NUM_ENTRIES];
+ int16_t rssi[API_RATE_NUM_ENTRIES];
+ int16_t cfo[API_RATE_NUM_ENTRIES];
+ uint32_t date;
+ uint32_t pwr_clk_freq;
+ uint8_t is_ext_pwr_clk;
+ int8_t current_temp;
+} __packed;
+
+union hif_indication_data {
+ struct hif_rx_stats rx_stats;
+ uint8_t raw_data[1];
+};
+
+struct hif_ind_generic {
+ uint32_t indication_type;
+ union hif_indication_data indication_data;
+} __packed;
+
+
+#define HIF_EXCEPTION_DATA_SIZE 124
+
+struct hif_ind_exception {
+ uint8_t data[HIF_EXCEPTION_DATA_SIZE];
+} __packed;
+
+
+enum hif_error {
+ HIF_ERROR_FIRMWARE_ROLLBACK = 0x0,
+ HIF_ERROR_FIRMWARE_DEBUG_ENABLED = 0x1,
+ HIF_ERROR_OUTDATED_SESSION_KEY = 0x2,
+ HIF_ERROR_INVALID_SESSION_KEY = 0x3,
+ HIF_ERROR_OOR_VOLTAGE = 0x4,
+ HIF_ERROR_PDS_VERSION = 0x5,
+ HIF_ERROR_OOR_TEMPERATURE = 0x6,
+ HIF_ERROR_REQ_DURING_KEY_EXCHANGE = 0x7,
+ HIF_ERROR_MULTI_TX_CNF_SECURELINK = 0x8,
+ HIF_ERROR_SECURELINK_OVERFLOW = 0x9,
+ HIF_ERROR_SECURELINK_DECRYPTION = 0xa
+};
+
+struct hif_ind_error {
+ uint32_t type;
+ uint8_t data[];
+} __packed;
+
+enum hif_secure_link_state {
+ SEC_LINK_UNAVAILABLE = 0x0,
+ SEC_LINK_RESERVED = 0x1,
+ SEC_LINK_EVAL = 0x2,
+ SEC_LINK_ENFORCED = 0x3
+};
+
+enum hif_sl_encryption_type {
+ NO_ENCRYPTION = 0,
+ TX_ENCRYPTION = 1,
+ RX_ENCRYPTION = 2,
+ HP_ENCRYPTION = 3
+};
+
+struct hif_sl_msg_hdr {
+ uint32_t seqnum:30;
+ uint32_t encrypted:2;
+} __packed;
+
+struct hif_sl_msg {
+ struct hif_sl_msg_hdr hdr;
+ uint16_t len;
+ uint8_t payload[];
+} __packed;
+
+#define AES_CCM_TAG_SIZE 16
+
+struct hif_sl_tag {
+ uint8_t tag[16];
+} __packed;
+
+enum hif_sl_mac_key_dest {
+ SL_MAC_KEY_DEST_OTP = 0x78,
+ SL_MAC_KEY_DEST_RAM = 0x87
+};
+
+#define API_KEY_VALUE_SIZE 32
+
+struct hif_req_set_sl_mac_key {
+ uint8_t otp_or_ram;
+ uint8_t key_value[API_KEY_VALUE_SIZE];
+} __packed;
+
+struct hif_cnf_set_sl_mac_key {
+ uint32_t status;
+} __packed;
+
+#define API_HOST_PUB_KEY_SIZE 32
+#define API_HOST_PUB_KEY_MAC_SIZE 64
+
+enum hif_sl_session_key_alg {
+ HIF_SL_CURVE25519 = 0x01,
+ HIF_SL_KDF = 0x02
+};
+
+struct hif_req_sl_exchange_pub_keys {
+ uint8_t algorithm:2;
+ uint8_t reserved1:6;
+ uint8_t reserved2[3];
+ uint8_t host_pub_key[API_HOST_PUB_KEY_SIZE];
+ uint8_t host_pub_key_mac[API_HOST_PUB_KEY_MAC_SIZE];
+} __packed;
+
+struct hif_cnf_sl_exchange_pub_keys {
+ uint32_t status;
+} __packed;
+
+#define API_NCP_PUB_KEY_SIZE 32
+#define API_NCP_PUB_KEY_MAC_SIZE 64
+
+struct hif_ind_sl_exchange_pub_keys {
+ uint32_t status;
+ uint8_t ncp_pub_key[API_NCP_PUB_KEY_SIZE];
+ uint8_t ncp_pub_key_mac[API_NCP_PUB_KEY_MAC_SIZE];
+} __packed;
+
+#define API_ENCR_BMP_SIZE 32
+
+struct hif_req_sl_configure {
+ uint8_t encr_bmp[API_ENCR_BMP_SIZE];
+ uint8_t disable_session_key_protection:1;
+ uint8_t reserved1:7;
+ uint8_t reserved2[3];
+} __packed;
+
+struct hif_cnf_sl_configure {
+ uint32_t status;
+} __packed;
+
+struct hif_req_prevent_rollback {
+ uint32_t magic_word;
+} __packed;
+
+struct hif_cnf_prevent_rollback {
+ uint32_t status;
+} __packed;
+
+enum hif_pta_mode {
+ PTA_1W_WLAN_MASTER = 0,
+ PTA_1W_COEX_MASTER = 1,
+ PTA_2W = 2,
+ PTA_3W = 3,
+ PTA_4W = 4
+};
+
+enum hif_signal_level {
+ SIGNAL_LOW = 0,
+ SIGNAL_HIGH = 1
+};
+
+enum hif_coex_type {
+ COEX_TYPE_GENERIC = 0,
+ COEX_TYPE_BLE = 1
+};
+
+enum hif_grant_state {
+ NO_GRANT = 0,
+ GRANT = 1
+};
+
+struct hif_req_pta_settings {
+ uint8_t pta_mode;
+ uint8_t request_signal_active_level;
+ uint8_t priority_signal_active_level;
+ uint8_t freq_signal_active_level;
+ uint8_t grant_signal_active_level;
+ uint8_t coex_type;
+ uint8_t default_grant_state;
+ uint8_t simultaneous_rx_accesses;
+ uint8_t priority_sampling_time;
+ uint8_t tx_rx_sampling_time;
+ uint8_t freq_sampling_time;
+ uint8_t grant_valid_time;
+ uint8_t fem_control_time;
+ uint8_t first_slot_time;
+ uint16_t periodic_tx_rx_sampling_time;
+ uint16_t coex_quota;
+ uint16_t wlan_quota;
+} __packed;
+
+struct hif_cnf_pta_settings {
+ uint32_t status;
+} __packed;
+
+enum hif_pta_priority {
+ HIF_PTA_PRIORITY_COEX_MAXIMIZED = 0x00000562,
+ HIF_PTA_PRIORITY_COEX_HIGH = 0x00000462,
+ HIF_PTA_PRIORITY_BALANCED = 0x00001461,
+ HIF_PTA_PRIORITY_WLAN_HIGH = 0x00001851,
+ HIF_PTA_PRIORITY_WLAN_MAXIMIZED = 0x00001A51
+};
+
+struct hif_req_pta_priority {
+ uint32_t priority;
+} __packed;
+
+struct hif_cnf_pta_priority {
+ uint32_t status;
+} __packed;
+
+enum hif_pta_state {
+ PTA_OFF = 0,
+ PTA_ON = 1
+};
+
+struct hif_req_pta_state {
+ uint32_t pta_state;
+} __packed;
+
+struct hif_cnf_pta_state {
+ uint32_t status;
+} __packed;
+
+#endif
diff --git a/drivers/staging/wfx/hif_api_mib.h b/drivers/staging/wfx/hif_api_mib.h
new file mode 100644
index 000000000000..af657555f894
--- /dev/null
+++ b/drivers/staging/wfx/hif_api_mib.h
@@ -0,0 +1,558 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/*
+ * WFx hardware interface definitions
+ *
+ * Copyright (c) 2018-2019, Silicon Laboratories Inc.
+ */
+
+#ifndef WFX_HIF_API_MIB_H
+#define WFX_HIF_API_MIB_H
+
+#include "hif_api_general.h"
+
+#define HIF_API_IPV4_ADDRESS_SIZE 4
+#define HIF_API_IPV6_ADDRESS_SIZE 16
+
+enum hif_mib_ids {
+ HIF_MIB_ID_GL_OPERATIONAL_POWER_MODE = 0x2000,
+ HIF_MIB_ID_GL_BLOCK_ACK_INFO = 0x2001,
+ HIF_MIB_ID_GL_SET_MULTI_MSG = 0x2002,
+ HIF_MIB_ID_CCA_CONFIG = 0x2003,
+ HIF_MIB_ID_ETHERTYPE_DATAFRAME_CONDITION = 0x2010,
+ HIF_MIB_ID_PORT_DATAFRAME_CONDITION = 0x2011,
+ HIF_MIB_ID_MAGIC_DATAFRAME_CONDITION = 0x2012,
+ HIF_MIB_ID_MAC_ADDR_DATAFRAME_CONDITION = 0x2013,
+ HIF_MIB_ID_IPV4_ADDR_DATAFRAME_CONDITION = 0x2014,
+ HIF_MIB_ID_IPV6_ADDR_DATAFRAME_CONDITION = 0x2015,
+ HIF_MIB_ID_UC_MC_BC_DATAFRAME_CONDITION = 0x2016,
+ HIF_MIB_ID_CONFIG_DATA_FILTER = 0x2017,
+ HIF_MIB_ID_SET_DATA_FILTERING = 0x2018,
+ HIF_MIB_ID_ARP_IP_ADDRESSES_TABLE = 0x2019,
+ HIF_MIB_ID_NS_IP_ADDRESSES_TABLE = 0x201A,
+ HIF_MIB_ID_RX_FILTER = 0x201B,
+ HIF_MIB_ID_BEACON_FILTER_TABLE = 0x201C,
+ HIF_MIB_ID_BEACON_FILTER_ENABLE = 0x201D,
+ HIF_MIB_ID_GRP_SEQ_COUNTER = 0x2030,
+ HIF_MIB_ID_TSF_COUNTER = 0x2031,
+ HIF_MIB_ID_STATISTICS_TABLE = 0x2032,
+ HIF_MIB_ID_COUNTERS_TABLE = 0x2033,
+ HIF_MIB_ID_MAX_TX_POWER_LEVEL = 0x2034,
+ HIF_MIB_ID_EXTENDED_COUNTERS_TABLE = 0x2035,
+ HIF_MIB_ID_DOT11_MAC_ADDRESS = 0x2040,
+ HIF_MIB_ID_DOT11_MAX_TRANSMIT_MSDU_LIFETIME = 0x2041,
+ HIF_MIB_ID_DOT11_MAX_RECEIVE_LIFETIME = 0x2042,
+ HIF_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID = 0x2043,
+ HIF_MIB_ID_DOT11_RTS_THRESHOLD = 0x2044,
+ HIF_MIB_ID_SLOT_TIME = 0x2045,
+ HIF_MIB_ID_CURRENT_TX_POWER_LEVEL = 0x2046,
+ HIF_MIB_ID_NON_ERP_PROTECTION = 0x2047,
+ HIF_MIB_ID_TEMPLATE_FRAME = 0x2048,
+ HIF_MIB_ID_BEACON_WAKEUP_PERIOD = 0x2049,
+ HIF_MIB_ID_RCPI_RSSI_THRESHOLD = 0x204A,
+ HIF_MIB_ID_BLOCK_ACK_POLICY = 0x204B,
+ HIF_MIB_ID_OVERRIDE_INTERNAL_TX_RATE = 0x204C,
+ HIF_MIB_ID_SET_ASSOCIATION_MODE = 0x204D,
+ HIF_MIB_ID_SET_UAPSD_INFORMATION = 0x204E,
+ HIF_MIB_ID_SET_TX_RATE_RETRY_POLICY = 0x204F,
+ HIF_MIB_ID_PROTECTED_MGMT_POLICY = 0x2050,
+ HIF_MIB_ID_SET_HT_PROTECTION = 0x2051,
+ HIF_MIB_ID_KEEP_ALIVE_PERIOD = 0x2052,
+ HIF_MIB_ID_ARP_KEEP_ALIVE_PERIOD = 0x2053,
+ HIF_MIB_ID_INACTIVITY_TIMER = 0x2054,
+ HIF_MIB_ID_INTERFACE_PROTECTION = 0x2055,
+ HIF_MIB_ID_BEACON_STATS = 0x2056,
+};
+
+#define HIF_OP_POWER_MODE_MASK 0xf
+
+enum hif_op_power_mode {
+ HIF_OP_POWER_MODE_ACTIVE = 0x0,
+ HIF_OP_POWER_MODE_DOZE = 0x1,
+ HIF_OP_POWER_MODE_QUIESCENT = 0x2
+};
+
+struct hif_mib_gl_operational_power_mode {
+ uint8_t power_mode:4;
+ uint8_t reserved1:3;
+ uint8_t wup_ind_activation:1;
+ uint8_t reserved2[3];
+} __packed;
+
+struct hif_mib_gl_block_ack_info {
+ uint8_t rx_buffer_size;
+ uint8_t rx_max_num_agreements;
+ uint8_t tx_buffer_size;
+ uint8_t tx_max_num_agreements;
+} __packed;
+
+struct hif_mib_gl_set_multi_msg {
+ uint8_t enable_multi_tx_conf:1;
+ uint8_t reserved1:7;
+ uint8_t reserved2[3];
+} __packed;
+
+enum hif_cca_thr_mode {
+ HIF_CCA_THR_MODE_RELATIVE = 0x0,
+ HIF_CCA_THR_MODE_ABSOLUTE = 0x1
+};
+
+struct hif_mib_gl_cca_config {
+ uint8_t cca_thr_mode;
+ uint8_t reserved[3];
+} __packed;
+
+#define MAX_NUMBER_DATA_FILTERS 0xA
+
+#define MAX_NUMBER_IPV4_ADDR_CONDITIONS 0x4
+#define MAX_NUMBER_IPV6_ADDR_CONDITIONS 0x4
+#define MAX_NUMBER_MAC_ADDR_CONDITIONS 0x4
+#define MAX_NUMBER_UC_MC_BC_CONDITIONS 0x4
+#define MAX_NUMBER_ETHER_TYPE_CONDITIONS 0x4
+#define MAX_NUMBER_PORT_CONDITIONS 0x4
+#define MAX_NUMBER_MAGIC_CONDITIONS 0x4
+#define MAX_NUMBER_ARP_CONDITIONS 0x2
+#define MAX_NUMBER_NS_CONDITIONS 0x2
+
+struct hif_mib_ethertype_data_frame_condition {
+ uint8_t condition_idx;
+ uint8_t reserved;
+ uint16_t ether_type;
+} __packed;
+
+enum hif_udp_tcp_protocol {
+ HIF_PROTOCOL_UDP = 0x0,
+ HIF_PROTOCOL_TCP = 0x1,
+ HIF_PROTOCOL_BOTH_UDP_TCP = 0x2
+};
+
+enum hif_which_port {
+ HIF_PORT_DST = 0x0,
+ HIF_PORT_SRC = 0x1,
+ HIF_PORT_SRC_OR_DST = 0x2
+};
+
+struct hif_mib_ports_data_frame_condition {
+ uint8_t condition_idx;
+ uint8_t protocol;
+ uint8_t which_port;
+ uint8_t reserved1;
+ uint16_t port_number;
+ uint8_t reserved2[2];
+} __packed;
+
+#define HIF_API_MAGIC_PATTERN_SIZE 32
+
+struct hif_mib_magic_data_frame_condition {
+ uint8_t condition_idx;
+ uint8_t offset;
+ uint8_t magic_pattern_length;
+ uint8_t reserved;
+ uint8_t magic_pattern[HIF_API_MAGIC_PATTERN_SIZE];
+} __packed;
+
+enum hif_mac_addr_type {
+ HIF_MAC_ADDR_A1 = 0x0,
+ HIF_MAC_ADDR_A2 = 0x1,
+ HIF_MAC_ADDR_A3 = 0x2
+};
+
+struct hif_mib_mac_addr_data_frame_condition {
+ uint8_t condition_idx;
+ uint8_t address_type;
+ uint8_t mac_address[ETH_ALEN];
+} __packed;
+
+enum hif_ip_addr_mode {
+ HIF_IP_ADDR_SRC = 0x0,
+ HIF_IP_ADDR_DST = 0x1
+};
+
+struct hif_mib_ipv4_addr_data_frame_condition {
+ uint8_t condition_idx;
+ uint8_t address_mode;
+ uint8_t reserved[2];
+ uint8_t i_pv4_address[HIF_API_IPV4_ADDRESS_SIZE];
+} __packed;
+
+struct hif_mib_ipv6_addr_data_frame_condition {
+ uint8_t condition_idx;
+ uint8_t address_mode;
+ uint8_t reserved[2];
+ uint8_t i_pv6_address[HIF_API_IPV6_ADDRESS_SIZE];
+} __packed;
+
+union hif_addr_type {
+ uint8_t value;
+ struct {
+ uint8_t type_unicast:1;
+ uint8_t type_multicast:1;
+ uint8_t type_broadcast:1;
+ uint8_t reserved:5;
+ } bits;
+};
+
+struct hif_mib_uc_mc_bc_data_frame_condition {
+ uint8_t condition_idx;
+ union hif_addr_type param;
+ uint8_t reserved[2];
+} __packed;
+
+struct hif_mib_config_data_filter {
+ uint8_t filter_idx;
+ uint8_t enable;
+ uint8_t reserved1[2];
+ uint8_t eth_type_cond;
+ uint8_t port_cond;
+ uint8_t magic_cond;
+ uint8_t mac_cond;
+ uint8_t ipv4_cond;
+ uint8_t ipv6_cond;
+ uint8_t uc_mc_bc_cond;
+ uint8_t reserved2;
+} __packed;
+
+struct hif_mib_set_data_filtering {
+ uint8_t default_filter;
+ uint8_t enable;
+ uint8_t reserved[2];
+} __packed;
+
+enum hif_arp_ns_frame_treatment {
+ HIF_ARP_NS_FILTERING_DISABLE = 0x0,
+ HIF_ARP_NS_FILTERING_ENABLE = 0x1,
+ HIF_ARP_NS_REPLY_ENABLE = 0x2
+};
+
+struct hif_mib_arp_ip_addr_table {
+ uint8_t condition_idx;
+ uint8_t arp_enable;
+ uint8_t reserved[2];
+ uint8_t ipv4_address[HIF_API_IPV4_ADDRESS_SIZE];
+} __packed;
+
+struct hif_mib_ns_ip_addr_table {
+ uint8_t condition_idx;
+ uint8_t ns_enable;
+ uint8_t reserved[2];
+ uint8_t ipv6_address[HIF_API_IPV6_ADDRESS_SIZE];
+} __packed;
+
+struct hif_mib_rx_filter {
+ uint8_t reserved1:1;
+ uint8_t bssid_filter:1;
+ uint8_t reserved2:1;
+ uint8_t fwd_probe_req:1;
+ uint8_t keep_alive_filter:1;
+ uint8_t reserved3:3;
+ uint8_t reserved4[3];
+} __packed;
+
+#define HIF_API_OUI_SIZE 3
+#define HIF_API_MATCH_DATA_SIZE 3
+
+struct hif_ie_table_entry {
+ uint8_t ie_id;
+ uint8_t has_changed:1;
+ uint8_t no_longer:1;
+ uint8_t has_appeared:1;
+ uint8_t reserved:1;
+ uint8_t num_match_data:4;
+ uint8_t oui[HIF_API_OUI_SIZE];
+ uint8_t match_data[HIF_API_MATCH_DATA_SIZE];
+} __packed;
+
+struct hif_mib_bcn_filter_table {
+ uint32_t num_of_info_elmts;
+ struct hif_ie_table_entry ie_table[];
+} __packed;
+
+enum hif_beacon_filter {
+ HIF_BEACON_FILTER_DISABLE = 0x0,
+ HIF_BEACON_FILTER_ENABLE = 0x1,
+ HIF_BEACON_FILTER_AUTO_ERP = 0x2
+};
+
+struct hif_mib_bcn_filter_enable {
+ uint32_t enable;
+ uint32_t bcn_count;
+} __packed;
+
+struct hif_mib_group_seq_counter {
+ uint32_t bits4716;
+ uint16_t bits1500;
+ uint16_t reserved;
+} __packed;
+
+struct hif_mib_tsf_counter {
+ uint32_t tsf_counterlo;
+ uint32_t tsf_counterhi;
+} __packed;
+
+struct hif_mib_stats_table {
+ int16_t latest_snr;
+ uint8_t latest_rcpi;
+ int8_t latest_rssi;
+} __packed;
+
+struct hif_mib_extended_count_table {
+ uint32_t count_plcp_errors;
+ uint32_t count_fcs_errors;
+ uint32_t count_tx_packets;
+ uint32_t count_rx_packets;
+ uint32_t count_rx_packet_errors;
+ uint32_t count_rx_decryption_failures;
+ uint32_t count_rx_mic_failures;
+ uint32_t count_rx_no_key_failures;
+ uint32_t count_tx_multicast_frames;
+ uint32_t count_tx_frames_success;
+ uint32_t count_tx_frame_failures;
+ uint32_t count_tx_frames_retried;
+ uint32_t count_tx_frames_multi_retried;
+ uint32_t count_rx_frame_duplicates;
+ uint32_t count_rts_success;
+ uint32_t count_rts_failures;
+ uint32_t count_ack_failures;
+ uint32_t count_rx_multicast_frames;
+ uint32_t count_rx_frames_success;
+ uint32_t count_rx_cmacicv_errors;
+ uint32_t count_rx_cmac_replays;
+ uint32_t count_rx_mgmt_ccmp_replays;
+ uint32_t count_rx_bipmic_errors;
+ uint32_t count_rx_beacon;
+ uint32_t count_miss_beacon;
+ uint32_t reserved[15];
+} __packed;
+
+struct hif_mib_count_table {
+ uint32_t count_plcp_errors;
+ uint32_t count_fcs_errors;
+ uint32_t count_tx_packets;
+ uint32_t count_rx_packets;
+ uint32_t count_rx_packet_errors;
+ uint32_t count_rx_decryption_failures;
+ uint32_t count_rx_mic_failures;
+ uint32_t count_rx_no_key_failures;
+ uint32_t count_tx_multicast_frames;
+ uint32_t count_tx_frames_success;
+ uint32_t count_tx_frame_failures;
+ uint32_t count_tx_frames_retried;
+ uint32_t count_tx_frames_multi_retried;
+ uint32_t count_rx_frame_duplicates;
+ uint32_t count_rts_success;
+ uint32_t count_rts_failures;
+ uint32_t count_ack_failures;
+ uint32_t count_rx_multicast_frames;
+ uint32_t count_rx_frames_success;
+ uint32_t count_rx_cmacicv_errors;
+ uint32_t count_rx_cmac_replays;
+ uint32_t count_rx_mgmt_ccmp_replays;
+ uint32_t count_rx_bipmic_errors;
+} __packed;
+
+struct hif_mib_max_tx_power_level {
+ int32_t max_tx_power_level_rf_port1;
+ int32_t max_tx_power_level_rf_port2;
+} __packed;
+
+struct hif_mib_beacon_stats {
+ int32_t latest_tbtt_diff;
+ uint32_t reserved[4];
+} __packed;
+
+struct hif_mib_mac_address {
+ uint8_t mac_addr[ETH_ALEN];
+ uint16_t reserved;
+} __packed;
+
+struct hif_mib_dot11_max_transmit_msdu_lifetime {
+ uint32_t max_life_time;
+} __packed;
+
+struct hif_mib_dot11_max_receive_lifetime {
+ uint32_t max_life_time;
+} __packed;
+
+struct hif_mib_wep_default_key_id {
+ uint8_t wep_default_key_id;
+ uint8_t reserved[3];
+} __packed;
+
+struct hif_mib_dot11_rts_threshold {
+ uint32_t threshold;
+} __packed;
+
+struct hif_mib_slot_time {
+ uint32_t slot_time;
+} __packed;
+
+struct hif_mib_current_tx_power_level {
+ int32_t power_level;
+} __packed;
+
+struct hif_mib_non_erp_protection {
+ uint8_t use_cts_to_self:1;
+ uint8_t reserved1:7;
+ uint8_t reserved2[3];
+} __packed;
+
+enum hif_tx_mode {
+ HIF_TX_MODE_MIXED = 0x0,
+ HIF_TX_MODE_GREENFIELD = 0x1
+};
+
+enum hif_tmplt {
+ HIF_TMPLT_PRBREQ = 0x0,
+ HIF_TMPLT_BCN = 0x1,
+ HIF_TMPLT_NULL = 0x2,
+ HIF_TMPLT_QOSNUL = 0x3,
+ HIF_TMPLT_PSPOLL = 0x4,
+ HIF_TMPLT_PRBRES = 0x5,
+ HIF_TMPLT_ARP = 0x6,
+ HIF_TMPLT_NA = 0x7
+};
+
+#define HIF_API_MAX_TEMPLATE_FRAME_SIZE 700
+
+struct hif_mib_template_frame {
+ uint8_t frame_type;
+ uint8_t init_rate:7;
+ uint8_t mode:1;
+ uint16_t frame_length;
+ uint8_t frame[HIF_API_MAX_TEMPLATE_FRAME_SIZE];
+} __packed;
+
+struct hif_mib_beacon_wake_up_period {
+ uint8_t wakeup_period_min;
+ uint8_t receive_dtim:1;
+ uint8_t reserved1:7;
+ uint8_t wakeup_period_max;
+ uint8_t reserved2;
+} __packed;
+
+struct hif_mib_rcpi_rssi_threshold {
+ uint8_t detection:1;
+ uint8_t rcpi_rssi:1;
+ uint8_t upperthresh:1;
+ uint8_t lowerthresh:1;
+ uint8_t reserved:4;
+ uint8_t lower_threshold;
+ uint8_t upper_threshold;
+ uint8_t rolling_average_count;
+} __packed;
+
+#define DEFAULT_BA_MAX_RX_BUFFER_SIZE 16
+
+struct hif_mib_block_ack_policy {
+ uint8_t block_ack_tx_tid_policy;
+ uint8_t reserved1;
+ uint8_t block_ack_rx_tid_policy;
+ uint8_t block_ack_rx_max_buffer_size;
+} __packed;
+
+struct hif_mib_override_int_rate {
+ uint8_t internal_tx_rate;
+ uint8_t non_erp_internal_tx_rate;
+ uint8_t reserved[2];
+} __packed;
+
+enum hif_mpdu_start_spacing {
+ HIF_MPDU_START_SPACING_NO_RESTRIC = 0x0,
+ HIF_MPDU_START_SPACING_QUARTER = 0x1,
+ HIF_MPDU_START_SPACING_HALF = 0x2,
+ HIF_MPDU_START_SPACING_ONE = 0x3,
+ HIF_MPDU_START_SPACING_TWO = 0x4,
+ HIF_MPDU_START_SPACING_FOUR = 0x5,
+ HIF_MPDU_START_SPACING_EIGHT = 0x6,
+ HIF_MPDU_START_SPACING_SIXTEEN = 0x7
+};
+
+struct hif_mib_set_association_mode {
+ uint8_t preambtype_use:1;
+ uint8_t mode:1;
+ uint8_t rateset:1;
+ uint8_t spacing:1;
+ uint8_t reserved:4;
+ uint8_t preamble_type;
+ uint8_t mixed_or_greenfield_type;
+ uint8_t mpdu_start_spacing;
+ uint32_t basic_rate_set;
+} __packed;
+
+struct hif_mib_set_uapsd_information {
+ uint8_t trig_bckgrnd:1;
+ uint8_t trig_be:1;
+ uint8_t trig_video:1;
+ uint8_t trig_voice:1;
+ uint8_t reserved1:4;
+ uint8_t deliv_bckgrnd:1;
+ uint8_t deliv_be:1;
+ uint8_t deliv_video:1;
+ uint8_t deliv_voice:1;
+ uint8_t reserved2:4;
+ uint16_t min_auto_trigger_interval;
+ uint16_t max_auto_trigger_interval;
+ uint16_t auto_trigger_step;
+} __packed;
+
+struct hif_mib_tx_rate_retry_policy {
+ uint8_t policy_index;
+ uint8_t short_retry_count;
+ uint8_t long_retry_count;
+ uint8_t first_rate_sel:2;
+ uint8_t terminate:1;
+ uint8_t count_init:1;
+ uint8_t reserved1:4;
+ uint8_t rate_recovery_count;
+ uint8_t reserved2[3];
+ uint8_t rates[12];
+} __packed;
+
+#define HIF_MIB_NUM_TX_RATE_RETRY_POLICIES 15
+
+struct hif_mib_set_tx_rate_retry_policy {
+ uint8_t num_tx_rate_policies;
+ uint8_t reserved[3];
+ struct hif_mib_tx_rate_retry_policy tx_rate_retry_policy[];
+} __packed;
+
+struct hif_mib_protected_mgmt_policy {
+ uint8_t pmf_enable:1;
+ uint8_t unpmf_allowed:1;
+ uint8_t host_enc_auth_frames:1;
+ uint8_t reserved1:5;
+ uint8_t reserved2[3];
+} __packed;
+
+struct hif_mib_set_ht_protection {
+ uint8_t dual_cts_prot:1;
+ uint8_t reserved1:7;
+ uint8_t reserved2[3];
+} __packed;
+
+struct hif_mib_keep_alive_period {
+ uint16_t keep_alive_period;
+ uint8_t reserved[2];
+} __packed;
+
+struct hif_mib_arp_keep_alive_period {
+ uint16_t arp_keep_alive_period;
+ uint8_t encr_type;
+ uint8_t reserved;
+ uint8_t sender_ipv4_address[HIF_API_IPV4_ADDRESS_SIZE];
+ uint8_t target_ipv4_address[HIF_API_IPV4_ADDRESS_SIZE];
+} __packed;
+
+struct hif_mib_inactivity_timer {
+ uint8_t min_active_time;
+ uint8_t max_active_time;
+ uint16_t reserved;
+} __packed;
+
+struct hif_mib_interface_protection {
+ uint8_t use_cts_prot:1;
+ uint8_t reserved1:7;
+ uint8_t reserved2[3];
+} __packed;
+
+
+#endif
diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c
new file mode 100644
index 000000000000..36e171b27ae2
--- /dev/null
+++ b/drivers/staging/wfx/hif_rx.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Implementation of chip-to-host event (aka indications) of WFxxx Split Mac
+ * (WSM) API.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+
+#include "hif_rx.h"
+#include "wfx.h"
+#include "scan.h"
+#include "bh.h"
+#include "sta.h"
+#include "data_rx.h"
+#include "secure_link.h"
+#include "hif_api_cmd.h"
+
+static int hif_generic_confirm(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ // All confirm messages start with status
+ int status = le32_to_cpu(*((__le32 *) buf));
+ int cmd = hif->id;
+ int len = hif->len - 4; // drop header
+
+ WARN(!mutex_is_locked(&wdev->hif_cmd.lock), "data locking error");
+
+ if (!wdev->hif_cmd.buf_send) {
+ dev_warn(wdev->dev, "unexpected confirmation: 0x%.2x\n", cmd);
+ return -EINVAL;
+ }
+
+ if (cmd != wdev->hif_cmd.buf_send->id) {
+ dev_warn(wdev->dev, "chip response mismatch request: 0x%.2x vs 0x%.2x\n",
+ cmd, wdev->hif_cmd.buf_send->id);
+ return -EINVAL;
+ }
+
+ if (wdev->hif_cmd.buf_recv) {
+ if (wdev->hif_cmd.len_recv >= len)
+ memcpy(wdev->hif_cmd.buf_recv, buf, len);
+ else
+ status = -ENOMEM;
+ }
+ wdev->hif_cmd.ret = status;
+
+ if (!wdev->hif_cmd.async) {
+ complete(&wdev->hif_cmd.done);
+ } else {
+ wdev->hif_cmd.buf_send = NULL;
+ mutex_unlock(&wdev->hif_cmd.lock);
+ if (cmd != HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS)
+ mutex_unlock(&wdev->hif_cmd.key_renew_lock);
+ }
+ return status;
+}
+
+static int hif_tx_confirm(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct hif_cnf_tx *body = buf;
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+
+ WARN_ON(!wvif);
+ if (!wvif)
+ return -EFAULT;
+
+ wfx_tx_confirm_cb(wvif, body);
+ return 0;
+}
+
+static int hif_multi_tx_confirm(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct hif_cnf_multi_transmit *body = buf;
+ struct hif_cnf_tx *buf_loc = (struct hif_cnf_tx *) &body->tx_conf_payload;
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+ int count = body->num_tx_confs;
+ int i;
+
+ WARN(count <= 0, "corrupted message");
+ WARN_ON(!wvif);
+ if (!wvif)
+ return -EFAULT;
+
+ for (i = 0; i < count; ++i) {
+ wfx_tx_confirm_cb(wvif, buf_loc);
+ buf_loc++;
+ }
+ return 0;
+}
+
+static int hif_startup_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct hif_ind_startup *body = buf;
+
+ if (body->status || body->firmware_type > 4) {
+ dev_err(wdev->dev, "received invalid startup indication");
+ return -EINVAL;
+ }
+ memcpy(&wdev->hw_caps, body, sizeof(struct hif_ind_startup));
+ le32_to_cpus(&wdev->hw_caps.status);
+ le16_to_cpus(&wdev->hw_caps.hardware_id);
+ le16_to_cpus(&wdev->hw_caps.num_inp_ch_bufs);
+ le16_to_cpus(&wdev->hw_caps.size_inp_ch_buf);
+
+ complete(&wdev->firmware_ready);
+ return 0;
+}
+
+static int hif_wakeup_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ if (!wdev->pdata.gpio_wakeup
+ || !gpiod_get_value(wdev->pdata.gpio_wakeup)) {
+ dev_warn(wdev->dev, "unexpected wake-up indication\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int hif_keys_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct hif_ind_sl_exchange_pub_keys *body = buf;
+
+ // Compatibility with legacy secure link
+ if (body->status == SL_PUB_KEY_EXCHANGE_STATUS_SUCCESS)
+ body->status = 0;
+ if (body->status)
+ dev_warn(wdev->dev, "secure link negociation error\n");
+ wfx_sl_check_pubkey(wdev, body->ncp_pub_key, body->ncp_pub_key_mac);
+ return 0;
+}
+
+static int hif_receive_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf, struct sk_buff *skb)
+{
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+ struct hif_ind_rx *body = buf;
+
+ if (!wvif) {
+ dev_warn(wdev->dev, "ignore rx data for non-existent vif %d\n", hif->interface);
+ return 0;
+ }
+ skb_pull(skb, sizeof(struct hif_msg) + sizeof(struct hif_ind_rx));
+ wfx_rx_cb(wvif, body, skb);
+
+ return 0;
+}
+
+static int hif_event_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+ struct hif_ind_event *body = buf;
+ struct wfx_hif_event *event;
+ int first;
+
+ WARN_ON(!wvif);
+ if (!wvif)
+ return 0;
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ return -ENOMEM;
+
+ memcpy(&event->evt, body, sizeof(struct hif_ind_event));
+ spin_lock(&wvif->event_queue_lock);
+ first = list_empty(&wvif->event_queue);
+ list_add_tail(&event->link, &wvif->event_queue);
+ spin_unlock(&wvif->event_queue_lock);
+
+ if (first)
+ schedule_work(&wvif->event_handler_work);
+
+ return 0;
+}
+
+static int hif_pm_mode_complete_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+
+ WARN_ON(!wvif);
+ complete(&wvif->set_pm_mode_complete);
+
+ return 0;
+}
+
+static int hif_scan_complete_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+ struct hif_ind_scan_cmpl *body = buf;
+
+ WARN_ON(!wvif);
+ wfx_scan_complete_cb(wvif, body);
+
+ return 0;
+}
+
+static int hif_join_complete_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+
+ WARN_ON(!wvif);
+ dev_warn(wdev->dev, "unattended JoinCompleteInd\n");
+
+ return 0;
+}
+
+static int hif_suspend_resume_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
+ struct hif_ind_suspend_resume_tx *body = buf;
+
+ WARN_ON(!wvif);
+ wfx_suspend_resume(wvif, body);
+
+ return 0;
+}
+
+static int hif_error_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct hif_ind_error *body = buf;
+ u8 *pRollback = (u8 *) body->data;
+ u32 *pStatus = (u32 *) body->data;
+
+ switch (body->type) {
+ case HIF_ERROR_FIRMWARE_ROLLBACK:
+ dev_err(wdev->dev, "asynchronous error: firmware rollback error %d\n", *pRollback);
+ break;
+ case HIF_ERROR_FIRMWARE_DEBUG_ENABLED:
+ dev_err(wdev->dev, "asynchronous error: firmware debug feature enabled\n");
+ break;
+ case HIF_ERROR_OUTDATED_SESSION_KEY:
+ dev_err(wdev->dev, "asynchronous error: secure link outdated key: %#.8x\n", *pStatus);
+ break;
+ case HIF_ERROR_INVALID_SESSION_KEY:
+ dev_err(wdev->dev, "asynchronous error: invalid session key\n");
+ break;
+ case HIF_ERROR_OOR_VOLTAGE:
+ dev_err(wdev->dev, "asynchronous error: out-of-range overvoltage: %#.8x\n", *pStatus);
+ break;
+ case HIF_ERROR_PDS_VERSION:
+ dev_err(wdev->dev, "asynchronous error: wrong PDS payload or version: %#.8x\n", *pStatus);
+ break;
+ default:
+ dev_err(wdev->dev, "asynchronous error: unknown (%d)\n", body->type);
+ break;
+ }
+ return 0;
+}
+
+static int hif_generic_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ struct hif_ind_generic *body = buf;
+
+ switch (body->indication_type) {
+ case HIF_GENERIC_INDICATION_TYPE_RAW:
+ return 0;
+ case HIF_GENERIC_INDICATION_TYPE_STRING:
+ dev_info(wdev->dev, "firmware says: %s\n", (char *) body->indication_data.raw_data);
+ return 0;
+ case HIF_GENERIC_INDICATION_TYPE_RX_STATS:
+ mutex_lock(&wdev->rx_stats_lock);
+ // Older firmware send a generic indication beside RxStats
+ if (!wfx_api_older_than(wdev, 1, 4))
+ dev_info(wdev->dev, "Rx test ongoing. Temperature: %d°C\n", body->indication_data.rx_stats.current_temp);
+ memcpy(&wdev->rx_stats, &body->indication_data.rx_stats, sizeof(wdev->rx_stats));
+ mutex_unlock(&wdev->rx_stats_lock);
+ return 0;
+ default:
+ dev_err(wdev->dev, "generic_indication: unknown indication type: %#.8x\n", body->indication_type);
+ return -EIO;
+ }
+}
+
+static int hif_exception_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
+{
+ size_t len = hif->len - 4; // drop header
+ dev_err(wdev->dev, "firmware exception\n");
+ print_hex_dump_bytes("Dump: ", DUMP_PREFIX_NONE, buf, len);
+ wdev->chip_frozen = 1;
+
+ return -1;
+}
+
+static const struct {
+ int msg_id;
+ int (*handler)(struct wfx_dev *wdev, struct hif_msg *hif, void *buf);
+} hif_handlers[] = {
+ /* Confirmations */
+ { HIF_CNF_ID_TX, hif_tx_confirm },
+ { HIF_CNF_ID_MULTI_TRANSMIT, hif_multi_tx_confirm },
+ /* Indications */
+ { HIF_IND_ID_STARTUP, hif_startup_indication },
+ { HIF_IND_ID_WAKEUP, hif_wakeup_indication },
+ { HIF_IND_ID_JOIN_COMPLETE, hif_join_complete_indication },
+ { HIF_IND_ID_SET_PM_MODE_CMPL, hif_pm_mode_complete_indication },
+ { HIF_IND_ID_SCAN_CMPL, hif_scan_complete_indication },
+ { HIF_IND_ID_SUSPEND_RESUME_TX, hif_suspend_resume_indication },
+ { HIF_IND_ID_SL_EXCHANGE_PUB_KEYS, hif_keys_indication },
+ { HIF_IND_ID_EVENT, hif_event_indication },
+ { HIF_IND_ID_GENERIC, hif_generic_indication },
+ { HIF_IND_ID_ERROR, hif_error_indication },
+ { HIF_IND_ID_EXCEPTION, hif_exception_indication },
+ // FIXME: allocate skb_p from hif_receive_indication and make it generic
+ //{ HIF_IND_ID_RX, hif_receive_indication },
+};
+
+void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb)
+{
+ int i;
+ struct hif_msg *hif = (struct hif_msg *) skb->data;
+ int hif_id = hif->id;
+
+ if (hif_id == HIF_IND_ID_RX) {
+ // hif_receive_indication take care of skb lifetime
+ hif_receive_indication(wdev, hif, hif->body, skb);
+ return;
+ }
+ // Note: mutex_is_lock cause an implicit memory barrier that protect
+ // buf_send
+ if (mutex_is_locked(&wdev->hif_cmd.lock)
+ && wdev->hif_cmd.buf_send
+ && wdev->hif_cmd.buf_send->id == hif_id) {
+ hif_generic_confirm(wdev, hif, hif->body);
+ goto free;
+ }
+ for (i = 0; i < ARRAY_SIZE(hif_handlers); i++) {
+ if (hif_handlers[i].msg_id == hif_id) {
+ if (hif_handlers[i].handler)
+ hif_handlers[i].handler(wdev, hif, hif->body);
+ goto free;
+ }
+ }
+ dev_err(wdev->dev, "unsupported HIF ID %02x\n", hif_id);
+free:
+ dev_kfree_skb(skb);
+}
diff --git a/drivers/staging/wfx/hif_rx.h b/drivers/staging/wfx/hif_rx.h
new file mode 100644
index 000000000000..f07c10c8c6bd
--- /dev/null
+++ b/drivers/staging/wfx/hif_rx.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Implementation of chip-to-host event (aka indications) of WFxxx Split Mac
+ * (WSM) API.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (C) 2010, ST-Ericsson SA
+ */
+#ifndef WFX_HIF_RX_H
+#define WFX_HIF_RX_H
+
+struct wfx_dev;
+struct sk_buff;
+
+void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb);
+
+#endif
diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c
new file mode 100644
index 000000000000..2d40225a0fce
--- /dev/null
+++ b/drivers/staging/wfx/hif_tx.c
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Implementation of host-to-chip commands (aka request/confirmation) of WFxxx
+ * Split Mac (WSM) API.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+
+#include "hif_tx.h"
+#include "wfx.h"
+#include "bh.h"
+#include "hwio.h"
+#include "debug.h"
+#include "sta.h"
+
+void wfx_init_hif_cmd(struct wfx_hif_cmd *hif_cmd)
+{
+ init_completion(&hif_cmd->ready);
+ init_completion(&hif_cmd->done);
+ mutex_init(&hif_cmd->lock);
+ mutex_init(&hif_cmd->key_renew_lock);
+}
+
+static void wfx_fill_header(struct hif_msg *hif, int if_id, unsigned int cmd, size_t size)
+{
+ if (if_id == -1)
+ if_id = 2;
+
+ WARN(cmd > 0x3f, "invalid WSM command %#.2x", cmd);
+ WARN(size > 0xFFF, "requested buffer is too large: %zu bytes", size);
+ WARN(if_id > 0x3, "invalid interface ID %d", if_id);
+
+ hif->len = cpu_to_le16(size + 4);
+ hif->id = cmd;
+ hif->interface = if_id;
+}
+
+static void *wfx_alloc_hif(size_t body_len, struct hif_msg **hif)
+{
+ *hif = kzalloc(sizeof(struct hif_msg) + body_len, GFP_KERNEL);
+ if (*hif)
+ return (*hif)->body;
+ else
+ return NULL;
+}
+
+int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, void *reply, size_t reply_len, bool async)
+{
+ const char *mib_name = "";
+ const char *mib_sep = "";
+ int cmd = request->id;
+ int vif = request->interface;
+ int ret;
+
+ WARN(wdev->hif_cmd.buf_recv && wdev->hif_cmd.async, "API usage error");
+
+ // Do not wait for any reply if chip is frozen
+ if (wdev->chip_frozen)
+ return -ETIMEDOUT;
+
+ if (cmd != HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS)
+ mutex_lock(&wdev->hif_cmd.key_renew_lock);
+
+ mutex_lock(&wdev->hif_cmd.lock);
+ WARN(wdev->hif_cmd.buf_send, "data locking error");
+
+ // Note: call to complete() below has an implicit memory barrier that
+ // hopefully protect buf_send
+ wdev->hif_cmd.buf_send = request;
+ wdev->hif_cmd.buf_recv = reply;
+ wdev->hif_cmd.len_recv = reply_len;
+ wdev->hif_cmd.async = async;
+ complete(&wdev->hif_cmd.ready);
+
+ wfx_bh_request_tx(wdev);
+
+ // NOTE: no timeout is catched async is enabled
+ if (async)
+ return 0;
+
+ ret = wait_for_completion_timeout(&wdev->hif_cmd.done, 1 * HZ);
+ if (!ret) {
+ dev_err(wdev->dev, "chip is abnormally long to answer\n");
+ reinit_completion(&wdev->hif_cmd.ready);
+ ret = wait_for_completion_timeout(&wdev->hif_cmd.done, 3 * HZ);
+ }
+ if (!ret) {
+ dev_err(wdev->dev, "chip did not answer\n");
+ wfx_pending_dump_old_frames(wdev, 3000);
+ wdev->chip_frozen = 1;
+ reinit_completion(&wdev->hif_cmd.done);
+ ret = -ETIMEDOUT;
+ } else {
+ ret = wdev->hif_cmd.ret;
+ }
+
+ wdev->hif_cmd.buf_send = NULL;
+ mutex_unlock(&wdev->hif_cmd.lock);
+
+ if (ret && (cmd == HIF_REQ_ID_READ_MIB || cmd == HIF_REQ_ID_WRITE_MIB)) {
+ mib_name = get_mib_name(((u16 *) request)[2]);
+ mib_sep = "/";
+ }
+ if (ret < 0)
+ dev_err(wdev->dev,
+ "WSM request %s%s%s (%#.2x) on vif %d returned error %d\n",
+ get_hif_name(cmd), mib_sep, mib_name, cmd, vif, ret);
+ if (ret > 0)
+ dev_warn(wdev->dev,
+ "WSM request %s%s%s (%#.2x) on vif %d returned status %d\n",
+ get_hif_name(cmd), mib_sep, mib_name, cmd, vif, ret);
+
+ if (cmd != HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS)
+ mutex_unlock(&wdev->hif_cmd.key_renew_lock);
+ return ret;
+}
+
+// This function is special. After HIF_REQ_ID_SHUT_DOWN, chip won't reply to any
+// request anymore. We need to slightly hack struct wfx_hif_cmd for that job. Be
+// carefull to only call this funcion during device unregister.
+int hif_shutdown(struct wfx_dev *wdev)
+{
+ int ret;
+ struct hif_msg *hif;
+
+ wfx_alloc_hif(0, &hif);
+ wfx_fill_header(hif, -1, HIF_REQ_ID_SHUT_DOWN, 0);
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, true);
+ // After this command, chip won't reply. Be sure to give enough time to
+ // bh to send buffer:
+ msleep(100);
+ wdev->hif_cmd.buf_send = NULL;
+ if (wdev->pdata.gpio_wakeup)
+ gpiod_set_value(wdev->pdata.gpio_wakeup, 0);
+ else
+ control_reg_write(wdev, 0);
+ mutex_unlock(&wdev->hif_cmd.lock);
+ kfree(hif);
+ return ret;
+}
+
+int hif_configuration(struct wfx_dev *wdev, const u8 *conf, size_t len)
+{
+ int ret;
+ size_t buf_len = sizeof(struct hif_req_configuration) + len;
+ struct hif_msg *hif;
+ struct hif_req_configuration *body = wfx_alloc_hif(buf_len, &hif);
+
+ body->length = cpu_to_le16(len);
+ memcpy(body->pds_data, conf, len);
+ wfx_fill_header(hif, -1, HIF_REQ_ID_CONFIGURATION, buf_len);
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_reset(struct wfx_vif *wvif, bool reset_stat)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_reset *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ body->reset_flags.reset_stat = reset_stat;
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_RESET, sizeof(*body));
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *val, size_t val_len)
+{
+ int ret;
+ struct hif_msg *hif;
+ int buf_len = sizeof(struct hif_cnf_read_mib) + val_len;
+ struct hif_req_read_mib *body = wfx_alloc_hif(sizeof(*body), &hif);
+ struct hif_cnf_read_mib *reply = kmalloc(buf_len, GFP_KERNEL);
+
+ body->mib_id = cpu_to_le16(mib_id);
+ wfx_fill_header(hif, vif_id, HIF_REQ_ID_READ_MIB, sizeof(*body));
+ ret = wfx_cmd_send(wdev, hif, reply, buf_len, false);
+
+ if (!ret && mib_id != reply->mib_id) {
+ dev_warn(wdev->dev, "%s: confirmation mismatch request\n", __func__);
+ ret = -EIO;
+ }
+ if (ret == -ENOMEM)
+ dev_err(wdev->dev, "buffer is too small to receive %s (%zu < %d)\n",
+ get_mib_name(mib_id), val_len, reply->length);
+ if (!ret)
+ memcpy(val, &reply->mib_data, reply->length);
+ else
+ memset(val, 0xFF, val_len);
+ kfree(hif);
+ kfree(reply);
+ return ret;
+}
+
+int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *val, size_t val_len)
+{
+ int ret;
+ struct hif_msg *hif;
+ int buf_len = sizeof(struct hif_req_write_mib) + val_len;
+ struct hif_req_write_mib *body = wfx_alloc_hif(buf_len, &hif);
+
+ body->mib_id = cpu_to_le16(mib_id);
+ body->length = cpu_to_le16(val_len);
+ memcpy(&body->mib_data, val, val_len);
+ wfx_fill_header(hif, vif_id, HIF_REQ_ID_WRITE_MIB, buf_len);
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_scan(struct wfx_vif *wvif, const struct wfx_scan_params *arg)
+{
+ int ret, i;
+ struct hif_msg *hif;
+ struct hif_ssid_def *ssids;
+ size_t buf_len = sizeof(struct hif_req_start_scan) +
+ arg->scan_req.num_of_channels * sizeof(u8) +
+ arg->scan_req.num_of_ssi_ds * sizeof(struct hif_ssid_def);
+ struct hif_req_start_scan *body = wfx_alloc_hif(buf_len, &hif);
+ u8 *ptr = (u8 *) body + sizeof(*body);
+
+ WARN(arg->scan_req.num_of_channels > HIF_API_MAX_NB_CHANNELS, "invalid params");
+ WARN(arg->scan_req.num_of_ssi_ds > 2, "invalid params");
+ WARN(arg->scan_req.band > 1, "invalid params");
+
+ // FIXME: This API is unnecessary complex, fixing NumOfChannels and
+ // adding a member SsidDef at end of struct hif_req_start_scan would
+ // simplify that a lot.
+ memcpy(body, &arg->scan_req, sizeof(*body));
+ cpu_to_le32s(&body->min_channel_time);
+ cpu_to_le32s(&body->max_channel_time);
+ cpu_to_le32s(&body->tx_power_level);
+ memcpy(ptr, arg->ssids, arg->scan_req.num_of_ssi_ds * sizeof(struct hif_ssid_def));
+ ssids = (struct hif_ssid_def *) ptr;
+ for (i = 0; i < body->num_of_ssi_ds; ++i)
+ cpu_to_le32s(&ssids[i].ssid_length);
+ ptr += arg->scan_req.num_of_ssi_ds * sizeof(struct hif_ssid_def);
+ memcpy(ptr, arg->ch, arg->scan_req.num_of_channels * sizeof(u8));
+ ptr += arg->scan_req.num_of_channels * sizeof(u8);
+ WARN(buf_len != ptr - (u8 *) body, "allocation size mismatch");
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START_SCAN, buf_len);
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_stop_scan(struct wfx_vif *wvif)
+{
+ int ret;
+ struct hif_msg *hif;
+ // body associated to HIF_REQ_ID_STOP_SCAN is empty
+ wfx_alloc_hif(0, &hif);
+
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_STOP_SCAN, 0);
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_join(struct wfx_vif *wvif, const struct hif_req_join *arg)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_join *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ memcpy(body, arg, sizeof(struct hif_req_join));
+ cpu_to_le16s(&body->channel_number);
+ cpu_to_le16s(&body->atim_window);
+ cpu_to_le32s(&body->ssid_length);
+ cpu_to_le32s(&body->beacon_interval);
+ cpu_to_le32s(&body->basic_rate_set);
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_JOIN, sizeof(*body));
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_set_bss_params(struct wfx_vif *wvif, const struct hif_req_set_bss_params *arg)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_set_bss_params *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ memcpy(body, arg, sizeof(*body));
+ cpu_to_le16s(&body->aid);
+ cpu_to_le32s(&body->operational_rate_set);
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_SET_BSS_PARAMS, sizeof(*body));
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_add_key(struct wfx_dev *wdev, const struct hif_req_add_key *arg)
+{
+ int ret;
+ struct hif_msg *hif;
+ // FIXME: only send necessary bits
+ struct hif_req_add_key *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ // FIXME: swap bytes as necessary in body
+ memcpy(body, arg, sizeof(*body));
+ if (wfx_api_older_than(wdev, 1, 5))
+ // Legacy firmwares expect that add_key to be sent on right
+ // interface.
+ wfx_fill_header(hif, arg->int_id, HIF_REQ_ID_ADD_KEY, sizeof(*body));
+ else
+ wfx_fill_header(hif, -1, HIF_REQ_ID_ADD_KEY, sizeof(*body));
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_remove_key(struct wfx_dev *wdev, int idx)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_remove_key *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ body->entry_index = idx;
+ wfx_fill_header(hif, -1, HIF_REQ_ID_REMOVE_KEY, sizeof(*body));
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_set_edca_queue_params(struct wfx_vif *wvif, const struct hif_req_edca_queue_params *arg)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_edca_queue_params *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ // NOTE: queues numerotation are not the same between WFx and Linux
+ memcpy(body, arg, sizeof(*body));
+ cpu_to_le16s(&body->cw_min);
+ cpu_to_le16s(&body->cw_max);
+ cpu_to_le16s(&body->tx_op_limit);
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_EDCA_QUEUE_PARAMS, sizeof(*body));
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_set_pm_mode *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ memcpy(body, arg, sizeof(*body));
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_SET_PM_MODE, sizeof(*body));
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_start(struct wfx_vif *wvif, const struct hif_req_start *arg)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_start *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ memcpy(body, arg, sizeof(*body));
+ cpu_to_le16s(&body->channel_number);
+ cpu_to_le32s(&body->beacon_interval);
+ cpu_to_le32s(&body->basic_rate_set);
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START, sizeof(*body));
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_beacon_transmit(struct wfx_vif *wvif, bool enable_beaconing)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_beacon_transmit *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ body->enable_beaconing = enable_beaconing ? 1 : 0;
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_BEACON_TRANSMIT, sizeof(*body));
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_map_link(struct wfx_vif *wvif, u8 *mac_addr, int flags, int sta_id)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_map_link *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ if (mac_addr)
+ ether_addr_copy(body->mac_addr, mac_addr);
+ body->map_link_flags = *(struct hif_map_link_flags *) &flags;
+ body->peer_sta_id = sta_id;
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_MAP_LINK, sizeof(*body));
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_update_ie(struct wfx_vif *wvif, const struct hif_ie_flags *target_frame,
+ const u8 *ies, size_t ies_len)
+{
+ int ret;
+ struct hif_msg *hif;
+ int buf_len = sizeof(struct hif_req_update_ie) + ies_len;
+ struct hif_req_update_ie *body = wfx_alloc_hif(buf_len, &hif);
+
+ memcpy(&body->ie_flags, target_frame, sizeof(struct hif_ie_flags));
+ body->num_i_es = cpu_to_le16(1);
+ memcpy(body->ie, ies, ies_len);
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_UPDATE_IE, buf_len);
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_sl_send_pub_keys(struct wfx_dev *wdev, const uint8_t *pubkey, const uint8_t *pubkey_hmac)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_sl_exchange_pub_keys *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ body->algorithm = HIF_SL_CURVE25519;
+ memcpy(body->host_pub_key, pubkey, sizeof(body->host_pub_key));
+ memcpy(body->host_pub_key_mac, pubkey_hmac, sizeof(body->host_pub_key_mac));
+ wfx_fill_header(hif, -1, HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS, sizeof(*body));
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+ kfree(hif);
+ // Compatibility with legacy secure link
+ if (ret == SL_PUB_KEY_EXCHANGE_STATUS_SUCCESS)
+ ret = 0;
+ return ret;
+}
+
+int hif_sl_config(struct wfx_dev *wdev, const unsigned long *bitmap)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_sl_configure *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ memcpy(body->encr_bmp, bitmap, sizeof(body->encr_bmp));
+ wfx_fill_header(hif, -1, HIF_REQ_ID_SL_CONFIGURE, sizeof(*body));
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
+int hif_sl_set_mac_key(struct wfx_dev *wdev, const uint8_t *slk_key, int destination)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_set_sl_mac_key *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+ memcpy(body->key_value, slk_key, sizeof(body->key_value));
+ body->otp_or_ram = destination;
+ wfx_fill_header(hif, -1, HIF_REQ_ID_SET_SL_MAC_KEY, sizeof(*body));
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+ kfree(hif);
+ // Compatibility with legacy secure link
+ if (ret == SL_MAC_KEY_STATUS_SUCCESS)
+ ret = 0;
+ return ret;
+}
diff --git a/drivers/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h
new file mode 100644
index 000000000000..6f2ea2f3a77d
--- /dev/null
+++ b/drivers/staging/wfx/hif_tx.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Implementation of host-to-chip commands (aka request/confirmation) of WFxxx
+ * Split Mac (WSM) API.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (C) 2010, ST-Ericsson SA
+ */
+#ifndef WFX_HIF_TX_H
+#define WFX_HIF_TX_H
+
+#include "hif_api_cmd.h"
+
+struct wfx_dev;
+struct wfx_vif;
+
+struct wfx_scan_params {
+ struct hif_req_start_scan scan_req;
+ struct hif_ssid_def *ssids;
+ uint8_t *ch;
+};
+
+struct wfx_hif_cmd {
+ struct mutex lock;
+ struct mutex key_renew_lock;
+ struct completion ready;
+ struct completion done;
+ bool async;
+ struct hif_msg *buf_send;
+ void *buf_recv;
+ size_t len_recv;
+ int ret;
+};
+
+void wfx_init_hif_cmd(struct wfx_hif_cmd *wfx_hif_cmd);
+int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request,
+ void *reply, size_t reply_len, bool async);
+
+int hif_shutdown(struct wfx_dev *wdev);
+int hif_configuration(struct wfx_dev *wdev, const u8 *conf, size_t len);
+int hif_reset(struct wfx_vif *wvif, bool reset_stat);
+int hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id,
+ void *buf, size_t buf_size);
+int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id,
+ void *buf, size_t buf_size);
+int hif_scan(struct wfx_vif *wvif, const struct wfx_scan_params *arg);
+int hif_stop_scan(struct wfx_vif *wvif);
+int hif_join(struct wfx_vif *wvif, const struct hif_req_join *arg);
+int hif_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg);
+int hif_set_bss_params(struct wfx_vif *wvif,
+ const struct hif_req_set_bss_params *arg);
+int hif_add_key(struct wfx_dev *wdev, const struct hif_req_add_key *arg);
+int hif_remove_key(struct wfx_dev *wdev, int idx);
+int hif_set_edca_queue_params(struct wfx_vif *wvif,
+ const struct hif_req_edca_queue_params *arg);
+int hif_start(struct wfx_vif *wvif, const struct hif_req_start *arg);
+int hif_beacon_transmit(struct wfx_vif *wvif, bool enable);
+int hif_map_link(struct wfx_vif *wvif, u8 *mac_addr, int flags, int sta_id);
+int hif_update_ie(struct wfx_vif *wvif, const struct hif_ie_flags *target_frame,
+ const u8 *ies, size_t ies_len);
+int hif_sl_set_mac_key(struct wfx_dev *wdev, const uint8_t *slk_key, int destination);
+int hif_sl_config(struct wfx_dev *wdev, const unsigned long *bitmap);
+int hif_sl_send_pub_keys(struct wfx_dev *wdev,
+ const uint8_t *pubkey, const uint8_t *pubkey_hmac);
+
+#endif
diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h
new file mode 100644
index 000000000000..3339ad95f732
--- /dev/null
+++ b/drivers/staging/wfx/hif_tx_mib.h
@@ -0,0 +1,290 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Implementation of host-to-chip MIBs of WFxxx Split Mac (WSM) API.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (C) 2010, ST-Ericsson SA
+ */
+#ifndef WFX_HIF_TX_MIB_H
+#define WFX_HIF_TX_MIB_H
+
+#include <linux/etherdevice.h>
+
+#include "wfx.h"
+#include "hif_tx.h"
+#include "hif_api_mib.h"
+
+static inline int hif_set_output_power(struct wfx_vif *wvif, int power_level)
+{
+ __le32 val = cpu_to_le32(power_level);
+
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_CURRENT_TX_POWER_LEVEL,
+ &val, sizeof(val));
+}
+
+static inline int hif_set_beacon_wakeup_period(struct wfx_vif *wvif,
+ unsigned int dtim_interval,
+ unsigned int listen_interval)
+{
+ struct hif_mib_beacon_wake_up_period val = {
+ .wakeup_period_min = dtim_interval,
+ .receive_dtim = 0,
+ .wakeup_period_max = cpu_to_le16(listen_interval),
+ };
+
+ if (dtim_interval > 0xFF || listen_interval > 0xFFFF)
+ return -EINVAL;
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_BEACON_WAKEUP_PERIOD,
+ &val, sizeof(val));
+}
+
+static inline int hif_set_rcpi_rssi_threshold(struct wfx_vif *wvif,
+ struct hif_mib_rcpi_rssi_threshold *arg)
+{
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_RCPI_RSSI_THRESHOLD, arg, sizeof(*arg));
+}
+
+static inline int hif_get_counters_table(struct wfx_dev *wdev,
+ struct hif_mib_extended_count_table *arg)
+{
+ if (wfx_api_older_than(wdev, 1, 3)) {
+ // extended_count_table is wider than count_table
+ memset(arg, 0xFF, sizeof(*arg));
+ return hif_read_mib(wdev, 0, HIF_MIB_ID_COUNTERS_TABLE,
+ arg, sizeof(struct hif_mib_count_table));
+ } else {
+ return hif_read_mib(wdev, 0, HIF_MIB_ID_EXTENDED_COUNTERS_TABLE,
+ arg, sizeof(struct hif_mib_extended_count_table));
+ }
+}
+
+static inline int hif_set_macaddr(struct wfx_vif *wvif, u8 *mac)
+{
+ struct hif_mib_mac_address msg = { };
+
+ if (mac)
+ ether_addr_copy(msg.mac_addr, mac);
+ return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_DOT11_MAC_ADDRESS,
+ &msg, sizeof(msg));
+}
+
+static inline int hif_set_rx_filter(struct wfx_vif *wvif, bool filter_bssid,
+ bool fwd_probe_req)
+{
+ struct hif_mib_rx_filter val = { };
+
+ if (filter_bssid)
+ val.bssid_filter = 1;
+ if (fwd_probe_req)
+ val.fwd_probe_req = 1;
+ return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_RX_FILTER,
+ &val, sizeof(val));
+}
+
+static inline int hif_set_beacon_filter_table(struct wfx_vif *wvif,
+ int tbl_len,
+ struct hif_ie_table_entry *tbl)
+{
+ int ret;
+ struct hif_mib_bcn_filter_table *val;
+ int buf_len = struct_size(val, ie_table, tbl_len);
+
+ val = kzalloc(buf_len, GFP_KERNEL);
+ if (!val)
+ return -ENOMEM;
+ val->num_of_info_elmts = cpu_to_le32(tbl_len);
+ memcpy(val->ie_table, tbl, tbl_len * sizeof(*tbl));
+ ret = hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_BEACON_FILTER_TABLE, val, buf_len);
+ kfree(val);
+ return ret;
+}
+
+static inline int hif_beacon_filter_control(struct wfx_vif *wvif,
+ int enable, int beacon_count)
+{
+ struct hif_mib_bcn_filter_enable arg = {
+ .enable = cpu_to_le32(enable),
+ .bcn_count = cpu_to_le32(beacon_count),
+ };
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_BEACON_FILTER_ENABLE, &arg, sizeof(arg));
+}
+
+static inline int hif_set_operational_mode(struct wfx_dev *wdev,
+ enum hif_op_power_mode mode)
+{
+ struct hif_mib_gl_operational_power_mode val = {
+ .power_mode = mode,
+ .wup_ind_activation = 1,
+ };
+
+ return hif_write_mib(wdev, -1, HIF_MIB_ID_GL_OPERATIONAL_POWER_MODE,
+ &val, sizeof(val));
+}
+
+static inline int hif_set_template_frame(struct wfx_vif *wvif,
+ struct hif_mib_template_frame *arg)
+{
+ return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_TEMPLATE_FRAME,
+ arg, sizeof(*arg));
+}
+
+static inline int hif_set_mfp(struct wfx_vif *wvif, bool capable, bool required)
+{
+ struct hif_mib_protected_mgmt_policy val = { };
+
+ WARN(required && !capable, "incoherent arguments");
+ if (capable) {
+ val.pmf_enable = 1;
+ val.host_enc_auth_frames = 1;
+ }
+ if (!required)
+ val.unpmf_allowed = 1;
+ cpu_to_le32s((uint32_t *) &val);
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_PROTECTED_MGMT_POLICY,
+ &val, sizeof(val));
+}
+
+static inline int hif_set_block_ack_policy(struct wfx_vif *wvif,
+ u8 tx_tid_policy, u8 rx_tid_policy)
+{
+ struct hif_mib_block_ack_policy val = {
+ .block_ack_tx_tid_policy = tx_tid_policy,
+ .block_ack_rx_tid_policy = rx_tid_policy,
+ };
+
+ return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_BLOCK_ACK_POLICY,
+ &val, sizeof(val));
+}
+
+static inline int hif_set_association_mode(struct wfx_vif *wvif,
+ struct hif_mib_set_association_mode *arg)
+{
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_SET_ASSOCIATION_MODE, arg, sizeof(*arg));
+}
+
+static inline int hif_set_tx_rate_retry_policy(struct wfx_vif *wvif,
+ struct hif_mib_set_tx_rate_retry_policy *arg)
+{
+ size_t size = struct_size(arg, tx_rate_retry_policy, arg->num_tx_rate_policies);
+
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_SET_TX_RATE_RETRY_POLICY, arg, size);
+}
+
+static inline int hif_set_mac_addr_condition(struct wfx_vif *wvif,
+ struct hif_mib_mac_addr_data_frame_condition *arg)
+{
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_MAC_ADDR_DATAFRAME_CONDITION,
+ arg, sizeof(*arg));
+}
+
+static inline int hif_set_uc_mc_bc_condition(struct wfx_vif *wvif,
+ struct hif_mib_uc_mc_bc_data_frame_condition *arg)
+{
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_UC_MC_BC_DATAFRAME_CONDITION,
+ arg, sizeof(*arg));
+}
+
+static inline int hif_set_config_data_filter(struct wfx_vif *wvif,
+ struct hif_mib_config_data_filter *arg)
+{
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_CONFIG_DATA_FILTER, arg, sizeof(*arg));
+}
+
+static inline int hif_set_data_filtering(struct wfx_vif *wvif,
+ struct hif_mib_set_data_filtering *arg)
+{
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_SET_DATA_FILTERING, arg, sizeof(*arg));
+}
+
+static inline int hif_keep_alive_period(struct wfx_vif *wvif, int period)
+{
+ struct hif_mib_keep_alive_period arg = {
+ .keep_alive_period = cpu_to_le16(period),
+ };
+
+ return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_KEEP_ALIVE_PERIOD,
+ &arg, sizeof(arg));
+};
+
+static inline int hif_set_arp_ipv4_filter(struct wfx_vif *wvif,
+ struct hif_mib_arp_ip_addr_table *fp)
+{
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_ARP_IP_ADDRESSES_TABLE,
+ fp, sizeof(*fp));
+}
+
+static inline int hif_use_multi_tx_conf(struct wfx_dev *wdev,
+ bool enabled)
+{
+ __le32 arg = enabled ? cpu_to_le32(1) : 0;
+
+ return hif_write_mib(wdev, -1, HIF_MIB_ID_GL_SET_MULTI_MSG,
+ &arg, sizeof(arg));
+}
+
+static inline int hif_set_uapsd_info(struct wfx_vif *wvif,
+ struct hif_mib_set_uapsd_information *arg)
+{
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_SET_UAPSD_INFORMATION,
+ arg, sizeof(*arg));
+}
+
+static inline int hif_erp_use_protection(struct wfx_vif *wvif, bool enable)
+{
+ __le32 arg = enable ? cpu_to_le32(1) : 0;
+
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_NON_ERP_PROTECTION, &arg, sizeof(arg));
+}
+
+static inline int hif_slot_time(struct wfx_vif *wvif, int val)
+{
+ __le32 arg = cpu_to_le32(val);
+
+ return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SLOT_TIME,
+ &arg, sizeof(arg));
+}
+
+static inline int hif_dual_cts_protection(struct wfx_vif *wvif, bool val)
+{
+ struct hif_mib_set_ht_protection arg = {
+ .dual_cts_prot = val,
+ };
+
+ return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SET_HT_PROTECTION,
+ &arg, sizeof(arg));
+}
+
+static inline int hif_wep_default_key_id(struct wfx_vif *wvif, int val)
+{
+ __le32 arg = cpu_to_le32(val);
+
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID,
+ &arg, sizeof(arg));
+}
+
+static inline int hif_rts_threshold(struct wfx_vif *wvif, int val)
+{
+ __le32 arg = cpu_to_le32(val > 0 ? val : 0xFFFF);
+
+ return hif_write_mib(wvif->wdev, wvif->id,
+ HIF_MIB_ID_DOT11_RTS_THRESHOLD, &arg, sizeof(arg));
+}
+
+#endif
diff --git a/drivers/staging/wfx/hwio.c b/drivers/staging/wfx/hwio.c
new file mode 100644
index 000000000000..0cf52aee10e7
--- /dev/null
+++ b/drivers/staging/wfx/hwio.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Low-level I/O functions.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "hwio.h"
+#include "wfx.h"
+#include "bus.h"
+#include "traces.h"
+
+/*
+ * Internal helpers.
+ *
+ * About CONFIG_VMAP_STACK:
+ * When CONFIG_VMAP_STACK is enabled, it is not possible to run DMA on stack
+ * allocated data. Functions below that work with registers (aka functions
+ * ending with "32") automatically reallocate buffers with kmalloc. However,
+ * functions that work with arbitrary length buffers let's caller to handle
+ * memory location. In doubt, enable CONFIG_DEBUG_SG to detect badly located
+ * buffer.
+ */
+
+static int read32(struct wfx_dev *wdev, int reg, u32 *val)
+{
+ int ret;
+ __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
+
+ *val = ~0; // Never return undefined value
+ if (!tmp)
+ return -ENOMEM;
+ ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, tmp, sizeof(u32));
+ if (ret >= 0)
+ *val = le32_to_cpu(*tmp);
+ kfree(tmp);
+ if (ret)
+ dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
+ return ret;
+}
+
+static int write32(struct wfx_dev *wdev, int reg, u32 val)
+{
+ int ret;
+ __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
+
+ if (!tmp)
+ return -ENOMEM;
+ *tmp = cpu_to_le32(val);
+ ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, tmp, sizeof(u32));
+ kfree(tmp);
+ if (ret)
+ dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
+ return ret;
+}
+
+static int read32_locked(struct wfx_dev *wdev, int reg, u32 *val)
+{
+ int ret;
+
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = read32(wdev, reg, val);
+ _trace_io_read32(reg, *val);
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ return ret;
+}
+
+static int write32_locked(struct wfx_dev *wdev, int reg, u32 val)
+{
+ int ret;
+
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = write32(wdev, reg, val);
+ _trace_io_write32(reg, val);
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ return ret;
+}
+
+static int write32_bits_locked(struct wfx_dev *wdev, int reg, u32 mask, u32 val)
+{
+ int ret;
+ u32 val_r, val_w;
+
+ WARN_ON(~mask & val);
+ val &= mask;
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = read32(wdev, reg, &val_r);
+ _trace_io_read32(reg, val_r);
+ if (ret < 0)
+ goto err;
+ val_w = (val_r & ~mask) | val;
+ if (val_w != val_r) {
+ ret = write32(wdev, reg, val_w);
+ _trace_io_write32(reg, val_w);
+ }
+err:
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ return ret;
+}
+
+static int indirect_read(struct wfx_dev *wdev, int reg, u32 addr, void *buf, size_t len)
+{
+ int ret;
+ int i;
+ u32 cfg;
+ u32 prefetch;
+
+ WARN_ON(len >= 0x2000);
+ WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
+
+ if (reg == WFX_REG_AHB_DPORT)
+ prefetch = CFG_PREFETCH_AHB;
+ else if (reg == WFX_REG_SRAM_DPORT)
+ prefetch = CFG_PREFETCH_SRAM;
+ else
+ return -ENODEV;
+
+ ret = write32(wdev, WFX_REG_BASE_ADDR, addr);
+ if (ret < 0)
+ goto err;
+
+ ret = read32(wdev, WFX_REG_CONFIG, &cfg);
+ if (ret < 0)
+ goto err;
+
+ ret = write32(wdev, WFX_REG_CONFIG, cfg | prefetch);
+ if (ret < 0)
+ goto err;
+
+ for (i = 0; i < 20; i++) {
+ ret = read32(wdev, WFX_REG_CONFIG, &cfg);
+ if (ret < 0)
+ goto err;
+ if (!(cfg & prefetch))
+ break;
+ udelay(200);
+ }
+ if (i == 20) {
+ ret = -ETIMEDOUT;
+ goto err;
+ }
+
+ ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, buf, len);
+
+err:
+ if (ret < 0)
+ memset(buf, 0xFF, len); // Never return undefined value
+ return ret;
+}
+
+static int indirect_write(struct wfx_dev *wdev, int reg, u32 addr, const void *buf, size_t len)
+{
+ int ret;
+
+ WARN_ON(len >= 0x2000);
+ WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
+ ret = write32(wdev, WFX_REG_BASE_ADDR, addr);
+ if (ret < 0)
+ return ret;
+
+ return wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, buf, len);
+}
+
+static int indirect_read_locked(struct wfx_dev *wdev, int reg, u32 addr, void *buf, size_t len)
+{
+ int ret;
+
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = indirect_read(wdev, reg, addr, buf, len);
+ _trace_io_ind_read(reg, addr, buf, len);
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ return ret;
+}
+
+static int indirect_write_locked(struct wfx_dev *wdev, int reg, u32 addr, const void *buf, size_t len)
+{
+ int ret;
+
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = indirect_write(wdev, reg, addr, buf, len);
+ _trace_io_ind_write(reg, addr, buf, len);
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ return ret;
+}
+
+static int indirect_read32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 *val)
+{
+ int ret;
+ __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
+
+ if (!tmp)
+ return -ENOMEM;
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = indirect_read(wdev, reg, addr, tmp, sizeof(u32));
+ *val = cpu_to_le32(*tmp);
+ _trace_io_ind_read32(reg, addr, *val);
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ kfree(tmp);
+ return ret;
+}
+
+static int indirect_write32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 val)
+{
+ int ret;
+ __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
+
+ if (!tmp)
+ return -ENOMEM;
+ *tmp = cpu_to_le32(val);
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = indirect_write(wdev, reg, addr, tmp, sizeof(u32));
+ _trace_io_ind_write32(reg, addr, val);
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ kfree(tmp);
+ return ret;
+}
+
+int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t len)
+{
+ int ret;
+
+ WARN((long) buf & 3, "%s: unaligned buffer", __func__);
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
+ _trace_io_read(WFX_REG_IN_OUT_QUEUE, buf, len);
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ if (ret)
+ dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
+ return ret;
+}
+
+int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t len)
+{
+ int ret;
+
+ WARN((long) buf & 3, "%s: unaligned buffer", __func__);
+ wdev->hwbus_ops->lock(wdev->hwbus_priv);
+ ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
+ _trace_io_write(WFX_REG_IN_OUT_QUEUE, buf, len);
+ wdev->hwbus_ops->unlock(wdev->hwbus_priv);
+ if (ret)
+ dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
+ return ret;
+}
+
+int sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
+{
+ return indirect_read_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
+}
+
+int ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
+{
+ return indirect_read_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
+}
+
+int sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
+{
+ return indirect_write_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
+}
+
+int ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
+{
+ return indirect_write_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
+}
+
+int sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
+{
+ return indirect_read32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
+}
+
+int ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
+{
+ return indirect_read32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
+}
+
+int sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
+{
+ return indirect_write32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
+}
+
+int ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
+{
+ return indirect_write32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
+}
+
+int config_reg_read(struct wfx_dev *wdev, u32 *val)
+{
+ return read32_locked(wdev, WFX_REG_CONFIG, val);
+}
+
+int config_reg_write(struct wfx_dev *wdev, u32 val)
+{
+ return write32_locked(wdev, WFX_REG_CONFIG, val);
+}
+
+int config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
+{
+ return write32_bits_locked(wdev, WFX_REG_CONFIG, mask, val);
+}
+
+int control_reg_read(struct wfx_dev *wdev, u32 *val)
+{
+ return read32_locked(wdev, WFX_REG_CONTROL, val);
+}
+
+int control_reg_write(struct wfx_dev *wdev, u32 val)
+{
+ return write32_locked(wdev, WFX_REG_CONTROL, val);
+}
+
+int control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
+{
+ return write32_bits_locked(wdev, WFX_REG_CONTROL, mask, val);
+}
+
+int igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val)
+{
+ int ret;
+
+ *val = ~0; // Never return undefined value
+ ret = write32_locked(wdev, WFX_REG_SET_GEN_R_W, IGPR_RW | index << 24);
+ if (ret)
+ return ret;
+ ret = read32_locked(wdev, WFX_REG_SET_GEN_R_W, val);
+ if (ret)
+ return ret;
+ *val &= IGPR_VALUE;
+ return ret;
+}
+
+int igpr_reg_write(struct wfx_dev *wdev, int index, u32 val)
+{
+ return write32_locked(wdev, WFX_REG_SET_GEN_R_W, index << 24 | val);
+}
diff --git a/drivers/staging/wfx/hwio.h b/drivers/staging/wfx/hwio.h
new file mode 100644
index 000000000000..906524f71fd1
--- /dev/null
+++ b/drivers/staging/wfx/hwio.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Low-level API.
+ *
+ * Copyright (c) 2017-2018, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_HWIO_H
+#define WFX_HWIO_H
+
+#include <linux/types.h>
+
+struct wfx_dev;
+
+int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t buf_len);
+int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t buf_len);
+
+int sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len);
+int sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len);
+
+int ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len);
+int ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len);
+
+int sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val);
+int sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val);
+
+int ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val);
+int ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val);
+
+#define CFG_ERR_SPI_FRAME 0x00000001 // only with SPI
+#define CFG_ERR_SDIO_BUF_MISMATCH 0x00000001 // only with SDIO
+#define CFG_ERR_BUF_UNDERRUN 0x00000002
+#define CFG_ERR_DATA_IN_TOO_LARGE 0x00000004
+#define CFG_ERR_HOST_NO_OUT_QUEUE 0x00000008
+#define CFG_ERR_BUF_OVERRUN 0x00000010
+#define CFG_ERR_DATA_OUT_TOO_LARGE 0x00000020
+#define CFG_ERR_HOST_NO_IN_QUEUE 0x00000040
+#define CFG_ERR_HOST_CRC_MISS 0x00000080 // only with SDIO
+#define CFG_SPI_IGNORE_CS 0x00000080 // only with SPI
+#define CFG_WORD_MODE_MASK 0x00000300 // Bytes ordering (only writable in SPI):
+#define CFG_WORD_MODE0 0x00000000 // B1,B0,B3,B2 (In SPI, register address and CONFIG data always use this mode)
+#define CFG_WORD_MODE1 0x00000100 // B3,B2,B1,B0
+#define CFG_WORD_MODE2 0x00000200 // B0,B1,B2,B3 (SDIO)
+#define CFG_DIRECT_ACCESS_MODE 0x00000400 // Direct or queue access mode
+#define CFG_PREFETCH_AHB 0x00000800
+#define CFG_DISABLE_CPU_CLK 0x00001000
+#define CFG_PREFETCH_SRAM 0x00002000
+#define CFG_CPU_RESET 0x00004000
+#define CFG_SDIO_DISABLE_IRQ 0x00008000 // only with SDIO
+#define CFG_IRQ_ENABLE_DATA 0x00010000
+#define CFG_IRQ_ENABLE_WRDY 0x00020000
+#define CFG_CLK_RISE_EDGE 0x00040000
+#define CFG_SDIO_DISABLE_CRC_CHK 0x00080000 // only with SDIO
+#define CFG_RESERVED 0x00F00000
+#define CFG_DEVICE_ID_MAJOR 0x07000000
+#define CFG_DEVICE_ID_RESERVED 0x78000000
+#define CFG_DEVICE_ID_TYPE 0x80000000
+int config_reg_read(struct wfx_dev *wdev, u32 *val);
+int config_reg_write(struct wfx_dev *wdev, u32 val);
+int config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val);
+
+#define CTRL_NEXT_LEN_MASK 0x00000FFF
+#define CTRL_WLAN_WAKEUP 0x00001000
+#define CTRL_WLAN_READY 0x00002000
+int control_reg_read(struct wfx_dev *wdev, u32 *val);
+int control_reg_write(struct wfx_dev *wdev, u32 val);
+int control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val);
+
+#define IGPR_RW 0x80000000
+#define IGPR_INDEX 0x7F000000
+#define IGPR_VALUE 0x00FFFFFF
+int igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val);
+int igpr_reg_write(struct wfx_dev *wdev, int index, u32 val);
+
+#endif /* WFX_HWIO_H */
diff --git a/drivers/staging/wfx/key.c b/drivers/staging/wfx/key.c
new file mode 100644
index 000000000000..6d03abec20e4
--- /dev/null
+++ b/drivers/staging/wfx/key.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Key management related functions.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <net/mac80211.h>
+
+#include "key.h"
+#include "wfx.h"
+#include "hif_tx_mib.h"
+
+static int wfx_alloc_key(struct wfx_dev *wdev)
+{
+ int idx;
+
+ idx = ffs(~wdev->key_map) - 1;
+ if (idx < 0 || idx >= MAX_KEY_ENTRIES)
+ return -1;
+
+ wdev->key_map |= BIT(idx);
+ wdev->keys[idx].entry_index = idx;
+ return idx;
+}
+
+static void wfx_free_key(struct wfx_dev *wdev, int idx)
+{
+ WARN(!(wdev->key_map & BIT(idx)), "inconsistent key allocation");
+ memset(&wdev->keys[idx], 0, sizeof(wdev->keys[idx]));
+ wdev->key_map &= ~BIT(idx);
+}
+
+static uint8_t fill_wep_pair(struct hif_wep_pairwise_key *msg,
+ struct ieee80211_key_conf *key, u8 *peer_addr)
+{
+ WARN(key->keylen > sizeof(msg->key_data), "inconsistent data");
+ msg->key_length = key->keylen;
+ memcpy(msg->key_data, key->key, key->keylen);
+ ether_addr_copy(msg->peer_address, peer_addr);
+ return HIF_KEY_TYPE_WEP_PAIRWISE;
+}
+
+static uint8_t fill_wep_group(struct hif_wep_group_key *msg,
+ struct ieee80211_key_conf *key)
+{
+ WARN(key->keylen > sizeof(msg->key_data), "inconsistent data");
+ msg->key_id = key->keyidx;
+ msg->key_length = key->keylen;
+ memcpy(msg->key_data, key->key, key->keylen);
+ return HIF_KEY_TYPE_WEP_DEFAULT;
+}
+
+static uint8_t fill_tkip_pair(struct hif_tkip_pairwise_key *msg,
+ struct ieee80211_key_conf *key, u8 *peer_addr)
+{
+ uint8_t *keybuf = key->key;
+
+ WARN(key->keylen != sizeof(msg->tkip_key_data)
+ + sizeof(msg->tx_mic_key)
+ + sizeof(msg->rx_mic_key), "inconsistent data");
+ memcpy(msg->tkip_key_data, keybuf, sizeof(msg->tkip_key_data));
+ keybuf += sizeof(msg->tkip_key_data);
+ memcpy(msg->tx_mic_key, keybuf, sizeof(msg->tx_mic_key));
+ keybuf += sizeof(msg->tx_mic_key);
+ memcpy(msg->rx_mic_key, keybuf, sizeof(msg->rx_mic_key));
+ ether_addr_copy(msg->peer_address, peer_addr);
+ return HIF_KEY_TYPE_TKIP_PAIRWISE;
+}
+
+static uint8_t fill_tkip_group(struct hif_tkip_group_key *msg,
+ struct ieee80211_key_conf *key,
+ struct ieee80211_key_seq *seq,
+ enum nl80211_iftype iftype)
+{
+ uint8_t *keybuf = key->key;
+
+ WARN(key->keylen != sizeof(msg->tkip_key_data)
+ + 2 * sizeof(msg->rx_mic_key), "inconsistent data");
+ msg->key_id = key->keyidx;
+ memcpy(msg->rx_sequence_counter, &seq->tkip.iv16, sizeof(seq->tkip.iv16));
+ memcpy(msg->rx_sequence_counter + sizeof(uint16_t), &seq->tkip.iv32, sizeof(seq->tkip.iv32));
+ memcpy(msg->tkip_key_data, keybuf, sizeof(msg->tkip_key_data));
+ keybuf += sizeof(msg->tkip_key_data);
+ if (iftype == NL80211_IFTYPE_AP)
+ // Use Tx MIC Key
+ memcpy(msg->rx_mic_key, keybuf + 0, sizeof(msg->rx_mic_key));
+ else
+ // Use Rx MIC Key
+ memcpy(msg->rx_mic_key, keybuf + 8, sizeof(msg->rx_mic_key));
+ return HIF_KEY_TYPE_TKIP_GROUP;
+}
+
+static uint8_t fill_ccmp_pair(struct hif_aes_pairwise_key *msg,
+ struct ieee80211_key_conf *key, u8 *peer_addr)
+{
+ WARN(key->keylen != sizeof(msg->aes_key_data), "inconsistent data");
+ ether_addr_copy(msg->peer_address, peer_addr);
+ memcpy(msg->aes_key_data, key->key, key->keylen);
+ return HIF_KEY_TYPE_AES_PAIRWISE;
+}
+
+static uint8_t fill_ccmp_group(struct hif_aes_group_key *msg,
+ struct ieee80211_key_conf *key,
+ struct ieee80211_key_seq *seq)
+{
+ WARN(key->keylen != sizeof(msg->aes_key_data), "inconsistent data");
+ memcpy(msg->aes_key_data, key->key, key->keylen);
+ memcpy(msg->rx_sequence_counter, seq->ccmp.pn, sizeof(seq->ccmp.pn));
+ memreverse(msg->rx_sequence_counter, sizeof(seq->ccmp.pn));
+ msg->key_id = key->keyidx;
+ return HIF_KEY_TYPE_AES_GROUP;
+}
+
+static uint8_t fill_sms4_pair(struct hif_wapi_pairwise_key *msg,
+ struct ieee80211_key_conf *key, u8 *peer_addr)
+{
+ uint8_t *keybuf = key->key;
+
+ WARN(key->keylen != sizeof(msg->wapi_key_data)
+ + sizeof(msg->mic_key_data), "inconsistent data");
+ ether_addr_copy(msg->peer_address, peer_addr);
+ memcpy(msg->wapi_key_data, keybuf, sizeof(msg->wapi_key_data));
+ keybuf += sizeof(msg->wapi_key_data);
+ memcpy(msg->mic_key_data, keybuf, sizeof(msg->mic_key_data));
+ msg->key_id = key->keyidx;
+ return HIF_KEY_TYPE_WAPI_PAIRWISE;
+}
+
+static uint8_t fill_sms4_group(struct hif_wapi_group_key *msg,
+ struct ieee80211_key_conf *key)
+{
+ uint8_t *keybuf = key->key;
+
+ WARN(key->keylen != sizeof(msg->wapi_key_data)
+ + sizeof(msg->mic_key_data), "inconsistent data");
+ memcpy(msg->wapi_key_data, keybuf, sizeof(msg->wapi_key_data));
+ keybuf += sizeof(msg->wapi_key_data);
+ memcpy(msg->mic_key_data, keybuf, sizeof(msg->mic_key_data));
+ msg->key_id = key->keyidx;
+ return HIF_KEY_TYPE_WAPI_GROUP;
+}
+
+static uint8_t fill_aes_cmac_group(struct hif_igtk_group_key *msg,
+ struct ieee80211_key_conf *key,
+ struct ieee80211_key_seq *seq)
+{
+ WARN(key->keylen != sizeof(msg->igtk_key_data), "inconsistent data");
+ memcpy(msg->igtk_key_data, key->key, key->keylen);
+ memcpy(msg->ipn, seq->aes_cmac.pn, sizeof(seq->aes_cmac.pn));
+ memreverse(msg->ipn, sizeof(seq->aes_cmac.pn));
+ msg->key_id = key->keyidx;
+ return HIF_KEY_TYPE_IGTK_GROUP;
+}
+
+static int wfx_add_key(struct wfx_vif *wvif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ int ret;
+ struct hif_req_add_key *k;
+ struct ieee80211_key_seq seq;
+ struct wfx_dev *wdev = wvif->wdev;
+ int idx = wfx_alloc_key(wvif->wdev);
+ bool pairwise = key->flags & IEEE80211_KEY_FLAG_PAIRWISE;
+
+ WARN(key->flags & IEEE80211_KEY_FLAG_PAIRWISE && !sta, "inconsistent data");
+ ieee80211_get_key_rx_seq(key, 0, &seq);
+ if (idx < 0)
+ return -EINVAL;
+ k = &wdev->keys[idx];
+ k->int_id = wvif->id;
+ if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) {
+ if (pairwise)
+ k->type = fill_wep_pair(&k->key.wep_pairwise_key, key, sta->addr);
+ else
+ k->type = fill_wep_group(&k->key.wep_group_key, key);
+ } else if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+ if (pairwise)
+ k->type = fill_tkip_pair(&k->key.tkip_pairwise_key, key, sta->addr);
+ else
+ k->type = fill_tkip_group(&k->key.tkip_group_key, key, &seq, wvif->vif->type);
+ } else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) {
+ if (pairwise)
+ k->type = fill_ccmp_pair(&k->key.aes_pairwise_key, key, sta->addr);
+ else
+ k->type = fill_ccmp_group(&k->key.aes_group_key, key, &seq);
+ } else if (key->cipher == WLAN_CIPHER_SUITE_SMS4) {
+ if (pairwise)
+ k->type = fill_sms4_pair(&k->key.wapi_pairwise_key, key, sta->addr);
+ else
+ k->type = fill_sms4_group(&k->key.wapi_group_key, key);
+ } else if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+ k->type = fill_aes_cmac_group(&k->key.igtk_group_key, key, &seq);
+ } else {
+ dev_warn(wdev->dev, "unsupported key type %d\n", key->cipher);
+ wfx_free_key(wdev, idx);
+ return -EOPNOTSUPP;
+ }
+ ret = hif_add_key(wdev, k);
+ if (ret) {
+ wfx_free_key(wdev, idx);
+ return -EOPNOTSUPP;
+ }
+ key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
+ key->hw_key_idx = idx;
+ return 0;
+}
+
+static int wfx_remove_key(struct wfx_vif *wvif, struct ieee80211_key_conf *key)
+{
+ WARN(key->hw_key_idx >= MAX_KEY_ENTRIES, "corrupted hw_key_idx");
+ wfx_free_key(wvif->wdev, key->hw_key_idx);
+ return hif_remove_key(wvif->wdev, key->hw_key_idx);
+}
+
+int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ int ret = -EOPNOTSUPP;
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+
+ mutex_lock(&wvif->wdev->conf_mutex);
+ if (cmd == SET_KEY)
+ ret = wfx_add_key(wvif, sta, key);
+ if (cmd == DISABLE_KEY)
+ ret = wfx_remove_key(wvif, key);
+ mutex_unlock(&wvif->wdev->conf_mutex);
+ return ret;
+}
+
+int wfx_upload_keys(struct wfx_vif *wvif)
+{
+ int i;
+ struct hif_req_add_key *key;
+ struct wfx_dev *wdev = wvif->wdev;
+
+ for (i = 0; i < ARRAY_SIZE(wdev->keys); i++) {
+ if (wdev->key_map & BIT(i)) {
+ key = &wdev->keys[i];
+ if (key->int_id == wvif->id)
+ hif_add_key(wdev, key);
+ }
+ }
+ return 0;
+}
+
+void wfx_wep_key_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, wep_key_work);
+
+ wfx_tx_flush(wvif->wdev);
+ hif_wep_default_key_id(wvif, wvif->wep_default_key_id);
+ wfx_pending_requeue(wvif->wdev, wvif->wep_pending_skb);
+ wvif->wep_pending_skb = NULL;
+ wfx_tx_unlock(wvif->wdev);
+}
diff --git a/drivers/staging/wfx/key.h b/drivers/staging/wfx/key.h
new file mode 100644
index 000000000000..9436ccdf4d3b
--- /dev/null
+++ b/drivers/staging/wfx/key.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Implementation of mac80211 API.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_KEY_H
+#define WFX_KEY_H
+
+#include <net/mac80211.h>
+
+struct wfx_dev;
+struct wfx_vif;
+
+int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key);
+int wfx_upload_keys(struct wfx_vif *wvif);
+void wfx_wep_key_work(struct work_struct *work);
+
+#endif /* WFX_STA_H */
diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c
new file mode 100644
index 000000000000..18f07f7ad347
--- /dev/null
+++ b/drivers/staging/wfx/main.c
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Device probe and register.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (c) 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ */
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/spi/spi.h>
+#include <linux/etherdevice.h>
+#include <linux/firmware.h>
+
+#include "main.h"
+#include "wfx.h"
+#include "fwio.h"
+#include "hwio.h"
+#include "bus.h"
+#include "bh.h"
+#include "sta.h"
+#include "key.h"
+#include "debug.h"
+#include "data_tx.h"
+#include "secure_link.h"
+#include "hif_tx_mib.h"
+#include "hif_api_cmd.h"
+
+#define WFX_PDS_MAX_SIZE 1500
+
+MODULE_DESCRIPTION("Silicon Labs 802.11 Wireless LAN driver for WFx");
+MODULE_AUTHOR("Jérôme Pouiller <jerome.pouiller@silabs.com>");
+MODULE_LICENSE("GPL");
+
+static int gpio_wakeup = -2;
+module_param(gpio_wakeup, int, 0644);
+MODULE_PARM_DESC(gpio_wakeup, "gpio number for wakeup. -1 for none.");
+
+#define RATETAB_ENT(_rate, _rateid, _flags) { \
+ .bitrate = (_rate), \
+ .hw_value = (_rateid), \
+ .flags = (_flags), \
+}
+
+static struct ieee80211_rate wfx_rates[] = {
+ RATETAB_ENT(10, 0, 0),
+ RATETAB_ENT(20, 1, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(55, 2, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(110, 3, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(60, 6, 0),
+ RATETAB_ENT(90, 7, 0),
+ RATETAB_ENT(120, 8, 0),
+ RATETAB_ENT(180, 9, 0),
+ RATETAB_ENT(240, 10, 0),
+ RATETAB_ENT(360, 11, 0),
+ RATETAB_ENT(480, 12, 0),
+ RATETAB_ENT(540, 13, 0),
+};
+
+#define CHAN2G(_channel, _freq, _flags) { \
+ .band = NL80211_BAND_2GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+static struct ieee80211_channel wfx_2ghz_chantable[] = {
+ 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 const struct ieee80211_supported_band wfx_band_2ghz = {
+ .channels = wfx_2ghz_chantable,
+ .n_channels = ARRAY_SIZE(wfx_2ghz_chantable),
+ .bitrates = wfx_rates,
+ .n_bitrates = ARRAY_SIZE(wfx_rates),
+ .ht_cap = {
+ // Receive caps
+ .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_MAX_AMSDU | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT),
+ .ht_supported = 1,
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
+ .mcs = {
+ .rx_mask = { 0xFF }, // MCS0 to MCS7
+ .rx_highest = 65,
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
+ },
+ },
+};
+
+static const struct ieee80211_iface_limit wdev_iface_limits[] = {
+ { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) },
+ { .max = 1, .types = BIT(NL80211_IFTYPE_AP) },
+};
+
+static const struct ieee80211_iface_combination wfx_iface_combinations[] = {
+ {
+ .num_different_channels = 2,
+ .max_interfaces = 2,
+ .limits = wdev_iface_limits,
+ .n_limits = ARRAY_SIZE(wdev_iface_limits),
+ }
+};
+
+static const struct ieee80211_ops wfx_ops = {
+ .start = wfx_start,
+ .stop = wfx_stop,
+ .add_interface = wfx_add_interface,
+ .remove_interface = wfx_remove_interface,
+ .config = wfx_config,
+ .tx = wfx_tx,
+ .conf_tx = wfx_conf_tx,
+ .hw_scan = wfx_hw_scan,
+ .sta_add = wfx_sta_add,
+ .sta_remove = wfx_sta_remove,
+ .sta_notify = wfx_sta_notify,
+ .set_tim = wfx_set_tim,
+ .set_key = wfx_set_key,
+ .set_rts_threshold = wfx_set_rts_threshold,
+ .bss_info_changed = wfx_bss_info_changed,
+ .prepare_multicast = wfx_prepare_multicast,
+ .configure_filter = wfx_configure_filter,
+ .ampdu_action = wfx_ampdu_action,
+ .flush = wfx_flush,
+ .add_chanctx = wfx_add_chanctx,
+ .remove_chanctx = wfx_remove_chanctx,
+ .change_chanctx = wfx_change_chanctx,
+ .assign_vif_chanctx = wfx_assign_vif_chanctx,
+ .unassign_vif_chanctx = wfx_unassign_vif_chanctx,
+};
+
+bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor)
+{
+ if (wdev->hw_caps.api_version_major < major)
+ return true;
+ if (wdev->hw_caps.api_version_major > major)
+ return false;
+ if (wdev->hw_caps.api_version_minor < minor)
+ return true;
+ return false;
+}
+
+struct gpio_desc *wfx_get_gpio(struct device *dev, int override, const char *label)
+{
+ struct gpio_desc *ret;
+ char label_buf[256];
+
+ if (override >= 0) {
+ snprintf(label_buf, sizeof(label_buf), "wfx_%s", label);
+ ret = ERR_PTR(devm_gpio_request_one(dev, override, GPIOF_OUT_INIT_LOW, label_buf));
+ if (!ret)
+ ret = gpio_to_desc(override);
+ } else if (override == -1) {
+ ret = NULL;
+ } else {
+ ret = devm_gpiod_get(dev, label, GPIOD_OUT_LOW);
+ }
+ if (IS_ERR(ret) || !ret) {
+ if (!ret || PTR_ERR(ret) == -ENOENT)
+ dev_warn(dev, "gpio %s is not defined\n", label);
+ else
+ dev_warn(dev, "error while requesting gpio %s\n", label);
+ ret = NULL;
+ } else {
+ dev_dbg(dev, "using gpio %d for %s\n", desc_to_gpio(ret), label);
+ }
+ return ret;
+}
+
+/* NOTE: wfx_send_pds() destroy buf */
+int wfx_send_pds(struct wfx_dev *wdev, unsigned char *buf, size_t len)
+{
+ int ret;
+ int start, brace_level, i;
+
+ start = 0;
+ brace_level = 0;
+ if (buf[0] != '{') {
+ dev_err(wdev->dev, "valid PDS start with '{'. Did you forget to compress it?\n");
+ return -EINVAL;
+ }
+ for (i = 1; i < len - 1; i++) {
+ if (buf[i] == '{')
+ brace_level++;
+ if (buf[i] == '}')
+ brace_level--;
+ if (buf[i] == '}' && !brace_level) {
+ i++;
+ if (i - start + 1 > WFX_PDS_MAX_SIZE)
+ return -EFBIG;
+ buf[start] = '{';
+ buf[i] = 0;
+ dev_dbg(wdev->dev, "send PDS '%s}'\n", buf + start);
+ buf[i] = '}';
+ ret = hif_configuration(wdev, buf + start, i - start + 1);
+ if (ret == HIF_STATUS_FAILURE) {
+ dev_err(wdev->dev, "PDS bytes %d to %d: invalid data (unsupported options?)\n", start, i);
+ return -EINVAL;
+ }
+ if (ret == -ETIMEDOUT) {
+ dev_err(wdev->dev, "PDS bytes %d to %d: chip didn't reply (corrupted file?)\n", start, i);
+ return ret;
+ }
+ if (ret) {
+ dev_err(wdev->dev, "PDS bytes %d to %d: chip returned an unknown error\n", start, i);
+ return -EIO;
+ }
+ buf[i] = ',';
+ start = i;
+ }
+ }
+ return 0;
+}
+
+static int wfx_send_pdata_pds(struct wfx_dev *wdev)
+{
+ int ret = 0;
+ const struct firmware *pds;
+ unsigned char *tmp_buf;
+
+ ret = request_firmware(&pds, wdev->pdata.file_pds, wdev->dev);
+ if (ret) {
+ dev_err(wdev->dev, "can't load PDS file %s\n", wdev->pdata.file_pds);
+ return ret;
+ }
+ tmp_buf = kmemdup(pds->data, pds->size, GFP_KERNEL);
+ ret = wfx_send_pds(wdev, tmp_buf, pds->size);
+ kfree(tmp_buf);
+ release_firmware(pds);
+ return ret;
+}
+
+struct wfx_dev *wfx_init_common(struct device *dev,
+ const struct wfx_platform_data *pdata,
+ const struct hwbus_ops *hwbus_ops,
+ void *hwbus_priv)
+{
+ struct ieee80211_hw *hw;
+ struct wfx_dev *wdev;
+
+ hw = ieee80211_alloc_hw(sizeof(struct wfx_dev), &wfx_ops);
+ if (!hw)
+ return NULL;
+
+ SET_IEEE80211_DEV(hw, dev);
+
+ ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
+ ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
+ ieee80211_hw_set(hw, AMPDU_AGGREGATION);
+ ieee80211_hw_set(hw, CONNECTION_MONITOR);
+ ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
+ ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
+ ieee80211_hw_set(hw, SIGNAL_DBM);
+ ieee80211_hw_set(hw, SUPPORTS_PS);
+ ieee80211_hw_set(hw, MFP_CAPABLE);
+
+ hw->vif_data_size = sizeof(struct wfx_vif);
+ hw->sta_data_size = sizeof(struct wfx_sta_priv);
+ hw->queues = 4;
+ hw->max_rates = 8;
+ hw->max_rate_tries = 15;
+ hw->extra_tx_headroom = sizeof(struct hif_sl_msg_hdr) + sizeof(struct hif_msg)
+ + sizeof(struct hif_req_tx)
+ + 4 /* alignment */ + 8 /* TKIP IV */;
+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP);
+ hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ hw->wiphy->max_ap_assoc_sta = WFX_MAX_STA_IN_AP_MODE;
+ hw->wiphy->max_scan_ssids = 2;
+ hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+ hw->wiphy->n_iface_combinations = ARRAY_SIZE(wfx_iface_combinations);
+ hw->wiphy->iface_combinations = wfx_iface_combinations;
+ hw->wiphy->bands[NL80211_BAND_2GHZ] = devm_kmalloc(dev, sizeof(wfx_band_2ghz), GFP_KERNEL);
+ // FIXME: also copy wfx_rates and wfx_2ghz_chantable
+ memcpy(hw->wiphy->bands[NL80211_BAND_2GHZ], &wfx_band_2ghz, sizeof(wfx_band_2ghz));
+
+ wdev = hw->priv;
+ wdev->hw = hw;
+ wdev->dev = dev;
+ wdev->hwbus_ops = hwbus_ops;
+ wdev->hwbus_priv = hwbus_priv;
+ memcpy(&wdev->pdata, pdata, sizeof(*pdata));
+ of_property_read_string(dev->of_node, "config-file", &wdev->pdata.file_pds);
+ wdev->pdata.gpio_wakeup = wfx_get_gpio(dev, gpio_wakeup, "wakeup");
+ wfx_sl_fill_pdata(dev, &wdev->pdata);
+
+ mutex_init(&wdev->conf_mutex);
+ mutex_init(&wdev->rx_stats_lock);
+ init_completion(&wdev->firmware_ready);
+ wfx_init_hif_cmd(&wdev->hif_cmd);
+ wfx_tx_queues_init(wdev);
+
+ return wdev;
+}
+
+void wfx_free_common(struct wfx_dev *wdev)
+{
+ mutex_destroy(&wdev->rx_stats_lock);
+ mutex_destroy(&wdev->conf_mutex);
+ wfx_tx_queues_deinit(wdev);
+ ieee80211_free_hw(wdev->hw);
+}
+
+int wfx_probe(struct wfx_dev *wdev)
+{
+ int i;
+ int err;
+ const void *macaddr;
+ struct gpio_desc *gpio_saved;
+
+ // During first part of boot, gpio_wakeup cannot yet been used. So
+ // prevent bh() to touch it.
+ gpio_saved = wdev->pdata.gpio_wakeup;
+ wdev->pdata.gpio_wakeup = NULL;
+
+ wfx_bh_register(wdev);
+
+ err = wfx_init_device(wdev);
+ if (err)
+ goto err1;
+
+ err = wait_for_completion_interruptible_timeout(&wdev->firmware_ready, 10 * HZ);
+ if (err <= 0) {
+ if (err == 0) {
+ dev_err(wdev->dev, "timeout while waiting for startup indication. IRQ configuration error?\n");
+ err = -ETIMEDOUT;
+ } else if (err == -ERESTARTSYS) {
+ dev_info(wdev->dev, "probe interrupted by user\n");
+ }
+ goto err1;
+ }
+
+ // FIXME: fill wiphy::hw_version
+ dev_info(wdev->dev, "started firmware %d.%d.%d \"%s\" (API: %d.%d, keyset: %02X, caps: 0x%.8X)\n",
+ wdev->hw_caps.firmware_major, wdev->hw_caps.firmware_minor,
+ wdev->hw_caps.firmware_build, wdev->hw_caps.firmware_label,
+ wdev->hw_caps.api_version_major, wdev->hw_caps.api_version_minor,
+ wdev->keyset, *((u32 *) &wdev->hw_caps.capabilities));
+ snprintf(wdev->hw->wiphy->fw_version, sizeof(wdev->hw->wiphy->fw_version),
+ "%d.%d.%d",
+ wdev->hw_caps.firmware_major,
+ wdev->hw_caps.firmware_minor,
+ wdev->hw_caps.firmware_build);
+
+ if (wfx_api_older_than(wdev, 1, 0)) {
+ dev_err(wdev->dev, "unsupported firmware API version (expect 1 while firmware returns %d)\n",
+ wdev->hw_caps.api_version_major);
+ err = -ENOTSUPP;
+ goto err1;
+ }
+
+ err = wfx_sl_init(wdev);
+ if (err && wdev->hw_caps.capabilities.link_mode == SEC_LINK_ENFORCED) {
+ dev_err(wdev->dev, "chip require secure_link, but can't negociate it\n");
+ goto err1;
+ }
+
+ if (wdev->hw_caps.regul_sel_mode_info.region_sel_mode) {
+ wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[11].flags |= IEEE80211_CHAN_NO_IR;
+ wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[12].flags |= IEEE80211_CHAN_NO_IR;
+ wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[13].flags |= IEEE80211_CHAN_DISABLED;
+ }
+
+ dev_dbg(wdev->dev, "sending configuration file %s\n", wdev->pdata.file_pds);
+ err = wfx_send_pdata_pds(wdev);
+ if (err < 0)
+ goto err1;
+
+ wdev->pdata.gpio_wakeup = gpio_saved;
+ if (wdev->pdata.gpio_wakeup) {
+ dev_dbg(wdev->dev, "enable 'quiescent' power mode with gpio %d and PDS file %s\n",
+ desc_to_gpio(wdev->pdata.gpio_wakeup), wdev->pdata.file_pds);
+ gpiod_set_value(wdev->pdata.gpio_wakeup, 1);
+ control_reg_write(wdev, 0);
+ hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_QUIESCENT);
+ } else {
+ hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_DOZE);
+ }
+
+ hif_use_multi_tx_conf(wdev, true);
+
+ for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) {
+ eth_zero_addr(wdev->addresses[i].addr);
+ macaddr = of_get_mac_address(wdev->dev->of_node);
+ if (!IS_ERR_OR_NULL(macaddr)) {
+ ether_addr_copy(wdev->addresses[i].addr, macaddr);
+ wdev->addresses[i].addr[ETH_ALEN - 1] += i;
+ } else {
+ ether_addr_copy(wdev->addresses[i].addr, wdev->hw_caps.mac_addr[i]);
+ }
+ if (!is_valid_ether_addr(wdev->addresses[i].addr)) {
+ dev_warn(wdev->dev, "using random MAC address\n");
+ eth_random_addr(wdev->addresses[i].addr);
+ }
+ dev_info(wdev->dev, "MAC address %d: %pM\n", i, wdev->addresses[i].addr);
+ }
+ wdev->hw->wiphy->n_addresses = ARRAY_SIZE(wdev->addresses);
+ wdev->hw->wiphy->addresses = wdev->addresses;
+
+ err = ieee80211_register_hw(wdev->hw);
+ if (err)
+ goto err1;
+
+ err = wfx_debug_init(wdev);
+ if (err)
+ goto err2;
+
+ return 0;
+
+err2:
+ ieee80211_unregister_hw(wdev->hw);
+ ieee80211_free_hw(wdev->hw);
+err1:
+ wfx_bh_unregister(wdev);
+ return err;
+}
+
+void wfx_release(struct wfx_dev *wdev)
+{
+ ieee80211_unregister_hw(wdev->hw);
+ hif_shutdown(wdev);
+ wfx_bh_unregister(wdev);
+ wfx_sl_deinit(wdev);
+}
+
+static int __init wfx_core_init(void)
+{
+ int ret = 0;
+
+ if (IS_ENABLED(CONFIG_SPI))
+ ret = spi_register_driver(&wfx_spi_driver);
+ if (IS_ENABLED(CONFIG_MMC) && !ret)
+ ret = sdio_register_driver(&wfx_sdio_driver);
+ return ret;
+}
+module_init(wfx_core_init);
+
+static void __exit wfx_core_exit(void)
+{
+ if (IS_ENABLED(CONFIG_MMC))
+ sdio_unregister_driver(&wfx_sdio_driver);
+ if (IS_ENABLED(CONFIG_SPI))
+ spi_unregister_driver(&wfx_spi_driver);
+}
+module_exit(wfx_core_exit);
diff --git a/drivers/staging/wfx/main.h b/drivers/staging/wfx/main.h
new file mode 100644
index 000000000000..875f8c227803
--- /dev/null
+++ b/drivers/staging/wfx/main.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Device probe and register.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ */
+#ifndef WFX_MAIN_H
+#define WFX_MAIN_H
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+
+#include "bus.h"
+#include "hif_api_general.h"
+
+struct wfx_dev;
+
+struct wfx_platform_data {
+ /* Keyset and ".sec" extention will appended to this string */
+ const char *file_fw;
+ const char *file_pds;
+ struct gpio_desc *gpio_wakeup;
+ /*
+ * if true HIF D_out is sampled on the rising edge of the clock
+ * (intended to be used in 50Mhz SDIO)
+ */
+ bool use_rising_clk;
+};
+
+struct wfx_dev *wfx_init_common(struct device *dev,
+ const struct wfx_platform_data *pdata,
+ const struct hwbus_ops *hwbus_ops,
+ void *hwbus_priv);
+void wfx_free_common(struct wfx_dev *wdev);
+
+int wfx_probe(struct wfx_dev *wdev);
+void wfx_release(struct wfx_dev *wdev);
+
+struct gpio_desc *wfx_get_gpio(struct device *dev, int override,
+ const char *label);
+bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor);
+int wfx_send_pds(struct wfx_dev *wdev, unsigned char *buf, size_t len);
+
+#endif
diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c
new file mode 100644
index 000000000000..71e92744fed0
--- /dev/null
+++ b/drivers/staging/wfx/queue.c
@@ -0,0 +1,608 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * O(1) TX queue with built-in allocator.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/sched.h>
+#include <net/mac80211.h>
+
+#include "queue.h"
+#include "wfx.h"
+#include "sta.h"
+#include "data_tx.h"
+
+void wfx_tx_lock(struct wfx_dev *wdev)
+{
+ atomic_inc(&wdev->tx_lock);
+}
+
+void wfx_tx_unlock(struct wfx_dev *wdev)
+{
+ int tx_lock = atomic_dec_return(&wdev->tx_lock);
+
+ WARN(tx_lock < 0, "inconsistent tx_lock value");
+ if (!tx_lock)
+ wfx_bh_request_tx(wdev);
+}
+
+void wfx_tx_flush(struct wfx_dev *wdev)
+{
+ int ret;
+
+ WARN(!atomic_read(&wdev->tx_lock), "tx_lock is not locked");
+
+ // Do not wait for any reply if chip is frozen
+ if (wdev->chip_frozen)
+ return;
+
+ mutex_lock(&wdev->hif_cmd.lock);
+ ret = wait_event_timeout(wdev->hif.tx_buffers_empty,
+ !wdev->hif.tx_buffers_used,
+ msecs_to_jiffies(3000));
+ if (!ret) {
+ dev_warn(wdev->dev, "cannot flush tx buffers (%d still busy)\n", wdev->hif.tx_buffers_used);
+ wfx_pending_dump_old_frames(wdev, 3000);
+ // FIXME: drop pending frames here
+ wdev->chip_frozen = 1;
+ }
+ mutex_unlock(&wdev->hif_cmd.lock);
+}
+
+void wfx_tx_lock_flush(struct wfx_dev *wdev)
+{
+ wfx_tx_lock(wdev);
+ wfx_tx_flush(wdev);
+}
+
+void wfx_tx_queues_lock(struct wfx_dev *wdev)
+{
+ int i;
+ struct wfx_queue *queue;
+
+ for (i = 0; i < IEEE80211_NUM_ACS; ++i) {
+ queue = &wdev->tx_queue[i];
+ spin_lock_bh(&queue->queue.lock);
+ if (queue->tx_locked_cnt++ == 0)
+ ieee80211_stop_queue(wdev->hw, queue->queue_id);
+ spin_unlock_bh(&queue->queue.lock);
+ }
+}
+
+void wfx_tx_queues_unlock(struct wfx_dev *wdev)
+{
+ int i;
+ struct wfx_queue *queue;
+
+ for (i = 0; i < IEEE80211_NUM_ACS; ++i) {
+ queue = &wdev->tx_queue[i];
+ spin_lock_bh(&queue->queue.lock);
+ WARN(!queue->tx_locked_cnt, "queue already unlocked");
+ if (--queue->tx_locked_cnt == 0)
+ ieee80211_wake_queue(wdev->hw, queue->queue_id);
+ spin_unlock_bh(&queue->queue.lock);
+ }
+}
+
+/* If successful, LOCKS the TX queue! */
+void wfx_tx_queues_wait_empty_vif(struct wfx_vif *wvif)
+{
+ int i;
+ bool done;
+ struct wfx_queue *queue;
+ struct sk_buff *item;
+ struct wfx_dev *wdev = wvif->wdev;
+ struct hif_msg *hif;
+
+ if (wvif->wdev->chip_frozen) {
+ wfx_tx_lock_flush(wdev);
+ wfx_tx_queues_clear(wdev);
+ return;
+ }
+
+ do {
+ done = true;
+ wfx_tx_lock_flush(wdev);
+ for (i = 0; i < IEEE80211_NUM_ACS && done; ++i) {
+ queue = &wdev->tx_queue[i];
+ spin_lock_bh(&queue->queue.lock);
+ skb_queue_walk(&queue->queue, item) {
+ hif = (struct hif_msg *) item->data;
+ if (hif->interface == wvif->id)
+ done = false;
+ }
+ spin_unlock_bh(&queue->queue.lock);
+ }
+ if (!done) {
+ wfx_tx_unlock(wdev);
+ msleep(20);
+ }
+ } while (!done);
+}
+
+static void wfx_tx_queue_clear(struct wfx_dev *wdev, struct wfx_queue *queue, struct sk_buff_head *gc_list)
+{
+ int i;
+ struct sk_buff *item;
+ struct wfx_queue_stats *stats = &wdev->tx_queue_stats;
+
+ spin_lock_bh(&queue->queue.lock);
+ while ((item = __skb_dequeue(&queue->queue)) != NULL)
+ skb_queue_head(gc_list, item);
+ spin_lock_bh(&stats->pending.lock);
+ for (i = 0; i < ARRAY_SIZE(stats->link_map_cache); ++i) {
+ stats->link_map_cache[i] -= queue->link_map_cache[i];
+ queue->link_map_cache[i] = 0;
+ }
+ spin_unlock_bh(&stats->pending.lock);
+ spin_unlock_bh(&queue->queue.lock);
+}
+
+void wfx_tx_queues_clear(struct wfx_dev *wdev)
+{
+ int i;
+ struct sk_buff *item;
+ struct sk_buff_head gc_list;
+ struct wfx_queue_stats *stats = &wdev->tx_queue_stats;
+
+ skb_queue_head_init(&gc_list);
+ for (i = 0; i < IEEE80211_NUM_ACS; ++i)
+ wfx_tx_queue_clear(wdev, &wdev->tx_queue[i], &gc_list);
+ wake_up(&stats->wait_link_id_empty);
+ while ((item = skb_dequeue(&gc_list)) != NULL)
+ wfx_skb_dtor(wdev, item);
+}
+
+void wfx_tx_queues_init(struct wfx_dev *wdev)
+{
+ int i;
+
+ memset(&wdev->tx_queue_stats, 0, sizeof(wdev->tx_queue_stats));
+ memset(wdev->tx_queue, 0, sizeof(wdev->tx_queue));
+ skb_queue_head_init(&wdev->tx_queue_stats.pending);
+ init_waitqueue_head(&wdev->tx_queue_stats.wait_link_id_empty);
+
+ for (i = 0; i < IEEE80211_NUM_ACS; ++i) {
+ wdev->tx_queue[i].queue_id = i;
+ skb_queue_head_init(&wdev->tx_queue[i].queue);
+ }
+}
+
+void wfx_tx_queues_deinit(struct wfx_dev *wdev)
+{
+ WARN_ON(!skb_queue_empty(&wdev->tx_queue_stats.pending));
+ wfx_tx_queues_clear(wdev);
+}
+
+size_t wfx_tx_queue_get_num_queued(struct wfx_queue *queue,
+ u32 link_id_map)
+{
+ size_t ret;
+ int i, bit;
+
+ if (!link_id_map)
+ return 0;
+
+ spin_lock_bh(&queue->queue.lock);
+ if (link_id_map == (u32)-1) {
+ ret = skb_queue_len(&queue->queue);
+ } else {
+ ret = 0;
+ for (i = 0, bit = 1; i < ARRAY_SIZE(queue->link_map_cache); ++i, bit <<= 1) {
+ if (link_id_map & bit)
+ ret += queue->link_map_cache[i];
+ }
+ }
+ spin_unlock_bh(&queue->queue.lock);
+ return ret;
+}
+
+void wfx_tx_queue_put(struct wfx_dev *wdev, struct wfx_queue *queue, struct sk_buff *skb)
+{
+ struct wfx_queue_stats *stats = &wdev->tx_queue_stats;
+ struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb);
+
+ WARN(tx_priv->link_id >= ARRAY_SIZE(stats->link_map_cache), "invalid link-id value");
+ spin_lock_bh(&queue->queue.lock);
+ __skb_queue_tail(&queue->queue, skb);
+
+ ++queue->link_map_cache[tx_priv->link_id];
+
+ spin_lock_bh(&stats->pending.lock);
+ ++stats->link_map_cache[tx_priv->link_id];
+ spin_unlock_bh(&stats->pending.lock);
+ spin_unlock_bh(&queue->queue.lock);
+}
+
+static struct sk_buff *wfx_tx_queue_get(struct wfx_dev *wdev,
+ struct wfx_queue *queue,
+ u32 link_id_map)
+{
+ struct sk_buff *skb = NULL;
+ struct sk_buff *item;
+ struct wfx_queue_stats *stats = &wdev->tx_queue_stats;
+ struct wfx_tx_priv *tx_priv;
+ bool wakeup_stats = false;
+
+ spin_lock_bh(&queue->queue.lock);
+ skb_queue_walk(&queue->queue, item) {
+ tx_priv = wfx_skb_tx_priv(item);
+ if (link_id_map & BIT(tx_priv->link_id)) {
+ skb = item;
+ break;
+ }
+ }
+ WARN_ON(!skb);
+ if (skb) {
+ tx_priv = wfx_skb_tx_priv(skb);
+ tx_priv->xmit_timestamp = ktime_get();
+ __skb_unlink(skb, &queue->queue);
+ --queue->link_map_cache[tx_priv->link_id];
+
+ spin_lock_bh(&stats->pending.lock);
+ __skb_queue_tail(&stats->pending, skb);
+ if (!--stats->link_map_cache[tx_priv->link_id])
+ wakeup_stats = true;
+ spin_unlock_bh(&stats->pending.lock);
+ }
+ spin_unlock_bh(&queue->queue.lock);
+ if (wakeup_stats)
+ wake_up(&stats->wait_link_id_empty);
+ return skb;
+}
+
+int wfx_pending_requeue(struct wfx_dev *wdev, struct sk_buff *skb)
+{
+ struct wfx_queue_stats *stats = &wdev->tx_queue_stats;
+ struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb);
+ struct wfx_queue *queue = &wdev->tx_queue[skb_get_queue_mapping(skb)];
+
+ WARN_ON(skb_get_queue_mapping(skb) > 3);
+ spin_lock_bh(&queue->queue.lock);
+ ++queue->link_map_cache[tx_priv->link_id];
+
+ spin_lock_bh(&stats->pending.lock);
+ ++stats->link_map_cache[tx_priv->link_id];
+ __skb_unlink(skb, &stats->pending);
+ spin_unlock_bh(&stats->pending.lock);
+ __skb_queue_tail(&queue->queue, skb);
+ spin_unlock_bh(&queue->queue.lock);
+ return 0;
+}
+
+int wfx_pending_remove(struct wfx_dev *wdev, struct sk_buff *skb)
+{
+ struct wfx_queue_stats *stats = &wdev->tx_queue_stats;
+
+ spin_lock_bh(&stats->pending.lock);
+ __skb_unlink(skb, &stats->pending);
+ spin_unlock_bh(&stats->pending.lock);
+ wfx_skb_dtor(wdev, skb);
+
+ return 0;
+}
+
+struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id)
+{
+ struct sk_buff *skb;
+ struct hif_req_tx *req;
+ struct wfx_queue_stats *stats = &wdev->tx_queue_stats;
+
+ spin_lock_bh(&stats->pending.lock);
+ skb_queue_walk(&stats->pending, skb) {
+ req = wfx_skb_txreq(skb);
+ if (req->packet_id == packet_id) {
+ spin_unlock_bh(&stats->pending.lock);
+ return skb;
+ }
+ }
+ spin_unlock_bh(&stats->pending.lock);
+ WARN(1, "cannot find packet in pending queue");
+ return NULL;
+}
+
+void wfx_pending_dump_old_frames(struct wfx_dev *wdev, unsigned int limit_ms)
+{
+ struct wfx_queue_stats *stats = &wdev->tx_queue_stats;
+ ktime_t now = ktime_get();
+ struct wfx_tx_priv *tx_priv;
+ struct hif_req_tx *req;
+ struct sk_buff *skb;
+ bool first = true;
+
+ spin_lock_bh(&stats->pending.lock);
+ skb_queue_walk(&stats->pending, skb) {
+ tx_priv = wfx_skb_tx_priv(skb);
+ req = wfx_skb_txreq(skb);
+ if (ktime_after(now, ktime_add_ms(tx_priv->xmit_timestamp, limit_ms))) {
+ if (first) {
+ dev_info(wdev->dev, "frames stuck in firmware since %dms or more:\n",
+ limit_ms);
+ first = false;
+ }
+ dev_info(wdev->dev, " id %08x sent %lldms ago\n",
+ req->packet_id,
+ ktime_ms_delta(now, tx_priv->xmit_timestamp));
+ }
+ }
+ spin_unlock_bh(&stats->pending.lock);
+}
+
+unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, struct sk_buff *skb)
+{
+ ktime_t now = ktime_get();
+ struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb);
+
+ return ktime_us_delta(now, tx_priv->xmit_timestamp);
+}
+
+bool wfx_tx_queues_is_empty(struct wfx_dev *wdev)
+{
+ int i;
+ struct sk_buff_head *queue;
+ bool ret = true;
+
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ queue = &wdev->tx_queue[i].queue;
+ spin_lock_bh(&queue->lock);
+ if (!skb_queue_empty(queue))
+ ret = false;
+ spin_unlock_bh(&queue->lock);
+ }
+ return ret;
+}
+
+static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb,
+ struct wfx_queue *queue)
+{
+ bool handled = false;
+ struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb);
+ struct hif_req_tx *req = wfx_skb_txreq(skb);
+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *) (req->frame + req->data_flags.fc_offset);
+
+ enum {
+ do_probe,
+ do_drop,
+ do_wep,
+ do_tx,
+ } action = do_tx;
+
+ switch (wvif->vif->type) {
+ case NL80211_IFTYPE_STATION:
+ if (wvif->state < WFX_STATE_PRE_STA)
+ action = do_drop;
+ break;
+ case NL80211_IFTYPE_AP:
+ if (!wvif->state) {
+ action = do_drop;
+ } else if (!(BIT(tx_priv->raw_link_id) & (BIT(0) | wvif->link_id_map))) {
+ dev_warn(wvif->wdev->dev, "a frame with expired link-id is dropped\n");
+ action = do_drop;
+ }
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ if (wvif->state != WFX_STATE_IBSS)
+ action = do_drop;
+ break;
+ case NL80211_IFTYPE_MONITOR:
+ default:
+ action = do_drop;
+ break;
+ }
+
+ if (action == do_tx) {
+ if (ieee80211_is_nullfunc(frame->frame_control)) {
+ mutex_lock(&wvif->bss_loss_lock);
+ if (wvif->bss_loss_state) {
+ wvif->bss_loss_confirm_id = req->packet_id;
+ req->queue_id.queue_id = HIF_QUEUE_ID_VOICE;
+ }
+ mutex_unlock(&wvif->bss_loss_lock);
+ } else if (ieee80211_has_protected(frame->frame_control) &&
+ tx_priv->hw_key &&
+ tx_priv->hw_key->keyidx != wvif->wep_default_key_id &&
+ (tx_priv->hw_key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ tx_priv->hw_key->cipher == WLAN_CIPHER_SUITE_WEP104)) {
+ action = do_wep;
+ }
+ }
+
+ switch (action) {
+ case do_drop:
+ wfx_pending_remove(wvif->wdev, skb);
+ handled = true;
+ break;
+ case do_wep:
+ wfx_tx_lock(wvif->wdev);
+ wvif->wep_default_key_id = tx_priv->hw_key->keyidx;
+ wvif->wep_pending_skb = skb;
+ if (!schedule_work(&wvif->wep_key_work))
+ wfx_tx_unlock(wvif->wdev);
+ handled = true;
+ break;
+ case do_tx:
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+ return handled;
+}
+
+static int wfx_get_prio_queue(struct wfx_vif *wvif,
+ u32 tx_allowed_mask, int *total)
+{
+ static const int urgent = BIT(WFX_LINK_ID_AFTER_DTIM) |
+ BIT(WFX_LINK_ID_UAPSD);
+ struct hif_req_edca_queue_params *edca;
+ unsigned int score, best = -1;
+ int winner = -1;
+ int i;
+
+ /* search for a winner using edca params */
+ for (i = 0; i < IEEE80211_NUM_ACS; ++i) {
+ int queued;
+
+ edca = &wvif->edca.params[i];
+ queued = wfx_tx_queue_get_num_queued(&wvif->wdev->tx_queue[i],
+ tx_allowed_mask);
+ if (!queued)
+ continue;
+ *total += queued;
+ score = ((edca->aifsn + edca->cw_min) << 16) +
+ ((edca->cw_max - edca->cw_min) *
+ (get_random_int() & 0xFFFF));
+ if (score < best && (winner < 0 || i != 3)) {
+ best = score;
+ winner = i;
+ }
+ }
+
+ /* override winner if bursting */
+ if (winner >= 0 && wvif->wdev->tx_burst_idx >= 0 &&
+ winner != wvif->wdev->tx_burst_idx &&
+ !wfx_tx_queue_get_num_queued(&wvif->wdev->tx_queue[winner], tx_allowed_mask & urgent) &&
+ wfx_tx_queue_get_num_queued(&wvif->wdev->tx_queue[wvif->wdev->tx_burst_idx], tx_allowed_mask))
+ winner = wvif->wdev->tx_burst_idx;
+
+ return winner;
+}
+
+static int wfx_tx_queue_mask_get(struct wfx_vif *wvif,
+ struct wfx_queue **queue_p,
+ u32 *tx_allowed_mask_p,
+ bool *more)
+{
+ int idx;
+ u32 tx_allowed_mask;
+ int total = 0;
+
+ /* Search for a queue with multicast frames buffered */
+ if (wvif->mcast_tx) {
+ tx_allowed_mask = BIT(WFX_LINK_ID_AFTER_DTIM);
+ idx = wfx_get_prio_queue(wvif, tx_allowed_mask, &total);
+ if (idx >= 0) {
+ *more = total > 1;
+ goto found;
+ }
+ }
+
+ /* Search for unicast traffic */
+ tx_allowed_mask = ~wvif->sta_asleep_mask;
+ tx_allowed_mask |= BIT(WFX_LINK_ID_UAPSD);
+ if (wvif->sta_asleep_mask) {
+ tx_allowed_mask |= wvif->pspoll_mask;
+ tx_allowed_mask &= ~BIT(WFX_LINK_ID_AFTER_DTIM);
+ } else {
+ tx_allowed_mask |= BIT(WFX_LINK_ID_AFTER_DTIM);
+ }
+ idx = wfx_get_prio_queue(wvif, tx_allowed_mask, &total);
+ if (idx < 0)
+ return -ENOENT;
+
+found:
+ *queue_p = &wvif->wdev->tx_queue[idx];
+ *tx_allowed_mask_p = tx_allowed_mask;
+ return 0;
+}
+
+struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev)
+{
+ struct sk_buff *skb;
+ struct hif_msg *hif = NULL;
+ struct hif_req_tx *req = NULL;
+ struct wfx_queue *queue = NULL;
+ struct wfx_queue *vif_queue = NULL;
+ u32 tx_allowed_mask = 0;
+ u32 vif_tx_allowed_mask = 0;
+ const struct wfx_tx_priv *tx_priv = NULL;
+ struct wfx_vif *wvif;
+ /* More is used only for broadcasts. */
+ bool more = false;
+ bool vif_more = false;
+ int not_found;
+ int burst;
+
+ for (;;) {
+ int ret = -ENOENT;
+ int queue_num;
+ struct ieee80211_hdr *hdr;
+
+ if (atomic_read(&wdev->tx_lock))
+ return NULL;
+
+ wvif = NULL;
+ while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
+ spin_lock_bh(&wvif->ps_state_lock);
+
+ not_found = wfx_tx_queue_mask_get(wvif, &vif_queue, &vif_tx_allowed_mask, &vif_more);
+
+ if (wvif->mcast_buffered && (not_found || !vif_more) &&
+ (wvif->mcast_tx || !wvif->sta_asleep_mask)) {
+ wvif->mcast_buffered = false;
+ if (wvif->mcast_tx) {
+ wvif->mcast_tx = false;
+ schedule_work(&wvif->mcast_stop_work);
+ }
+ }
+
+ spin_unlock_bh(&wvif->ps_state_lock);
+
+ if (vif_more) {
+ more = true;
+ tx_allowed_mask = vif_tx_allowed_mask;
+ queue = vif_queue;
+ ret = 0;
+ break;
+ } else if (!not_found) {
+ if (queue && queue != vif_queue)
+ dev_info(wdev->dev, "vifs disagree about queue priority\n");
+ tx_allowed_mask |= vif_tx_allowed_mask;
+ queue = vif_queue;
+ ret = 0;
+ }
+ }
+
+ if (ret)
+ return NULL;
+
+ queue_num = queue - wdev->tx_queue;
+
+ skb = wfx_tx_queue_get(wdev, queue, tx_allowed_mask);
+ if (!skb)
+ continue;
+ tx_priv = wfx_skb_tx_priv(skb);
+ hif = (struct hif_msg *) skb->data;
+ wvif = wdev_to_wvif(wdev, hif->interface);
+ WARN_ON(!wvif);
+
+ if (hif_handle_tx_data(wvif, skb, queue))
+ continue; /* Handled by WSM */
+
+ wvif->pspoll_mask &= ~BIT(tx_priv->raw_link_id);
+
+ /* allow bursting if txop is set */
+ if (wvif->edca.params[queue_num].tx_op_limit)
+ burst = (int)wfx_tx_queue_get_num_queued(queue, tx_allowed_mask) + 1;
+ else
+ burst = 1;
+
+ /* store index of bursting queue */
+ if (burst > 1)
+ wdev->tx_burst_idx = queue_num;
+ else
+ wdev->tx_burst_idx = -1;
+
+ /* more buffered multicast/broadcast frames
+ * ==> set MoreData flag in IEEE 802.11 header
+ * to inform PS STAs
+ */
+ if (more) {
+ req = (struct hif_req_tx *) hif->body;
+ hdr = (struct ieee80211_hdr *) (req->frame + req->data_flags.fc_offset);
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ }
+ return hif;
+ }
+}
diff --git a/drivers/staging/wfx/queue.h b/drivers/staging/wfx/queue.h
new file mode 100644
index 000000000000..938dbf3469e7
--- /dev/null
+++ b/drivers/staging/wfx/queue.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * O(1) TX queue with built-in allocator.
+ *
+ * Copyright (c) 2017-2018, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_QUEUE_H
+#define WFX_QUEUE_H
+
+#include <linux/skbuff.h>
+
+#include "hif_api_cmd.h"
+
+#define WFX_MAX_STA_IN_AP_MODE 14
+#define WFX_LINK_ID_AFTER_DTIM (WFX_MAX_STA_IN_AP_MODE + 1)
+#define WFX_LINK_ID_UAPSD (WFX_MAX_STA_IN_AP_MODE + 2)
+#define WFX_LINK_ID_MAX (WFX_MAX_STA_IN_AP_MODE + 3)
+
+struct wfx_dev;
+struct wfx_vif;
+
+struct wfx_queue {
+ struct sk_buff_head queue;
+ int tx_locked_cnt;
+ int link_map_cache[WFX_LINK_ID_MAX];
+ u8 queue_id;
+};
+
+struct wfx_queue_stats {
+ int link_map_cache[WFX_LINK_ID_MAX];
+ struct sk_buff_head pending;
+ wait_queue_head_t wait_link_id_empty;
+};
+
+void wfx_tx_lock(struct wfx_dev *wdev);
+void wfx_tx_unlock(struct wfx_dev *wdev);
+void wfx_tx_flush(struct wfx_dev *wdev);
+void wfx_tx_lock_flush(struct wfx_dev *wdev);
+
+void wfx_tx_queues_init(struct wfx_dev *wdev);
+void wfx_tx_queues_deinit(struct wfx_dev *wdev);
+void wfx_tx_queues_lock(struct wfx_dev *wdev);
+void wfx_tx_queues_unlock(struct wfx_dev *wdev);
+void wfx_tx_queues_clear(struct wfx_dev *wdev);
+bool wfx_tx_queues_is_empty(struct wfx_dev *wdev);
+void wfx_tx_queues_wait_empty_vif(struct wfx_vif *wvif);
+struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev);
+
+void wfx_tx_queue_put(struct wfx_dev *wdev, struct wfx_queue *queue, struct sk_buff *skb);
+size_t wfx_tx_queue_get_num_queued(struct wfx_queue *queue, u32 link_id_map);
+
+struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id);
+int wfx_pending_remove(struct wfx_dev *wdev, struct sk_buff *skb);
+int wfx_pending_requeue(struct wfx_dev *wdev, struct sk_buff *skb);
+unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, struct sk_buff *skb);
+void wfx_pending_dump_old_frames(struct wfx_dev *wdev, unsigned int limit_ms);
+
+#endif /* WFX_QUEUE_H */
diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c
new file mode 100644
index 000000000000..cba735c1e73c
--- /dev/null
+++ b/drivers/staging/wfx/scan.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Scan related functions.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <net/mac80211.h>
+
+#include "scan.h"
+#include "wfx.h"
+#include "sta.h"
+#include "hif_tx_mib.h"
+
+static void __ieee80211_scan_completed_compat(struct ieee80211_hw *hw, bool aborted)
+{
+ struct cfg80211_scan_info info = {
+ .aborted = aborted ? 1 : 0,
+ };
+
+ ieee80211_scan_completed(hw, &info);
+}
+
+static void wfx_scan_restart_delayed(struct wfx_vif *wvif)
+{
+ if (wvif->delayed_unjoin) {
+ wvif->delayed_unjoin = false;
+ if (!schedule_work(&wvif->unjoin_work))
+ wfx_tx_unlock(wvif->wdev);
+ } else if (wvif->delayed_link_loss) {
+ wvif->delayed_link_loss = 0;
+ wfx_cqm_bssloss_sm(wvif, 1, 0, 0);
+ }
+}
+
+static int wfx_scan_start(struct wfx_vif *wvif, struct wfx_scan_params *scan)
+{
+ int ret;
+ int tmo = 500;
+
+ if (wvif->state == WFX_STATE_PRE_STA)
+ return -EBUSY;
+
+ tmo += scan->scan_req.num_of_channels *
+ ((20 * (scan->scan_req.max_channel_time)) + 10);
+ atomic_set(&wvif->scan.in_progress, 1);
+ atomic_set(&wvif->wdev->scan_in_progress, 1);
+
+ schedule_delayed_work(&wvif->scan.timeout, msecs_to_jiffies(tmo));
+ ret = hif_scan(wvif, scan);
+ if (ret) {
+ wfx_scan_failed_cb(wvif);
+ atomic_set(&wvif->scan.in_progress, 0);
+ atomic_set(&wvif->wdev->scan_in_progress, 0);
+ cancel_delayed_work_sync(&wvif->scan.timeout);
+ wfx_scan_restart_delayed(wvif);
+ }
+ return ret;
+}
+
+int wfx_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ struct cfg80211_scan_request *req = &hw_req->req;
+ struct sk_buff *skb;
+ int i, ret;
+ struct hif_mib_template_frame *p;
+
+ if (!wvif)
+ return -EINVAL;
+
+ if (wvif->state == WFX_STATE_AP)
+ return -EOPNOTSUPP;
+
+ if (req->n_ssids == 1 && !req->ssids[0].ssid_len)
+ req->n_ssids = 0;
+
+ if (req->n_ssids > HIF_API_MAX_NB_SSIDS)
+ return -EINVAL;
+
+ skb = ieee80211_probereq_get(hw, wvif->vif->addr, NULL, 0, req->ie_len);
+ if (!skb)
+ return -ENOMEM;
+
+ if (req->ie_len)
+ memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len);
+
+ mutex_lock(&wdev->conf_mutex);
+
+ p = (struct hif_mib_template_frame *)skb_push(skb, 4);
+ p->frame_type = HIF_TMPLT_PRBREQ;
+ p->frame_length = cpu_to_le16(skb->len - 4);
+ ret = hif_set_template_frame(wvif, p);
+ skb_pull(skb, 4);
+
+ if (!ret)
+ /* Host want to be the probe responder. */
+ ret = wfx_fwd_probe_req(wvif, true);
+ if (ret) {
+ mutex_unlock(&wdev->conf_mutex);
+ dev_kfree_skb(skb);
+ return ret;
+ }
+
+ wfx_tx_lock_flush(wdev);
+
+ WARN(wvif->scan.req, "unexpected concurrent scan");
+ wvif->scan.req = req;
+ wvif->scan.n_ssids = 0;
+ wvif->scan.status = 0;
+ wvif->scan.begin = &req->channels[0];
+ wvif->scan.curr = wvif->scan.begin;
+ wvif->scan.end = &req->channels[req->n_channels];
+ wvif->scan.output_power = wdev->output_power;
+
+ for (i = 0; i < req->n_ssids; ++i) {
+ struct hif_ssid_def *dst = &wvif->scan.ssids[wvif->scan.n_ssids];
+
+ memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid));
+ dst->ssid_length = req->ssids[i].ssid_len;
+ ++wvif->scan.n_ssids;
+ }
+
+ mutex_unlock(&wdev->conf_mutex);
+
+ if (skb)
+ dev_kfree_skb(skb);
+ schedule_work(&wvif->scan.work);
+ return 0;
+}
+
+void wfx_scan_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, scan.work);
+ struct ieee80211_channel **it;
+ struct wfx_scan_params scan = {
+ .scan_req.scan_type.type = 0, /* Foreground */
+ };
+ struct ieee80211_channel *first;
+ bool first_run = (wvif->scan.begin == wvif->scan.curr &&
+ wvif->scan.begin != wvif->scan.end);
+ int i;
+
+ down(&wvif->scan.lock);
+ mutex_lock(&wvif->wdev->conf_mutex);
+
+ if (first_run) {
+ if (wvif->state == WFX_STATE_STA &&
+ !(wvif->powersave_mode.pm_mode.enter_psm)) {
+ struct hif_req_set_pm_mode pm = wvif->powersave_mode;
+
+ pm.pm_mode.enter_psm = 1;
+ wfx_set_pm(wvif, &pm);
+ }
+ }
+
+ if (!wvif->scan.req || wvif->scan.curr == wvif->scan.end) {
+ if (wvif->scan.output_power != wvif->wdev->output_power)
+ hif_set_output_power(wvif, wvif->wdev->output_power * 10);
+
+ if (wvif->scan.status < 0)
+ dev_warn(wvif->wdev->dev, "scan failed\n");
+ else if (wvif->scan.req)
+ dev_dbg(wvif->wdev->dev, "scan completed\n");
+ else
+ dev_dbg(wvif->wdev->dev, "scan canceled\n");
+
+ wvif->scan.req = NULL;
+ wfx_scan_restart_delayed(wvif);
+ wfx_tx_unlock(wvif->wdev);
+ mutex_unlock(&wvif->wdev->conf_mutex);
+ __ieee80211_scan_completed_compat(wvif->wdev->hw, wvif->scan.status ? 1 : 0);
+ up(&wvif->scan.lock);
+ if (wvif->state == WFX_STATE_STA &&
+ !(wvif->powersave_mode.pm_mode.enter_psm))
+ wfx_set_pm(wvif, &wvif->powersave_mode);
+ return;
+ }
+ first = *wvif->scan.curr;
+
+ for (it = wvif->scan.curr + 1, i = 1;
+ it != wvif->scan.end && i < HIF_API_MAX_NB_CHANNELS;
+ ++it, ++i) {
+ if ((*it)->band != first->band)
+ break;
+ if (((*it)->flags ^ first->flags) &
+ IEEE80211_CHAN_NO_IR)
+ break;
+ if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
+ (*it)->max_power != first->max_power)
+ break;
+ }
+ scan.scan_req.band = first->band;
+
+ if (wvif->scan.req->no_cck)
+ scan.scan_req.max_transmit_rate = API_RATE_INDEX_G_6MBPS;
+ else
+ scan.scan_req.max_transmit_rate = API_RATE_INDEX_B_1MBPS;
+ scan.scan_req.num_of_probe_requests =
+ (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2;
+ scan.scan_req.num_of_ssi_ds = wvif->scan.n_ssids;
+ scan.ssids = &wvif->scan.ssids[0];
+ scan.scan_req.num_of_channels = it - wvif->scan.curr;
+ scan.scan_req.probe_delay = 100;
+ // FIXME: Check if FW can do active scan while joined.
+ if (wvif->state == WFX_STATE_STA) {
+ scan.scan_req.scan_type.type = 1;
+ scan.scan_req.scan_flags.fbg = 1;
+ }
+
+ scan.ch = kcalloc(scan.scan_req.num_of_channels, sizeof(u8), GFP_KERNEL);
+
+ if (!scan.ch) {
+ wvif->scan.status = -ENOMEM;
+ goto fail;
+ }
+ for (i = 0; i < scan.scan_req.num_of_channels; ++i)
+ scan.ch[i] = wvif->scan.curr[i]->hw_value;
+
+ if (wvif->scan.curr[0]->flags & IEEE80211_CHAN_NO_IR) {
+ scan.scan_req.min_channel_time = 50;
+ scan.scan_req.max_channel_time = 150;
+ } else {
+ scan.scan_req.min_channel_time = 10;
+ scan.scan_req.max_channel_time = 50;
+ }
+ if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
+ wvif->scan.output_power != first->max_power) {
+ wvif->scan.output_power = first->max_power;
+ hif_set_output_power(wvif, wvif->scan.output_power * 10);
+ }
+ wvif->scan.status = wfx_scan_start(wvif, &scan);
+ kfree(scan.ch);
+ if (wvif->scan.status)
+ goto fail;
+ wvif->scan.curr = it;
+ mutex_unlock(&wvif->wdev->conf_mutex);
+ return;
+
+fail:
+ wvif->scan.curr = wvif->scan.end;
+ mutex_unlock(&wvif->wdev->conf_mutex);
+ up(&wvif->scan.lock);
+ schedule_work(&wvif->scan.work);
+}
+
+static void wfx_scan_complete(struct wfx_vif *wvif)
+{
+ up(&wvif->scan.lock);
+ atomic_set(&wvif->wdev->scan_in_progress, 0);
+
+ wfx_scan_work(&wvif->scan.work);
+}
+
+void wfx_scan_failed_cb(struct wfx_vif *wvif)
+{
+ if (cancel_delayed_work_sync(&wvif->scan.timeout) > 0) {
+ wvif->scan.status = -EIO;
+ schedule_work(&wvif->scan.timeout.work);
+ }
+}
+
+void wfx_scan_complete_cb(struct wfx_vif *wvif, struct hif_ind_scan_cmpl *arg)
+{
+ if (cancel_delayed_work_sync(&wvif->scan.timeout) > 0) {
+ wvif->scan.status = 1;
+ schedule_work(&wvif->scan.timeout.work);
+ }
+}
+
+void wfx_scan_timeout(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, scan.timeout.work);
+
+ if (atomic_xchg(&wvif->scan.in_progress, 0)) {
+ if (wvif->scan.status > 0) {
+ wvif->scan.status = 0;
+ } else if (!wvif->scan.status) {
+ dev_warn(wvif->wdev->dev, "timeout waiting for scan complete notification\n");
+ wvif->scan.status = -ETIMEDOUT;
+ wvif->scan.curr = wvif->scan.end;
+ hif_stop_scan(wvif);
+ }
+ wfx_scan_complete(wvif);
+ }
+}
diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h
new file mode 100644
index 000000000000..b4ddd0771a9b
--- /dev/null
+++ b/drivers/staging/wfx/scan.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Scan related functions.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_SCAN_H
+#define WFX_SCAN_H
+
+#include <linux/semaphore.h>
+#include <linux/workqueue.h>
+#include <net/mac80211.h>
+
+#include "hif_api_cmd.h"
+
+struct wfx_dev;
+struct wfx_vif;
+
+struct wfx_scan {
+ struct semaphore lock;
+ struct work_struct work;
+ struct delayed_work timeout;
+ struct cfg80211_scan_request *req;
+ struct ieee80211_channel **begin;
+ struct ieee80211_channel **curr;
+ struct ieee80211_channel **end;
+ struct hif_ssid_def ssids[HIF_API_MAX_NB_SSIDS];
+ int output_power;
+ int n_ssids;
+ int status;
+ atomic_t in_progress;
+};
+
+int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *req);
+void wfx_scan_work(struct work_struct *work);
+void wfx_scan_timeout(struct work_struct *work);
+void wfx_scan_complete_cb(struct wfx_vif *wvif, struct hif_ind_scan_cmpl *arg);
+void wfx_scan_failed_cb(struct wfx_vif *wvif);
+
+#endif /* WFX_SCAN_H */
diff --git a/drivers/staging/wfx/secure_link.h b/drivers/staging/wfx/secure_link.h
new file mode 100644
index 000000000000..376d7bc4c0c4
--- /dev/null
+++ b/drivers/staging/wfx/secure_link.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019, Silicon Laboratories, Inc.
+ */
+#ifndef WFX_SECURE_LINK_H
+#define WFX_SECURE_LINK_H
+
+#include <linux/of.h>
+
+#include "hif_api_general.h"
+
+struct wfx_dev;
+
+
+struct sl_context {
+};
+
+static inline bool wfx_is_secure_command(struct wfx_dev *wdev, int cmd_id)
+{
+ return false;
+}
+
+static inline int wfx_sl_decode(struct wfx_dev *wdev, struct hif_sl_msg *m)
+{
+ return -EIO;
+}
+
+static inline int wfx_sl_encode(struct wfx_dev *wdev, struct hif_msg *input, struct hif_sl_msg *output)
+{
+ return -EIO;
+}
+
+static inline int wfx_sl_check_pubkey(struct wfx_dev *wdev, uint8_t *ncp_pubkey, uint8_t *ncp_pubmac)
+{
+ return -EIO;
+}
+
+static inline void wfx_sl_fill_pdata(struct device *dev,
+ struct wfx_platform_data *pdata)
+{
+ if (of_find_property(dev->of_node, "slk_key", NULL))
+ dev_err(dev, "secure link is not supported by this driver, ignoring provided key\n");
+}
+
+static inline int wfx_sl_init(struct wfx_dev *wdev)
+{
+ return -EIO;
+}
+
+static inline void wfx_sl_deinit(struct wfx_dev *wdev)
+{
+}
+
+
+#endif
diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c
new file mode 100644
index 000000000000..2ab5ba9742ad
--- /dev/null
+++ b/drivers/staging/wfx/sta.c
@@ -0,0 +1,1636 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Implementation of mac80211 API.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <net/mac80211.h>
+
+#include "sta.h"
+#include "wfx.h"
+#include "fwio.h"
+#include "bh.h"
+#include "key.h"
+#include "scan.h"
+#include "debug.h"
+#include "hif_tx.h"
+#include "hif_tx_mib.h"
+
+#define TXOP_UNIT 32
+#define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2
+
+static u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
+{
+ int i;
+ u32 ret = 0;
+ // WFx only support 2GHz
+ struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ if (rates & BIT(i)) {
+ if (i >= sband->n_bitrates)
+ dev_warn(wdev->dev, "unsupported basic rate\n");
+ else
+ ret |= BIT(sband->bitrates[i].hw_value);
+ }
+ }
+ return ret;
+}
+
+static void __wfx_free_event_queue(struct list_head *list)
+{
+ struct wfx_hif_event *event, *tmp;
+
+ list_for_each_entry_safe(event, tmp, list, link) {
+ list_del(&event->link);
+ kfree(event);
+ }
+}
+
+static void wfx_free_event_queue(struct wfx_vif *wvif)
+{
+ LIST_HEAD(list);
+
+ spin_lock(&wvif->event_queue_lock);
+ list_splice_init(&wvif->event_queue, &list);
+ spin_unlock(&wvif->event_queue_lock);
+
+ __wfx_free_event_queue(&list);
+}
+
+void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad)
+{
+ int tx = 0;
+
+ mutex_lock(&wvif->bss_loss_lock);
+ wvif->delayed_link_loss = 0;
+ cancel_work_sync(&wvif->bss_params_work);
+
+ /* If we have a pending unjoin */
+ if (wvif->delayed_unjoin)
+ goto end;
+
+ if (init) {
+ schedule_delayed_work(&wvif->bss_loss_work, HZ);
+ wvif->bss_loss_state = 0;
+
+ if (!atomic_read(&wvif->wdev->tx_lock))
+ tx = 1;
+ } else if (good) {
+ cancel_delayed_work_sync(&wvif->bss_loss_work);
+ wvif->bss_loss_state = 0;
+ schedule_work(&wvif->bss_params_work);
+ } else if (bad) {
+ /* FIXME Should we just keep going until we time out? */
+ if (wvif->bss_loss_state < 3)
+ tx = 1;
+ } else {
+ cancel_delayed_work_sync(&wvif->bss_loss_work);
+ wvif->bss_loss_state = 0;
+ }
+
+ /* Spit out a NULL packet to our AP if necessary */
+ // FIXME: call ieee80211_beacon_loss/ieee80211_connection_loss instead
+ if (tx) {
+ struct sk_buff *skb;
+
+ wvif->bss_loss_state++;
+
+ skb = ieee80211_nullfunc_get(wvif->wdev->hw, wvif->vif, false);
+ if (!skb)
+ goto end;
+ memset(IEEE80211_SKB_CB(skb), 0, sizeof(*IEEE80211_SKB_CB(skb)));
+ IEEE80211_SKB_CB(skb)->control.vif = wvif->vif;
+ IEEE80211_SKB_CB(skb)->driver_rates[0].idx = 0;
+ IEEE80211_SKB_CB(skb)->driver_rates[0].count = 1;
+ IEEE80211_SKB_CB(skb)->driver_rates[1].idx = -1;
+ wfx_tx(wvif->wdev->hw, NULL, skb);
+ }
+end:
+ mutex_unlock(&wvif->bss_loss_lock);
+}
+
+static int wfx_set_uapsd_param(struct wfx_vif *wvif,
+ const struct wfx_edca_params *arg)
+{
+ /* Here's the mapping AC [queue, bit]
+ * VO [0,3], VI [1, 2], BE [2, 1], BK [3, 0]
+ */
+
+ if (arg->uapsd_enable[IEEE80211_AC_VO])
+ wvif->uapsd_info.trig_voice = 1;
+ else
+ wvif->uapsd_info.trig_voice = 0;
+
+ if (arg->uapsd_enable[IEEE80211_AC_VI])
+ wvif->uapsd_info.trig_video = 1;
+ else
+ wvif->uapsd_info.trig_video = 0;
+
+ if (arg->uapsd_enable[IEEE80211_AC_BE])
+ wvif->uapsd_info.trig_be = 1;
+ else
+ wvif->uapsd_info.trig_be = 0;
+
+ if (arg->uapsd_enable[IEEE80211_AC_BK])
+ wvif->uapsd_info.trig_bckgrnd = 1;
+ else
+ wvif->uapsd_info.trig_bckgrnd = 0;
+
+ /* Currently pseudo U-APSD operation is not supported, so setting
+ * MinAutoTriggerInterval, MaxAutoTriggerInterval and
+ * AutoTriggerStep to 0
+ */
+ wvif->uapsd_info.min_auto_trigger_interval = 0;
+ wvif->uapsd_info.max_auto_trigger_interval = 0;
+ wvif->uapsd_info.auto_trigger_step = 0;
+
+ return hif_set_uapsd_info(wvif, &wvif->uapsd_info);
+}
+
+int wfx_fwd_probe_req(struct wfx_vif *wvif, bool enable)
+{
+ wvif->fwd_probe_req = enable;
+ return hif_set_rx_filter(wvif, wvif->filter_bssid,
+ wvif->fwd_probe_req);
+}
+
+static int wfx_set_mcast_filter(struct wfx_vif *wvif,
+ struct wfx_grp_addr_table *fp)
+{
+ int i, ret;
+ struct hif_mib_config_data_filter config = { };
+ struct hif_mib_set_data_filtering filter_data = { };
+ struct hif_mib_mac_addr_data_frame_condition filter_addr_val = { };
+ struct hif_mib_uc_mc_bc_data_frame_condition filter_addr_type = { };
+
+ // Temporary workaround for filters
+ return hif_set_data_filtering(wvif, &filter_data);
+
+ if (!fp->enable) {
+ filter_data.enable = 0;
+ return hif_set_data_filtering(wvif, &filter_data);
+ }
+
+ // A1 Address match on list
+ for (i = 0; i < fp->num_addresses; i++) {
+ filter_addr_val.condition_idx = i;
+ filter_addr_val.address_type = HIF_MAC_ADDR_A1;
+ ether_addr_copy(filter_addr_val.mac_address, fp->address_list[i]);
+ ret = hif_set_mac_addr_condition(wvif, &filter_addr_val);
+ if (ret)
+ return ret;
+ config.mac_cond |= 1 << i;
+ }
+
+ // Accept unicast and broadcast
+ filter_addr_type.condition_idx = 0;
+ filter_addr_type.param.bits.type_unicast = 1;
+ filter_addr_type.param.bits.type_broadcast = 1;
+ ret = hif_set_uc_mc_bc_condition(wvif, &filter_addr_type);
+ if (ret)
+ return ret;
+
+ config.uc_mc_bc_cond = 1;
+ config.filter_idx = 0; // TODO #define MULTICAST_FILTERING 0
+ config.enable = 1;
+ ret = hif_set_config_data_filter(wvif, &config);
+ if (ret)
+ return ret;
+
+ // discard all data frames except match filter
+ filter_data.enable = 1;
+ filter_data.default_filter = 1; // discard all
+ ret = hif_set_data_filtering(wvif, &filter_data);
+
+ return ret;
+}
+
+void wfx_update_filtering(struct wfx_vif *wvif)
+{
+ int ret;
+ bool is_sta = wvif->vif && NL80211_IFTYPE_STATION == wvif->vif->type;
+ bool filter_bssid = wvif->filter_bssid;
+ bool fwd_probe_req = wvif->fwd_probe_req;
+ struct hif_mib_bcn_filter_enable bf_ctrl;
+ struct hif_ie_table_entry filter_ies[] = {
+ {
+ .ie_id = WLAN_EID_VENDOR_SPECIFIC,
+ .has_changed = 1,
+ .no_longer = 1,
+ .has_appeared = 1,
+ .oui = { 0x50, 0x6F, 0x9A },
+ }, {
+ .ie_id = WLAN_EID_HT_OPERATION,
+ .has_changed = 1,
+ .no_longer = 1,
+ .has_appeared = 1,
+ }, {
+ .ie_id = WLAN_EID_ERP_INFO,
+ .has_changed = 1,
+ .no_longer = 1,
+ .has_appeared = 1,
+ }
+ };
+ int n_filter_ies;
+
+ if (wvif->state == WFX_STATE_PASSIVE)
+ return;
+
+ if (wvif->disable_beacon_filter) {
+ bf_ctrl.enable = 0;
+ bf_ctrl.bcn_count = 1;
+ n_filter_ies = 0;
+ } else if (!is_sta) {
+ bf_ctrl.enable = HIF_BEACON_FILTER_ENABLE | HIF_BEACON_FILTER_AUTO_ERP;
+ bf_ctrl.bcn_count = 0;
+ n_filter_ies = 2;
+ } else {
+ bf_ctrl.enable = HIF_BEACON_FILTER_ENABLE;
+ bf_ctrl.bcn_count = 0;
+ n_filter_ies = 3;
+ }
+
+ ret = hif_set_rx_filter(wvif, filter_bssid, fwd_probe_req);
+ if (!ret)
+ ret = hif_set_beacon_filter_table(wvif, n_filter_ies, filter_ies);
+ if (!ret)
+ ret = hif_beacon_filter_control(wvif, bf_ctrl.enable, bf_ctrl.bcn_count);
+ if (!ret)
+ ret = wfx_set_mcast_filter(wvif, &wvif->mcast_filter);
+ if (ret)
+ dev_err(wvif->wdev->dev, "update filtering failed: %d\n", ret);
+}
+
+static void wfx_update_filtering_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_filtering_work);
+
+ wfx_update_filtering(wvif);
+}
+
+u64 wfx_prepare_multicast(struct ieee80211_hw *hw, struct netdev_hw_addr_list *mc_list)
+{
+ int i;
+ struct netdev_hw_addr *ha;
+ struct wfx_vif *wvif = NULL;
+ struct wfx_dev *wdev = hw->priv;
+ int count = netdev_hw_addr_list_count(mc_list);
+
+ while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
+ memset(&wvif->mcast_filter, 0x00, sizeof(wvif->mcast_filter));
+ if (!count || count > ARRAY_SIZE(wvif->mcast_filter.address_list))
+ continue;
+
+ i = 0;
+ netdev_hw_addr_list_for_each(ha, mc_list) {
+ ether_addr_copy(wvif->mcast_filter.address_list[i], ha->addr);
+ i++;
+ }
+ wvif->mcast_filter.enable = true;
+ wvif->mcast_filter.num_addresses = count;
+ }
+
+ return 0;
+}
+
+void wfx_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ u64 unused)
+{
+ struct wfx_vif *wvif = NULL;
+ struct wfx_dev *wdev = hw->priv;
+
+ *total_flags &= FIF_OTHER_BSS | FIF_FCSFAIL | FIF_PROBE_REQ;
+
+ while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
+ down(&wvif->scan.lock);
+ wvif->filter_bssid = (*total_flags & (FIF_OTHER_BSS | FIF_PROBE_REQ)) ? 0 : 1;
+ wvif->disable_beacon_filter = !(*total_flags & FIF_PROBE_REQ);
+ wfx_fwd_probe_req(wvif, true);
+ wfx_update_filtering(wvif);
+ up(&wvif->scan.lock);
+ }
+}
+
+int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u16 queue, const struct ieee80211_tx_queue_params *params)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ int ret = 0;
+ /* To prevent re-applying PM request OID again and again*/
+ u16 old_uapsd_flags, new_uapsd_flags;
+ struct hif_req_edca_queue_params *edca;
+
+ mutex_lock(&wdev->conf_mutex);
+
+ if (queue < hw->queues) {
+ old_uapsd_flags = *((u16 *) &wvif->uapsd_info);
+ edca = &wvif->edca.params[queue];
+
+ wvif->edca.uapsd_enable[queue] = params->uapsd;
+ edca->aifsn = params->aifs;
+ edca->cw_min = params->cw_min;
+ edca->cw_max = params->cw_max;
+ edca->tx_op_limit = params->txop * TXOP_UNIT;
+ edca->allowed_medium_time = 0;
+ ret = hif_set_edca_queue_params(wvif, edca);
+ if (ret) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (wvif->vif->type == NL80211_IFTYPE_STATION) {
+ ret = wfx_set_uapsd_param(wvif, &wvif->edca);
+ new_uapsd_flags = *((u16 *) &wvif->uapsd_info);
+ if (!ret && wvif->setbssparams_done &&
+ wvif->state == WFX_STATE_STA &&
+ old_uapsd_flags != new_uapsd_flags)
+ ret = wfx_set_pm(wvif, &wvif->powersave_mode);
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+out:
+ mutex_unlock(&wdev->conf_mutex);
+ return ret;
+}
+
+int wfx_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg)
+{
+ struct hif_req_set_pm_mode pm = *arg;
+ u16 uapsd_flags;
+ int ret;
+
+ if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid)
+ return 0;
+
+ memcpy(&uapsd_flags, &wvif->uapsd_info, sizeof(uapsd_flags));
+
+ if (uapsd_flags != 0)
+ pm.pm_mode.fast_psm = 0;
+
+ // Kernel disable PowerSave when multiple vifs are in use. In contrary,
+ // it is absolutly necessary to enable PowerSave for WF200
+ if (wvif_count(wvif->wdev) > 1) {
+ pm.pm_mode.enter_psm = 1;
+ pm.pm_mode.fast_psm = 0;
+ }
+
+ if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300)))
+ dev_warn(wvif->wdev->dev, "timeout while waiting of set_pm_mode_complete\n");
+ ret = hif_set_pm(wvif, &pm);
+ // FIXME: why ?
+ if (-ETIMEDOUT == wvif->scan.status)
+ wvif->scan.status = 1;
+ return ret;
+}
+
+int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = NULL;
+
+ while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
+ hif_rts_threshold(wvif, value);
+ return 0;
+}
+
+/* If successful, LOCKS the TX queue! */
+static int __wfx_flush(struct wfx_dev *wdev, bool drop)
+{
+ int ret;
+
+ for (;;) {
+ if (drop) {
+ wfx_tx_queues_clear(wdev);
+ } else {
+ ret = wait_event_timeout(
+ wdev->tx_queue_stats.wait_link_id_empty,
+ wfx_tx_queues_is_empty(wdev),
+ 2 * HZ);
+ }
+
+ if (!drop && ret <= 0) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ ret = 0;
+
+ wfx_tx_lock_flush(wdev);
+ if (!wfx_tx_queues_is_empty(wdev)) {
+ /* Highly unlikely: WSM requeued frames. */
+ wfx_tx_unlock(wdev);
+ continue;
+ }
+ break;
+ }
+ return ret;
+}
+
+void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif;
+
+ if (vif) {
+ wvif = (struct wfx_vif *) vif->drv_priv;
+ if (wvif->vif->type == NL80211_IFTYPE_MONITOR)
+ drop = true;
+ if (wvif->vif->type == NL80211_IFTYPE_AP && !wvif->enable_beacon)
+ drop = true;
+ }
+
+ // FIXME: only flush requested vif
+ if (!__wfx_flush(wdev, drop))
+ wfx_tx_unlock(wdev);
+}
+
+/* WSM callbacks */
+
+static void wfx_event_report_rssi(struct wfx_vif *wvif, uint8_t raw_rcpi_rssi)
+{
+ /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
+ * RSSI = RCPI / 2 - 110
+ */
+ int rcpi_rssi;
+ int cqm_evt;
+
+ rcpi_rssi = raw_rcpi_rssi / 2 - 110;
+ if (rcpi_rssi <= wvif->cqm_rssi_thold)
+ cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
+ else
+ cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+ ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
+}
+
+static void wfx_event_handler_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif =
+ container_of(work, struct wfx_vif, event_handler_work);
+ struct wfx_hif_event *event;
+
+ LIST_HEAD(list);
+
+ spin_lock(&wvif->event_queue_lock);
+ list_splice_init(&wvif->event_queue, &list);
+ spin_unlock(&wvif->event_queue_lock);
+
+ list_for_each_entry(event, &list, link) {
+ switch (event->evt.event_id) {
+ case HIF_EVENT_IND_BSSLOST:
+ cancel_work_sync(&wvif->unjoin_work);
+ if (!down_trylock(&wvif->scan.lock)) {
+ wfx_cqm_bssloss_sm(wvif, 1, 0, 0);
+ up(&wvif->scan.lock);
+ } else {
+ /* Scan is in progress. Delay reporting.
+ * Scan complete will trigger bss_loss_work
+ */
+ wvif->delayed_link_loss = 1;
+ /* Also start a watchdog. */
+ schedule_delayed_work(&wvif->bss_loss_work, 5 * HZ);
+ }
+ break;
+ case HIF_EVENT_IND_BSSREGAINED:
+ wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
+ cancel_work_sync(&wvif->unjoin_work);
+ break;
+ case HIF_EVENT_IND_RCPI_RSSI:
+ wfx_event_report_rssi(wvif, event->evt.event_data.rcpi_rssi);
+ break;
+ case HIF_EVENT_IND_PS_MODE_ERROR:
+ dev_warn(wvif->wdev->dev, "error while processing power save request\n");
+ break;
+ default:
+ dev_warn(wvif->wdev->dev, "unhandled event indication: %.2x\n", event->evt.event_id);
+ break;
+ }
+ }
+ __wfx_free_event_queue(&list);
+}
+
+static void wfx_bss_loss_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, bss_loss_work.work);
+
+ ieee80211_connection_loss(wvif->vif);
+}
+
+static void wfx_bss_params_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, bss_params_work);
+
+ mutex_lock(&wvif->wdev->conf_mutex);
+ wvif->bss_params.bss_flags.lost_count_only = 1;
+ hif_set_bss_params(wvif, &wvif->bss_params);
+ wvif->bss_params.bss_flags.lost_count_only = 0;
+ mutex_unlock(&wvif->wdev->conf_mutex);
+}
+
+static void wfx_set_beacon_wakeup_period_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, set_beacon_wakeup_period_work);
+
+ hif_set_beacon_wakeup_period(wvif, wvif->dtim_period, wvif->dtim_period);
+}
+
+static void wfx_do_unjoin(struct wfx_vif *wvif)
+{
+ mutex_lock(&wvif->wdev->conf_mutex);
+
+ if (atomic_read(&wvif->scan.in_progress)) {
+ if (wvif->delayed_unjoin)
+ dev_dbg(wvif->wdev->dev, "delayed unjoin is already scheduled\n");
+ else
+ wvif->delayed_unjoin = true;
+ goto done;
+ }
+
+ wvif->delayed_link_loss = false;
+
+ if (!wvif->state)
+ goto done;
+
+ if (wvif->state == WFX_STATE_AP)
+ goto done;
+
+ cancel_work_sync(&wvif->update_filtering_work);
+ cancel_work_sync(&wvif->set_beacon_wakeup_period_work);
+ wvif->state = WFX_STATE_PASSIVE;
+
+ /* Unjoin is a reset. */
+ wfx_tx_flush(wvif->wdev);
+ hif_keep_alive_period(wvif, 0);
+ hif_reset(wvif, false);
+ hif_set_output_power(wvif, wvif->wdev->output_power * 10);
+ wvif->dtim_period = 0;
+ hif_set_macaddr(wvif, wvif->vif->addr);
+ wfx_free_event_queue(wvif);
+ cancel_work_sync(&wvif->event_handler_work);
+ wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
+
+ /* Disable Block ACKs */
+ hif_set_block_ack_policy(wvif, 0, 0);
+
+ wvif->disable_beacon_filter = false;
+ wfx_update_filtering(wvif);
+ memset(&wvif->bss_params, 0, sizeof(wvif->bss_params));
+ wvif->setbssparams_done = false;
+ memset(&wvif->ht_info, 0, sizeof(wvif->ht_info));
+
+done:
+ mutex_unlock(&wvif->wdev->conf_mutex);
+}
+
+static void wfx_set_mfp(struct wfx_vif *wvif, struct cfg80211_bss *bss)
+{
+ const int pairwise_cipher_suite_count_offset = 8 / sizeof(uint16_t);
+ const int pairwise_cipher_suite_size = 4 / sizeof(uint16_t);
+ const int akm_suite_size = 4 / sizeof(uint16_t);
+ const uint16_t *ptr = NULL;
+ bool mfpc = false;
+ bool mfpr = false;
+
+ /* 802.11w protected mgmt frames */
+
+ /* retrieve MFPC and MFPR flags from beacon or PBRSP */
+
+ rcu_read_lock();
+ if (bss)
+ ptr = (const uint16_t *) ieee80211_bss_get_ie(bss, WLAN_EID_RSN);
+
+ if (ptr) {
+ ptr += pairwise_cipher_suite_count_offset;
+ ptr += 1 + pairwise_cipher_suite_size * *ptr;
+ ptr += 1 + akm_suite_size * *ptr;
+ mfpr = *ptr & BIT(6);
+ mfpc = *ptr & BIT(7);
+ }
+ rcu_read_unlock();
+
+ hif_set_mfp(wvif, mfpc, mfpr);
+}
+
+/* MUST be called with tx_lock held! It will be unlocked for us. */
+static void wfx_do_join(struct wfx_vif *wvif)
+{
+ const u8 *bssid;
+ struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
+ struct cfg80211_bss *bss = NULL;
+ struct hif_req_join join = {
+ .mode = conf->ibss_joined ? HIF_MODE_IBSS : HIF_MODE_BSS,
+ .preamble_type = conf->use_short_preamble ? HIF_PREAMBLE_SHORT : HIF_PREAMBLE_LONG,
+ .probe_for_join = 1,
+ .atim_window = 0,
+ .basic_rate_set = wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates),
+ };
+
+ if (wvif->channel->flags & IEEE80211_CHAN_NO_IR)
+ join.probe_for_join = 0;
+
+ if (wvif->state)
+ wfx_do_unjoin(wvif);
+
+ bssid = wvif->vif->bss_conf.bssid;
+
+ bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel, bssid, NULL, 0,
+ IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
+
+ if (!bss && !conf->ibss_joined) {
+ wfx_tx_unlock(wvif->wdev);
+ return;
+ }
+
+ mutex_lock(&wvif->wdev->conf_mutex);
+
+ /* Under the conf lock: check scan status and
+ * bail out if it is in progress.
+ */
+ if (atomic_read(&wvif->scan.in_progress)) {
+ wfx_tx_unlock(wvif->wdev);
+ goto done_put;
+ }
+
+ /* Sanity check basic rates */
+ if (!join.basic_rate_set)
+ join.basic_rate_set = 7;
+
+ /* Sanity check beacon interval */
+ if (!wvif->beacon_int)
+ wvif->beacon_int = 1;
+
+ join.beacon_interval = wvif->beacon_int;
+
+ // DTIM period will be set on first Beacon
+ wvif->dtim_period = 0;
+
+ join.channel_number = wvif->channel->hw_value;
+ memcpy(join.bssid, bssid, sizeof(join.bssid));
+
+ if (!conf->ibss_joined) {
+ const u8 *ssidie;
+
+ rcu_read_lock();
+ ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
+ if (ssidie) {
+ join.ssid_length = ssidie[1];
+ memcpy(join.ssid, &ssidie[2], join.ssid_length);
+ }
+ rcu_read_unlock();
+ }
+
+ wfx_tx_flush(wvif->wdev);
+
+ if (wvif_count(wvif->wdev) <= 1)
+ hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
+
+ wfx_set_mfp(wvif, bss);
+
+ /* Perform actual join */
+ wvif->wdev->tx_burst_idx = -1;
+ if (hif_join(wvif, &join)) {
+ ieee80211_connection_loss(wvif->vif);
+ wvif->join_complete_status = -1;
+ /* Tx lock still held, unjoin will clear it. */
+ if (!schedule_work(&wvif->unjoin_work))
+ wfx_tx_unlock(wvif->wdev);
+ } else {
+ wvif->join_complete_status = 0;
+ if (wvif->vif->type == NL80211_IFTYPE_ADHOC)
+ wvif->state = WFX_STATE_IBSS;
+ else
+ wvif->state = WFX_STATE_PRE_STA;
+ wfx_tx_unlock(wvif->wdev);
+
+ /* Upload keys */
+ wfx_upload_keys(wvif);
+
+ /* Due to beacon filtering it is possible that the
+ * AP's beacon is not known for the mac80211 stack.
+ * Disable filtering temporary to make sure the stack
+ * receives at least one
+ */
+ wvif->disable_beacon_filter = true;
+ }
+ wfx_update_filtering(wvif);
+
+done_put:
+ mutex_unlock(&wvif->wdev->conf_mutex);
+ if (bss)
+ cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
+}
+
+static void wfx_unjoin_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, unjoin_work);
+
+ wfx_do_unjoin(wvif);
+ wfx_tx_unlock(wvif->wdev);
+}
+
+int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
+ struct wfx_link_entry *entry;
+ struct sk_buff *skb;
+
+ if (wvif->vif->type != NL80211_IFTYPE_AP)
+ return 0;
+
+ sta_priv->vif_id = wvif->id;
+ sta_priv->link_id = wfx_find_link_id(wvif, sta->addr);
+ if (!sta_priv->link_id) {
+ dev_warn(wdev->dev, "mo more link-id available\n");
+ return -ENOENT;
+ }
+
+ entry = &wvif->link_id_db[sta_priv->link_id - 1];
+ spin_lock_bh(&wvif->ps_state_lock);
+ if ((sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) ==
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
+ wvif->sta_asleep_mask |= BIT(sta_priv->link_id);
+ entry->status = WFX_LINK_HARD;
+ while ((skb = skb_dequeue(&entry->rx_queue)))
+ ieee80211_rx_irqsafe(wdev->hw, skb);
+ spin_unlock_bh(&wvif->ps_state_lock);
+ return 0;
+}
+
+int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
+ struct wfx_link_entry *entry;
+
+ if (wvif->vif->type != NL80211_IFTYPE_AP || !sta_priv->link_id)
+ return 0;
+
+ entry = &wvif->link_id_db[sta_priv->link_id - 1];
+ spin_lock_bh(&wvif->ps_state_lock);
+ entry->status = WFX_LINK_RESERVE;
+ entry->timestamp = jiffies;
+ wfx_tx_lock(wdev);
+ if (!schedule_work(&wvif->link_id_work))
+ wfx_tx_unlock(wdev);
+ spin_unlock_bh(&wvif->ps_state_lock);
+ flush_work(&wvif->link_id_work);
+ return 0;
+}
+
+static void wfx_set_cts_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, set_cts_work);
+ u8 erp_ie[3] = { WLAN_EID_ERP_INFO, 1, 0 };
+ struct hif_ie_flags target_frame = {
+ .beacon = 1,
+ };
+
+ mutex_lock(&wvif->wdev->conf_mutex);
+ erp_ie[2] = wvif->erp_info;
+ mutex_unlock(&wvif->wdev->conf_mutex);
+
+ hif_erp_use_protection(wvif, erp_ie[2] & WLAN_ERP_USE_PROTECTION);
+
+ if (wvif->vif->type != NL80211_IFTYPE_STATION)
+ hif_update_ie(wvif, &target_frame, erp_ie, sizeof(erp_ie));
+}
+
+static int wfx_start_ap(struct wfx_vif *wvif)
+{
+ int ret;
+ struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
+ struct hif_req_start start = {
+ .channel_number = wvif->channel->hw_value,
+ .beacon_interval = conf->beacon_int,
+ .dtim_period = conf->dtim_period,
+ .preamble_type = conf->use_short_preamble ? HIF_PREAMBLE_SHORT : HIF_PREAMBLE_LONG,
+ .basic_rate_set = wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates),
+ };
+
+ memset(start.ssid, 0, sizeof(start.ssid));
+ if (!conf->hidden_ssid) {
+ start.ssid_length = conf->ssid_len;
+ memcpy(start.ssid, conf->ssid, start.ssid_length);
+ }
+
+ wvif->beacon_int = conf->beacon_int;
+ wvif->dtim_period = conf->dtim_period;
+
+ memset(&wvif->link_id_db, 0, sizeof(wvif->link_id_db));
+
+ wvif->wdev->tx_burst_idx = -1;
+ ret = hif_start(wvif, &start);
+ if (!ret)
+ ret = wfx_upload_keys(wvif);
+ if (!ret) {
+ if (wvif_count(wvif->wdev) <= 1)
+ hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
+ wvif->state = WFX_STATE_AP;
+ wfx_update_filtering(wvif);
+ }
+ return ret;
+}
+
+static int wfx_update_beaconing(struct wfx_vif *wvif)
+{
+ struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
+
+ if (wvif->vif->type == NL80211_IFTYPE_AP) {
+ /* TODO: check if changed channel, band */
+ if (wvif->state != WFX_STATE_AP ||
+ wvif->beacon_int != conf->beacon_int) {
+ wfx_tx_lock_flush(wvif->wdev);
+ if (wvif->state != WFX_STATE_PASSIVE)
+ hif_reset(wvif, false);
+ wvif->state = WFX_STATE_PASSIVE;
+ wfx_start_ap(wvif);
+ wfx_tx_unlock(wvif->wdev);
+ } else {
+ }
+ }
+ return 0;
+}
+
+static int wfx_upload_beacon(struct wfx_vif *wvif)
+{
+ int ret = 0;
+ struct sk_buff *skb = NULL;
+ struct ieee80211_mgmt *mgmt;
+ struct hif_mib_template_frame *p;
+
+ if (wvif->vif->type == NL80211_IFTYPE_STATION ||
+ wvif->vif->type == NL80211_IFTYPE_MONITOR ||
+ wvif->vif->type == NL80211_IFTYPE_UNSPECIFIED)
+ goto done;
+
+ skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
+
+ if (!skb)
+ return -ENOMEM;
+
+ p = (struct hif_mib_template_frame *) skb_push(skb, 4);
+ p->frame_type = HIF_TMPLT_BCN;
+ p->init_rate = API_RATE_INDEX_B_1MBPS; /* 1Mbps DSSS */
+ p->frame_length = cpu_to_le16(skb->len - 4);
+
+ ret = hif_set_template_frame(wvif, p);
+
+ skb_pull(skb, 4);
+
+ if (ret)
+ goto done;
+ /* TODO: Distill probe resp; remove TIM and any other beacon-specific
+ * IEs
+ */
+ mgmt = (void *)skb->data;
+ mgmt->frame_control =
+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
+
+ p->frame_type = HIF_TMPLT_PRBRES;
+
+ ret = hif_set_template_frame(wvif, p);
+ wfx_fwd_probe_req(wvif, false);
+
+done:
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static int wfx_is_ht(const struct wfx_ht_info *ht_info)
+{
+ return ht_info->channel_type != NL80211_CHAN_NO_HT;
+}
+
+static int wfx_ht_greenfield(const struct wfx_ht_info *ht_info)
+{
+ return wfx_is_ht(ht_info) &&
+ (ht_info->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
+ !(ht_info->operation_mode &
+ IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+}
+
+static int wfx_ht_ampdu_density(const struct wfx_ht_info *ht_info)
+{
+ if (!wfx_is_ht(ht_info))
+ return 0;
+ return ht_info->ht_cap.ampdu_density;
+}
+
+static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_bss_conf *info)
+{
+ struct ieee80211_sta *sta = NULL;
+ struct hif_mib_set_association_mode association_mode = { };
+
+ if (info->dtim_period)
+ wvif->dtim_period = info->dtim_period;
+ wvif->beacon_int = info->beacon_int;
+
+ rcu_read_lock();
+ if (info->bssid && !info->ibss_joined)
+ sta = ieee80211_find_sta(wvif->vif, info->bssid);
+ if (sta) {
+ wvif->ht_info.ht_cap = sta->ht_cap;
+ wvif->bss_params.operational_rate_set =
+ wfx_rate_mask_to_hw(wvif->wdev, sta->supp_rates[wvif->channel->band]);
+ wvif->ht_info.operation_mode = info->ht_operation_mode;
+ } else {
+ memset(&wvif->ht_info, 0, sizeof(wvif->ht_info));
+ wvif->bss_params.operational_rate_set = -1;
+ }
+ rcu_read_unlock();
+
+ /* Non Greenfield stations present */
+ if (wvif->ht_info.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
+ hif_dual_cts_protection(wvif, true);
+ else
+ hif_dual_cts_protection(wvif, false);
+
+ association_mode.preambtype_use = 1;
+ association_mode.mode = 1;
+ association_mode.rateset = 1;
+ association_mode.spacing = 1;
+ association_mode.preamble_type = info->use_short_preamble ? HIF_PREAMBLE_SHORT : HIF_PREAMBLE_LONG;
+ association_mode.basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, info->basic_rates));
+ association_mode.mixed_or_greenfield_type = wfx_ht_greenfield(&wvif->ht_info);
+ association_mode.mpdu_start_spacing = wfx_ht_ampdu_density(&wvif->ht_info);
+
+ wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
+ cancel_work_sync(&wvif->unjoin_work);
+
+ wvif->bss_params.beacon_lost_count = 20;
+ wvif->bss_params.aid = info->aid;
+
+ if (wvif->dtim_period < 1)
+ wvif->dtim_period = 1;
+
+ hif_set_association_mode(wvif, &association_mode);
+
+ if (!info->ibss_joined) {
+ hif_keep_alive_period(wvif, 30 /* sec */);
+ hif_set_bss_params(wvif, &wvif->bss_params);
+ wvif->setbssparams_done = true;
+ wfx_set_beacon_wakeup_period_work(&wvif->set_beacon_wakeup_period_work);
+ wfx_set_pm(wvif, &wvif->powersave_mode);
+ }
+}
+
+void wfx_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ bool do_join = false;
+ int i;
+ int nb_arp_addr;
+
+ mutex_lock(&wdev->conf_mutex);
+
+ /* TODO: BSS_CHANGED_QOS */
+ if (changed & BSS_CHANGED_ARP_FILTER) {
+ struct hif_mib_arp_ip_addr_table filter = { };
+
+ nb_arp_addr = info->arp_addr_cnt;
+ if (nb_arp_addr <= 0 || nb_arp_addr > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
+ nb_arp_addr = 0;
+
+ for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) {
+ filter.condition_idx = i;
+ if (i < nb_arp_addr) {
+ // Caution: type of arp_addr_list[i] is __be32
+ memcpy(filter.ipv4_address, &info->arp_addr_list[i], sizeof(filter.ipv4_address));
+ filter.arp_enable = HIF_ARP_NS_FILTERING_ENABLE;
+ } else {
+ filter.arp_enable = HIF_ARP_NS_FILTERING_DISABLE;
+ }
+ hif_set_arp_ipv4_filter(wvif, &filter);
+ }
+ }
+
+ if (changed &
+ (BSS_CHANGED_BEACON | BSS_CHANGED_AP_PROBE_RESP |
+ BSS_CHANGED_BSSID | BSS_CHANGED_SSID | BSS_CHANGED_IBSS)) {
+ wvif->beacon_int = info->beacon_int;
+ wfx_update_beaconing(wvif);
+ wfx_upload_beacon(wvif);
+ }
+
+ if (changed & BSS_CHANGED_BEACON_ENABLED && wvif->state != WFX_STATE_IBSS) {
+ if (wvif->enable_beacon != info->enable_beacon) {
+ hif_beacon_transmit(wvif, info->enable_beacon);
+ wvif->enable_beacon = info->enable_beacon;
+ }
+ }
+
+ /* assoc/disassoc, or maybe AID changed */
+ if (changed & BSS_CHANGED_ASSOC) {
+ wfx_tx_lock_flush(wdev);
+ wvif->wep_default_key_id = -1;
+ wfx_tx_unlock(wdev);
+ }
+
+ if (changed & BSS_CHANGED_ASSOC && !info->assoc &&
+ (wvif->state == WFX_STATE_STA || wvif->state == WFX_STATE_IBSS)) {
+ /* Shedule unjoin work */
+ wfx_tx_lock(wdev);
+ if (!schedule_work(&wvif->unjoin_work))
+ wfx_tx_unlock(wdev);
+ } else {
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ if (info->ibss_joined)
+ do_join = true;
+ else if (wvif->state == WFX_STATE_AP)
+ wfx_update_beaconing(wvif);
+ }
+
+ if (changed & BSS_CHANGED_BSSID)
+ do_join = true;
+
+ if (changed &
+ (BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID |
+ BSS_CHANGED_IBSS | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_HT)) {
+ if (info->assoc) {
+ if (wvif->state < WFX_STATE_PRE_STA) {
+ ieee80211_connection_loss(vif);
+ mutex_unlock(&wdev->conf_mutex);
+ return;
+ } else if (wvif->state == WFX_STATE_PRE_STA) {
+ wvif->state = WFX_STATE_STA;
+ }
+ } else {
+ do_join = true;
+ }
+
+ if (info->assoc || info->ibss_joined)
+ wfx_join_finalize(wvif, info);
+ else
+ memset(&wvif->bss_params, 0, sizeof(wvif->bss_params));
+ }
+ }
+
+ /* ERP Protection */
+ if (changed & (BSS_CHANGED_ASSOC |
+ BSS_CHANGED_ERP_CTS_PROT |
+ BSS_CHANGED_ERP_PREAMBLE)) {
+ u32 prev_erp_info = wvif->erp_info;
+
+ if (info->use_cts_prot)
+ wvif->erp_info |= WLAN_ERP_USE_PROTECTION;
+ else if (!(prev_erp_info & WLAN_ERP_NON_ERP_PRESENT))
+ wvif->erp_info &= ~WLAN_ERP_USE_PROTECTION;
+
+ if (info->use_short_preamble)
+ wvif->erp_info |= WLAN_ERP_BARKER_PREAMBLE;
+ else
+ wvif->erp_info &= ~WLAN_ERP_BARKER_PREAMBLE;
+
+ if (prev_erp_info != wvif->erp_info)
+ schedule_work(&wvif->set_cts_work);
+ }
+
+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_SLOT))
+ hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
+
+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_CQM)) {
+ struct hif_mib_rcpi_rssi_threshold th = {
+ .rolling_average_count = 8,
+ .detection = 1,
+ };
+
+ wvif->cqm_rssi_thold = info->cqm_rssi_thold;
+
+ if (!info->cqm_rssi_thold && !info->cqm_rssi_hyst) {
+ th.upperthresh = 1;
+ th.lowerthresh = 1;
+ } else {
+ /* FIXME It's not a correct way of setting threshold.
+ * Upper and lower must be set equal here and adjusted
+ * in callback. However current implementation is much
+ * more reliable and stable.
+ */
+ /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
+ * RSSI = RCPI / 2 - 110
+ */
+ th.upper_threshold = info->cqm_rssi_thold + info->cqm_rssi_hyst;
+ th.upper_threshold = (th.upper_threshold + 110) * 2;
+ th.lower_threshold = info->cqm_rssi_thold;
+ th.lower_threshold = (th.lower_threshold + 110) * 2;
+ }
+ hif_set_rcpi_rssi_threshold(wvif, &th);
+ }
+
+ if (changed & BSS_CHANGED_TXPOWER && info->txpower != wdev->output_power) {
+ wdev->output_power = info->txpower;
+ hif_set_output_power(wvif, wdev->output_power * 10);
+ }
+ mutex_unlock(&wdev->conf_mutex);
+
+ if (do_join) {
+ wfx_tx_lock_flush(wdev);
+ wfx_do_join(wvif); /* Will unlock it for us */
+ }
+}
+
+static void wfx_ps_notify(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd,
+ int link_id)
+{
+ u32 bit, prev;
+
+ spin_lock_bh(&wvif->ps_state_lock);
+ /* Zero link id means "for all link IDs" */
+ if (link_id) {
+ bit = BIT(link_id);
+ } else if (notify_cmd != STA_NOTIFY_AWAKE) {
+ dev_warn(wvif->wdev->dev, "unsupported notify command\n");
+ bit = 0;
+ } else {
+ bit = wvif->link_id_map;
+ }
+ prev = wvif->sta_asleep_mask & bit;
+
+ switch (notify_cmd) {
+ case STA_NOTIFY_SLEEP:
+ if (!prev) {
+ if (wvif->mcast_buffered && !wvif->sta_asleep_mask)
+ schedule_work(&wvif->mcast_start_work);
+ wvif->sta_asleep_mask |= bit;
+ }
+ break;
+ case STA_NOTIFY_AWAKE:
+ if (prev) {
+ wvif->sta_asleep_mask &= ~bit;
+ wvif->pspoll_mask &= ~bit;
+ if (link_id && !wvif->sta_asleep_mask)
+ schedule_work(&wvif->mcast_stop_work);
+ wfx_bh_request_tx(wvif->wdev);
+ }
+ break;
+ }
+ spin_unlock_bh(&wvif->ps_state_lock);
+}
+
+void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ enum sta_notify_cmd notify_cmd, struct ieee80211_sta *sta)
+{
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
+
+ wfx_ps_notify(wvif, notify_cmd, sta_priv->link_id);
+}
+
+static int wfx_set_tim_impl(struct wfx_vif *wvif, bool aid0_bit_set)
+{
+ struct sk_buff *skb;
+ struct hif_ie_flags target_frame = {
+ .beacon = 1,
+ };
+ u16 tim_offset, tim_length;
+ u8 *tim_ptr;
+
+ skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif,
+ &tim_offset, &tim_length);
+ if (!skb) {
+ if (!__wfx_flush(wvif->wdev, true))
+ wfx_tx_unlock(wvif->wdev);
+ return -ENOENT;
+ }
+ tim_ptr = skb->data + tim_offset;
+
+ if (tim_offset && tim_length >= 6) {
+ /* Ignore DTIM count from mac80211:
+ * firmware handles DTIM internally.
+ */
+ tim_ptr[2] = 0;
+
+ /* Set/reset aid0 bit */
+ if (aid0_bit_set)
+ tim_ptr[4] |= 1;
+ else
+ tim_ptr[4] &= ~1;
+ }
+
+ hif_update_ie(wvif, &target_frame, tim_ptr, tim_length);
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
+static void wfx_set_tim_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, set_tim_work);
+
+ wfx_set_tim_impl(wvif, wvif->aid0_bit_set);
+}
+
+int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *) &sta->drv_priv;
+ struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id);
+
+ schedule_work(&wvif->set_tim_work);
+ return 0;
+}
+
+static void wfx_mcast_start_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, mcast_start_work);
+ long tmo = wvif->dtim_period * TU_TO_JIFFIES(wvif->beacon_int + 20);
+
+ cancel_work_sync(&wvif->mcast_stop_work);
+ if (!wvif->aid0_bit_set) {
+ wfx_tx_lock_flush(wvif->wdev);
+ wfx_set_tim_impl(wvif, true);
+ wvif->aid0_bit_set = true;
+ mod_timer(&wvif->mcast_timeout, jiffies + tmo);
+ wfx_tx_unlock(wvif->wdev);
+ }
+}
+
+static void wfx_mcast_stop_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, mcast_stop_work);
+
+ if (wvif->aid0_bit_set) {
+ del_timer_sync(&wvif->mcast_timeout);
+ wfx_tx_lock_flush(wvif->wdev);
+ wvif->aid0_bit_set = false;
+ wfx_set_tim_impl(wvif, false);
+ wfx_tx_unlock(wvif->wdev);
+ }
+}
+
+static void wfx_mcast_timeout(struct timer_list *t)
+{
+ struct wfx_vif *wvif = from_timer(wvif, t, mcast_timeout);
+
+ dev_warn(wvif->wdev->dev, "multicast delivery timeout\n");
+ spin_lock_bh(&wvif->ps_state_lock);
+ wvif->mcast_tx = wvif->aid0_bit_set && wvif->mcast_buffered;
+ if (wvif->mcast_tx)
+ wfx_bh_request_tx(wvif->wdev);
+ spin_unlock_bh(&wvif->ps_state_lock);
+}
+
+int wfx_ampdu_action(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params)
+{
+ /* Aggregation is implemented fully in firmware,
+ * including block ack negotiation. Do not allow
+ * mac80211 stack to do anything: it interferes with
+ * the firmware.
+ */
+
+ /* Note that we still need this function stubbed. */
+
+ return -ENOTSUPP;
+}
+
+void wfx_suspend_resume(struct wfx_vif *wvif,
+ struct hif_ind_suspend_resume_tx *arg)
+{
+ if (arg->suspend_resume_flags.bc_mc_only) {
+ bool cancel_tmo = false;
+
+ spin_lock_bh(&wvif->ps_state_lock);
+ if (!arg->suspend_resume_flags.resume)
+ wvif->mcast_tx = false;
+ else
+ wvif->mcast_tx = wvif->aid0_bit_set && wvif->mcast_buffered;
+ if (wvif->mcast_tx) {
+ cancel_tmo = true;
+ wfx_bh_request_tx(wvif->wdev);
+ }
+ spin_unlock_bh(&wvif->ps_state_lock);
+ if (cancel_tmo)
+ del_timer_sync(&wvif->mcast_timeout);
+ } else if (arg->suspend_resume_flags.resume) {
+ // FIXME: should change each station status independently
+ wfx_ps_notify(wvif, STA_NOTIFY_AWAKE, 0);
+ wfx_bh_request_tx(wvif->wdev);
+ } else {
+ // FIXME: should change each station status independently
+ wfx_ps_notify(wvif, STA_NOTIFY_SLEEP, 0);
+ }
+}
+
+int wfx_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf)
+{
+ return 0;
+}
+
+void wfx_remove_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf)
+{
+}
+
+void wfx_change_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf,
+ u32 changed)
+{
+}
+
+int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *conf)
+{
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ struct ieee80211_channel *ch = conf->def.chan;
+
+ WARN(wvif->channel, "channel overwrite");
+ wvif->channel = ch;
+ wvif->ht_info.channel_type = cfg80211_get_chandef_type(&conf->def);
+
+ return 0;
+}
+
+void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *conf)
+{
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ struct ieee80211_channel *ch = conf->def.chan;
+
+ WARN(wvif->channel != ch, "channel mismatch");
+ wvif->channel = NULL;
+}
+
+int wfx_config(struct ieee80211_hw *hw, u32 changed)
+{
+ int ret = 0;
+ struct wfx_dev *wdev = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+ struct wfx_vif *wvif;
+
+ // FIXME: Interface id should not been hardcoded
+ wvif = wdev_to_wvif(wdev, 0);
+ if (!wvif) {
+ WARN(1, "interface 0 does not exist anymore");
+ return 0;
+ }
+
+ down(&wvif->scan.lock);
+ mutex_lock(&wdev->conf_mutex);
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ wdev->output_power = conf->power_level;
+ hif_set_output_power(wvif, wdev->output_power * 10);
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_PS) {
+ wvif = NULL;
+ while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
+ memset(&wvif->powersave_mode, 0, sizeof(wvif->powersave_mode));
+ if (conf->flags & IEEE80211_CONF_PS) {
+ wvif->powersave_mode.pm_mode.enter_psm = 1;
+ if (conf->dynamic_ps_timeout > 0) {
+ wvif->powersave_mode.pm_mode.fast_psm = 1;
+ // Firmware does not support more than 128ms
+ wvif->powersave_mode.fast_psm_idle_period =
+ min(conf->dynamic_ps_timeout * 2, 255);
+ }
+ }
+ if (wvif->state == WFX_STATE_STA && wvif->bss_params.aid)
+ wfx_set_pm(wvif, &wvif->powersave_mode);
+ }
+ wvif = wdev_to_wvif(wdev, 0);
+ }
+
+ mutex_unlock(&wdev->conf_mutex);
+ up(&wvif->scan.lock);
+ return ret;
+}
+
+int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+ int i;
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ // FIXME: parameters are set by kernel juste after interface_add.
+ // Keep struct hif_req_edca_queue_params blank?
+ struct hif_req_edca_queue_params default_edca_params[] = {
+ [IEEE80211_AC_VO] = {
+ .queue_id = HIF_QUEUE_ID_VOICE,
+ .aifsn = 2,
+ .cw_min = 3,
+ .cw_max = 7,
+ .tx_op_limit = TXOP_UNIT * 47,
+ },
+ [IEEE80211_AC_VI] = {
+ .queue_id = HIF_QUEUE_ID_VIDEO,
+ .aifsn = 2,
+ .cw_min = 7,
+ .cw_max = 15,
+ .tx_op_limit = TXOP_UNIT * 94,
+ },
+ [IEEE80211_AC_BE] = {
+ .queue_id = HIF_QUEUE_ID_BESTEFFORT,
+ .aifsn = 3,
+ .cw_min = 15,
+ .cw_max = 1023,
+ .tx_op_limit = TXOP_UNIT * 0,
+ },
+ [IEEE80211_AC_BK] = {
+ .queue_id = HIF_QUEUE_ID_BACKGROUND,
+ .aifsn = 7,
+ .cw_min = 15,
+ .cw_max = 1023,
+ .tx_op_limit = TXOP_UNIT * 0,
+ },
+ };
+
+ BUILD_BUG_ON(ARRAY_SIZE(default_edca_params) != ARRAY_SIZE(wvif->edca.params));
+ if (wfx_api_older_than(wdev, 2, 0)) {
+ default_edca_params[IEEE80211_AC_BE].queue_id = HIF_QUEUE_ID_BACKGROUND;
+ default_edca_params[IEEE80211_AC_BK].queue_id = HIF_QUEUE_ID_BESTEFFORT;
+ }
+
+ vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
+ IEEE80211_VIF_SUPPORTS_UAPSD |
+ IEEE80211_VIF_SUPPORTS_CQM_RSSI;
+
+ mutex_lock(&wdev->conf_mutex);
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP:
+ break;
+ default:
+ mutex_unlock(&wdev->conf_mutex);
+ return -EOPNOTSUPP;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
+ if (!wdev->vif[i]) {
+ wdev->vif[i] = vif;
+ wvif->id = i;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(wdev->vif)) {
+ mutex_unlock(&wdev->conf_mutex);
+ return -EOPNOTSUPP;
+ }
+ // FIXME: prefer use of container_of() to get vif
+ wvif->vif = vif;
+ wvif->wdev = wdev;
+
+ INIT_WORK(&wvif->link_id_work, wfx_link_id_work);
+ INIT_DELAYED_WORK(&wvif->link_id_gc_work, wfx_link_id_gc_work);
+
+ spin_lock_init(&wvif->ps_state_lock);
+ INIT_WORK(&wvif->set_tim_work, wfx_set_tim_work);
+
+ INIT_WORK(&wvif->mcast_start_work, wfx_mcast_start_work);
+ INIT_WORK(&wvif->mcast_stop_work, wfx_mcast_stop_work);
+ timer_setup(&wvif->mcast_timeout, wfx_mcast_timeout, 0);
+
+ wvif->setbssparams_done = false;
+ mutex_init(&wvif->bss_loss_lock);
+ INIT_DELAYED_WORK(&wvif->bss_loss_work, wfx_bss_loss_work);
+
+ wvif->wep_default_key_id = -1;
+ INIT_WORK(&wvif->wep_key_work, wfx_wep_key_work);
+
+ sema_init(&wvif->scan.lock, 1);
+ INIT_WORK(&wvif->scan.work, wfx_scan_work);
+ INIT_DELAYED_WORK(&wvif->scan.timeout, wfx_scan_timeout);
+
+ spin_lock_init(&wvif->event_queue_lock);
+ INIT_LIST_HEAD(&wvif->event_queue);
+ INIT_WORK(&wvif->event_handler_work, wfx_event_handler_work);
+
+ init_completion(&wvif->set_pm_mode_complete);
+ complete(&wvif->set_pm_mode_complete);
+ INIT_WORK(&wvif->set_beacon_wakeup_period_work, wfx_set_beacon_wakeup_period_work);
+ INIT_WORK(&wvif->update_filtering_work, wfx_update_filtering_work);
+ INIT_WORK(&wvif->bss_params_work, wfx_bss_params_work);
+ INIT_WORK(&wvif->set_cts_work, wfx_set_cts_work);
+ INIT_WORK(&wvif->unjoin_work, wfx_unjoin_work);
+
+ mutex_unlock(&wdev->conf_mutex);
+
+ hif_set_macaddr(wvif, vif->addr);
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ memcpy(&wvif->edca.params[i], &default_edca_params[i], sizeof(default_edca_params[i]));
+ wvif->edca.uapsd_enable[i] = false;
+ hif_set_edca_queue_params(wvif, &wvif->edca.params[i]);
+ }
+ wfx_set_uapsd_param(wvif, &wvif->edca);
+
+ wfx_tx_policy_init(wvif);
+ wvif = NULL;
+ while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
+ // Combo mode does not support Block Acks. We can re-enable them
+ if (wvif_count(wdev) == 1)
+ hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
+ else
+ hif_set_block_ack_policy(wvif, 0x00, 0x00);
+ // Combo force powersave mode. We can re-enable it now
+ wfx_set_pm(wvif, &wvif->powersave_mode);
+ }
+ return 0;
+}
+
+void wfx_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
+ int i;
+
+ // If scan is in progress, stop it
+ while (down_trylock(&wvif->scan.lock))
+ schedule();
+ up(&wvif->scan.lock);
+ wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
+
+ mutex_lock(&wdev->conf_mutex);
+ switch (wvif->state) {
+ case WFX_STATE_PRE_STA:
+ case WFX_STATE_STA:
+ case WFX_STATE_IBSS:
+ wfx_tx_lock_flush(wdev);
+ if (!schedule_work(&wvif->unjoin_work))
+ wfx_tx_unlock(wdev);
+ break;
+ case WFX_STATE_AP:
+ for (i = 0; wvif->link_id_map; ++i) {
+ if (wvif->link_id_map & BIT(i)) {
+ wfx_unmap_link(wvif, i);
+ wvif->link_id_map &= ~BIT(i);
+ }
+ }
+ memset(wvif->link_id_db, 0, sizeof(wvif->link_id_db));
+ wvif->sta_asleep_mask = 0;
+ wvif->enable_beacon = false;
+ wvif->mcast_tx = false;
+ wvif->aid0_bit_set = false;
+ wvif->mcast_buffered = false;
+ wvif->pspoll_mask = 0;
+ /* reset.link_id = 0; */
+ hif_reset(wvif, false);
+ break;
+ default:
+ break;
+ }
+
+ wvif->state = WFX_STATE_PASSIVE;
+ wfx_tx_queues_wait_empty_vif(wvif);
+ wfx_tx_unlock(wdev);
+
+ /* FIXME: In add to reset MAC address, try to reset interface */
+ hif_set_macaddr(wvif, NULL);
+
+ cancel_delayed_work_sync(&wvif->scan.timeout);
+
+ wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
+ cancel_work_sync(&wvif->unjoin_work);
+ cancel_delayed_work_sync(&wvif->link_id_gc_work);
+ del_timer_sync(&wvif->mcast_timeout);
+ wfx_free_event_queue(wvif);
+
+ wdev->vif[wvif->id] = NULL;
+ wvif->vif = NULL;
+
+ mutex_unlock(&wdev->conf_mutex);
+ wvif = NULL;
+ while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
+ // Combo mode does not support Block Acks. We can re-enable them
+ if (wvif_count(wdev) == 1)
+ hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
+ else
+ hif_set_block_ack_policy(wvif, 0x00, 0x00);
+ // Combo force powersave mode. We can re-enable it now
+ wfx_set_pm(wvif, &wvif->powersave_mode);
+ }
+}
+
+int wfx_start(struct ieee80211_hw *hw)
+{
+ return 0;
+}
+
+void wfx_stop(struct ieee80211_hw *hw)
+{
+ struct wfx_dev *wdev = hw->priv;
+
+ wfx_tx_lock_flush(wdev);
+ mutex_lock(&wdev->conf_mutex);
+ wfx_tx_queues_clear(wdev);
+ mutex_unlock(&wdev->conf_mutex);
+ wfx_tx_unlock(wdev);
+ WARN(atomic_read(&wdev->tx_lock), "tx_lock is locked");
+}
diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h
new file mode 100644
index 000000000000..307ed0196110
--- /dev/null
+++ b/drivers/staging/wfx/sta.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Implementation of mac80211 API.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_STA_H
+#define WFX_STA_H
+
+#include <net/mac80211.h>
+
+#include "hif_api_cmd.h"
+
+struct wfx_dev;
+struct wfx_vif;
+
+enum wfx_state {
+ WFX_STATE_PASSIVE = 0,
+ WFX_STATE_PRE_STA,
+ WFX_STATE_STA,
+ WFX_STATE_IBSS,
+ WFX_STATE_AP,
+};
+
+struct wfx_ht_info {
+ struct ieee80211_sta_ht_cap ht_cap;
+ enum nl80211_channel_type channel_type;
+ uint16_t operation_mode;
+};
+
+struct wfx_hif_event {
+ struct list_head link;
+ struct hif_ind_event evt;
+};
+
+struct wfx_edca_params {
+ /* NOTE: index is a linux queue id. */
+ struct hif_req_edca_queue_params params[IEEE80211_NUM_ACS];
+ bool uapsd_enable[IEEE80211_NUM_ACS];
+};
+
+struct wfx_grp_addr_table {
+ bool enable;
+ int num_addresses;
+ u8 address_list[8][ETH_ALEN];
+};
+
+struct wfx_sta_priv {
+ int link_id;
+ int vif_id;
+};
+
+// mac80211 interface
+int wfx_start(struct ieee80211_hw *hw);
+void wfx_stop(struct ieee80211_hw *hw);
+int wfx_config(struct ieee80211_hw *hw, u32 changed);
+int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
+u64 wfx_prepare_multicast(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list);
+void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
+ unsigned int *total_flags, u64 unused);
+
+int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop);
+int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u16 queue, const struct ieee80211_tx_queue_params *params);
+void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info, u32 changed);
+int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd, struct ieee80211_sta *sta);
+int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set);
+int wfx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params);
+int wfx_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf);
+void wfx_remove_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf);
+void wfx_change_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf, u32 changed);
+int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *conf);
+void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *conf);
+
+// WSM Callbacks
+void wfx_suspend_resume(struct wfx_vif *wvif, struct hif_ind_suspend_resume_tx *arg);
+
+// Other Helpers
+void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad);
+void wfx_update_filtering(struct wfx_vif *wvif);
+int wfx_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg);
+int wfx_fwd_probe_req(struct wfx_vif *wvif, bool enable);
+
+#endif /* WFX_STA_H */
diff --git a/drivers/staging/wfx/traces.h b/drivers/staging/wfx/traces.h
new file mode 100644
index 000000000000..67457cda133b
--- /dev/null
+++ b/drivers/staging/wfx/traces.h
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Tracepoints definitions.
+ *
+ * Copyright (c) 2018-2019, Silicon Laboratories, Inc.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM wfx
+
+#if !defined(_WFX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _WFX_TRACE_H
+
+#include <linux/tracepoint.h>
+#include <net/mac80211.h>
+
+#include "bus.h"
+#include "hif_api_cmd.h"
+#include "hif_api_mib.h"
+
+/* The hell below need some explanations. For each symbolic number, we need to
+ * define it with TRACE_DEFINE_ENUM() and in a list for __print_symbolic.
+ *
+ * 1. Define a new macro that call TRACE_DEFINE_ENUM():
+ *
+ * #define xxx_name(sym) TRACE_DEFINE_ENUM(sym);
+ *
+ * 2. Define list of all symbols:
+ *
+ * #define list_names \
+ * ... \
+ * xxx_name(XXX) \
+ * ...
+ *
+ * 3. Instanciate that list_names:
+ *
+ * list_names
+ *
+ * 4. Redefine xxx_name() as a entry of array for __print_symbolic()
+ *
+ * #undef xxx_name
+ * #define xxx_name(msg) { msg, #msg },
+ *
+ * 5. list_name can now nearlu be used with __print_symbolic() but,
+ * __print_symbolic() dislike last comma of list. So we define a new list
+ * with a dummy element:
+ *
+ * #define list_for_print_symbolic list_names { -1, NULL }
+ */
+
+#define _hif_msg_list \
+ hif_cnf_name(ADD_KEY) \
+ hif_cnf_name(BEACON_TRANSMIT) \
+ hif_cnf_name(EDCA_QUEUE_PARAMS) \
+ hif_cnf_name(JOIN) \
+ hif_cnf_name(MAP_LINK) \
+ hif_cnf_name(READ_MIB) \
+ hif_cnf_name(REMOVE_KEY) \
+ hif_cnf_name(RESET) \
+ hif_cnf_name(SET_BSS_PARAMS) \
+ hif_cnf_name(SET_PM_MODE) \
+ hif_cnf_name(START) \
+ hif_cnf_name(START_SCAN) \
+ hif_cnf_name(STOP_SCAN) \
+ hif_cnf_name(TX) \
+ hif_cnf_name(MULTI_TRANSMIT) \
+ hif_cnf_name(UPDATE_IE) \
+ hif_cnf_name(WRITE_MIB) \
+ hif_cnf_name(CONFIGURATION) \
+ hif_cnf_name(CONTROL_GPIO) \
+ hif_cnf_name(PREVENT_ROLLBACK) \
+ hif_cnf_name(SET_SL_MAC_KEY) \
+ hif_cnf_name(SL_CONFIGURE) \
+ hif_cnf_name(SL_EXCHANGE_PUB_KEYS) \
+ hif_cnf_name(SHUT_DOWN) \
+ hif_ind_name(EVENT) \
+ hif_ind_name(JOIN_COMPLETE) \
+ hif_ind_name(RX) \
+ hif_ind_name(SCAN_CMPL) \
+ hif_ind_name(SET_PM_MODE_CMPL) \
+ hif_ind_name(SUSPEND_RESUME_TX) \
+ hif_ind_name(SL_EXCHANGE_PUB_KEYS) \
+ hif_ind_name(ERROR) \
+ hif_ind_name(EXCEPTION) \
+ hif_ind_name(GENERIC) \
+ hif_ind_name(WAKEUP) \
+ hif_ind_name(STARTUP)
+
+#define hif_msg_list_enum _hif_msg_list
+
+#undef hif_cnf_name
+#undef hif_ind_name
+#define hif_cnf_name(msg) TRACE_DEFINE_ENUM(HIF_CNF_ID_##msg);
+#define hif_ind_name(msg) TRACE_DEFINE_ENUM(HIF_IND_ID_##msg);
+hif_msg_list_enum
+#undef hif_cnf_name
+#undef hif_ind_name
+#define hif_cnf_name(msg) { HIF_CNF_ID_##msg, #msg },
+#define hif_ind_name(msg) { HIF_IND_ID_##msg, #msg },
+#define hif_msg_list hif_msg_list_enum { -1, NULL }
+
+#define _hif_mib_list \
+ hif_mib_name(ARP_IP_ADDRESSES_TABLE) \
+ hif_mib_name(ARP_KEEP_ALIVE_PERIOD) \
+ hif_mib_name(BEACON_FILTER_ENABLE) \
+ hif_mib_name(BEACON_FILTER_TABLE) \
+ hif_mib_name(BEACON_WAKEUP_PERIOD) \
+ hif_mib_name(BLOCK_ACK_POLICY) \
+ hif_mib_name(CONFIG_DATA_FILTER) \
+ hif_mib_name(COUNTERS_TABLE) \
+ hif_mib_name(CURRENT_TX_POWER_LEVEL) \
+ hif_mib_name(DOT11_MAC_ADDRESS) \
+ hif_mib_name(DOT11_MAX_RECEIVE_LIFETIME) \
+ hif_mib_name(DOT11_MAX_TRANSMIT_MSDU_LIFETIME) \
+ hif_mib_name(DOT11_RTS_THRESHOLD) \
+ hif_mib_name(DOT11_WEP_DEFAULT_KEY_ID) \
+ hif_mib_name(GL_BLOCK_ACK_INFO) \
+ hif_mib_name(GL_OPERATIONAL_POWER_MODE) \
+ hif_mib_name(GL_SET_MULTI_MSG) \
+ hif_mib_name(INACTIVITY_TIMER) \
+ hif_mib_name(INTERFACE_PROTECTION) \
+ hif_mib_name(IPV4_ADDR_DATAFRAME_CONDITION) \
+ hif_mib_name(IPV6_ADDR_DATAFRAME_CONDITION) \
+ hif_mib_name(KEEP_ALIVE_PERIOD) \
+ hif_mib_name(MAC_ADDR_DATAFRAME_CONDITION) \
+ hif_mib_name(NON_ERP_PROTECTION) \
+ hif_mib_name(NS_IP_ADDRESSES_TABLE) \
+ hif_mib_name(OVERRIDE_INTERNAL_TX_RATE) \
+ hif_mib_name(PROTECTED_MGMT_POLICY) \
+ hif_mib_name(RX_FILTER) \
+ hif_mib_name(RCPI_RSSI_THRESHOLD) \
+ hif_mib_name(SET_ASSOCIATION_MODE) \
+ hif_mib_name(SET_DATA_FILTERING) \
+ hif_mib_name(ETHERTYPE_DATAFRAME_CONDITION) \
+ hif_mib_name(SET_HT_PROTECTION) \
+ hif_mib_name(MAGIC_DATAFRAME_CONDITION) \
+ hif_mib_name(SET_TX_RATE_RETRY_POLICY) \
+ hif_mib_name(SET_UAPSD_INFORMATION) \
+ hif_mib_name(PORT_DATAFRAME_CONDITION) \
+ hif_mib_name(SLOT_TIME) \
+ hif_mib_name(STATISTICS_TABLE) \
+ hif_mib_name(TEMPLATE_FRAME) \
+ hif_mib_name(TSF_COUNTER) \
+ hif_mib_name(UC_MC_BC_DATAFRAME_CONDITION)
+
+#define hif_mib_list_enum _hif_mib_list
+
+#undef hif_mib_name
+#define hif_mib_name(mib) TRACE_DEFINE_ENUM(HIF_MIB_ID_##mib);
+hif_mib_list_enum
+#undef hif_mib_name
+#define hif_mib_name(mib) { HIF_MIB_ID_##mib, #mib },
+#define hif_mib_list hif_mib_list_enum { -1, NULL }
+
+DECLARE_EVENT_CLASS(hif_data,
+ TP_PROTO(struct hif_msg *hif, int tx_fill_level, bool is_recv),
+ TP_ARGS(hif, tx_fill_level, is_recv),
+ TP_STRUCT__entry(
+ __field(int, tx_fill_level)
+ __field(int, msg_id)
+ __field(const char *, msg_type)
+ __field(int, msg_len)
+ __field(int, buf_len)
+ __field(int, if_id)
+ __field(int, mib)
+ __array(u8, buf, 128)
+ ),
+ TP_fast_assign(
+ int header_len;
+
+ __entry->tx_fill_level = tx_fill_level;
+ __entry->msg_len = hif->len;
+ __entry->msg_id = hif->id;
+ __entry->if_id = hif->interface;
+ if (is_recv)
+ __entry->msg_type = __entry->msg_id & 0x80 ? "IND" : "CNF";
+ else
+ __entry->msg_type = "REQ";
+ if (!is_recv &&
+ (__entry->msg_id == HIF_REQ_ID_READ_MIB || __entry->msg_id == HIF_REQ_ID_WRITE_MIB)) {
+ __entry->mib = le16_to_cpup((u16 *) hif->body);
+ header_len = 4;
+ } else {
+ __entry->mib = -1;
+ header_len = 0;
+ }
+ __entry->buf_len = min_t(int, __entry->msg_len, sizeof(__entry->buf))
+ - sizeof(struct hif_msg) - header_len;
+ memcpy(__entry->buf, hif->body + header_len, __entry->buf_len);
+ ),
+ TP_printk("%d:%d:%s_%s%s%s: %s%s (%d bytes)",
+ __entry->tx_fill_level,
+ __entry->if_id,
+ __print_symbolic(__entry->msg_id, hif_msg_list),
+ __entry->msg_type,
+ __entry->mib != -1 ? "/" : "",
+ __entry->mib != -1 ? __print_symbolic(__entry->mib, hif_mib_list) : "",
+ __print_hex(__entry->buf, __entry->buf_len),
+ __entry->msg_len > sizeof(__entry->buf) ? " ..." : "",
+ __entry->msg_len
+ )
+);
+DEFINE_EVENT(hif_data, hif_send,
+ TP_PROTO(struct hif_msg *hif, int tx_fill_level, bool is_recv),
+ TP_ARGS(hif, tx_fill_level, is_recv));
+#define _trace_hif_send(hif, tx_fill_level) trace_hif_send(hif, tx_fill_level, false)
+DEFINE_EVENT(hif_data, hif_recv,
+ TP_PROTO(struct hif_msg *hif, int tx_fill_level, bool is_recv),
+ TP_ARGS(hif, tx_fill_level, is_recv));
+#define _trace_hif_recv(hif, tx_fill_level) trace_hif_recv(hif, tx_fill_level, true)
+
+#define wfx_reg_list_enum \
+ wfx_reg_name(WFX_REG_CONFIG, "CONFIG") \
+ wfx_reg_name(WFX_REG_CONTROL, "CONTROL") \
+ wfx_reg_name(WFX_REG_IN_OUT_QUEUE, "QUEUE") \
+ wfx_reg_name(WFX_REG_AHB_DPORT, "AHB") \
+ wfx_reg_name(WFX_REG_BASE_ADDR, "BASE_ADDR") \
+ wfx_reg_name(WFX_REG_SRAM_DPORT, "SRAM") \
+ wfx_reg_name(WFX_REG_SET_GEN_R_W, "SET_GEN_R_W") \
+ wfx_reg_name(WFX_REG_FRAME_OUT, "FRAME_OUT")
+
+#undef wfx_reg_name
+#define wfx_reg_name(sym, name) TRACE_DEFINE_ENUM(sym);
+wfx_reg_list_enum
+#undef wfx_reg_name
+#define wfx_reg_name(sym, name) { sym, name },
+#define wfx_reg_list wfx_reg_list_enum { -1, NULL }
+
+DECLARE_EVENT_CLASS(io_data,
+ TP_PROTO(int reg, int addr, const void *io_buf, size_t len),
+ TP_ARGS(reg, addr, io_buf, len),
+ TP_STRUCT__entry(
+ __field(int, reg)
+ __field(int, addr)
+ __field(int, msg_len)
+ __field(int, buf_len)
+ __array(u8, buf, 32)
+ __array(u8, addr_str, 10)
+ ),
+ TP_fast_assign(
+ __entry->reg = reg;
+ __entry->addr = addr;
+ __entry->msg_len = len;
+ __entry->buf_len = min_t(int, sizeof(__entry->buf), __entry->msg_len);
+ memcpy(__entry->buf, io_buf, __entry->buf_len);
+ if (addr >= 0)
+ snprintf(__entry->addr_str, 10, "/%08x", addr);
+ else
+ __entry->addr_str[0] = 0;
+ ),
+ TP_printk("%s%s: %s%s (%d bytes)",
+ __print_symbolic(__entry->reg, wfx_reg_list),
+ __entry->addr_str,
+ __print_hex(__entry->buf, __entry->buf_len),
+ __entry->msg_len > sizeof(__entry->buf) ? " ..." : "",
+ __entry->msg_len
+ )
+);
+DEFINE_EVENT(io_data, io_write,
+ TP_PROTO(int reg, int addr, const void *io_buf, size_t len),
+ TP_ARGS(reg, addr, io_buf, len));
+#define _trace_io_ind_write(reg, addr, io_buf, len) trace_io_write(reg, addr, io_buf, len)
+#define _trace_io_write(reg, io_buf, len) trace_io_write(reg, -1, io_buf, len)
+DEFINE_EVENT(io_data, io_read,
+ TP_PROTO(int reg, int addr, const void *io_buf, size_t len),
+ TP_ARGS(reg, addr, io_buf, len));
+#define _trace_io_ind_read(reg, addr, io_buf, len) trace_io_read(reg, addr, io_buf, len)
+#define _trace_io_read(reg, io_buf, len) trace_io_read(reg, -1, io_buf, len)
+
+DECLARE_EVENT_CLASS(io_data32,
+ TP_PROTO(int reg, int addr, u32 val),
+ TP_ARGS(reg, addr, val),
+ TP_STRUCT__entry(
+ __field(int, reg)
+ __field(int, addr)
+ __field(int, val)
+ __array(u8, addr_str, 10)
+ ),
+ TP_fast_assign(
+ __entry->reg = reg;
+ __entry->addr = addr;
+ __entry->val = val;
+ if (addr >= 0)
+ snprintf(__entry->addr_str, 10, "/%08x", addr);
+ else
+ __entry->addr_str[0] = 0;
+ ),
+ TP_printk("%s%s: %08x",
+ __print_symbolic(__entry->reg, wfx_reg_list),
+ __entry->addr_str,
+ __entry->val
+ )
+);
+DEFINE_EVENT(io_data32, io_write32,
+ TP_PROTO(int reg, int addr, u32 val),
+ TP_ARGS(reg, addr, val));
+#define _trace_io_ind_write32(reg, addr, val) trace_io_write32(reg, addr, val)
+#define _trace_io_write32(reg, val) trace_io_write32(reg, -1, val)
+DEFINE_EVENT(io_data32, io_read32,
+ TP_PROTO(int reg, int addr, u32 val),
+ TP_ARGS(reg, addr, val));
+#define _trace_io_ind_read32(reg, addr, val) trace_io_read32(reg, addr, val)
+#define _trace_io_read32(reg, val) trace_io_read32(reg, -1, val)
+
+DECLARE_EVENT_CLASS(piggyback,
+ TP_PROTO(u32 val, bool ignored),
+ TP_ARGS(val, ignored),
+ TP_STRUCT__entry(
+ __field(int, val)
+ __field(bool, ignored)
+ ),
+ TP_fast_assign(
+ __entry->val = val;
+ __entry->ignored = ignored;
+ ),
+ TP_printk("CONTROL: %08x%s",
+ __entry->val,
+ __entry->ignored ? " (ignored)" : ""
+ )
+);
+DEFINE_EVENT(piggyback, piggyback,
+ TP_PROTO(u32 val, bool ignored),
+ TP_ARGS(val, ignored));
+#define _trace_piggyback(val, ignored) trace_piggyback(val, ignored)
+
+TRACE_EVENT(bh_stats,
+ TP_PROTO(int ind, int req, int cnf, int busy, bool release),
+ TP_ARGS(ind, req, cnf, busy, release),
+ TP_STRUCT__entry(
+ __field(int, ind)
+ __field(int, req)
+ __field(int, cnf)
+ __field(int, busy)
+ __field(bool, release)
+ ),
+ TP_fast_assign(
+ __entry->ind = ind;
+ __entry->req = req;
+ __entry->cnf = cnf;
+ __entry->busy = busy;
+ __entry->release = release;
+ ),
+ TP_printk("IND/REQ/CNF:%3d/%3d/%3d, REQ in progress:%3d, WUP: %s",
+ __entry->ind,
+ __entry->req,
+ __entry->cnf,
+ __entry->busy,
+ __entry->release ? "release" : "keep"
+ )
+);
+#define _trace_bh_stats(ind, req, cnf, busy, release) trace_bh_stats(ind, req, cnf, busy, release)
+
+TRACE_EVENT(tx_stats,
+ TP_PROTO(struct hif_cnf_tx *tx_cnf, struct sk_buff *skb, int delay),
+ TP_ARGS(tx_cnf, skb, delay),
+ TP_STRUCT__entry(
+ __field(int, pkt_id)
+ __field(int, delay_media)
+ __field(int, delay_queue)
+ __field(int, delay_fw)
+ __field(int, ack_failures)
+ __field(int, flags)
+ __array(int, rate, 4)
+ __array(int, tx_count, 4)
+ ),
+ TP_fast_assign(
+ // Keep sync with wfx_rates definition in main.c
+ static const int hw_rate[] = { 0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13 };
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_tx_rate *rates = tx_info->driver_rates;
+ int i;
+
+ __entry->pkt_id = tx_cnf->packet_id;
+ __entry->delay_media = tx_cnf->media_delay;
+ __entry->delay_queue = tx_cnf->tx_queue_delay;
+ __entry->delay_fw = delay;
+ __entry->ack_failures = tx_cnf->ack_failures;
+ if (!tx_cnf->status || __entry->ack_failures)
+ __entry->ack_failures += 1;
+
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ if (rates[0].flags & IEEE80211_TX_RC_MCS)
+ __entry->rate[i] = rates[i].idx;
+ else
+ __entry->rate[i] = hw_rate[rates[i].idx];
+ __entry->tx_count[i] = rates[i].count;
+ }
+ __entry->flags = 0;
+ if (rates[0].flags & IEEE80211_TX_RC_MCS)
+ __entry->flags |= 0x01;
+ if (rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
+ __entry->flags |= 0x02;
+ if (rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)
+ __entry->flags |= 0x04;
+ if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ __entry->flags |= 0x08;
+ if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)
+ __entry->flags |= 0x10;
+ if (tx_cnf->status)
+ __entry->flags |= 0x20;
+ if (tx_cnf->status == HIF_REQUEUE)
+ __entry->flags |= 0x40;
+ ),
+ TP_printk("packet ID: %08x, rate policy: %s %d|%d %d|%d %d|%d %d|%d -> %d attempt, Delays media/queue/total: %4dus/%4dus/%4dus",
+ __entry->pkt_id,
+ __print_flags(__entry->flags, NULL,
+ { 0x01, "M" }, { 0x02, "S" }, { 0x04, "G" },
+ { 0x08, "R" }, { 0x10, "D" }, { 0x20, "F" },
+ { 0x40, "Q" }),
+ __entry->rate[0],
+ __entry->tx_count[0],
+ __entry->rate[1],
+ __entry->tx_count[1],
+ __entry->rate[2],
+ __entry->tx_count[2],
+ __entry->rate[3],
+ __entry->tx_count[3],
+ __entry->ack_failures,
+ __entry->delay_media,
+ __entry->delay_queue,
+ __entry->delay_fw
+ )
+);
+#define _trace_tx_stats(tx_cnf, skb, delay) trace_tx_stats(tx_cnf, skb, delay)
+
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE traces
+
+#include <trace/define_trace.h>
diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h
new file mode 100644
index 000000000000..d678b5a08873
--- /dev/null
+++ b/drivers/staging/wfx/wfx.h
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Common private data for Silicon Labs WFx chips.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ */
+#ifndef WFX_H
+#define WFX_H
+
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/nospec.h>
+#include <net/mac80211.h>
+
+#include "bh.h"
+#include "data_tx.h"
+#include "main.h"
+#include "queue.h"
+#include "secure_link.h"
+#include "sta.h"
+#include "scan.h"
+#include "hif_tx.h"
+#include "hif_api_general.h"
+
+struct hwbus_ops;
+
+struct wfx_dev {
+ struct wfx_platform_data pdata;
+ struct device *dev;
+ struct ieee80211_hw *hw;
+ struct ieee80211_vif *vif[2];
+ struct mac_address addresses[2];
+ const struct hwbus_ops *hwbus_ops;
+ void *hwbus_priv;
+
+ u8 keyset;
+ struct completion firmware_ready;
+ struct hif_ind_startup hw_caps;
+ struct wfx_hif hif;
+ struct sl_context sl;
+ int chip_frozen;
+ struct mutex conf_mutex;
+
+ struct wfx_hif_cmd hif_cmd;
+ struct wfx_queue tx_queue[4];
+ struct wfx_queue_stats tx_queue_stats;
+ int tx_burst_idx;
+ atomic_t tx_lock;
+
+ u32 key_map;
+ struct hif_req_add_key keys[MAX_KEY_ENTRIES];
+
+ struct hif_rx_stats rx_stats;
+ struct mutex rx_stats_lock;
+
+ int output_power;
+ atomic_t scan_in_progress;
+};
+
+struct wfx_vif {
+ struct wfx_dev *wdev;
+ struct ieee80211_vif *vif;
+ struct ieee80211_channel *channel;
+ int id;
+ enum wfx_state state;
+
+ int delayed_link_loss;
+ int bss_loss_state;
+ u32 bss_loss_confirm_id;
+ struct mutex bss_loss_lock;
+ struct delayed_work bss_loss_work;
+
+ u32 link_id_map;
+ struct wfx_link_entry link_id_db[WFX_MAX_STA_IN_AP_MODE];
+ struct delayed_work link_id_gc_work;
+ struct work_struct link_id_work;
+
+ bool aid0_bit_set;
+ bool mcast_tx;
+ bool mcast_buffered;
+ struct wfx_grp_addr_table mcast_filter;
+ struct timer_list mcast_timeout;
+ struct work_struct mcast_start_work;
+ struct work_struct mcast_stop_work;
+
+ s8 wep_default_key_id;
+ struct sk_buff *wep_pending_skb;
+ struct work_struct wep_key_work;
+
+ struct tx_policy_cache tx_policy_cache;
+ struct work_struct tx_policy_upload_work;
+
+ u32 sta_asleep_mask;
+ u32 pspoll_mask;
+ spinlock_t ps_state_lock;
+ struct work_struct set_tim_work;
+
+ int dtim_period;
+ int beacon_int;
+ bool enable_beacon;
+ struct work_struct set_beacon_wakeup_period_work;
+
+ bool filter_bssid;
+ bool fwd_probe_req;
+ bool disable_beacon_filter;
+ struct work_struct update_filtering_work;
+
+ u32 erp_info;
+ int cqm_rssi_thold;
+ bool setbssparams_done;
+ struct wfx_ht_info ht_info;
+ struct wfx_edca_params edca;
+ struct hif_mib_set_uapsd_information uapsd_info;
+ struct hif_req_set_bss_params bss_params;
+ struct work_struct bss_params_work;
+ struct work_struct set_cts_work;
+
+ int join_complete_status;
+ bool delayed_unjoin;
+ struct work_struct unjoin_work;
+
+ struct wfx_scan scan;
+
+ struct hif_req_set_pm_mode powersave_mode;
+ struct completion set_pm_mode_complete;
+
+ struct list_head event_queue;
+ spinlock_t event_queue_lock;
+ struct work_struct event_handler_work;
+};
+
+static inline struct wfx_vif *wdev_to_wvif(struct wfx_dev *wdev, int vif_id)
+{
+ if (vif_id >= ARRAY_SIZE(wdev->vif)) {
+ dev_dbg(wdev->dev, "requesting non-existent vif: %d\n", vif_id);
+ return NULL;
+ }
+ vif_id = array_index_nospec(vif_id, ARRAY_SIZE(wdev->vif));
+ if (!wdev->vif[vif_id]) {
+ dev_dbg(wdev->dev, "requesting non-allocated vif: %d\n", vif_id);
+ return NULL;
+ }
+ return (struct wfx_vif *) wdev->vif[vif_id]->drv_priv;
+}
+
+static inline struct wfx_vif *wvif_iterate(struct wfx_dev *wdev, struct wfx_vif *cur)
+{
+ int i;
+ int mark = 0;
+ struct wfx_vif *tmp;
+
+ if (!cur)
+ mark = 1;
+ for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
+ tmp = wdev_to_wvif(wdev, i);
+ if (mark && tmp)
+ return tmp;
+ if (tmp == cur)
+ mark = 1;
+ }
+ return NULL;
+}
+
+static inline int wvif_count(struct wfx_dev *wdev)
+{
+ int i;
+ int ret = 0;
+ struct wfx_vif *wvif;
+
+ for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
+ wvif = wdev_to_wvif(wdev, i);
+ if (wvif)
+ ret++;
+ }
+ return ret;
+}
+
+static inline void memreverse(uint8_t *src, uint8_t length)
+{
+ uint8_t *lo = src;
+ uint8_t *hi = src + length - 1;
+ uint8_t swap;
+
+ while (lo < hi) {
+ swap = *lo;
+ *lo++ = *hi;
+ *hi-- = swap;
+ }
+}
+
+static inline int memzcmp(void *src, unsigned int size)
+{
+ uint8_t *buf = src;
+
+ if (!size)
+ return 0;
+ if (*buf)
+ return 1;
+ return memcmp(buf, buf + 1, size - 1);
+}
+
+#endif /* WFX_H */
diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile
index a5a8e806b98e..a3305a0a888a 100644
--- a/drivers/staging/wilc1000/Makefile
+++ b/drivers/staging/wilc1000/Makefile
@@ -4,11 +4,11 @@ obj-$(CONFIG_WILC1000) += wilc1000.o
ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \
-DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\"
-wilc1000-objs := wilc_wfi_cfgoperations.o wilc_netdev.o wilc_mon.o \
- wilc_hif.o wilc_wlan_cfg.o wilc_wlan.o
+wilc1000-objs := cfg80211.o netdev.o mon.o \
+ hif.o wlan_cfg.o wlan.o
obj-$(CONFIG_WILC1000_SDIO) += wilc1000-sdio.o
-wilc1000-sdio-objs += wilc_sdio.o
+wilc1000-sdio-objs += sdio.o
obj-$(CONFIG_WILC1000_SPI) += wilc1000-spi.o
-wilc1000-spi-objs += wilc_spi.o
+wilc1000-spi-objs += spi.o
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/cfg80211.c
index 22f21831649b..4863e516ff13 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/cfg80211.c
@@ -4,7 +4,7 @@
* All rights reserved.
*/
-#include "wilc_wfi_cfgoperations.h"
+#include "cfg80211.h"
#define FRAME_TYPE_ID 0
#define ACTION_CAT_ID 24
@@ -137,6 +137,7 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,
struct wilc *wl = vif->wilc;
struct host_if_drv *wfi_drv = priv->hif_drv;
struct wilc_conn_info *conn_info = &wfi_drv->conn_info;
+ struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
vif->connecting = false;
@@ -158,12 +159,16 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,
memcpy(priv->associated_bss, conn_info->bssid,
ETH_ALEN);
- cfg80211_connect_result(dev, conn_info->bssid,
- conn_info->req_ies,
- conn_info->req_ies_len,
- conn_info->resp_ies,
- conn_info->resp_ies_len, connect_status,
- GFP_KERNEL);
+ cfg80211_ref_bss(wiphy, vif->bss);
+ cfg80211_connect_bss(dev, conn_info->bssid, vif->bss,
+ conn_info->req_ies,
+ conn_info->req_ies_len,
+ conn_info->resp_ies,
+ conn_info->resp_ies_len,
+ connect_status, GFP_KERNEL,
+ NL80211_TIMEOUT_UNSPECIFIED);
+
+ vif->bss = NULL;
} else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) {
u16 reason = 0;
@@ -186,15 +191,15 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,
}
}
-static struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)
+struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)
{
- int i;
+ struct wilc_vif *vif;
- for (i = 0; i < wl->vif_num; i++)
- if (wl->vif[i])
- return wl->vif[i];
+ vif = list_first_or_null_rcu(&wl->vif_list, typeof(*vif), list);
+ if (!vif)
+ return ERR_PTR(-EINVAL);
- return ERR_PTR(-EINVAL);
+ return vif;
}
static int set_channel(struct wiphy *wiphy,
@@ -204,11 +209,12 @@ static int set_channel(struct wiphy *wiphy,
struct wilc_vif *vif;
u32 channelnum;
int result;
+ int srcu_idx;
- mutex_lock(&wl->vif_mutex);
+ srcu_idx = srcu_read_lock(&wl->srcu);
vif = wilc_get_wl_to_vif(wl);
if (IS_ERR(vif)) {
- mutex_unlock(&wl->vif_mutex);
+ srcu_read_unlock(&wl->srcu, srcu_idx);
return PTR_ERR(vif);
}
@@ -219,7 +225,7 @@ static int set_channel(struct wiphy *wiphy,
if (result)
netdev_err(vif->ndev, "Error in setting channel\n");
- mutex_unlock(&wl->vif_mutex);
+ srcu_read_unlock(&wl->srcu, srcu_idx);
return result;
}
@@ -405,6 +411,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
goto out_put_bss;
}
kfree(join_params);
+ vif->bss = bss;
cfg80211_put_bss(wiphy, bss);
return 0;
@@ -450,6 +457,8 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev,
ret = -EINVAL;
}
+ vif->bss = NULL;
+
return ret;
}
@@ -620,29 +629,26 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
bool pairwise,
const u8 *mac_addr)
{
- struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(netdev);
struct wilc_priv *priv = &vif->priv;
- if (netdev == wl->vif[0]->ndev) {
- if (priv->wilc_gtk[key_index]) {
- kfree(priv->wilc_gtk[key_index]->key);
- priv->wilc_gtk[key_index]->key = NULL;
- kfree(priv->wilc_gtk[key_index]->seq);
- priv->wilc_gtk[key_index]->seq = NULL;
+ if (priv->wilc_gtk[key_index]) {
+ kfree(priv->wilc_gtk[key_index]->key);
+ priv->wilc_gtk[key_index]->key = NULL;
+ kfree(priv->wilc_gtk[key_index]->seq);
+ priv->wilc_gtk[key_index]->seq = NULL;
- kfree(priv->wilc_gtk[key_index]);
- priv->wilc_gtk[key_index] = NULL;
- }
+ kfree(priv->wilc_gtk[key_index]);
+ priv->wilc_gtk[key_index] = NULL;
+ }
- if (priv->wilc_ptk[key_index]) {
- kfree(priv->wilc_ptk[key_index]->key);
- priv->wilc_ptk[key_index]->key = NULL;
- kfree(priv->wilc_ptk[key_index]->seq);
- priv->wilc_ptk[key_index]->seq = NULL;
- kfree(priv->wilc_ptk[key_index]);
- priv->wilc_ptk[key_index] = NULL;
- }
+ if (priv->wilc_ptk[key_index]) {
+ kfree(priv->wilc_ptk[key_index]->key);
+ priv->wilc_ptk[key_index]->key = NULL;
+ kfree(priv->wilc_ptk[key_index]->seq);
+ priv->wilc_ptk[key_index]->seq = NULL;
+ kfree(priv->wilc_ptk[key_index]);
+ priv->wilc_ptk[key_index] = NULL;
}
if (key_index <= 3 && priv->wep_key_len[key_index]) {
@@ -752,33 +758,19 @@ static int change_bss(struct wiphy *wiphy, struct net_device *dev,
return 0;
}
-struct wilc_vif *wilc_get_interface(struct wilc *wl)
-{
- int i;
- struct wilc_vif *vif = NULL;
-
- mutex_lock(&wl->vif_mutex);
- for (i = 0; i < wl->vif_num; i++) {
- if (wl->vif[i]) {
- vif = wl->vif[i];
- break;
- }
- }
- mutex_unlock(&wl->vif_mutex);
- return vif;
-}
-
static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
{
- int ret;
+ int ret = -EINVAL;
struct cfg_param_attr cfg_param_val;
struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif;
struct wilc_priv *priv;
+ int srcu_idx;
- vif = wilc_get_interface(wl);
- if (!vif)
- return -EINVAL;
+ srcu_idx = srcu_read_lock(&wl->srcu);
+ vif = wilc_get_wl_to_vif(wl);
+ if (IS_ERR(vif))
+ goto out;
priv = &vif->priv;
cfg_param_val.flag = 0;
@@ -808,7 +800,7 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
} else {
netdev_err(vif->ndev,
"Fragmentation threshold out of range\n");
- return -EINVAL;
+ goto out;
}
}
@@ -821,7 +813,7 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
cfg_param_val.rts_threshold = wiphy->rts_threshold;
} else {
netdev_err(vif->ndev, "RTS threshold out of range\n");
- return -EINVAL;
+ goto out;
}
}
@@ -829,6 +821,8 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
if (ret)
netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");
+out:
+ srcu_read_unlock(&wl->srcu, srcu_idx);
return ret;
}
@@ -1144,7 +1138,7 @@ static int remain_on_channel(struct wiphy *wiphy,
cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL);
mod_timer(&vif->hif_drv->remain_on_ch_timer,
- jiffies + msecs_to_jiffies(duration));
+ jiffies + msecs_to_jiffies(duration + 1000));
return ret;
}
@@ -1419,8 +1413,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE)
wilc_wfi_deinit_mon_interface(wl, true);
vif->iftype = WILC_STATION_MODE;
- wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
- WILC_STATION_MODE, vif->idx);
+
+ if (wl->initialized)
+ wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+ WILC_STATION_MODE, vif->idx);
memset(priv->assoc_stainfo.sta_associated_bss, 0,
WILC_MAX_NUM_STA * ETH_ALEN);
@@ -1432,8 +1428,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
priv->wdev.iftype = type;
vif->monitor_flag = 0;
vif->iftype = WILC_CLIENT_MODE;
- wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
- WILC_STATION_MODE, vif->idx);
+
+ if (wl->initialized)
+ wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+ WILC_STATION_MODE, vif->idx);
break;
case NL80211_IFTYPE_AP:
@@ -1450,8 +1448,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
dev->ieee80211_ptr->iftype = type;
priv->wdev.iftype = type;
vif->iftype = WILC_GO_MODE;
- wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
- WILC_AP_MODE, vif->idx);
+
+ if (wl->initialized)
+ wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+ WILC_AP_MODE, vif->idx);
break;
default:
@@ -1557,20 +1557,16 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
-static int wilc_get_vif_from_type(struct wilc *wl, int type)
+static struct wilc_vif *wilc_get_vif_from_type(struct wilc *wl, int type)
{
- int i;
+ struct wilc_vif *vif;
- mutex_lock(&wl->vif_mutex);
- for (i = 0; i < wl->vif_num; i++) {
- if (wl->vif[i]->iftype == type) {
- mutex_unlock(&wl->vif_mutex);
- return i;
- }
+ list_for_each_entry_rcu(vif, &wl->vif_list, list) {
+ if (vif->iftype == type)
+ return vif;
}
- mutex_unlock(&wl->vif_mutex);
- return -EINVAL;
+ return NULL;
}
static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
@@ -1583,29 +1579,36 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
struct wilc_vif *vif;
struct wireless_dev *wdev;
int iftype;
- int ret;
if (type == NL80211_IFTYPE_MONITOR) {
struct net_device *ndev;
- int ap_index = wilc_get_vif_from_type(wl, WILC_AP_MODE);
-
- if (ap_index < 0) {
- ap_index = wilc_get_vif_from_type(wl, WILC_GO_MODE);
- if (ap_index < 0)
+ int srcu_idx;
+
+ srcu_idx = srcu_read_lock(&wl->srcu);
+ vif = wilc_get_vif_from_type(wl, WILC_AP_MODE);
+ if (!vif) {
+ vif = wilc_get_vif_from_type(wl, WILC_GO_MODE);
+ if (!vif) {
+ srcu_read_unlock(&wl->srcu, srcu_idx);
goto validate_interface;
+ }
}
- vif = wl->vif[ap_index];
- if (vif->monitor_flag)
+ if (vif->monitor_flag) {
+ srcu_read_unlock(&wl->srcu, srcu_idx);
goto validate_interface;
+ }
ndev = wilc_wfi_init_mon_interface(wl, name, vif->ndev);
- if (ndev)
+ if (ndev) {
vif->monitor_flag = 1;
- else
+ } else {
+ srcu_read_unlock(&wl->srcu, srcu_idx);
return ERR_PTR(-EINVAL);
+ }
wdev = &vif->priv.wdev;
+ srcu_read_unlock(&wl->srcu, srcu_idx);
return wdev;
}
@@ -1613,9 +1616,10 @@ validate_interface:
mutex_lock(&wl->vif_mutex);
if (wl->vif_num == WILC_NUM_CONCURRENT_IFC) {
pr_err("Reached maximum number of interface\n");
- ret = -EINVAL;
- goto out_err;
+ mutex_unlock(&wl->vif_mutex);
+ return ERR_PTR(-EINVAL);
}
+ mutex_unlock(&wl->vif_mutex);
switch (type) {
case NL80211_IFTYPE_STATION:
@@ -1625,30 +1629,20 @@ validate_interface:
iftype = WILC_AP_MODE;
break;
default:
- ret = -EOPNOTSUPP;
- goto out_err;
+ return ERR_PTR(-EOPNOTSUPP);
}
vif = wilc_netdev_ifc_init(wl, name, iftype, type, true);
- if (IS_ERR(vif)) {
- ret = PTR_ERR(vif);
- goto out_err;
- }
-
- mutex_unlock(&wl->vif_mutex);
+ if (IS_ERR(vif))
+ return ERR_CAST(vif);
return &vif->priv.wdev;
-
-out_err:
- mutex_unlock(&wl->vif_mutex);
- return ERR_PTR(ret);
}
static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
{
struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif;
- int i;
if (wdev->iftype == NL80211_IFTYPE_AP ||
wdev->iftype == NL80211_IFTYPE_P2P_GO)
@@ -1658,22 +1652,12 @@ static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
unregister_netdevice(vif->ndev);
vif->monitor_flag = 0;
- mutex_lock(&wl->vif_mutex);
wilc_set_operation_mode(vif, 0, 0, 0);
- for (i = vif->idx; i < wl->vif_num; i++) {
- if ((i + 1) >= wl->vif_num) {
- wl->vif[i] = NULL;
- } else {
- vif = wl->vif[i + 1];
- vif->idx = i;
- wl->vif[i] = vif;
- wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
- vif->iftype, vif->idx);
- }
- }
+ mutex_lock(&wl->vif_mutex);
+ list_del_rcu(&vif->list);
wl->vif_num--;
mutex_unlock(&wl->vif_mutex);
-
+ synchronize_srcu(&wl->srcu);
return 0;
}
@@ -1698,25 +1682,39 @@ static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
{
struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif;
+ int srcu_idx;
- mutex_lock(&wl->vif_mutex);
+ srcu_idx = srcu_read_lock(&wl->srcu);
vif = wilc_get_wl_to_vif(wl);
if (IS_ERR(vif)) {
- mutex_unlock(&wl->vif_mutex);
+ srcu_read_unlock(&wl->srcu, srcu_idx);
return;
}
netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);
- mutex_unlock(&wl->vif_mutex);
+ srcu_read_unlock(&wl->srcu, srcu_idx);
}
static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm)
{
int ret;
+ int srcu_idx;
s32 tx_power = MBM_TO_DBM(mbm);
- struct wilc_vif *vif = netdev_priv(wdev->netdev);
+ struct wilc *wl = wiphy_priv(wiphy);
+ struct wilc_vif *vif;
+
+ if (!wl->initialized)
+ return -EIO;
+ srcu_idx = srcu_read_lock(&wl->srcu);
+ vif = wilc_get_wl_to_vif(wl);
+ if (IS_ERR(vif)) {
+ srcu_read_unlock(&wl->srcu, srcu_idx);
+ return -EINVAL;
+ }
+
+ netdev_info(vif->ndev, "Setting tx power %d\n", tx_power);
if (tx_power < 0)
tx_power = 0;
else if (tx_power > 18)
@@ -1724,6 +1722,7 @@ static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
ret = wilc_set_tx_power(vif, tx_power);
if (ret)
netdev_err(vif->ndev, "Failed to set tx power\n");
+ srcu_read_unlock(&wl->srcu, srcu_idx);
return ret;
}
@@ -1803,6 +1802,17 @@ static void wlan_init_locks(struct wilc *wl)
init_completion(&wl->cfg_event);
init_completion(&wl->sync_event);
init_completion(&wl->txq_thread_started);
+ init_srcu_struct(&wl->srcu);
+}
+
+void wlan_deinit_locks(struct wilc *wilc)
+{
+ mutex_destroy(&wilc->hif_cs);
+ mutex_destroy(&wilc->rxq_cs);
+ mutex_destroy(&wilc->cfg_cmd_lock);
+ mutex_destroy(&wilc->txq_add_to_head_cs);
+ mutex_destroy(&wilc->vif_mutex);
+ cleanup_srcu_struct(&wilc->srcu);
}
int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
@@ -1816,6 +1826,8 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
if (!wl)
return -EINVAL;
+ wlan_init_locks(wl);
+
ret = wilc_wlan_cfg_init(wl);
if (ret)
goto free_wl;
@@ -1826,6 +1838,7 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
wl->chip_ps_state = WILC_CHIP_WAKEDUP;
INIT_LIST_HEAD(&wl->txq_head.list);
INIT_LIST_HEAD(&wl->rxq_head.list);
+ INIT_LIST_HEAD(&wl->vif_list);
wl->hif_workqueue = create_singlethread_workqueue("WILC_wq");
if (!wl->hif_workqueue) {
@@ -1839,8 +1852,6 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
goto free_hq;
}
- wlan_init_locks(wl);
-
return 0;
free_hq:
@@ -1850,6 +1861,7 @@ free_cfg:
wilc_wlan_cfg_deinit(wl);
free_wl:
+ wlan_deinit_locks(wl);
wiphy_unregister(wl->wiphy);
wiphy_free(wl->wiphy);
return ret;
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h b/drivers/staging/wilc1000/cfg80211.h
index 234faaabdb82..5e5d63f70df2 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
+++ b/drivers/staging/wilc1000/cfg80211.h
@@ -4,9 +4,9 @@
* All rights reserved.
*/
-#ifndef NM_WFI_CFGOPERATIONS
-#define NM_WFI_CFGOPERATIONS
-#include "wilc_wfi_netdevice.h"
+#ifndef WILC_CFG80211_H
+#define WILC_CFG80211_H
+#include "netdev.h"
struct wiphy *wilc_cfg_alloc(void);
int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
@@ -24,4 +24,6 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
u16 frame_type, bool reg);
struct wilc_vif *wilc_get_interface(struct wilc *wl);
+struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl);
+void wlan_deinit_locks(struct wilc *wilc);
#endif
diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/hif.c
index f2b7d5a1be17..5f6706bcedf6 100644
--- a/drivers/staging/wilc1000/wilc_hif.c
+++ b/drivers/staging/wilc1000/hif.c
@@ -4,7 +4,7 @@
* All rights reserved.
*/
-#include "wilc_wfi_netdevice.h"
+#include "netdev.h"
#define WILC_HIF_SCAN_TIMEOUT_MS 5000
#define WILC_HIF_CONNECT_TIMEOUT_MS 9500
@@ -32,7 +32,7 @@ struct wilc_op_mode {
};
struct wilc_reg_frame {
- bool reg;
+ u8 reg;
u8 reg_id;
__le16 frame_type;
} __packed;
@@ -183,11 +183,17 @@ int wilc_get_vif_idx(struct wilc_vif *vif)
static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
{
int index = idx - 1;
+ struct wilc_vif *vif;
if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
return NULL;
- return wilc->vif[index];
+ list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+ if (vif->idx == index)
+ return vif;
+ }
+
+ return NULL;
}
static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
@@ -473,6 +479,8 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
if (rates_ie) {
rates_len = rates_ie[1];
+ if (rates_len > WILC_MAX_RATES_SUPPORTED)
+ rates_len = WILC_MAX_RATES_SUPPORTED;
param->supp_rates[0] = rates_len;
memcpy(&param->supp_rates[1], rates_ie + 2, rates_len);
}
@@ -544,7 +552,7 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
param->mode_802_11i = 2;
param->rsn_found = true;
- //extract RSN capabilities
+ /* extract RSN capabilities */
offset += (rsn_ie[offset] * 4) + 2;
offset += (rsn_ie[offset] * 4) + 2;
memcpy(param->rsn_cap, &rsn_ie[offset], 2);
@@ -1776,7 +1784,9 @@ void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
wid.val = (u8 *)&reg_frame;
memset(&reg_frame, 0x0, sizeof(reg_frame));
- reg_frame.reg = reg;
+
+ if (reg)
+ reg_frame.reg = 1;
switch (frame_type) {
case IEEE80211_STYPE_ACTION:
diff --git a/drivers/staging/wilc1000/wilc_hif.h b/drivers/staging/wilc1000/hif.h
index ac5fe57f872b..22ee6fffd599 100644
--- a/drivers/staging/wilc1000/wilc_hif.h
+++ b/drivers/staging/wilc1000/hif.h
@@ -4,10 +4,10 @@
* All rights reserved.
*/
-#ifndef HOST_INT_H
-#define HOST_INT_H
+#ifndef WILC_HIF_H
+#define WILC_HIF_H
#include <linux/ieee80211.h>
-#include "wilc_wlan_if.h"
+#include "wlan_if.h"
enum {
WILC_IDLE_MODE = 0x0,
diff --git a/drivers/staging/wilc1000/wilc_mon.c b/drivers/staging/wilc1000/mon.c
index d6f14f69ad64..48ac33f06f63 100644
--- a/drivers/staging/wilc1000/wilc_mon.c
+++ b/drivers/staging/wilc1000/mon.c
@@ -4,7 +4,7 @@
* All rights reserved.
*/
-#include "wilc_wfi_cfgoperations.h"
+#include "cfg80211.h"
struct wilc_wfi_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
@@ -220,7 +220,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
{
struct wilc_wfi_mon_priv *priv;
- /*If monitor interface is already initialized, return it*/
+ /* If monitor interface is already initialized, return it */
if (wl->monitor_dev)
return wl->monitor_dev;
diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/netdev.c
index 508acb8bb089..d2c0b0f7cf63 100644
--- a/drivers/staging/wilc1000/wilc_netdev.c
+++ b/drivers/staging/wilc1000/netdev.c
@@ -10,8 +10,8 @@
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
-#include "wilc_wfi_cfgoperations.h"
-#include "wilc_wlan_cfg.h"
+#include "cfg80211.h"
+#include "wlan_cfg.h"
#define WILC_MULTICAST_TABLE_SIZE 8
@@ -97,29 +97,25 @@ void wilc_mac_indicate(struct wilc *wilc)
static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
{
u8 *bssid, *bssid1;
- int i = 0;
struct net_device *ndev = NULL;
+ struct wilc_vif *vif;
bssid = mac_header + 10;
bssid1 = mac_header + 4;
- mutex_lock(&wilc->vif_mutex);
- for (i = 0; i < wilc->vif_num; i++) {
- if (wilc->vif[i]->mode == WILC_STATION_MODE)
- if (ether_addr_equal_unaligned(bssid,
- wilc->vif[i]->bssid)) {
- ndev = wilc->vif[i]->ndev;
+ list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+ if (vif->mode == WILC_STATION_MODE)
+ if (ether_addr_equal_unaligned(bssid, vif->bssid)) {
+ ndev = vif->ndev;
goto out;
}
- if (wilc->vif[i]->mode == WILC_AP_MODE)
- if (ether_addr_equal_unaligned(bssid1,
- wilc->vif[i]->bssid)) {
- ndev = wilc->vif[i]->ndev;
+ if (vif->mode == WILC_AP_MODE)
+ if (ether_addr_equal_unaligned(bssid1, vif->bssid)) {
+ ndev = vif->ndev;
goto out;
}
}
out:
- mutex_unlock(&wilc->vif_mutex);
return ndev;
}
@@ -137,13 +133,16 @@ void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
{
- u8 i = 0;
+ int srcu_idx;
u8 ret_val = 0;
+ struct wilc_vif *vif;
- for (i = 0; i < wilc->vif_num; i++)
- if (!is_zero_ether_addr(wilc->vif[i]->bssid))
+ srcu_idx = srcu_read_lock(&wilc->srcu);
+ list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+ if (!is_zero_ether_addr(vif->bssid))
ret_val++;
-
+ }
+ srcu_read_unlock(&wilc->srcu, srcu_idx);
return ret_val;
}
@@ -167,16 +166,16 @@ static int wilc_txq_task(void *vp)
do {
ret = wilc_wlan_handle_txq(wl, &txq_count);
if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
- int i;
+ int srcu_idx;
struct wilc_vif *ifc;
- mutex_lock(&wl->vif_mutex);
- for (i = 0; i < wl->vif_num; i++) {
- ifc = wl->vif[i];
+ srcu_idx = srcu_read_lock(&wl->srcu);
+ list_for_each_entry_rcu(ifc, &wl->vif_list,
+ list) {
if (ifc->mac_opened && ifc->ndev)
netif_wake_queue(ifc->ndev);
}
- mutex_unlock(&wl->vif_mutex);
+ srcu_read_unlock(&wl->srcu, srcu_idx);
}
} while (ret == -ENOBUFS && !wl->close);
}
@@ -424,18 +423,6 @@ fail:
return -1;
}
-static void wlan_deinit_locks(struct net_device *dev)
-{
- struct wilc_vif *vif = netdev_priv(dev);
- struct wilc *wilc = vif->wilc;
-
- mutex_destroy(&wilc->hif_cs);
- mutex_destroy(&wilc->rxq_cs);
- mutex_destroy(&wilc->cfg_cmd_lock);
- mutex_destroy(&wilc->txq_add_to_head_cs);
- mutex_destroy(&wilc->vif_mutex);
-}
-
static void wlan_deinitialize_threads(struct net_device *dev)
{
struct wilc_vif *vif = netdev_priv(dev);
@@ -477,7 +464,6 @@ static void wilc_wlan_deinitialize(struct net_device *dev)
wilc_wlan_stop(wl, vif);
wilc_wlan_cleanup(dev);
- wlan_deinit_locks(dev);
wl->initialized = false;
@@ -738,14 +724,15 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
wilc_tx_complete);
if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
- int i;
+ int srcu_idx;
+ struct wilc_vif *vif;
- mutex_lock(&wilc->vif_mutex);
- for (i = 0; i < wilc->vif_num; i++) {
- if (wilc->vif[i]->mac_opened)
- netif_stop_queue(wilc->vif[i]->ndev);
+ srcu_idx = srcu_read_lock(&wilc->srcu);
+ list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+ if (vif->mac_opened)
+ netif_stop_queue(vif->ndev);
}
- mutex_unlock(&wilc->vif_mutex);
+ srcu_read_unlock(&wilc->srcu, srcu_idx);
}
return 0;
@@ -823,26 +810,22 @@ void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
{
- int i = 0;
+ int srcu_idx;
struct wilc_vif *vif;
- mutex_lock(&wilc->vif_mutex);
- for (i = 0; i < wilc->vif_num; i++) {
+ srcu_idx = srcu_read_lock(&wilc->srcu);
+ list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
u16 type = le16_to_cpup((__le16 *)buff);
- vif = netdev_priv(wilc->vif[i]->ndev);
- if ((type == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
- (type == vif->frame_reg[1].type && vif->frame_reg[1].reg)) {
+ if (vif->priv.p2p_listen_state &&
+ ((type == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
+ (type == vif->frame_reg[1].type && vif->frame_reg[1].reg)))
wilc_wfi_p2p_rx(vif, buff, size);
- break;
- }
- if (vif->monitor_flag) {
+ if (vif->monitor_flag)
wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);
- break;
- }
}
- mutex_unlock(&wilc->vif_mutex);
+ srcu_read_unlock(&wilc->srcu, srcu_idx);
}
static const struct net_device_ops wilc_netdev_ops = {
@@ -856,7 +839,8 @@ static const struct net_device_ops wilc_netdev_ops = {
void wilc_netdev_cleanup(struct wilc *wilc)
{
- int i;
+ struct wilc_vif *vif;
+ int srcu_idx;
if (!wilc)
return;
@@ -866,21 +850,57 @@ void wilc_netdev_cleanup(struct wilc *wilc)
wilc->firmware = NULL;
}
- for (i = 0; i < wilc->vif_num; i++) {
- if (wilc->vif[i] && wilc->vif[i]->ndev)
- unregister_netdev(wilc->vif[i]->ndev);
+ srcu_idx = srcu_read_lock(&wilc->srcu);
+ list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+ if (vif->ndev)
+ unregister_netdev(vif->ndev);
}
+ srcu_read_unlock(&wilc->srcu, srcu_idx);
wilc_wfi_deinit_mon_interface(wilc, false);
flush_workqueue(wilc->hif_workqueue);
destroy_workqueue(wilc->hif_workqueue);
+
+ do {
+ mutex_lock(&wilc->vif_mutex);
+ if (wilc->vif_num <= 0) {
+ mutex_unlock(&wilc->vif_mutex);
+ break;
+ }
+ vif = wilc_get_wl_to_vif(wilc);
+ if (!IS_ERR(vif))
+ list_del_rcu(&vif->list);
+
+ wilc->vif_num--;
+ mutex_unlock(&wilc->vif_mutex);
+ synchronize_srcu(&wilc->srcu);
+ } while (1);
+
wilc_wlan_cfg_deinit(wilc);
+ wlan_deinit_locks(wilc);
kfree(wilc->bus_data);
wiphy_unregister(wilc->wiphy);
wiphy_free(wilc->wiphy);
}
EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
+static u8 wilc_get_available_idx(struct wilc *wl)
+{
+ int idx = 0;
+ struct wilc_vif *vif;
+ int srcu_idx;
+
+ srcu_idx = srcu_read_lock(&wl->srcu);
+ list_for_each_entry_rcu(vif, &wl->vif_list, list) {
+ if (vif->idx == 0)
+ idx = 1;
+ else
+ idx = 0;
+ }
+ srcu_read_unlock(&wl->srcu, srcu_idx);
+ return idx;
+}
+
struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
int vif_type, enum nl80211_iftype type,
bool rtnl_locked)
@@ -921,10 +941,14 @@ struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
ndev->needs_free_netdev = true;
vif->iftype = vif_type;
- vif->wilc->vif[wl->vif_num] = vif;
- vif->idx = wl->vif_num;
- wl->vif_num += 1;
+ vif->idx = wilc_get_available_idx(wl);
vif->mac_opened = 0;
+ mutex_lock(&wl->vif_mutex);
+ list_add_tail_rcu(&vif->list, &wl->vif_list);
+ wl->vif_num += 1;
+ mutex_unlock(&wl->vif_mutex);
+ synchronize_srcu(&wl->srcu);
+
return vif;
}
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/netdev.h
index 978a8bdbfc40..cd8f0d72caaa 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/netdev.h
@@ -4,8 +4,8 @@
* All rights reserved.
*/
-#ifndef WILC_WFI_NETDEVICE
-#define WILC_WFI_NETDEVICE
+#ifndef WILC_NETDEV_H
+#define WILC_NETDEV_H
#include <linux/tcp.h>
#include <linux/ieee80211.h>
@@ -14,9 +14,9 @@
#include <linux/if_arp.h>
#include <linux/gpio/consumer.h>
-#include "wilc_hif.h"
-#include "wilc_wlan.h"
-#include "wilc_wlan_cfg.h"
+#include "hif.h"
+#include "wlan.h"
+#include "wlan_cfg.h"
#define FLOW_CONTROL_LOWER_THRESHOLD 128
#define FLOW_CONTROL_UPPER_THRESHOLD 256
@@ -60,7 +60,7 @@ struct sta_info {
u8 sta_associated_bss[WILC_MAX_NUM_STA][ETH_ALEN];
};
-/*Parameters needed for host interface for remaining on channel*/
+/* Parameters needed for host interface for remaining on channel */
struct wilc_wfi_p2p_listen_params {
struct ieee80211_channel *listen_ch;
u32 listen_duration;
@@ -145,11 +145,13 @@ struct wilc_priv {
struct wilc_pmkid_attr pmkid_list;
u8 wep_key[4][WLAN_KEY_LEN_WEP104];
u8 wep_key_len[4];
+
/* The real interface that the monitor is on */
struct net_device *real_ndev;
struct wilc_wfi_key *wilc_gtk[WILC_MAX_NUM_STA];
struct wilc_wfi_key *wilc_ptk[WILC_MAX_NUM_STA];
u8 wilc_groupkey;
+
/* mutexes */
struct mutex scan_req_lock;
bool p2p_listen_state;
@@ -208,6 +210,8 @@ struct wilc_vif {
struct tcp_ack_filter ack_filter;
bool connecting;
struct wilc_priv priv;
+ struct list_head list;
+ struct cfg80211_bss *bss;
};
struct wilc {
@@ -221,16 +225,22 @@ struct wilc {
int dev_irq_num;
int close;
u8 vif_num;
- struct wilc_vif *vif[WILC_NUM_CONCURRENT_IFC];
- /*protect vif list*/
+ struct list_head vif_list;
+
+ /* protect vif list */
struct mutex vif_mutex;
+ struct srcu_struct srcu;
u8 open_ifcs;
- /*protect head of transmit queue*/
+
+ /* protect head of transmit queue */
struct mutex txq_add_to_head_cs;
- /*protect txq_entry_t transmit queue*/
+
+ /* protect txq_entry_t transmit queue */
spinlock_t txq_spinlock;
- /*protect rxq_entry_t receiver queue*/
+
+ /* protect rxq_entry_t receiver queue */
struct mutex rxq_cs;
+
/* lock to protect hif access */
struct mutex hif_cs;
@@ -242,6 +252,7 @@ struct wilc {
struct task_struct *txq_thread;
int quit;
+
/* lock to protect issue of wid command to firmware */
struct mutex cfg_cmd_lock;
struct wilc_cfg_frame cfg_frame;
@@ -268,6 +279,7 @@ struct wilc {
struct wilc_cfg cfg;
void *bus_data;
struct net_device *monitor_dev;
+
/* deinit lock */
struct mutex deinit_lock;
u8 sta_ch;
diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/sdio.c
index c787c5da8f2b..319e039380b0 100644
--- a/drivers/staging/wilc1000/wilc_sdio.c
+++ b/drivers/staging/wilc1000/sdio.c
@@ -8,8 +8,8 @@
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/host.h>
-#include "wilc_wfi_netdevice.h"
-#include "wilc_wfi_cfgoperations.h"
+#include "netdev.h"
+#include "cfg80211.h"
#define SDIO_MODALIAS "wilc1000_sdio"
diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/spi.c
index 3c1ae9e9f9aa..55f8757325f0 100644
--- a/drivers/staging/wilc1000/wilc_spi.c
+++ b/drivers/staging/wilc1000/spi.c
@@ -4,10 +4,11 @@
* All rights reserved.
*/
+#include <linux/clk.h>
#include <linux/spi/spi.h>
-#include "wilc_wfi_netdevice.h"
-#include "wilc_wfi_cfgoperations.h"
+#include "netdev.h"
+#include "cfg80211.h"
struct wilc_spi {
int crc_off;
@@ -132,6 +133,12 @@ static int wilc_bus_probe(struct spi_device *spi)
wilc->bus_data = spi_priv;
wilc->gpio_irq = gpio;
+ wilc->rtc_clk = devm_clk_get(&spi->dev, "rtc_clk");
+ if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ else if (!IS_ERR(wilc->rtc_clk))
+ clk_prepare_enable(wilc->rtc_clk);
+
return 0;
}
@@ -142,6 +149,10 @@ static int wilc_bus_remove(struct spi_device *spi)
/* free the GPIO in module remove */
if (wilc->gpio_irq)
gpiod_put(wilc->gpio_irq);
+
+ if (!IS_ERR(wilc->rtc_clk))
+ clk_disable_unprepare(wilc->rtc_clk);
+
wilc_netdev_cleanup(wilc);
return 0;
}
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wlan.c
index 771d8cb68dc1..d3de76126b78 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wlan.c
@@ -6,8 +6,8 @@
#include <linux/if_ether.h>
#include <linux/ip.h>
-#include "wilc_wfi_cfgoperations.h"
-#include "wilc_wlan_cfg.h"
+#include "cfg80211.h"
+#include "wlan_cfg.h"
static inline bool is_wilc1000(u32 id)
{
diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wlan.h
index 7469fa47d588..1f6957cf2e9c 100644
--- a/drivers/staging/wilc1000/wilc_wlan.h
+++ b/drivers/staging/wilc1000/wlan.h
@@ -190,7 +190,7 @@
#define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM)
#define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM)
-/*time for expiring the completion of cfg packets*/
+/* time for expiring the completion of cfg packets */
#define WILC_CFG_PKTS_TIMEOUT msecs_to_jiffies(2000)
#define IS_MANAGMEMENT 0x100
diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wlan_cfg.c
index 3f53807cee0f..6f6b286788d1 100644
--- a/drivers/staging/wilc1000/wilc_wlan_cfg.c
+++ b/drivers/staging/wilc1000/wlan_cfg.c
@@ -4,10 +4,10 @@
* All rights reserved.
*/
-#include "wilc_wlan_if.h"
-#include "wilc_wlan.h"
-#include "wilc_wlan_cfg.h"
-#include "wilc_wfi_netdevice.h"
+#include "wlan_if.h"
+#include "wlan.h"
+#include "wlan_cfg.h"
+#include "netdev.h"
enum cfg_cmd_type {
CFG_BYTE_CMD = 0,
@@ -44,6 +44,11 @@ static const struct wilc_cfg_str g_cfg_str[] = {
{WID_NIL, NULL}
};
+#define WILC_RESP_MSG_TYPE_CONFIG_REPLY 'R'
+#define WILC_RESP_MSG_TYPE_STATUS_INFO 'I'
+#define WILC_RESP_MSG_TYPE_NETWORK_INFO 'N'
+#define WILC_RESP_MSG_TYPE_SCAN_COMPLETE 'S'
+
/********************************************
*
* Configuration Functions
@@ -360,33 +365,26 @@ void wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
size -= 4;
rsp->type = 0;
- /*
- * The valid types of response messages are
- * 'R' (Response),
- * 'I' (Information), and
- * 'N' (Network Information)
- */
-
switch (msg_type) {
- case 'R':
+ case WILC_RESP_MSG_TYPE_CONFIG_REPLY:
wilc_wlan_parse_response_frame(wilc, frame, size);
rsp->type = WILC_CFG_RSP;
rsp->seq_no = msg_id;
break;
- case 'I':
+ case WILC_RESP_MSG_TYPE_STATUS_INFO:
wilc_wlan_parse_info_frame(wilc, frame);
rsp->type = WILC_CFG_RSP_STATUS;
rsp->seq_no = msg_id;
- /*call host interface info parse as well*/
+ /* call host interface info parse as well */
wilc_gnrl_async_info_received(wilc, frame - 4, size + 4);
break;
- case 'N':
+ case WILC_RESP_MSG_TYPE_NETWORK_INFO:
wilc_network_info_received(wilc, frame - 4, size + 4);
break;
- case 'S':
+ case WILC_RESP_MSG_TYPE_SCAN_COMPLETE:
wilc_scan_complete_received(wilc, frame - 4, size + 4);
break;
diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.h b/drivers/staging/wilc1000/wlan_cfg.h
index 614c5673f232..614c5673f232 100644
--- a/drivers/staging/wilc1000/wilc_wlan_cfg.h
+++ b/drivers/staging/wilc1000/wlan_cfg.h
diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wlan_if.h
index 70eac586f80c..7c7ee66c35f5 100644
--- a/drivers/staging/wilc1000/wilc_wlan_if.h
+++ b/drivers/staging/wilc1000/wlan_if.h
@@ -750,10 +750,10 @@ enum {
WID_REMOVE_KEY = 0x301E,
WID_ASSOC_REQ_INFO = 0x301F,
WID_ASSOC_RES_INFO = 0x3020,
- WID_MANUFACTURER = 0x3026, /*Added for CAPI tool */
- WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */
- WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */
- WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */
+ WID_MANUFACTURER = 0x3026, /* Added for CAPI tool */
+ WID_MODEL_NAME = 0x3027, /* Added for CAPI tool */
+ WID_MODEL_NUM = 0x3028, /* Added for CAPI tool */
+ WID_DEVICE_NAME = 0x3029, /* Added for CAPI tool */
/* NMAC String WID list */
WID_SET_OPERATION_MODE = 0x3079,
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index 5ff740a8837d..bdd7f414fdbb 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -1181,8 +1181,6 @@ struct hfa384x_usbctlx {
ctlx_cmdcb_t cmdcb; /* Async command callback */
ctlx_usercb_t usercb; /* Async user callback, */
void *usercb_data; /* at CTLX completion */
-
- int variant; /* Identifies cmd variant */
};
struct hfa384x_usbctlxq {
@@ -1337,7 +1335,9 @@ struct hfa384x {
* interface
*/
- struct hfa384x_caplevel cap_act_sta_mfi; /* sta f/w to modem interface */
+ struct hfa384x_caplevel cap_act_sta_mfi; /*
+ * sta f/w to modem interface
+ */
struct hfa384x_caplevel cap_act_ap_cfi; /*
* ap f/w to controller
@@ -1359,7 +1359,9 @@ struct hfa384x {
struct hfa384x_inf_frame *scanresults;
- struct prism2sta_authlist authlist; /* Authenticated station list. */
+ 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. */
@@ -1370,12 +1372,13 @@ void hfa384x_create(struct hfa384x *hw, struct usb_device *usb);
void hfa384x_destroy(struct hfa384x *hw);
int hfa384x_corereset(struct hfa384x *hw, int holdtime, int settletime,
- int genesis);
+ 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_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);
@@ -1383,7 +1386,8 @@ 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(struct hfa384x *hw, u16 rid, void *val)
+static inline int
+hfa384x_drvr_getconfig16(struct hfa384x *hw, u16 rid, void *val)
{
int result = 0;
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index 28d372a0663a..b71756ab0394 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -293,13 +293,11 @@ void dbprint_urb(struct urb *urb)
pr_debug("urb->transfer_buffer_length=0x%08x\n",
urb->transfer_buffer_length);
pr_debug("urb->actual_length=0x%08x\n", urb->actual_length);
- pr_debug("urb->bandwidth=0x%08x\n", urb->bandwidth);
pr_debug("urb->setup_packet(ctl)=0x%08x\n",
(unsigned int)urb->setup_packet);
pr_debug("urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame);
pr_debug("urb->interval(irq)=0x%08x\n", urb->interval);
pr_debug("urb->error_count(iso)=0x%08x\n", urb->error_count);
- pr_debug("urb->timeout=0x%08x\n", urb->timeout);
pr_debug("urb->context=0x%08x\n", (unsigned int)urb->context);
pr_debug("urb->complete=0x%08x\n", (unsigned int)urb->complete);
}
diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c
index 8bd92bba0ac1..51d917c8cdc8 100644
--- a/drivers/staging/wlan-ng/p80211wep.c
+++ b/drivers/staging/wlan-ng/p80211wep.c
@@ -49,6 +49,7 @@
/*================================================================*/
/* System Includes */
+#include <linux/crc32.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/random.h>
@@ -61,61 +62,6 @@
#define WEP_KEY(x) (((x) & 0xC0) >> 6)
-static const u32 wep_crc32_table[256] = {
- 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
- 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
- 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
- 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
- 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
- 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
- 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
- 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
- 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
- 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
- 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
- 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
- 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
- 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
- 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
- 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
- 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
- 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
- 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
- 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
- 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
- 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
- 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
- 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
- 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
- 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
- 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
- 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
- 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
- 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
- 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
- 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
- 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
- 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
- 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
- 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
- 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
- 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
- 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
- 0x2d02ef8dL
-};
-
/* keylen in bytes! */
int wep_change_key(struct wlandevice *wlandev, int keynum, u8 *key, int keylen)
@@ -184,7 +130,6 @@ int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override,
}
/* Apply the RC4 to the data, update the CRC32 */
- crc = ~0;
i = 0;
j = 0;
for (k = 0; k < len; k++) {
@@ -192,9 +137,8 @@ int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override,
j = (j + s[i]) & 0xff;
swap(i, j);
buf[k] ^= s[(s[i] + s[j]) & 0xff];
- crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8);
}
- crc = ~crc;
+ crc = ~crc32_le(~0, buf, len);
/* now let's check the crc */
c_crc[0] = crc;
@@ -257,17 +201,15 @@ int wep_encrypt(struct wlandevice *wlandev, u8 *buf,
}
/* Update CRC32 then apply RC4 to the data */
- crc = ~0;
i = 0;
j = 0;
for (k = 0; k < len; k++) {
- crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8);
i = (i + 1) & 0xff;
j = (j + s[i]) & 0xff;
swap(i, j);
dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff];
}
- crc = ~crc;
+ crc = ~crc32_le(~0, buf, len);
/* now let's encrypt the crc */
icv[0] = crc;
diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c
index b5ba176004c1..352556f6870a 100644
--- a/drivers/staging/wlan-ng/prism2usb.c
+++ b/drivers/staging/wlan-ng/prism2usb.c
@@ -137,7 +137,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface)
{
struct wlandevice *wlandev;
- wlandev = (struct wlandevice *)usb_get_intfdata(interface);
+ wlandev = usb_get_intfdata(interface);
if (wlandev) {
LIST_HEAD(cleanlist);
struct hfa384x_usbctlx *ctlx, *temp;
@@ -222,7 +222,7 @@ static int prism2sta_suspend(struct usb_interface *interface,
struct hfa384x *hw = NULL;
struct wlandevice *wlandev;
- wlandev = (struct wlandevice *)usb_get_intfdata(interface);
+ wlandev = usb_get_intfdata(interface);
if (!wlandev)
return -ENODEV;
@@ -245,7 +245,7 @@ static int prism2sta_resume(struct usb_interface *interface)
struct hfa384x *hw = NULL;
struct wlandevice *wlandev;
- wlandev = (struct wlandevice *)usb_get_intfdata(interface);
+ wlandev = usb_get_intfdata(interface);
if (!wlandev)
return -ENODEV;